wait.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "lib.h"
  2. #include <stdlib.h>
  3. #include <sys/wait.h>
  4. #include <sys/stat.h>
  5. #include <unistd.h>
  6. #include <errno.h>
  7. #include <stdio.h>
  8. #include "sys9.h"
  9. /*
  10. ** PID cache
  11. */
  12. typedef struct wdesc wdesc;
  13. struct wdesc {
  14. pid_t w_pid;
  15. Waitmsg *w_msg;
  16. wdesc *w_next;
  17. };
  18. static wdesc *wd = 0;
  19. static Waitmsg *
  20. lookpid (pid_t pid) {
  21. wdesc **wp0 = &wd, *wp;
  22. Waitmsg *msg;
  23. if (pid == -1) {
  24. if (wd == 0)
  25. return 0;
  26. pid = wd->w_pid;
  27. }
  28. for (wp = wd; wp; wp = wp->w_next) {
  29. if (wp->w_pid == pid) {
  30. msg = wp->w_msg;
  31. *wp0 = wp->w_next;
  32. free (wp);
  33. return msg;
  34. }
  35. wp0 = &(wp->w_next);
  36. }
  37. return 0;
  38. }
  39. static void
  40. addpid (Waitmsg *msg) {
  41. wdesc *wp = malloc (sizeof (wdesc));
  42. wp->w_msg = msg;
  43. wp->w_pid = msg->pid;
  44. wp->w_next = wd;
  45. wd = wp;
  46. }
  47. pid_t
  48. wait (int *status) {
  49. return wait4(-1, status, 0, 0);
  50. }
  51. pid_t
  52. waitpid (pid_t wpid, int *status, int options) {
  53. return wait4(wpid, status, options, 0);
  54. }
  55. pid_t
  56. wait3 (int *status, int options, Waitmsg *waitmsg) {
  57. return wait4(-1, status, options, waitmsg);
  58. }
  59. pid_t
  60. wait4 (pid_t wpid, int *status, int options, Waitmsg *waitmsg) {
  61. Waitmsg *w;
  62. if (options & WNOHANG) {
  63. char pname[128];
  64. int i;
  65. struct stat buf;
  66. snprintf (pname, sizeof (pname), "/proc/%d/wait", getpid());
  67. i = stat (pname, &buf);
  68. if (i >= 0 && buf.st_size == 0)
  69. return 0;
  70. }
  71. if (w = lookpid (wpid)) {
  72. waitmsg = w;
  73. wpid = w->pid;
  74. return wpid;
  75. }
  76. w = _WAIT();
  77. while (w) {
  78. if (wpid <= 0) {
  79. waitmsg = w;
  80. wpid = w->pid;
  81. return wpid;
  82. }
  83. if (w->pid == wpid) {
  84. if (status) {
  85. int r = 0;
  86. int t = 0;
  87. char *bp, *ep;
  88. if (w->msg[0]) {
  89. /* message is 'prog pid:string' */
  90. bp = w->msg;
  91. while (*bp) {
  92. if (*bp++ == ':')
  93. break;
  94. }
  95. if (*bp == 0)
  96. bp = w->msg;
  97. r = strtol (bp, &ep, 10);
  98. if (*ep == 0) {
  99. if (r < 0 || r >= 256)
  100. r = 1;
  101. } else {
  102. t = _stringsig (bp);
  103. if (t == 0)
  104. r = 1;
  105. }
  106. }
  107. *status = (r << 8) | t;
  108. }
  109. waitmsg = w;
  110. wpid = w->pid;
  111. return wpid;
  112. } else {
  113. addpid (w);
  114. }
  115. w = _WAIT();
  116. }
  117. if (w == 0) {
  118. _syserrno ();
  119. }
  120. }