9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

havefork.c (4415B)


      1 #include <u.h>
      2 #include <signal.h>
      3 #include "rc.h"
      4 #include "getflags.h"
      5 #include "exec.h"
      6 #include "io.h"
      7 #include "fns.h"
      8 
      9 int havefork = 1;
     10 
     11 void
     12 Xasync(void)
     13 {
     14 	int null = open("/dev/null", 0);
     15 	int pid;
     16 	char npid[10];
     17 	if(null<0){
     18 		Xerror("Can't open /dev/null\n");
     19 		return;
     20 	}
     21 	switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
     22 	case -1:
     23 		close(null);
     24 		Xerror("try again");
     25 		break;
     26 	case 0:
     27 		clearwaitpids();
     28 		pushredir(ROPEN, null, 0);
     29 		start(runq->code, runq->pc+1, runq->local);
     30 		runq->ret = 0;
     31 		break;
     32 	default:
     33 		addwaitpid(pid);
     34 		close(null);
     35 		runq->pc = runq->code[runq->pc].i;
     36 		inttoascii(npid, pid);
     37 		setvar("apid", newword(npid, (word *)0));
     38 		break;
     39 	}
     40 }
     41 
     42 void
     43 Xpipe(void)
     44 {
     45 	struct thread *p = runq;
     46 	int pc = p->pc, forkid;
     47 	int lfd = p->code[pc++].i;
     48 	int rfd = p->code[pc++].i;
     49 	int pfd[2];
     50 	if(pipe(pfd)<0){
     51 		Xerror("can't get pipe");
     52 		return;
     53 	}
     54 	switch(forkid = fork()){
     55 	case -1:
     56 		Xerror("try again");
     57 		break;
     58 	case 0:
     59 		clearwaitpids();
     60 		start(p->code, pc+2, runq->local);
     61 		runq->ret = 0;
     62 		close(pfd[PRD]);
     63 		pushredir(ROPEN, pfd[PWR], lfd);
     64 		break;
     65 	default:
     66 		addwaitpid(forkid);
     67 		start(p->code, p->code[pc].i, runq->local);
     68 		close(pfd[PWR]);
     69 		pushredir(ROPEN, pfd[PRD], rfd);
     70 		p->pc = p->code[pc+1].i;
     71 		p->pid = forkid;
     72 		break;
     73 	}
     74 }
     75 
     76 /*
     77  * Who should wait for the exit from the fork?
     78  */
     79 void
     80 Xbackq(void)
     81 {
     82 	struct thread *p = runq;
     83 	char wd[8193];
     84 	int c, n;
     85 	char *s, *ewd=&wd[8192], *stop, *q;
     86 	struct io *f;
     87 	var *ifs = vlook("ifs");
     88 	word *v, *nextv;
     89 	int pfd[2];
     90 	int pid;
     91 	Rune r;
     92 	stop = ifs->val?ifs->val->word:"";
     93 	if(pipe(pfd)<0){
     94 		Xerror("can't make pipe");
     95 		return;
     96 	}
     97 	switch(pid = fork()){
     98 	case -1:
     99 		Xerror("try again");
    100 		close(pfd[PRD]);
    101 		close(pfd[PWR]);
    102 		return;
    103 	case 0:
    104 		clearwaitpids();
    105 		close(pfd[PRD]);
    106 		start(runq->code, runq->pc+1, runq->local);
    107 		pushredir(ROPEN, pfd[PWR], 1);
    108 		return;
    109 	default:
    110 		addwaitpid(pid);
    111 		close(pfd[PWR]);
    112 		f = openfd(pfd[PRD]);
    113 		s = wd;
    114 		v = 0;
    115 		while((c = rchr(f))!=EOF){
    116 			if(s != ewd) {
    117 				*s++ = c;
    118 				for(q=stop; *q; q+=n) {
    119 					n = chartorune(&r, q);
    120 					if(s-wd >= n && memcmp(s-n, q, n) == 0) {
    121 						s -= n;
    122 						goto stop;
    123 					}
    124 				}
    125 				continue;
    126 			}
    127 		stop:
    128 			if(s != wd) {
    129 				*s = '\0';
    130 				v = newword(wd, v);
    131 			}
    132 			s = wd;
    133 		}
    134 		if(s!=wd){
    135 			*s='\0';
    136 			v = newword(wd, v);
    137 		}
    138 		closeio(f);
    139 		Waitfor(pid, 0);
    140 		/* v points to reversed arglist -- reverse it onto argv */
    141 		while(v){
    142 			nextv = v->next;
    143 			v->next = runq->argv->words;
    144 			runq->argv->words = v;
    145 			v = nextv;
    146 		}
    147 		p->pc = p->code[p->pc].i;
    148 		return;
    149 	}
    150 }
    151 
    152 void
    153 Xpipefd(void)
    154 {
    155 	struct thread *p = runq;
    156 	int pc = p->pc, pid;
    157 	char name[40];
    158 	int pfd[2];
    159 	struct { int sidefd, mainfd; } fd[2], *r, *w;
    160 
    161 	r = &fd[0];
    162 	w = &fd[1];
    163 	switch(p->code[pc].i){
    164 	case READ:
    165 		w = nil;
    166 		break;
    167 	case WRITE:
    168 		r = nil;
    169 	}
    170 
    171 	if(r){
    172 		if(pipe(pfd)<0){
    173 			Xerror("can't get pipe");
    174 			return;
    175 		}
    176 		r->sidefd = pfd[PWR];
    177 		r->mainfd = pfd[PRD];
    178 	}
    179 	if(w){
    180 		if(pipe(pfd)<0){
    181 			Xerror("can't get pipe");
    182 			return;
    183 		}
    184 		w->sidefd = pfd[PRD];
    185 		w->mainfd = pfd[PWR];
    186 	}
    187 	switch(pid = fork()){
    188 	case -1:
    189 		Xerror("try again");
    190 		break;
    191 	case 0:
    192 		clearwaitpids();
    193 		start(p->code, pc+2, runq->local);
    194 		if(r){
    195 			close(r->mainfd);
    196 			pushredir(ROPEN, r->sidefd, 1);
    197 		}
    198 		if(w){
    199 			close(w->mainfd);
    200 			pushredir(ROPEN, w->sidefd, 0);
    201 		}
    202 		runq->ret = 0;
    203 		break;
    204 	default:
    205 		addwaitpid(pid);
    206 		if(w){
    207 			close(w->sidefd);
    208 			pushredir(ROPEN, w->mainfd, w->mainfd);	/* so that Xpopredir can close it later */
    209 			strcpy(name, Fdprefix);
    210 			inttoascii(name+strlen(name), w->mainfd);
    211 			pushword(name);
    212 		}
    213 		if(r){
    214 			close(r->sidefd);
    215 			pushredir(ROPEN, r->mainfd, r->mainfd);
    216 			strcpy(name, Fdprefix);
    217 			inttoascii(name+strlen(name), r->mainfd);
    218 			pushword(name);
    219 		}
    220 		p->pc = p->code[pc+1].i;
    221 		break;
    222 	}
    223 }
    224 
    225 void
    226 Xsubshell(void)
    227 {
    228 	int pid;
    229 	switch(pid = fork()){
    230 	case -1:
    231 		Xerror("try again");
    232 		break;
    233 	case 0:
    234 		clearwaitpids();
    235 		start(runq->code, runq->pc+1, runq->local);
    236 		runq->ret = 0;
    237 		break;
    238 	default:
    239 		addwaitpid(pid);
    240 		Waitfor(pid, 1);
    241 		runq->pc = runq->code[runq->pc].i;
    242 		break;
    243 	}
    244 }
    245 
    246 int
    247 execforkexec(void)
    248 {
    249 	int pid;
    250 	int n;
    251 	char buf[ERRMAX];
    252 
    253 	switch(pid = fork()){
    254 	case -1:
    255 		return -1;
    256 	case 0:
    257 		clearwaitpids();
    258 		pushword("exec");
    259 		execexec();
    260 		strcpy(buf, "can't exec: ");
    261 		n = strlen(buf);
    262 		errstr(buf+n, ERRMAX-n);
    263 		Exit(buf);
    264 	}
    265 	addwaitpid(pid);
    266 	return pid;
    267 }