void vtAttach(void) { int pid; Thread *p; static int init; static Lock lk; lock(&lk); if(!init) { rfork(RFREND); vtThreadInit(); init = 1; } unlock(&lk); pid = getpid(); p = *vtRock; if(p != nil && p->pid == pid) { p->ref++; return; } p = vtMemAllocZ(sizeof(Thread)); p->ref = 1; p->pid = pid; *vtRock = p; }
void execproc(void *v) { Channel *sync; Exec *e; int p[2], q[2]; char *cmd; threadsetname("execproc"); e = v; p[0] = e->p[0]; p[1] = e->p[1]; q[0] = e->q[0]; q[1] = e->q[1]; cmd = e->cmd; sync = e->sync; rfork(RFFDG); free(e); dup(p[0], 0); close(p[0]); close(p[1]); if(q[0]){ dup(q[1], 1); close(q[0]); close(q[1]); } if(!procstderr) close(2); procexecl(sync, "/bin/rc", "rc", "-c", cmd, 0); error("can't exec"); }
/* * process to notify other servers of changes * (also reads in new databases) */ void notifyproc(void) { Request req; switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ case -1: return; case 0: break; default: return; } procsetname("notify slaves"); memset(&req, 0, sizeof req); req.isslave = 1; /* don't fork off subprocesses */ for(;;){ getactivity(&req, 0); notify_areas(owned, &req); putactivity(0); sleep(60*1000); } }
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 fromstdin(Conn *c) { int n; char buf[1024]; int pid; int eofs; switch(pid = rfork(RFMEM|RFPROC|RFNOWAIT)){ case -1: error("fork: %r"); case 0: break; default: atexitkill(pid); return; } atexit(atexitkiller); if(interactive) rawon(); notify(cookedcatchint); eofs = 0; for(;;){ n = read(0, buf, sizeof(buf)); if(n < 0){ if(wasintr()){ if(!raw){ buf[0] = 0x7f; n = 1; }else continue; }else break; } if(n == 0){ if(!c->interactive || ++eofs > 32) break; }else eofs = 0; if(interactive && usemenu && n && memchr(buf, 0x1c, n)) { if(menu(c)=='q'){ sendwritemsg(c, "", 0); exits("quit"); } continue; } if(!raw && n==0){ buf[0] = 0x4; n = 1; } sendwritemsg(c, buf, n); } sendwritemsg(c, "", 0); if(n >= 0) /* weren't hung up upon? */ atexitdont(atexitkiller); exits(nil); }
static void execproc(void *a) { int i, fd; Client *c; char tmp[32]; c = a; snprint(tmp, sizeof tmp, "execproc%d", c->num); threadsetname(tmp); if(pipe(c->fd) < 0){ rerrstr(c->err, sizeof c->err); sendul(c->execpid, -1); return; } rfork(RFFDG); fd = c->fd[1]; close(c->fd[0]); dup(fd, 0); dup(fd, 1); for(i=3; i<100; i++) /* should do better */ close(i); strcpy(c->err, "exec failed"); procexecl(c->execpid, "/bin/rc", "rc", "-c", c->cmd, nil); }
void spawnWaiter(Lock *l) { int pid; int64_t start; switch((pid = rfork(RFMEM|RFPROC|RFNOWAIT))) { case 0: /* wait for the alwaysLocked to be locked by the main process */ qlock(&rl); while(resInWaiter == 0xff) rsleep(&rStart); start = nsec(); resInWaiter = lockt(l, 6000); elapsedInWaiter = (nsec() - start) / (1000 * 1000); if(verbose) print("lockt returned %d, elapsed = %d ms\n", resInWaiter, elapsedInWaiter); rwakeup(&rCompleted); qunlock(&rl); exits(0); break; case -1: print("spawnWaiter: %r\n"); exits("rfork fails"); break; default: if(verbose) print("spawn waiter %d\n", pid); break; } }
void main(int argc, char **argv) { Mainarg *a; Proc *p; rfork(RFREND); mainp = &p; if(setjmp(_mainjmp)) _schedinit(p); //_threaddebuglevel = (DBGSCHED|DBGCHAN|DBGREND)^~0; _systhreadinit(); _qlockinit(_threadrendezvous); _sysfatal = _threadsysfatal; _dial = _threaddial; __assert = _threadassert; notify(_threadnote); if(mainstacksize == 0) mainstacksize = 8*1024; a = _threadmalloc(sizeof *a, 1); a->argc = argc; a->argv = argv; p = _newproc(mainlauncher, a, mainstacksize, "threadmain", 0, 0); _schedinit(p); abort(); /* not reached */ }
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); }
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; }
/* Connect us to new window, if possible */ int newwindow(char *str) { int fd; char *wsys; char buf[256]; wsys = getenv("wsys"); if(wsys == nil) return -1; fd = open(wsys, ORDWR); if(fd < 0){ free(wsys); return -1; } rfork(RFNAMEG); unmount(wsys, "/dev"); /* drop reference to old window */ free(wsys); if(str) snprint(buf, sizeof buf, "new %s", str); else strcpy(buf, "new"); if(mount(fd, -1, "/mnt/wsys", MREPL, buf) < 0) return mount(fd, -1, "/dev", MBEFORE, buf); return bind("/mnt/wsys", "/dev", MBEFORE); }
// main takes care of OS-specific startup and dispatches to xmain. void main(int argc, char **argv) { Buf b; setvbuf(stdout, nil, _IOLBF, BUFSIZ); setvbuf(stderr, nil, _IOLBF, BUFSIZ); binit(&b); rfork(RFENVG); slash = "/"; gohostos = "plan9"; xgetenv(&b, "objtype"); if(b.len == 0) fatal("$objtype is unset"); gohostarch = btake(&b); xgetenv(&b, "GOBIN"); if(b.len == 0){ bpathf(&b, "/%s/bin", gohostarch); xsetenv("GOBIN", bstr(&b)); } srand(time(0)+getpid()); init(); xmain(argc, argv); bfree(&b); exits(nil); }
void copyout(Conn *c, int fd, int mtype) { char buf[8192]; int n, max, pid; Msg *m; max = sizeof buf; if(max > maxmsg - 32) /* 32 is an overestimate of packet overhead */ max = maxmsg - 32; if(max <= 0) sysfatal("maximum message size too small"); switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ case -1: sysfatal("fork: %r"); case 0: break; default: atexitkill(pid); return; } while((n = read(fd, buf, max)) > 0){ m = allocmsg(c, mtype, 4+n); putlong(m, n); putbytes(m, buf, n); sendmsg(m); } exits(nil); }
void main(int, char **) { int ctl; wdog = open("#w/wdctl", ORDWR); if (wdog < 0) sysfatal("open #w/wdctl: %r"); switch(rfork(RFPROC|RFNOWAIT|RFFDG)){ case 0: break; default: exits(0); } ctl = procctl(getpid()); fprint(ctl, "pri 18"); close(ctl); if (fprint(wdog, "enable") < 0) sysfatal("write #w/wdctl enable: %r"); for(;;){ sleep(300); /* allows 4.2GHz CPU, with some slop */ seek(wdog, 0, 0); if (fprint(wdog, "restart") < 0) sysfatal("write #w/wdctl restart: %r"); } }
static int eforkslave(ulong key) { int i, pid; for(i=0; i<MAXSLAVE; i++) if((key & ~(1<<i)) == 0 && eslave[i].pid == 0){ if(nslave <= i) nslave = i + 1; /* * share the file descriptors so the last child * out closes all connections to the window server. */ switch(pid = rfork(RFPROC)){ case 0: return MAXSLAVE+i; case -1: fprint(2, "events: fork error\n"); exits("fork"); } eslave[i].pid = pid; eslave[i].head = eslave[i].tail = 0; return i; } drawerror(display, "events: bad slave assignment"); return 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 _schedexecwait(void) { int pid; Channel *c; Proc *p; Thread *t; Waitmsg *w; p = _threadgetproc(); t = p->thread; pid = t->ret; _threaddebug(DBGEXEC, "_schedexecwait %d", t->ret); rfork(RFCFDG); for(;;){ w = wait(); if(w == nil) break; if(w->pid == pid) break; free(w); } if(w != nil){ if((c = _threadwaitchan) != nil) sendp(c, w); else free(w); } threadexits("procexec"); }
/* * Stream the three temp files to an archive */ void install(char *arname, Arfile *astart, Arfile *amiddle, Arfile *aend, int createflag) { int fd; if(allobj && dupfound) { fprint(2, "%s not changed\n", arname); return; } /* leave note group behind when copying back; i.e. sidestep interrupts */ rfork(RFNOTEG); if(createflag) fprint(2, "ar: creating %s\n", arname); fd = arcreate(arname); if(allobj) rl(fd); if (astart) { arstream(fd, astart); arfree(astart); } if (amiddle) { arstream(fd, amiddle); arfree(amiddle); } if (aend) { arstream(fd, aend); arfree(aend); } close(fd); }
int main(int argc, char *argv[]) { void *map; int page_size; int status; page_size = getpagesize(); if ((map = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0)) == MAP_FAILED) err(1, "mmap"); memset(map, 0, sizeof(MAGIC)); switch(rfork(RFFDG|RFPROC|RFMEM)) { case -1: err(1, "fork"); case 0: memcpy(map, MAGIC, sizeof(MAGIC)); _exit(0); } if (wait(&status) < 0) err(1, "wait"); if (!WIFEXITED(status)) err(1, "child error"); if (memcmp(map, MAGIC, sizeof(MAGIC)) != 0) return 1; return WEXITSTATUS(status) != 0; }
int main(int argc, char *argv[]) { struct kevent ev; int status; int kq; if ((kq = kqueue()) < 0) err(1, "kqueue"); signal(SIGINT, SIG_IGN); EV_SET(&ev, SIGINT, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, 0); switch(rfork(RFPROC)) { case -1: err(1, "rfork"); case 0: if (kevent(kq, &ev, 1, NULL, 0, NULL)) err(1, "kevent"); raise(SIGINT); _exit(0); } if (wait(&status) < 0) err(1, "wait"); if (!WIFEXITED(status)) err(1, "child error"); return WEXITSTATUS(status) != 0; }
void runcmd(int reqfd, int datafd, char *svc, char *cmd, char *arg1, char *arg2) { char *p; int fd, cmdpid, child; cmdpid = rfork(RFPROC|RFMEM|RFNOTEG|RFFDG|RFENVG); switch (cmdpid) { case -1: syslog(0, "ssh", "fork failed: %r"); exits("fork"); case 0: if (restdir == nil) { p = smprint("/usr/%s", uname); if (p && access(p, AREAD) == 0 && chdir(p) < 0) { syslog(0, "ssh", "can't chdir(%s): %r", p); exits("can't chdir"); } free(p); } p = strrchr(cmd, '/'); if (p) ++p; else p = cmd; dup(datafd, 0); dup(datafd, 1); dup(datafd, 2); close(datafd); putenv("service", svc); fprint(errfd, "starting %s\n", cmd); execl(cmd, p, arg1, arg2, nil); syslog(0, "ssh", "cannot exec %s: %r", cmd); exits("exec"); default: close(datafd); fprint(errfd, "waiting for child %d\n", cmdpid); while ((child = waitpid()) != cmdpid && child != -1) fprint(errfd, "child %d passed\n", child); if (child == -1) fprint(errfd, "wait failed: %r\n"); syslog(0, "ssh", "server closing ssh session for %s", uname); fprint(errfd, "closing connection\n"); fprint(reqfd, "close"); p = smprint("/proc/%d/notepg", toppid); if (p) { fd = open(p, OWRITE); fprint(fd, "interrupt"); close(fd); } exits(nil); } }
void threadmain(int argc, char *argv[]) { static Args args; args.argc = argc; args.argv = argv; rfork(RFNAMEG); proccreate(realmain, &args, 16*1024); }
static int buildns(int newns, char *user, char *file) { Biobuf *b; char home[4*ANAMELEN]; int afd, cdroot; char *path; AuthRpc *rpc; rpc = nil; /* try for factotum now because later is impossible */ afd = open("/mnt/factotum/rpc", ORDWR); if(afd < 0 && newnsdebug) fprint(2, "open /mnt/factotum/rpc: %r\n"); if(afd >= 0){ rpc = auth_allocrpc(afd); if(rpc == nil) close(afd); } /* rpc != nil iff afd >= 0 */ if(file == nil){ if(!newns){ werrstr("no namespace file specified"); return freecloserpc(rpc); } file = "/lib/namespace"; } b = Bopen(file, OREAD); if(b == 0){ werrstr("can't open %s: %r", file); return freecloserpc(rpc); } if(newns){ rfork(RFENVG|RFCNAMEG); setenv("user", user); snprint(home, sizeof home, "/usr/%s", user); setenv("home", home); } cdroot = nsfile(newns ? "newns" : "addns", b, rpc); Bterm(b); freecloserpc(rpc); /* make sure we managed to cd into the new name space */ if(newns && !cdroot){ path = malloc(1024); if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0) chdir("/"); if(path != nil) free(path); } return 0; }
int fcall(int fd) { int i, r, n, l; uchar *p, *buf; int pipefd[2]; if(pipe(pipefd) < 0) fatal("fcall pipe: %r"); buf = malloc(MAXRPC); if(buf == nil) fatal("fcall malloc"); switch(rfork(RFPROC|RFMEM|RFFDG|RFCNAMEG)){ default: return pipefd[0]; /* parent returns fd */ case 0: break; /* child builds buffers */ case -1: fatal("fcall fork: %r"); } /* close file descriptors */ for(i=0; i<20; i++) if(i!=fd && i!=pipefd[1]) close(i); l = MAXRPC; p = buf; for(;;) { n = read(fd, p, l); if(n < 0) break; p += n; l -= n; for(;;) { r = mntrpclen(buf, p - buf); if(r == 0) break; if(write(pipefd[1], buf, r) < 0) break; n = (p - buf) - r; memmove(buf, buf+r, n); p = buf+n; l = MAXRPC - n; } } close(pipefd[1]); fatal(nil); return -1; }
void runtime·newosproc(M *mp, void *stk) { mp->tls[0] = mp->id; // so 386 asm can find it if(0){ runtime·printf("newosproc stk=%p m=%p g=%p rfork=%p id=%d/%d ostk=%p\n", stk, mp, mp->g0, runtime·rfork, mp->id, (int32)mp->tls[0], &mp); } if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, mp, mp->g0, runtime·mstart) < 0) runtime·throw("newosproc: rfork failed"); }
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); }
void runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) { m->tls[0] = m->id; // so 386 asm can find it if(0){ runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n", stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m); } if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0) runtime·throw("newosproc: rfork failed"); }
int _schedexec(Execargs *e) { int pid; switch(pid = rfork(RFREND|RFNOTEG|RFFDG|RFMEM|RFPROC)){ case 0: efork(e); default: return pid; } }
void main(void) { int64_t start, elapsed, res; static Lock l; rfork(RFNOTEG|RFREND); rStart.l = &rl; rCompleted.l = &rl; resInWaiter = 0xff; spawnWaiter(&l); lock(&l); alarm(20000); /* global timeout, FAIL if reached */ if (!atnotify(failOnTimeout, 1)){ fprint(2, "%r\n"); exits("atnotify fails"); } /* verify that lockt returns 0 on timeout */ start = nsec(); res = lockt(&l, 1000); elapsed = (nsec() - start) / (1000 * 1000); if(verbose) print("lockt returned %d, elapsed = %d ms\n", res, elapsed); if(res != 0 || elapsed < 900 || elapsed > 1300){ print("FAIL: lockt timeout\n"); exits("FAIL"); } /* verify that lockt returns 1 if the lock is released and * it can take it */ resInWaiter = -1; qlock(&rl); rwakeupall(&rStart); qunlock(&rl); sleep(1200); unlock(&l); qlock(&rl); while(elapsedInWaiter == 0) rsleep(&rCompleted); qunlock(&rl); if(resInWaiter != 1 || elapsedInWaiter < 1100 || elapsedInWaiter > 1500){ print("FAIL: lockt delayed acquisition\n"); exits("FAIL"); } print("PASS\n"); exits("PASS"); }
uint32_t thread(void(*f)(void*), void *a) { int pid; pid = rfork(RFNOWAIT|RFMEM|RFPROC); if(pid < 0) myfatal("rfork failed: %r"); if(pid != 0) return pid; (*f)(a); return 0; /* never reaches here */ }