diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/cmd/make/dosys.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/cmd/make/dosys.c')
-rwxr-xr-x | sys/src/ape/cmd/make/dosys.c | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/sys/src/ape/cmd/make/dosys.c b/sys/src/ape/cmd/make/dosys.c new file mode 100755 index 000000000..7d28eaa4d --- /dev/null +++ b/sys/src/ape/cmd/make/dosys.c @@ -0,0 +1,287 @@ +#include "defs.h" +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +static int metas(char *); +static int waitproc(int *); +static int doshell(char *, int); +static int doexec(char *); + +int +dosys(char *comstring, int nohalt, int nowait, char *prefix) +{ +int status; +struct process *procp; + +/* make sure there is room in the process stack */ +if(nproc >= MAXPROC) + waitstack(MAXPROC-1); + +/* make sure fewer than proclimit processes are running */ +while(proclive >= proclimit) + { + enbint(SIG_IGN); + waitproc(&status); + enbint(intrupt); + } + +if(prefix) + { + fputs(prefix, stdout); + fputs(comstring, stdout); + } + +procp = procstack + nproc; +procp->pid = (forceshell || metas(comstring) ) ? + doshell(comstring,nohalt) : doexec(comstring); +if(procp->pid == -1) + fatal("fork failed"); +procstack[nproc].nohalt = nohalt; +procstack[nproc].nowait = nowait; +procstack[nproc].done = NO; +++proclive; +++nproc; + +if(nowait) + { + printf(" &%d\n", procp->pid); + fflush(stdout); + return 0; + } +if(prefix) + { + putchar('\n'); + fflush(stdout); + } +return waitstack(nproc-1); +} + +static int +metas(char *s) /* Are there are any Shell meta-characters? */ +{ +char c; + +while( (funny[c = *s++] & META) == 0 ) + ; +return( c ); +} + +static void +doclose(void) /* Close open directory files before exec'ing */ +{ +struct dirhd *od; + +for (od = firstod; od; od = od->nxtdirhd) + if(od->dirfc) + closedir(od->dirfc); +} + +/* wait till none of the processes in the stack starting at k is live */ +int +waitstack(int k) +{ +int npending, status, totstatus; +int i; + +totstatus = 0; +npending = 0; +for(i=k ; i<nproc; ++i) + if(! procstack[i].done) + ++npending; +enbint(SIG_IGN); +if(dbgflag > 1) + printf("waitstack(%d)\n", k); + +while(npending>0 && proclive>0) + { + if(waitproc(&status) >= k) + --npending; + totstatus |= status; + } + +if(nproc > k) + nproc = k; +enbint(intrupt); +return totstatus; +} + +static int +waitproc(int *statp) +{ +pid_t pid; +int status; +int i; +struct process *procp; +char junk[50]; +static int inwait = NO; + +if(inwait) /* avoid infinite recursions on errors */ + return MAXPROC; +inwait = YES; + +pid = wait(&status); +if(dbgflag > 1) + fprintf(stderr, "process %d done, status = %d\n", pid, status); +if(pid == -1) + { + if(errno == ECHILD) /* multiple deaths, no problem */ + { + if(proclive) + { + for(i=0, procp=procstack; i<nproc; ++i, ++procp) + procp->done = YES; + proclive = nproc = 0; + } + return MAXPROC; + } + fatal("bad wait code"); + } +for(i=0, procp=procstack; i<nproc; ++i, ++procp) + if(procp->pid == pid) + { + --proclive; + procp->done = YES; + + if(status) + { + if(procp->nowait) + printf("%d: ", pid); + if( WEXITSTATUS(status) ) + printf("*** Error code %d", WEXITSTATUS(status) ); + else printf("*** Termination code %d", WTERMSIG(status)); + + printf(procp->nohalt ? "(ignored)\n" : "\n"); + fflush(stdout); + if(!keepgoing && !procp->nohalt) + fatal(CHNULL); + } + *statp = status; + inwait = NO; + return i; + } + +sprintf(junk, "spurious return from process %d", pid); +fatal(junk); +/*NOTREACHED*/ +} + +static int +doshell(char *comstring, int nohalt) +{ +pid_t pid; + +if((pid = fork()) == 0) + { + enbint(SIG_DFL); + doclose(); + + execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, NULL); + fatal("Couldn't load Shell"); + } + +return pid; +} + +static int +doexec(char *str) +{ +char *t, *tend; +char **argv; +char **p; +int nargs; +pid_t pid; + +while( *str==' ' || *str=='\t' ) + ++str; +if( *str == '\0' ) + return(-1); /* no command */ + +nargs = 1; +for(t = str ; *t ; ) + { + ++nargs; + while(*t!=' ' && *t!='\t' && *t!='\0') + ++t; + if(*t) /* replace first white space with \0, skip rest */ + for( *t++ = '\0' ; *t==' ' || *t=='\t' ; ++t) + ; + } + +/* now allocate args array, copy pointer to start of each string, + then terminate array with a null +*/ +p = argv = (char **) ckalloc(nargs*sizeof(char *)); +tend = t; +for(t = str ; t<tend ; ) + { + *p++ = t; + while( *t ) + ++t; + do { + ++t; + } while(t<tend && (*t==' ' || *t=='\t') ); + } +*p = NULL; +/*TEMP for(p=argv; *p; ++p)printf("arg=%s\n", *p);*/ + +if((pid = fork()) == 0) + { + enbint(SIG_DFL); + doclose(); + enbint(intrupt); + execvp(str, argv); + printf("\n"); + fatal1("Cannot load %s",str); + } + +free( (char *) argv); +return pid; +} + +void +touch(int force, char *name) +{ +struct stat stbuff; +char junk[1]; +int fd; + +if( stat(name,&stbuff) < 0) + if(force) + goto create; + else + { + fprintf(stderr, "touch: file %s does not exist.\n", name); + return; + } + +if(stbuff.st_size == 0) + goto create; + +if( (fd = open(name, O_RDWR)) < 0) + goto bad; + +if( read(fd, junk, 1) < 1) + { + close(fd); + goto bad; + } +lseek(fd, 0L, SEEK_SET); +if( write(fd, junk, 1) < 1 ) + { + close(fd); + goto bad; + } +close(fd); +return; + +bad: + fprintf(stderr, "Cannot touch %s\n", name); + return; + +create: + if( (fd = creat(name, 0666)) < 0) + goto bad; + close(fd); +} |