wait.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. #include "lib.h"
  2. #include <stdlib.h>
  3. #include <sys/wait.h>
  4. #include <sys/time.h>
  5. #include <sys/resource.h>
  6. #include <sys/stat.h>
  7. #include <unistd.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #include "sys9.h"
  12. #include "dir.h"
  13. /*
  14. * status not yet collected for processes that have exited
  15. */
  16. typedef struct Waited Waited;
  17. struct Waited {
  18. Waitmsg* msg;
  19. Waited* next;
  20. };
  21. static Waited *wd;
  22. static Waitmsg *
  23. lookpid(int pid)
  24. {
  25. Waited **wl, *w;
  26. Waitmsg *msg;
  27. for(wl = &wd; (w = *wl) != nil; wl = &w->next)
  28. if(pid <= 0 || w->msg->pid == pid){
  29. msg = w->msg;
  30. *wl = w->next;
  31. free(w);
  32. return msg;
  33. }
  34. return 0;
  35. }
  36. static void
  37. addpid(Waitmsg *msg)
  38. {
  39. Waited *w;
  40. w = malloc(sizeof(*w));
  41. if(w == nil){
  42. /* lost it; what can we do? */
  43. free(msg);
  44. return;
  45. }
  46. w->msg = msg;
  47. w->next = wd;
  48. wd = w;
  49. }
  50. static int
  51. waitstatus(Waitmsg *w)
  52. {
  53. int r, t;
  54. char *bp, *ep;
  55. r = 0;
  56. t = 0;
  57. if(w->msg[0]){
  58. /* message is 'prog pid:string' */
  59. bp = w->msg;
  60. while(*bp){
  61. if(*bp++ == ':')
  62. break;
  63. }
  64. if(*bp == 0)
  65. bp = w->msg;
  66. r = strtol(bp, &ep, 10);
  67. if(*ep == 0){
  68. if(r < 0 || r >= 256)
  69. r = 1;
  70. }else{
  71. t = _stringsig(bp);
  72. if(t == 0)
  73. r = 1;
  74. }
  75. }
  76. return (r<<8) | t;
  77. }
  78. static void
  79. waitresource(struct rusage *ru, Waitmsg *w)
  80. {
  81. memset(ru, 0, sizeof(*ru));
  82. ru->ru_utime.tv_sec = w->time[0]/1000;
  83. ru->ru_utime.tv_usec = (w->time[0]%1000)*1000;
  84. ru->ru_stime.tv_sec = w->time[1]/1000;
  85. ru->ru_stime.tv_usec = (w->time[1]%1000)*1000;
  86. }
  87. pid_t
  88. wait(int *status)
  89. {
  90. return wait4(-1, status, 0, nil);
  91. }
  92. pid_t
  93. waitpid(pid_t wpid, int *status, int options)
  94. {
  95. return wait4(wpid, status, options, nil);
  96. }
  97. pid_t
  98. wait3(int *status, int options, struct rusage *res)
  99. {
  100. return wait4(-1, status, options, res);
  101. }
  102. pid_t
  103. wait4(pid_t wpid, int *status, int options, struct rusage *res)
  104. {
  105. char pname[50];
  106. Dir *d;
  107. Waitmsg *w;
  108. w = lookpid(wpid);
  109. if(w == nil){
  110. if(options & WNOHANG){
  111. snprintf(pname, sizeof(pname), "/proc/%d/wait", getpid());
  112. d = _dirstat(pname);
  113. if(d != nil && d->length == 0){
  114. free(d);
  115. return 0;
  116. }
  117. free(d);
  118. }
  119. for(;;){
  120. w = _WAIT();
  121. if(w == nil){
  122. _syserrno();
  123. return -1;
  124. }
  125. if(wpid <= 0 || w->pid == wpid)
  126. break;
  127. addpid(w);
  128. }
  129. }
  130. if(res != nil)
  131. waitresource(res, w);
  132. if(status != nil)
  133. *status = waitstatus(w);
  134. wpid = w->pid;
  135. free(w);
  136. return wpid;
  137. }