Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1265 lines
28 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. dllproc.c
  5. Abstract:
  6. This module implements POSIX process structure APIs
  7. Author:
  8. Mark Lucovsky (markl) 27-Jun-1989
  9. Revision History:
  10. --*/
  11. #include <sys\utsname.h>
  12. #include <unistd.h>
  13. #include <time.h>
  14. #include <string.h>
  15. #include <stdarg.h>
  16. #ifdef _ALPHA_
  17. #include "psxalpha.h"
  18. #endif
  19. #ifdef _MIPS_
  20. #include "psxmips.h"
  21. #endif
  22. #ifdef _PPC_
  23. #include "psxppc.h"
  24. #endif
  25. #ifdef _X86_
  26. #include "psxi386.h"
  27. #endif
  28. #ifdef _IA64_
  29. #include "psxia64.h"
  30. #endif
  31. #include "psxdll.h"
  32. void
  33. __cdecl
  34. _exit(int status)
  35. {
  36. PSX_API_MSG m;
  37. PPSX_EXIT_MSG args;
  38. NTSTATUS st;
  39. args = &m.u.Exit;
  40. PSX_FORMAT_API_MSG(m, PsxExitApi, sizeof(*args));
  41. args->ExitStatus = (ULONG)status;
  42. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  43. (PPORT_MESSAGE)&m);
  44. #ifdef PSX_MORE_ERRORS
  45. if (!NT_SUCCESS(st)) {
  46. KdPrint(("PSXDLL: _exit: 0x%x\n", st));
  47. }
  48. #endif
  49. NtTerminateProcess(NtCurrentProcess(), 0);
  50. }
  51. gid_t
  52. __cdecl
  53. getegid(void)
  54. {
  55. PSX_API_MSG m;
  56. PPSX_GETIDS_MSG args;
  57. NTSTATUS st;
  58. args = &m.u.GetIds;
  59. PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
  60. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  61. (PPORT_MESSAGE)&m);
  62. #ifdef PSX_MORE_ERRORS
  63. ASSERT(NT_SUCCESS(st));
  64. #endif
  65. return args->EffectiveGid;
  66. }
  67. gid_t
  68. __cdecl
  69. getgid(void)
  70. {
  71. PSX_API_MSG m;
  72. PPSX_GETIDS_MSG args;
  73. NTSTATUS st;
  74. args = &m.u.GetIds;
  75. PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
  76. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  77. (PPORT_MESSAGE)&m);
  78. #ifdef PSX_MORE_ERRORS
  79. ASSERT(NT_SUCCESS(st));
  80. #endif
  81. return args->RealGid;
  82. }
  83. uid_t
  84. __cdecl
  85. geteuid(void)
  86. {
  87. PSX_API_MSG m;
  88. PPSX_GETIDS_MSG args;
  89. NTSTATUS st;
  90. args = &m.u.GetIds;
  91. PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
  92. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  93. (PPORT_MESSAGE)&m);
  94. #ifdef PSX_MORE_ERRORS
  95. ASSERT(NT_SUCCESS(st));
  96. #endif
  97. return args->EffectiveUid;
  98. }
  99. uid_t
  100. __cdecl
  101. getuid(void)
  102. {
  103. PSX_API_MSG m;
  104. PPSX_GETIDS_MSG args;
  105. NTSTATUS st;
  106. args = &m.u.GetIds;
  107. PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
  108. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  109. (PPORT_MESSAGE)&m);
  110. #ifdef PSX_MORE_ERRORS
  111. ASSERT(NT_SUCCESS(st));
  112. #endif
  113. return args->RealUid;
  114. }
  115. pid_t
  116. __cdecl
  117. getppid(void)
  118. {
  119. PSX_API_MSG m;
  120. PPSX_GETIDS_MSG args;
  121. NTSTATUS st;
  122. args = &m.u.GetIds;
  123. PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
  124. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  125. (PPORT_MESSAGE)&m);
  126. #ifdef PSX_MORE_ERRORS
  127. ASSERT(NT_SUCCESS(st));
  128. #endif
  129. return args->ParentPid;
  130. }
  131. pid_t
  132. __cdecl
  133. getpid(void)
  134. {
  135. PSX_API_MSG m;
  136. PPSX_GETIDS_MSG args;
  137. NTSTATUS st;
  138. args = &m.u.GetIds;
  139. PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
  140. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  141. (PPORT_MESSAGE)&m);
  142. #ifdef PSX_MORE_ERRORS
  143. ASSERT(NT_SUCCESS(st));
  144. #endif
  145. return args->Pid;
  146. }
  147. pid_t
  148. __cdecl
  149. getpgrp(void)
  150. {
  151. PSX_API_MSG m;
  152. PPSX_GETIDS_MSG args;
  153. NTSTATUS st;
  154. args = &m.u.GetIds;
  155. PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
  156. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  157. (PPORT_MESSAGE)&m);
  158. #ifdef PSX_MORE_ERRORS
  159. ASSERT(NT_SUCCESS(st));
  160. #endif
  161. return args->GroupId;
  162. }
  163. pid_t
  164. __cdecl
  165. setsid(void)
  166. {
  167. PSX_API_MSG m;
  168. NTSTATUS st;
  169. PSX_FORMAT_API_MSG(m, PsxSetSidApi, 0);
  170. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  171. (PPORT_MESSAGE)&m);
  172. #ifdef PSX_MORE_ERRORS
  173. ASSERT(NT_SUCCESS(st));
  174. #endif
  175. if (m.Error) {
  176. errno = m.Error;
  177. return -1;
  178. }
  179. return (pid_t)m.ReturnValue;
  180. }
  181. int
  182. __cdecl
  183. setpgid(pid_t pid, pid_t pgid)
  184. {
  185. PSX_API_MSG m;
  186. PPSX_SETPGROUPID_MSG args;
  187. NTSTATUS st;
  188. args = &m.u.SetPGroupId;
  189. PSX_FORMAT_API_MSG(m, PsxSetPGroupIdApi, sizeof(*args));
  190. args->Pid = pid;
  191. args->Pgid = pgid;
  192. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  193. (PPORT_MESSAGE)&m);
  194. #ifdef PSX_MORE_ERRORS
  195. ASSERT(NT_SUCCESS(st));
  196. #endif
  197. if (m.Error) {
  198. errno = (int)m.Error;
  199. return -1;
  200. }
  201. return (int)m.ReturnValue;
  202. }
  203. pid_t
  204. __cdecl
  205. waitpid(pid_t pid, int *stat_loc, int options)
  206. {
  207. PSX_API_MSG m;
  208. PPSX_WAITPID_MSG args;
  209. NTSTATUS st;
  210. args = &m.u.WaitPid;
  211. PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
  212. args->Pid = pid;
  213. args->Options = options;
  214. for (;;) {
  215. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  216. (PPORT_MESSAGE)&m);
  217. #ifdef PSX_MORE_ERRORS
  218. if (!NT_SUCCESS(st)) {
  219. KdPrint(("PSXDLL: waitpid: 0x%x\n", st));
  220. }
  221. ASSERT(NT_SUCCESS(st));
  222. #endif
  223. if (EINTR == m.Error && SIGCONT == m.Signal) {
  224. // We were stopped and then continued. Continue
  225. // waiting.
  226. PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
  227. continue;
  228. }
  229. if (m.Error) {
  230. errno = (int)m.Error;
  231. return -1;
  232. }
  233. if (NULL != stat_loc) {
  234. try {
  235. *stat_loc = args->StatLocValue;
  236. } except (EXCEPTION_EXECUTE_HANDLER) {
  237. errno = EFAULT;
  238. m.ReturnValue = (ULONG)-1;
  239. }
  240. }
  241. return (int)m.ReturnValue;
  242. }
  243. }
  244. pid_t
  245. __cdecl
  246. wait(int *stat_loc)
  247. {
  248. PSX_API_MSG m;
  249. PPSX_WAITPID_MSG args;
  250. NTSTATUS st;
  251. args = &m.u.WaitPid;
  252. PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
  253. args->Pid = (pid_t)-1;
  254. args->Options = (pid_t)0;
  255. for (;;) {
  256. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  257. (PPORT_MESSAGE)&m);
  258. #ifdef PSX_MORE_ERRORS
  259. if (!NT_SUCCESS(st)) {
  260. KdPrint(("PSXDLL: wait: NtRequest: 0x%x\n", st));
  261. }
  262. ASSERT(NT_SUCCESS(st));
  263. #endif
  264. if (EINTR == m.Error && SIGCONT == m.Signal) {
  265. // We were stopped and continued. Continue waiting.
  266. PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
  267. continue;
  268. }
  269. if (m.Error) {
  270. errno = (int)m.Error;
  271. return -1;
  272. }
  273. if (ARGUMENT_PRESENT(stat_loc)) {
  274. try {
  275. *stat_loc = args->StatLocValue;
  276. } except (EXCEPTION_EXECUTE_HANDLER) {
  277. errno = EFAULT;
  278. m.ReturnValue = (ULONG)-1;
  279. }
  280. }
  281. return (int)m.ReturnValue;
  282. }
  283. }
  284. pid_t
  285. __cdecl
  286. fork(void)
  287. {
  288. PSX_API_MSG m;
  289. NTSTATUS st;
  290. PPSX_FORK_MSG args;
  291. PTEB ThreadInfo;
  292. args = &m.u.Fork;
  293. again:
  294. PSX_FORMAT_API_MSG(m, PsxForkApi, sizeof(*args));
  295. ThreadInfo = NtCurrentTeb();
  296. args->StackBase = ThreadInfo->NtTib.StackBase;
  297. args->StackLimit = ThreadInfo->NtTib.StackLimit;
  298. args->StackAllocationBase = ThreadInfo->DeallocationStack;
  299. #ifdef _IA64_
  300. args->BStoreLimit = ThreadInfo->BStoreLimit;
  301. #endif
  302. try {
  303. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  304. (PPORT_MESSAGE)&m);
  305. } except (EXCEPTION_EXECUTE_HANDLER) {
  306. KdPrint(("PSXDLL: fork: took an exception\n"));
  307. KdPrint(("PSXDLL: exception is 0x%x\n", GetExceptionCode()));
  308. }
  309. #ifdef PSX_MORE_ERRORS
  310. ASSERT(NT_SUCCESS(st));
  311. #endif
  312. if (st == PSX_FORK_RETURN) {
  313. st = PsxConnectToServer();
  314. if (!NT_SUCCESS(st)) {
  315. KdPrint(("PsxConnectToServer: 0x%x\n", st));
  316. NtTerminateProcess(NtCurrentProcess(), 1);
  317. ASSERT(0);
  318. }
  319. // take any pending signals now.
  320. PdxNullPosixApi();
  321. return 0;
  322. }
  323. if (EINTR == m.Error) {
  324. // try again.
  325. goto again;
  326. }
  327. if (m.Error) {
  328. errno = (int)m.Error;
  329. return -1;
  330. }
  331. return (int)m.ReturnValue;
  332. }
  333. //
  334. // vexec -- Varargs exec program, called by execl*.
  335. //
  336. int
  337. vexec(const char *path, const char *arg0, char * const envp[], va_list arglist)
  338. {
  339. NTSTATUS st;
  340. PSX_API_MSG m;
  341. PPSX_EXEC_MSG args;
  342. char **ppch;
  343. char *pch, *pcharg;
  344. int i;
  345. int retval = 0;
  346. char *Args; // the args + env for the call
  347. va_list save_arglist;
  348. try {
  349. if (0 == *path) {
  350. errno = ENOENT;
  351. return -1;
  352. }
  353. } except (EXCEPTION_EXECUTE_HANDLER) {
  354. errno = EFAULT;
  355. retval = -1;
  356. }
  357. if (0 != retval) {
  358. return retval;
  359. }
  360. args = &m.u.Exec;
  361. PSX_FORMAT_API_MSG(m, PsxExecApi, sizeof(*args));
  362. if (!PdxCanonicalize((PSZ)path, &args->Path, PdxHeap)) {
  363. return -1;
  364. }
  365. Args = RtlAllocateHeap(PdxPortHeap, 0, ARG_MAX);
  366. if (NULL == Args) {
  367. errno = ENOMEM;
  368. return -1;
  369. }
  370. args->Args = Args + PsxPortMemoryRemoteDelta;
  371. //
  372. // Port Memory Setup is same as for execve, see below.
  373. //
  374. //
  375. // first we count the strings so we know how much space to leave
  376. // for pointers.
  377. //
  378. save_arglist = arglist;
  379. for (i = 0, pcharg = va_arg(arglist, char *); NULL != pcharg;
  380. pcharg = va_arg(arglist, char *)) {
  381. ++i;
  382. }
  383. ++i; // add one for arg0
  384. for (ppch = (char **)envp; NULL != *ppch; ++ppch)
  385. ++i;
  386. i += 2; // add space for the NULL pointers
  387. pch = Args + sizeof(char *) * i;
  388. if (pch > Args + ARG_MAX) {
  389. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  390. errno = E2BIG;
  391. return -1;
  392. }
  393. ppch = (char **)Args;
  394. arglist = save_arglist; // restart arglist
  395. try {
  396. pcharg = (char *)arg0;
  397. while (NULL != pcharg) {
  398. if (pch + strlen(pcharg) + 1 > Args + ARG_MAX) {
  399. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  400. errno = E2BIG;
  401. return -1;
  402. }
  403. *ppch = pch - (ULONG_PTR)Args;
  404. ppch++;
  405. (void)strcpy(pch, pcharg);
  406. pcharg = va_arg(arglist, char *);
  407. pch += strlen(pch);
  408. *pch++ = '\0';
  409. }
  410. *ppch = NULL;
  411. ppch++;
  412. while (NULL != *envp) {
  413. if (pch + strlen(*envp) + 1 > Args + ARG_MAX) {
  414. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  415. errno = E2BIG;
  416. return -1;
  417. }
  418. *ppch = pch - (ULONG_PTR)Args;
  419. ppch++;
  420. (void)strcpy(pch, *envp);
  421. envp++;
  422. pch += strlen(pch);
  423. *pch++ = '\0';
  424. }
  425. *ppch = NULL;
  426. } except (EXCEPTION_EXECUTE_HANDLER) {
  427. errno = EFAULT;
  428. retval = -1;
  429. }
  430. if (0 != retval) {
  431. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  432. return -1;
  433. }
  434. (void)NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  435. (PPORT_MESSAGE)&m);
  436. //
  437. // If we get here, there's been an error.
  438. //
  439. errno = (int)m.Error;
  440. RtlFreeHeap(PdxHeap, 0, (PVOID)&args->Path);
  441. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  442. return -1;
  443. }
  444. int
  445. __cdecl
  446. execve(const char *path, char * const argv[], char * const envp[])
  447. {
  448. NTSTATUS st;
  449. PSX_API_MSG m;
  450. PPSX_EXEC_MSG args;
  451. PCHAR Args; // allocate args + environ
  452. char **ppch;
  453. char *pch;
  454. int i;
  455. int retval = 0;
  456. try {
  457. if (0 == strlen(path)) {
  458. errno = ENOENT;
  459. return -1;
  460. }
  461. } except (EXCEPTION_EXECUTE_HANDLER) {
  462. retval = -1;
  463. errno = EFAULT;
  464. }
  465. if (0 != retval) {
  466. return -1;
  467. }
  468. args = &m.u.Exec;
  469. PSX_FORMAT_API_MSG(m, PsxExecApi, sizeof(*args));
  470. if (!PdxCanonicalize((PSZ)path, &args->Path, PdxHeap)) {
  471. return -1;
  472. }
  473. //
  474. // Copy the caller's environment into view memory so that it may
  475. // be transmitted to the "overlaid" process. We set up the port
  476. // memory to look like:
  477. //
  478. // ClientPortMemory:
  479. // argv[0]
  480. // argv[1]
  481. // ...
  482. // NULL
  483. // envp[0]
  484. // envp[1]
  485. // ...
  486. // NULL
  487. // <argv strings>
  488. // <environ strings>
  489. //
  490. // The argv and envp pointers are converted to offsets relative to
  491. // ClientPortMemory.
  492. //
  493. // Because we need all this memory for args and environ, we destroy
  494. // the heap and recreate it if the call fails.
  495. //
  496. Args = RtlAllocateHeap(PdxPortHeap, 0, ARG_MAX);
  497. if (NULL == Args) {
  498. errno = ENOMEM;
  499. return -1;
  500. }
  501. args->Args = Args + PsxPortMemoryRemoteDelta;
  502. try {
  503. // first we count the strings so we know how much space to leave
  504. // for pointers.
  505. for (i = 0, ppch = (char **)argv; NULL != *ppch; ++ppch)
  506. ++i;
  507. for (ppch = (char **)envp; NULL != *ppch; ++ppch)
  508. ++i;
  509. i += 2; // add space for the NULL pointers
  510. pch = Args + sizeof(char *) * i;
  511. if (pch > Args + ARG_MAX) {
  512. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  513. errno = E2BIG;
  514. return -1;
  515. }
  516. ppch = (char **)Args;
  517. while (NULL != *argv) {
  518. if (pch + strlen(*argv) + 1 > Args + ARG_MAX) {
  519. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  520. errno = E2BIG;
  521. return -1;
  522. }
  523. *ppch = pch - (ULONG_PTR)Args;
  524. ppch++;
  525. (void)strcpy(pch, *argv);
  526. argv++;
  527. pch += strlen(pch);
  528. *pch++ = '\0';
  529. }
  530. *ppch = NULL;
  531. ppch++;
  532. while (NULL != *envp) {
  533. if (pch + strlen(*envp) + 1 > Args + ARG_MAX) {
  534. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  535. errno = E2BIG;
  536. return -1;
  537. }
  538. *ppch = pch - (ULONG_PTR)Args;
  539. ppch++;
  540. (void)strcpy(pch, *envp);
  541. envp++;
  542. pch += strlen(pch);
  543. *pch++ = '\0';
  544. }
  545. *ppch = NULL;
  546. } except (EXCEPTION_EXECUTE_HANDLER) {
  547. retval = -1;
  548. errno = EFAULT;
  549. }
  550. if (0 != retval) {
  551. return -1;
  552. }
  553. (void)NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  554. (PPORT_MESSAGE)&m);
  555. //
  556. // If we get here, there's been an error.
  557. //
  558. errno = (int)m.Error;
  559. RtlFreeHeap(PdxHeap, 0, (PVOID)&args->Path);
  560. RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
  561. return -1;
  562. }
  563. int
  564. __cdecl
  565. execv(const char *path, char * const argv[])
  566. {
  567. return execve(path, argv, environ);
  568. }
  569. int
  570. __cdecl
  571. execl(const char *path, const char *arg0, ...)
  572. {
  573. va_list args;
  574. int retval;
  575. va_start(args, arg0);
  576. retval = vexec(path, arg0, environ, args);
  577. va_end(args);
  578. return retval;
  579. }
  580. int
  581. __cdecl
  582. execle(const char *path, const char *arg0, ...)
  583. {
  584. va_list args;
  585. char * const *Env;
  586. int retval;
  587. va_start(args, arg0);
  588. // Skip up to the NULL, then one more, to find environ.
  589. do {
  590. Env = va_arg(args, char * const *);
  591. } while (NULL != Env);
  592. Env = va_arg(args, char * const *);
  593. va_end(args);
  594. if (NULL == Env) {
  595. return EINVAL;
  596. }
  597. // Restart the arglist traversal
  598. va_start(args, arg0);
  599. retval = vexec(path, arg0, Env, args);
  600. va_end(args);
  601. return retval;
  602. }
  603. int
  604. __cdecl
  605. execlp(const char *file, const char *arg0, ...)
  606. {
  607. char *pch;
  608. char *path;
  609. static char buf[PATH_MAX + 1];
  610. va_list args;
  611. int retval = 0;
  612. BOOLEAN done = FALSE;
  613. va_start(args, arg0);
  614. //
  615. // 1003.1-1990 (3.1.2.2): If the file argument contains a slash
  616. // character, the file argument shall be used as the pathname for
  617. // this file....
  618. //
  619. try {
  620. if ('\0' == *file) {
  621. errno = ENOENT;
  622. va_end(args);
  623. return -1;
  624. }
  625. if (NULL != (pch = strchr(file, '/'))) {
  626. if (-1 == access(file, F_OK)) {
  627. va_end(args);
  628. return -1;
  629. }
  630. retval = vexec(file, arg0, environ, args);
  631. va_end(args);
  632. return retval;
  633. }
  634. } except (EXCEPTION_EXECUTE_HANDLER) {
  635. errno = EFAULT;
  636. retval = -1;
  637. }
  638. if (0 != retval) {
  639. va_end(args);
  640. return -1;
  641. }
  642. //
  643. // ... Otherwise, the path prefix for this file is obtained by a
  644. // search of the directories passed as the environment variable
  645. // PATH.
  646. //
  647. if (NULL == (path = getenv("PATH"))) {
  648. //
  649. // The file name doesn't contain a slash, and we have
  650. // no PATH. We just try for it in the current working
  651. // directory, and will return ENOENT if it's not there.
  652. //
  653. retval = vexec(file, arg0, environ, args);
  654. va_end(args);
  655. return retval;
  656. }
  657. errno = 0;
  658. do {
  659. pch = strchr(path, ':');
  660. if (NULL == pch) {
  661. done = TRUE;
  662. } else {
  663. *pch = '\0';
  664. }
  665. if (strlen(path) + strlen(file) + 1 > PATH_MAX) {
  666. if (pch) {
  667. *pch = ':';
  668. }
  669. errno = ENAMETOOLONG;
  670. va_end(args);
  671. return -1;
  672. }
  673. strcpy(buf, path);
  674. if (!done) {
  675. *pch = ':';
  676. path = pch + 1;
  677. }
  678. if (strlen(buf) > 0) {
  679. // this case is "::" in the PATH
  680. strcat(buf, "/");
  681. }
  682. strcat(buf, file);
  683. // avoid trying to execute files that do not exist.
  684. if (-1 != access(buf, F_OK)) {
  685. (void)vexec(buf, arg0, environ, args);
  686. break;
  687. }
  688. } while (!done);
  689. va_end(args);
  690. if (0 == errno) {
  691. //
  692. // We went all the way through the PATH without finding
  693. // a file to exec. Since errno didn't get set by execve(),
  694. // we set it here.
  695. //
  696. errno = ENOENT;
  697. }
  698. return -1;
  699. }
  700. int
  701. __cdecl
  702. execvp(const char *file, char * const argv[])
  703. {
  704. char *pch;
  705. char *path;
  706. static char buf[PATH_MAX + 1];
  707. BOOLEAN done = FALSE;
  708. int retval = 0;
  709. //
  710. // 1003.1-1990 (3.1.2.2): If the file argument contains a slash
  711. // character, the file argument shall be used as the pathname for
  712. // this file....
  713. //
  714. try {
  715. if ('\0' == *file) {
  716. errno = ENOENT;
  717. return -1;
  718. }
  719. if (NULL != (pch = strchr(file, '/'))) {
  720. if (-1 == access(file, F_OK)) {
  721. return -1;
  722. }
  723. return execve(file, argv, environ);
  724. }
  725. } except (EXCEPTION_EXECUTE_HANDLER) {
  726. errno = EFAULT;
  727. retval = -1;
  728. }
  729. if (0 != retval) {
  730. return -1;
  731. }
  732. //
  733. // ... Otherwise, the path prefix for this file is obtained by a
  734. // search of the directories passed as the environment variable
  735. // PATH.
  736. //
  737. if (NULL == (path = getenv("PATH"))) {
  738. return execve(file, argv, environ);
  739. }
  740. errno = 0;
  741. do {
  742. pch = strchr(path, ':');
  743. if (NULL == pch) {
  744. done = TRUE;
  745. } else {
  746. *pch = '\0';
  747. }
  748. if (strlen(path) + strlen(file) + 1 > PATH_MAX) {
  749. if (pch) {
  750. *pch = ':';
  751. }
  752. errno = ENAMETOOLONG;
  753. return -1;
  754. }
  755. strcpy(buf, path);
  756. if (!done) {
  757. *pch = ':';
  758. path = pch + 1;
  759. }
  760. if (strlen(buf) > 0) {
  761. // this case is "::" in the PATH
  762. strcat(buf, "/");
  763. }
  764. strcat(buf, file);
  765. // avoid trying to execute files that do not exist
  766. if (-1 != access(buf, F_OK)) {
  767. (void)execve(buf, argv, environ);
  768. break;
  769. }
  770. } while (!done);
  771. if (0 == errno) {
  772. //
  773. // We went all the way through the PATH without finding
  774. // a file to exec. Since errno didn't get set by execve(),
  775. // we set it here.
  776. //
  777. errno = ENOENT;
  778. }
  779. return -1;
  780. }
  781. #define COMPUTERNAME_ROOT \
  782. L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName"
  783. #define NON_VOLATILE_COMPUTERNAME L"ComputerName"
  784. #define COMPUTERNAME_VALUE_NAME L"ComputerName"
  785. #define VALUE_BUFFER_SIZE \
  786. (sizeof(KEY_VALUE_PARTIAL_INFORMATION) \
  787. + (_POSIX_NAME_MAX * sizeof(WCHAR)))
  788. int __cdecl
  789. uname(struct utsname *name)
  790. {
  791. NTSTATUS Status;
  792. SYSTEM_PROCESSOR_INFORMATION
  793. ProcInfo;
  794. UNICODE_STRING
  795. KeyName,
  796. Class,
  797. ValueName,
  798. Computer_U;
  799. ANSI_STRING
  800. Computer_A;
  801. OBJECT_ATTRIBUTES
  802. ObjectAttributes;
  803. HANDLE hKey = NULL,
  804. hSubKey = NULL;
  805. WCHAR ValueBuf[VALUE_BUFFER_SIZE];
  806. PKEY_VALUE_PARTIAL_INFORMATION
  807. pKeyValueInfo = (PVOID)ValueBuf;
  808. ULONG ValueLength;
  809. char *pchProcType, // processor type
  810. *pchNode = ""; // node name
  811. int retval = 0;
  812. Status = NtQuerySystemInformation(SystemProcessorInformation,
  813. (PVOID)&ProcInfo, sizeof(ProcInfo), NULL);
  814. if (!NT_SUCCESS(Status)) {
  815. errno = PdxStatusToErrno(Status);
  816. return -1;
  817. }
  818. switch (ProcInfo.ProcessorArchitecture) {
  819. case PROCESSOR_ARCHITECTURE_INTEL:
  820. if (ProcInfo.ProcessorLevel == 3) {
  821. pchProcType = "i386";
  822. } else if (ProcInfo.ProcessorLevel == 4) {
  823. pchProcType = "i486";
  824. } else if (ProcInfo.ProcessorLevel == 5) {
  825. pchProcType = "Pentium";
  826. } else {
  827. pchProcType = "Intel Unknown";
  828. }
  829. break;
  830. case PROCESSOR_ARCHITECTURE_IA64:
  831. pchProcType = "IA64";
  832. break;
  833. case PROCESSOR_ARCHITECTURE_MIPS:
  834. pchProcType = "R4000";
  835. break;
  836. case PROCESSOR_ARCHITECTURE_ALPHA:
  837. if (ProcInfo.ProcessorLevel == 21064) {
  838. pchProcType = "Alpha 21064";
  839. } else if (ProcInfo.ProcessorLevel == 21164) {
  840. pchProcType = "Alpha 21164";
  841. } else {
  842. pchProcType = "Alpha Unknown";
  843. }
  844. break;
  845. case PROCESSOR_ARCHITECTURE_PPC:
  846. if (ProcInfo.ProcessorLevel == 1) {
  847. pchProcType = "PowerPC 601";
  848. } else if (ProcInfo.ProcessorLevel == 3) {
  849. pchProcType = "PowerPC 603";
  850. } else if (ProcInfo.ProcessorLevel == 4) {
  851. pchProcType = "PowerPC 604";
  852. } else if (ProcInfo.ProcessorLevel == 6) {
  853. pchProcType = "PowerPC 603+";
  854. } else if (ProcInfo.ProcessorLevel == 9) {
  855. pchProcType = "PowerPC 604+";
  856. } else if (ProcInfo.ProcessorLevel == 20) {
  857. pchProcType = "PowerPC 620";
  858. } else {
  859. pchProcType = "PowerPC Unknown";
  860. }
  861. break;
  862. default:
  863. pchProcType = "unknown";
  864. break;
  865. }
  866. //
  867. // Find the node name: this code lifted from
  868. // windows/base/client/compname.c
  869. //
  870. RtlInitUnicodeString(&KeyName, COMPUTERNAME_ROOT);
  871. InitializeObjectAttributes(&ObjectAttributes, &KeyName,
  872. OBJ_CASE_INSENSITIVE, NULL, NULL);
  873. Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
  874. if (!NT_SUCCESS(Status)) {
  875. KdPrint(("PSXDLL: NtOpenKey: 0x%x\n", Status));
  876. goto done;
  877. }
  878. RtlInitUnicodeString(&KeyName, NON_VOLATILE_COMPUTERNAME);
  879. InitializeObjectAttributes(&ObjectAttributes, &KeyName,
  880. OBJ_CASE_INSENSITIVE, hKey, NULL);
  881. Status = NtOpenKey(&hSubKey, KEY_READ, &ObjectAttributes);
  882. if (!NT_SUCCESS(Status)) {
  883. KdPrint(("PSXDLL: NtOpenKey: 0x%x\n", Status));
  884. goto done;
  885. }
  886. RtlInitUnicodeString(&ValueName, COMPUTERNAME_VALUE_NAME);
  887. Status = NtQueryValueKey(hSubKey, &ValueName,
  888. KeyValuePartialInformation,
  889. (PVOID)pKeyValueInfo, VALUE_BUFFER_SIZE, &ValueLength);
  890. ASSERT(ValueLength < VALUE_BUFFER_SIZE);
  891. if (!NT_SUCCESS(Status)) {
  892. KdPrint(("PSXDLL: NtQueryValueKey: 0x%x\n", Status));
  893. goto done;
  894. }
  895. if (pKeyValueInfo->DataLength == 0) {
  896. goto done;
  897. }
  898. Computer_U.Buffer = (PVOID)&pKeyValueInfo->Data;
  899. Computer_U.Length = Computer_U.MaximumLength =
  900. (USHORT)pKeyValueInfo->DataLength;
  901. Status = RtlUnicodeStringToAnsiString(&Computer_A, &Computer_U, TRUE);
  902. if (!NT_SUCCESS(Status)) {
  903. goto done;
  904. }
  905. pchNode = Computer_A.Buffer;
  906. done:
  907. if (NULL != hSubKey) {
  908. NtClose(hSubKey);
  909. }
  910. if (NULL != hKey) {
  911. NtClose(hKey);
  912. }
  913. try {
  914. strncpy((PCHAR)name->sysname, (PCHAR)UNAME_SYSNAME, sizeof(name->sysname));
  915. strncpy((PCHAR)name->release, (PCHAR)UNAME_RELEASE, sizeof(name->release));
  916. strncpy((PCHAR)name->version, (PCHAR)UNAME_VERSION, sizeof(name->version));
  917. strncpy((PCHAR)name->nodename, (PCHAR)pchNode, sizeof(name->nodename));
  918. strncpy((PCHAR)name->machine, (PCHAR)pchProcType, sizeof(name->machine));
  919. } except (EXCEPTION_EXECUTE_HANDLER) {
  920. errno = EFAULT;
  921. retval = -1;
  922. }
  923. RtlFreeAnsiString(&Computer_A);
  924. return retval;
  925. }
  926. char * __cdecl
  927. getenv(const char *name)
  928. {
  929. char **ppch;
  930. char *pch;
  931. try {
  932. for (ppch = environ; NULL != *ppch; ++ppch) {
  933. if (NULL == (pch = strchr(*ppch, '='))) {
  934. continue;
  935. }
  936. *pch = '\0'; // delete the equals
  937. if (0 == strcmp(*ppch, name)) {
  938. *pch = '=';
  939. return pch + 1;
  940. }
  941. *pch = '=';
  942. }
  943. return NULL;
  944. } except (EXCEPTION_EXECUTE_HANDLER) {
  945. errno = EFAULT;
  946. }
  947. return NULL;
  948. }
  949. time_t __cdecl
  950. time(time_t *tloc)
  951. {
  952. LARGE_INTEGER TimeOfDay;
  953. ULONG PosixTime;
  954. NtQuerySystemTime(&TimeOfDay);
  955. if (RtlTimeToSecondsSince1970(&TimeOfDay, &PosixTime)) {
  956. if (ARGUMENT_PRESENT(tloc)) {
  957. try {
  958. *tloc = PosixTime;
  959. } except (EXCEPTION_EXECUTE_HANDLER) {
  960. errno = EFAULT;
  961. }
  962. }
  963. } else {
  964. PosixTime = (ULONG)-1; // Time not within range of 1970 - 2105
  965. }
  966. return (time_t)PosixTime;
  967. }
  968. clock_t
  969. __cdecl
  970. times(struct tms *buffer)
  971. {
  972. PSX_API_MSG m;
  973. PPSX_GETPROCESSTIMES_MSG args;
  974. LARGE_INTEGER TimeOfDay;
  975. ULONG Remainder;
  976. NTSTATUS st;
  977. int retval = 0;
  978. args = &m.u.GetProcessTimes;
  979. PSX_FORMAT_API_MSG(m, PsxGetProcessTimesApi, sizeof(*args));
  980. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  981. (PPORT_MESSAGE)&m);
  982. #ifdef PSX_MORE_ERRORS
  983. ASSERT(NT_SUCCESS(st));
  984. #endif
  985. if (m.Error) {
  986. errno = (int)m.Error;
  987. return -1;
  988. }
  989. try {
  990. *buffer = args->ProcessTimes;
  991. } except (EXCEPTION_EXECUTE_HANDLER) {
  992. errno = EFAULT;
  993. retval = -1;
  994. }
  995. if (0 != retval) {
  996. return -1;
  997. }
  998. NtQuerySystemTime(&TimeOfDay);
  999. TimeOfDay = RtlExtendedLargeIntegerDivide(TimeOfDay, 10000L,
  1000. &Remainder);
  1001. return TimeOfDay.LowPart;
  1002. }
  1003. long
  1004. __cdecl
  1005. sysconf(int name)
  1006. {
  1007. PSX_API_MSG m;
  1008. PPSX_SYSCONF_MSG args;
  1009. NTSTATUS st;
  1010. args = &m.u.Sysconf;
  1011. args->Name = name;
  1012. PSX_FORMAT_API_MSG(m, PsxSysconfApi, sizeof(*args));
  1013. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  1014. (PPORT_MESSAGE)&m);
  1015. #ifdef PSX_MORE_ERRORS
  1016. ASSERT(NT_SUCCESS(st));
  1017. #endif
  1018. if (0 != m.Error) {
  1019. errno = m.Error;
  1020. return -1;
  1021. }
  1022. return m.ReturnValue;
  1023. }
  1024. int
  1025. __cdecl
  1026. getgroups(int gidsetsize, gid_t *grouplist)
  1027. {
  1028. PSX_API_MSG m;
  1029. PPSX_GETGROUPS_MSG args;
  1030. NTSTATUS st;
  1031. args = &m.u.GetGroups;
  1032. args->GroupList = grouplist;
  1033. args->NGroups = gidsetsize;
  1034. //
  1035. // The Posix server will write group id's into the group
  1036. // array with NtWriteVirtualMemory, unless gidsetsize is
  1037. // 0. In that case, he returns the size required and does
  1038. // not try to write the list.
  1039. //
  1040. PSX_FORMAT_API_MSG(m, PsxGetGroupsApi, sizeof(*args));
  1041. st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
  1042. (PPORT_MESSAGE)&m);
  1043. #ifdef PSX_MORE_ERRORS
  1044. ASSERT(NT_SUCCESS(st));
  1045. #endif
  1046. if (0 != m.Error) {
  1047. errno = m.Error;
  1048. return -1;
  1049. }
  1050. return m.ReturnValue;
  1051. }