dosys.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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. }
  148. static int
  149. doshell(char *comstring, int nohalt)
  150. {
  151. pid_t pid;
  152. if((pid = fork()) == 0)
  153. {
  154. enbint(SIG_DFL);
  155. doclose();
  156. execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, NULL);
  157. fatal("Couldn't load Shell");
  158. }
  159. return pid;
  160. }
  161. static int
  162. doexec(char *str)
  163. {
  164. char *t, *tend;
  165. char **argv;
  166. char **p;
  167. int nargs;
  168. pid_t pid;
  169. while( *str==' ' || *str=='\t' )
  170. ++str;
  171. if( *str == '\0' )
  172. return(-1); /* no command */
  173. nargs = 1;
  174. for(t = str ; *t ; )
  175. {
  176. ++nargs;
  177. while(*t!=' ' && *t!='\t' && *t!='\0')
  178. ++t;
  179. if(*t) /* replace first white space with \0, skip rest */
  180. for( *t++ = '\0' ; *t==' ' || *t=='\t' ; ++t)
  181. ;
  182. }
  183. /* now allocate args array, copy pointer to start of each string,
  184. then terminate array with a null
  185. */
  186. p = argv = (char **) ckalloc(nargs*sizeof(char *));
  187. tend = t;
  188. for(t = str ; t<tend ; )
  189. {
  190. *p++ = t;
  191. while( *t )
  192. ++t;
  193. do {
  194. ++t;
  195. } while(t<tend && (*t==' ' || *t=='\t') );
  196. }
  197. *p = NULL;
  198. /*TEMP for(p=argv; *p; ++p)printf("arg=%s\n", *p);*/
  199. if((pid = fork()) == 0)
  200. {
  201. enbint(SIG_DFL);
  202. doclose();
  203. enbint(intrupt);
  204. execvp(str, argv);
  205. printf("\n");
  206. fatal1("Cannot load %s",str);
  207. }
  208. free( (char *) argv);
  209. return pid;
  210. }
  211. void
  212. touch(int force, char *name)
  213. {
  214. struct stat stbuff;
  215. char junk[1];
  216. int fd;
  217. if( stat(name,&stbuff) < 0)
  218. if(force)
  219. goto create;
  220. else
  221. {
  222. fprintf(stderr, "touch: file %s does not exist.\n", name);
  223. return;
  224. }
  225. if(stbuff.st_size == 0)
  226. goto create;
  227. if( (fd = open(name, O_RDWR)) < 0)
  228. goto bad;
  229. if( read(fd, junk, 1) < 1)
  230. {
  231. close(fd);
  232. goto bad;
  233. }
  234. lseek(fd, 0L, SEEK_SET);
  235. if( write(fd, junk, 1) < 1 )
  236. {
  237. close(fd);
  238. goto bad;
  239. }
  240. close(fd);
  241. return;
  242. bad:
  243. fprintf(stderr, "Cannot touch %s\n", name);
  244. return;
  245. create:
  246. if( (fd = creat(name, 0666)) < 0)
  247. goto bad;
  248. close(fd);
  249. }