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