dosys.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include "defs.h"
  2. #include <sys/wait.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <errno.h>
  6. static int metas(char *);
  7. static int waitproc(int *);
  8. static int doshell(char *, int);
  9. static int doexec(char *);
  10. int
  11. dosys(char *comstring, int nohalt, int nowait, char *prefix)
  12. {
  13. int status;
  14. struct process *procp;
  15. /* make sure there is room in the process stack */
  16. if(nproc >= MAXPROC)
  17. waitstack(MAXPROC-1);
  18. /* make sure fewer than proclimit processes are running */
  19. while(proclive >= proclimit)
  20. {
  21. enbint(SIG_IGN);
  22. waitproc(&status);
  23. enbint(intrupt);
  24. }
  25. if(prefix)
  26. {
  27. fputs(prefix, stdout);
  28. fputs(comstring, stdout);
  29. }
  30. procp = procstack + nproc;
  31. procp->pid = (forceshell || metas(comstring) ) ?
  32. doshell(comstring,nohalt) : doexec(comstring);
  33. if(procp->pid == -1)
  34. fatal("fork failed");
  35. procstack[nproc].nohalt = nohalt;
  36. procstack[nproc].nowait = nowait;
  37. procstack[nproc].done = NO;
  38. ++proclive;
  39. ++nproc;
  40. if(nowait)
  41. {
  42. printf(" &%d\n", procp->pid);
  43. fflush(stdout);
  44. return 0;
  45. }
  46. if(prefix)
  47. {
  48. putchar('\n');
  49. fflush(stdout);
  50. }
  51. return waitstack(nproc-1);
  52. }
  53. static int
  54. metas(char *s) /* Are there are any Shell meta-characters? */
  55. {
  56. char c;
  57. while( (funny[c = *s++] & META) == 0 )
  58. ;
  59. return( c );
  60. }
  61. static void
  62. doclose(void) /* Close open directory files before exec'ing */
  63. {
  64. struct dirhd *od;
  65. for (od = firstod; od; od = od->nxtdirhd)
  66. if(od->dirfc)
  67. closedir(od->dirfc);
  68. }
  69. /* wait till none of the processes in the stack starting at k is live */
  70. int
  71. waitstack(int k)
  72. {
  73. int npending, status, totstatus;
  74. int i;
  75. totstatus = 0;
  76. npending = 0;
  77. for(i=k ; i<nproc; ++i)
  78. if(! procstack[i].done)
  79. ++npending;
  80. enbint(SIG_IGN);
  81. if(dbgflag > 1)
  82. printf("waitstack(%d)\n", k);
  83. while(npending>0 && proclive>0)
  84. {
  85. if(waitproc(&status) >= k)
  86. --npending;
  87. totstatus |= status;
  88. }
  89. if(nproc > k)
  90. nproc = k;
  91. enbint(intrupt);
  92. return totstatus;
  93. }
  94. static int
  95. waitproc(int *statp)
  96. {
  97. pid_t pid;
  98. int status;
  99. int i;
  100. struct process *procp;
  101. char junk[50];
  102. static int inwait = NO;
  103. if(inwait) /* avoid infinite recursions on errors */
  104. return MAXPROC;
  105. inwait = YES;
  106. pid = wait(&status);
  107. if(dbgflag > 1)
  108. fprintf(stderr, "process %d done, status = %d\n", pid, status);
  109. if(pid == -1)
  110. {
  111. if(errno == ECHILD) /* multiple deaths, no problem */
  112. {
  113. if(proclive)
  114. {
  115. for(i=0, procp=procstack; i<nproc; ++i, ++procp)
  116. procp->done = YES;
  117. proclive = nproc = 0;
  118. }
  119. return MAXPROC;
  120. }
  121. fatal("bad wait code");
  122. }
  123. for(i=0, procp=procstack; i<nproc; ++i, ++procp)
  124. if(procp->pid == pid)
  125. {
  126. --proclive;
  127. procp->done = YES;
  128. if(status)
  129. {
  130. if(procp->nowait)
  131. printf("%d: ", pid);
  132. if( WEXITSTATUS(status) )
  133. printf("*** Error code %d", WEXITSTATUS(status) );
  134. else printf("*** Termination code %d", WTERMSIG(status));
  135. printf(procp->nohalt ? "(ignored)\n" : "\n");
  136. fflush(stdout);
  137. if(!keepgoing && !procp->nohalt)
  138. fatal(CHNULL);
  139. }
  140. *statp = status;
  141. inwait = NO;
  142. return i;
  143. }
  144. sprintf(junk, "spurious return from process %d", pid);
  145. fatal(junk);
  146. /*NOTREACHED*/
  147. return -1;
  148. }
  149. static int
  150. doshell(char *comstring, int nohalt)
  151. {
  152. pid_t pid;
  153. if((pid = fork()) == 0)
  154. {
  155. enbint(SIG_DFL);
  156. doclose();
  157. execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, NULL);
  158. fatal("Couldn't load Shell");
  159. }
  160. return pid;
  161. }
  162. static int
  163. doexec(char *str)
  164. {
  165. char *t, *tend;
  166. char **argv;
  167. char **p;
  168. int nargs;
  169. pid_t pid;
  170. while( *str==' ' || *str=='\t' )
  171. ++str;
  172. if( *str == '\0' )
  173. return(-1); /* no command */
  174. nargs = 1;
  175. for(t = str ; *t ; )
  176. {
  177. ++nargs;
  178. while(*t!=' ' && *t!='\t' && *t!='\0')
  179. ++t;
  180. if(*t) /* replace first white space with \0, skip rest */
  181. for( *t++ = '\0' ; *t==' ' || *t=='\t' ; ++t)
  182. ;
  183. }
  184. /* now allocate args array, copy pointer to start of each string,
  185. then terminate array with a null
  186. */
  187. p = argv = (char **) ckalloc(nargs*sizeof(char *));
  188. tend = t;
  189. for(t = str ; t<tend ; )
  190. {
  191. *p++ = t;
  192. while( *t )
  193. ++t;
  194. do {
  195. ++t;
  196. } while(t<tend && (*t==' ' || *t=='\t') );
  197. }
  198. *p = NULL;
  199. /*TEMP for(p=argv; *p; ++p)printf("arg=%s\n", *p);*/
  200. if((pid = fork()) == 0)
  201. {
  202. enbint(SIG_DFL);
  203. doclose();
  204. enbint(intrupt);
  205. execvp(str, argv);
  206. printf("\n");
  207. fatal1("Cannot load %s",str);
  208. }
  209. free( (char *) argv);
  210. return pid;
  211. }
  212. void
  213. touch(int force, char *name)
  214. {
  215. struct stat stbuff;
  216. char junk[1];
  217. int fd;
  218. if( stat(name,&stbuff) < 0)
  219. if(force)
  220. goto create;
  221. else
  222. {
  223. fprintf(stderr, "touch: file %s does not exist.\n", name);
  224. return;
  225. }
  226. if(stbuff.st_size == 0)
  227. goto create;
  228. if( (fd = open(name, O_RDWR)) < 0)
  229. goto bad;
  230. if( read(fd, junk, 1) < 1)
  231. {
  232. close(fd);
  233. goto bad;
  234. }
  235. lseek(fd, 0L, SEEK_SET);
  236. if( write(fd, junk, 1) < 1 )
  237. {
  238. close(fd);
  239. goto bad;
  240. }
  241. close(fd);
  242. return;
  243. bad:
  244. fprintf(stderr, "Cannot touch %s\n", name);
  245. return;
  246. create:
  247. if( (fd = creat(name, 0666)) < 0)
  248. goto bad;
  249. close(fd);
  250. }