void worker(int fdf, int fdt, char *from, char *to) { char buf[DEFB], *bp; long len, n; vlong o; len = sizeof(buf); bp = buf; o = nextoff(); while(n = pread(fdf, bp, len, o)){ if(n < 0){ fprint(2, "reading %s at %lld: %r\n", from, o); _exits("bad"); } if(pwrite(fdt, buf, n, o) != n){ fprint(2, "writing %s: %r\n", to); _exits("bad"); } bp += n; o += n; len -= n; if(len == 0){ len = sizeof buf; bp = buf; o = nextoff(); } } _exits(nil); }
static int start_host(void) { int fd; cs = consctl(); switch((hostpid = rfork(RFPROC|RFNAMEG|RFFDG|RFNOTEG))) { case 0: fd = open("/dev/cons", OREAD); dup(fd,0); if(fd != 0) close(fd); fd = open("/dev/cons", OWRITE); dup(fd,1); dup(fd,2); if(fd != 1 && fd !=2) close(fd); execl("/bin/rc","rcX",nil); fprint(2,"failed to start up rc\n"); _exits("rc"); case -1: fprint(2,"rc startup: fork error\n"); _exits("rc_fork"); } return open("/mnt/cons/data", ORDWR); }
/* * called by vstack once it has moved to * the unshared stack in the new process. */ void exectramp(Targ *t) { int *fd, i, nfd; char filename[128], err[ERRMAX], status[2*ERRMAX]; t->pid = getpid(); *t->spin = 0; /* allow parent to proceed: can't just rendezvous: see below */ fd = t->fd; snprint(filename, sizeof(filename), "#d/%d", t->wfd); t->wfd = open(filename, OWRITE|OCEXEC); /* if it failed, we'll manage */ nfd = MAXNFD; /* TO DO: should read from /fd */ for(i = 0; i < nfd; i++) if(i != fd[0] && i != fd[1] && i != fd[2] && i != t->wfd) close(i); if(fd[0] != 0){ dup(fd[0], 0); close(fd[0]); } if(fd[1] != 1){ dup(fd[1], 1); close(fd[1]); } if(fd[2] != 2){ dup(fd[2], 2); close(fd[2]); } if(t->dir != nil && chdir(t->dir) < 0){ if(t->wfd > 0) fprint(t->wfd, "chdir: %s: %r", t->dir); _exits("bad dir"); } if(t->nice) oslopri(); exec(t->args[0], t->args); err[0] = 0; errstr(err, sizeof(err)); if(t->args[0][0] != '/' && t->args[0][0] != '#' && strncmp(t->args[0], "../", 3) != 0 && strncmp(t->args[0], "./", 2) != 0 && strlen(t->args[0])+5 < sizeof(filename)){ snprint(filename, sizeof(filename), "/bin/%s", t->args[0]); exec(filename, t->args); errstr(err, sizeof(err)); } snprint(status, sizeof(status), "%s: can't exec: %s", t->args[0], err); if(t->wfd > 0) write(t->wfd, status, strlen(status)); _exits(status); }
/* * loop reading /mnt/term/dev/note looking for notes. * The child returns to start the shell. */ void rmtnoteproc(void) { int n, fd, pid, notepid; char buf[256]; /* new proc returns to start shell */ pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM); switch(pid){ case -1: syslog(0, "cpu", "cpu -R: can't start noteproc: %r"); return; case 0: return; } /* new proc reads notes from other side and posts them to shell */ switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){ case -1: syslog(0, "cpu", "cpu -R: can't start wait proc: %r"); _exits(0); case 0: fd = open(rmtnotefile, OREAD); if(fd < 0){ syslog(0, "cpu", "cpu -R: can't open %s", rmtnotefile); _exits(0); } for(;;){ n = read(fd, buf, sizeof(buf)-1); if(n <= 0){ postnote(PNGROUP, pid, "hangup"); _exits(0); } buf[n] = 0; postnote(PNGROUP, pid, buf); } } /* original proc waits for shell proc to die and kills note proc */ for(;;){ n = waitpid(); if(n < 0 || n == pid) break; } postnote(PNPROC, notepid, "kill"); _exits(0); }
/* * like trylock, but we've already got the lock on fd, * and don't want an L. lock file. */ static Mlock * keeplockalive(char *path, int fd) { char buf[1]; Mlock *l; l = malloc(sizeof(Mlock)); if(l == 0) return 0; l->fd = fd; l->name = s_new(); s_append(l->name, path); /* fork process to keep lock alive until sysunlock(l) */ switch(l->pid = rfork(RFPROC)){ default: break; case 0: fd = l->fd; for(;;){ sleep(1000*60); if(pread(fd, buf, 1, 0) < 0) break; } _exits(0); } return l; }
void _threadnote(void *v, char *s) { Proc *p; Note *n; _threaddebug(DBGNOTE, "Got note %s", s); if(strncmp(s, "sys:", 4) == 0) noted(NDFLT); if(_threadexitsallstatus){ _threaddebug(DBGNOTE, "Threadexitsallstatus = '%s'\n", _threadexitsallstatus); _exits(_threadexitsallstatus); } if(strcmp(s, "threadint")==0) noted(NCONT); p = _threadgetproc(); if(p == nil) noted(NDFLT); for(n=notes; n<enotes; n++) if(canlock(&n->inuse)) break; if(n==enotes) sysfatal("libthread: too many delayed notes"); utfecpy(n->s, n->s+ERRMAX, s); n->proc = p; p->pending = 1; if(!p->splhi) delayednotes(p, v); noted(NCONT); }
int blockread(int in, char *first, int nfirst) { int p[2], out, n, rv; char blk[512]; if(pipe(p) < 0) sysfatal("pipe: %r"); rv = p[0]; out = p[1]; switch(rfork(RFPROC|RFNOTEG|RFFDG)){ case -1: sysfatal("fork: %r"); case 0: close(rv); break; default: close(in); close(out); return rv; } write(out, first, nfirst); while((n=read(in, blk, sizeof blk)) > 0){ if(write(out, blk, n) != n) break; if(n == sizeof(blk) && memcmp(zero, blk, n) == n) break; } _exits(0); return -1; }
void sigusr2handler(int s) { /* fprint(2, "%d usr2 %d\n", time(0), getpid()); */ if(threadexitsmsg) _exits(threadexitsmsg); }
void main(int argc, char **argv) { int i; ARGBEGIN{ }ARGEND; if(argc == 0){ fprint(2, "usage: %s portrange\n", argv0); exits("usage"); } switch(rfork(RFREND|RFNOTEG|RFFDG|RFPROC|RFNAMEG)){ case 0: close(0); close(1); break; case -1: abort(); /* "fork failed\n" */; default: _exits(0); } for(i = 0; i < argc; i++) hogrange(argv[i]); close(2); for(;;) sleep(10000); }
void failure(void*, char *note) { if(strcmp(note, "failure") == 0) _exits(nil); noted(NDFLT); }
void startmc(void) { int p[2]; if(fd1 == -1) fd1 = dup(1, -1); if(pipe(p) < 0) return; switch(fork()){ case -1: return; default: close(p[0]); dup(p[1], 1); if(p[1] != 1) close(p[1]); return; case 0: close(p[1]); dup(p[0], 0); if(p[0] != 0) close(p[0]); execl("/bin/mc", "mc", nil); cat(); _exits(0); } }
void spawnmonitor(int fd) { char buf[4096]; char *xbuf; int n; int out; int first; switch(rfork(RFFDG|RFNOTEG|RFPROC)){ case -1: default: return; case 0: break; } out = open("/dev/cons", OWRITE); if(out < 0) out = 2; xbuf = buf; /* for ease of acid */ first = 1; while((n = read(fd, xbuf, sizeof buf)) > 0){ if(first){ first = 0; fprint(2, "Ghostscript Error:\n"); } write(out, xbuf, n); alarm(500); } _exits(0); }
int getname(char **namep) { int c; char buf[64], *p; if(!savec) return 0; while(*savec == ' ' || *savec == '\t') savec++; for(p = buf; (c = *savec) && c != ' ' && c != '\t'; p++){ if(p >= buf+sizeof buf -1) return 0; *p = *savec++; } *p = '\0'; *namep = strdup(buf); if(*namep == 0){ clog("internal error: strdup failure"); _exits(0); } while(*savec == ' ' || *savec == '\t') savec++; return p > buf; }
Waitmsg* system(char *name, char **argv) { char err[ERRMAX]; Waitmsg *w; int pid; switch(pid = fork()){ /* assign = */ case -1: return nil; case 0: exec(name, argv); errstr(err, sizeof err); _exits(err); } for(;;){ w = wait(); if(w == nil) break; if(w->pid == pid) return w; free(w); } return nil; }
static void ekeyslave(int fd) { Rune r; char t[1+UTFmax], k[10]; int kr, kn, w; if(eforkslave(Ekeyboard) < MAXSLAVE) return; kn = 0; t[0] = Skeyboard; for(;;){ while(!fullrune(k, kn)){ kr = read(fd, k+kn, sizeof k - kn); if(kr <= 0) goto breakout; kn += kr; } w = chartorune(&r, k); kn -= w; memmove(t+1, k, w); memmove(k, &k[w], kn); if(write(epipe[1], t, sizeof(t)) != sizeof(t)) break; } breakout:; t[0] = MAXSLAVE; write(epipe[1], t, 1); _exits(0); }
void doexec(void) { char *argl[MAXARG]; char args[LINSIZ]; char *p; char **ap; char *thisarg; ap = argl; p = args; *ap++ = symfil; for (rdc(); lastc != EOR;) { thisarg = p; if (lastc == '<' || lastc == '>') { *p++ = lastc; rdc(); } while (lastc != EOR && lastc != SPC && lastc != TB) { *p++ = lastc; readchar(); } if (lastc == SPC || lastc == TB) rdc(); *p++ = 0; if (*thisarg == '<') { close(0); if (open(&thisarg[1], OREAD) < 0) { print("%s: cannot open\n", &thisarg[1]); _exits(0); } } else if (*thisarg == '>') { close(1); if (create(&thisarg[1], OWRITE, 0666) < 0) { print("%s: cannot create\n", &thisarg[1]); _exits(0); } } else *ap++ = thisarg; } *ap = 0; exec(symfil, argl); perror(symfil); }
void call_host(char *machine, char **argv, char **end) { int ph2t[2], pt2h[2]; if(machine){ dup(remotefd0, 0); dup(remotefd1, 1); close(remotefd0); close(remotefd1); argv[0] = "hplace"; *end = 0; exec(hplace, argv); fprint(2, "can't exec: "); perror(hplace); _exits("damn"); } if(pipe(ph2t)==-1 || pipe(pt2h)==-1) panic("pipe"); switch(fork()){ case 0: dup(ph2t[0], 0); dup(pt2h[1], 1); close(ph2t[0]); close(ph2t[1]); close(pt2h[0]); close(pt2h[1]); argv[0] = "hplace"; *end = 0; exec(hplace, argv); fprint(2, "can't exec: "); perror(hplace); _exits("damn"); case -1: panic("can't fork hplace"); } dup(pt2h[0], 0); dup(ph2t[1], 1); close(ph2t[0]); close(ph2t[1]); close(pt2h[0]); close(pt2h[1]); }
void setupuser(AuthInfo *ai) { Waitmsg *w; int pid; if(ai){ strecpy(username, username+sizeof username, ai->cuid); if(auth_chuid(ai, nil) < 0) bye("user auth failed: %r"); auth_freeAI(ai); }else strecpy(username, username+sizeof username, getuser()); if(newns(username, 0) < 0) bye("user login failed: %r"); /* * hack to allow access to outgoing smtp forwarding */ enableForwarding(); snprint(mboxDir, MboxNameLen, "/mail/box/%s", username); if(myChdir(mboxDir) < 0) bye("can't open user's mailbox"); switch(pid = fork()){ case -1: bye("can't initialize mail system"); break; case 0: execl("/bin/upas/fs", "upas/fs", "-np", nil); _exits("rob1"); _exits(0); break; default: break; } if((w=wait()) == nil || w->pid != pid || w->msg[0] != '\0') bye("can't initialize mail system"); free(w); }
void _finish(int status, char *term) { char *cp; if(_finishing) _exits(exitstatus); _finishing = 1; if(status){ cp = _ultoa(exitstatus, status & 0xFF); *cp = 0; }else if(term){ strncpy(exitstatus, term, ERRMAX); exitstatus[ERRMAX-1] = '\0'; } if(_sessleader) kill(0, SIGTERM); _exits(exitstatus); }
void bootterm(char *machine, char **argv) { int ph2t[2], pt2h[2]; if(machine){ dup(remotefd0, 0); dup(remotefd1, 1); close(remotefd0); close(remotefd1); argv[0] = "samterm"; exec(samterm, argv); fprint(2, "can't exec: "); perror(samterm); _exits("damn"); } if(pipe(ph2t)==-1 || pipe(pt2h)==-1) panic("pipe"); switch(fork()){ case 0: dup(ph2t[0], 0); dup(pt2h[1], 1); close(ph2t[0]); close(ph2t[1]); close(pt2h[0]); close(pt2h[1]); argv[0] = "samterm"; exec(samterm, argv); fprint(2, "can't exec: "); perror(samterm); _exits("damn"); case -1: panic("can't fork samterm"); } dup(pt2h[0], 0); dup(ph2t[1], 1); close(ph2t[0]); close(ph2t[1]); close(pt2h[0]); close(pt2h[1]); }
void chatsrv(char *name) { int n, sfd, pfd[2]; char *p, buf[256]; if(name && *name) snprint(nbuf, sizeof nbuf, "/srv/%s", name); else{ if(p = strrchr(argv0, '/')) /* assign = */ name = p+1; else name = argv0; snprint(nbuf, sizeof nbuf, "/srv/%s.chat", name); } remove(nbuf); if(pipe(pfd) < 0) panic("chatsrv pipe"); sfd = create(nbuf, OWRITE, 0600); if(sfd < 0) panic("chatsrv create %s", nbuf); chatpid = rfork(RFPROC|RFMEM); switch(chatpid){ case -1: panic("chatsrv fork"); case 0: break; default: atexit(killchat); return; } fprint(sfd, "%d", pfd[1]); close(sfd); close(pfd[1]); for(;;){ n = read(pfd[0], buf, sizeof(buf)-1); if(n < 0) break; if(n == 0) continue; buf[n] = 0; if(buf[0] == 'c') conftime = 999; chatty = strtol(buf, 0, 0); if(abs(chatty) < 2) rpcdebug = 0; else rpcdebug = abs(chatty) - 1; fprint(2, "%s: chatty=%d, rpcdebug=%d, conftime=%d\n", nbuf, chatty, rpcdebug, conftime); } _exits(0); }
/* * Translate Unicode to HTML by asking tcs(1). * This way we don't have yet another table. */ Rune* rune2html(Rune r) { static Biobuf b; static int fd = -1; static Rune **tcscache[256]; int p[2]; char *q; if(r == '\n') return L("\n"); if(((uint)r&~0xFFFF) != 0){ /* The cache must grow a lot to handle them */ fprint(2, "%s: can't handle rune '%C'\n", argv0, r); return L("?"); } if(tcscache[r>>8] && tcscache[r>>8][r&0xFF]) return tcscache[r>>8][r&0xFF]; if(fd < 0){ if(pipe(p) < 0) sysfatal("pipe: %r"); switch(fork()){ case -1: sysfatal("fork: %r"); case 0: dup2(p[0], 0); dup2(p[1], 1); close(p[0]); close(p[1]); execl(BINDIR "/tcs", "tcs", "-t", "html", nil); _exits(0); default: fd = p[1]; Binit(&b, p[0], OREAD); break; } } /* HACK: extra newlines force rune+\n through tcs now */ fprint(fd, "%C\n\n\n\n", r); q = Brdline(&(b.Biobufhdr), '\n'); while (q != nil && *q == '\n') q = Brdline(&(b.Biobufhdr), '\n'); if(q == nil) sysfatal("tcs: early eof"); q[Blinelen(&(b.Biobufhdr))-1] = 0; if(tcscache[r>>8] == nil) tcscache[r>>8] = emalloc(256*sizeof tcscache[0][0]); tcscache[r>>8][r&0xFF] = erunesmprint("%s", q); return tcscache[r>>8][r&0xFF]; }
int timeout(void *x, char *msg) { USED(x); syslog(0, "smtp.fail", "interrupt: %s: %s", farend, msg); if(strstr(msg, "alarm")){ fprint(2, "smtp timeout: connection to %s timed out\n", farend); if(quitting) exits(quitrv); exits(Retry); } if(strstr(msg, "closed pipe")){ /* call _exits() to prevent Bio from trying to flush closed pipe */ fprint(2, "smtp timeout: connection closed to %s\n", farend); if(quitting){ syslog(0, "smtp.fail", "closed pipe to %s", farend); _exits(quitrv); } _exits(Retry); } return 0; }
void exits(const char *s) { int i, pid; void (*f)(void); pid = getpid(); for(i = NEXIT-1; i >= 0; i--) if((f = onex[i].f) && pid == onex[i].pid) { onex[i].f = 0; (*f)(); } _exits(s); }
int connectcmd(char *cmd) { int p[2]; if(pipe(p) < 0) return -1; switch(fork()){ case -1: fprint(2, "fork failed: %r\n"); _exits("exec"); case 0: rfork(RFNOTEG); dup(p[0], 0); dup(p[0], 1); close(p[1]); execl("/bin/rc", "rc", "-c", cmd, nil); fprint(2, "exec failed: %r\n"); _exits("exec"); default: close(p[0]); return p[1]; } }
void startproc(void (*f)(void), char *name) { switch(rfork(RFMEM|RFFDG|RFPROC)){ case -1: panic("can't fork"); case 0: break; default: return; } procname = name; f(); _exits(nil); }
static void efork(Execargs *e) { char buf[ERRMAX]; _threaddebug(DBGEXEC, "_schedexec %s", e->prog); close(e->fd[0]); exec(e->prog, e->args); _threaddebug(DBGEXEC, "_schedexec failed: %r"); rerrstr(buf, sizeof buf); if(buf[0]=='\0') strcpy(buf, "exec failed"); write(e->fd[1], buf, strlen(buf)); close(e->fd[1]); _exits(buf); }
main(int ac, char **av) { Resub rs[10]; Reprog *p; char *s; int i; p = regcomp("[^a-z]"); s = "\n"; rs[0].s.sp = 0; rs[0].e.ep = 0; if(regexec(p, s, rs, 10)) printf("%s %x %x %x\n", s, s, rs[0].s.sp, rs[0].e.ep); s = "0"; if(regexec(p, s, rs, 10)) printf("%s %x %x %x\n", s, s, rs[0].s.sp, rs[0].e.ep); _exits(0); }
void winshell(void *args) { print_func_entry(); Window *w; Channel *pidc; void **arg; char *cmd, *dir; char **argv; arg = args; w = arg[0]; pidc = arg[1]; cmd = arg[2]; argv = arg[3]; dir = arg[4]; rfork(RFNAMEG|RFFDG|RFENVG); if(filsysmount(filsys, w->id) < 0){ fprint(2, "mount failed: %r\n"); sendul(pidc, 0); threadexits("mount failed"); } close(0); if(open("/dev/cons", OREAD) < 0){ fprint(2, "can't open /dev/cons: %r\n"); sendul(pidc, 0); threadexits("/dev/cons"); } close(1); if(open("/dev/cons", OWRITE) < 0){ fprint(2, "can't open /dev/cons: %r\n"); sendul(pidc, 0); threadexits("open"); /* BUG? was terminate() */ } if(wclose(w) == 0){ /* remove extra ref hanging from creation */ notify(nil); dup(1, 2); if(dir) chdir(dir); procexec(pidc, cmd, argv); _exits("exec failed"); } print_func_exit(); }
int startserveproc(void (*f)(Chan*, uint8_t*, int), char *name, Chan *c, uint8_t *b, int nb) { int pid; switch(pid = rfork(RFMEM|RFPROC)){ case -1: panic("can't fork"); case 0: break; default: return pid; } procname = name; f(c, b, nb); _exits(nil); return -1; /* can't happen */ }