9base

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

haventfork.c (3436B)


      1 #include "rc.h"
      2 #include "getflags.h"
      3 #include "exec.h"
      4 #include "io.h"
      5 #include "fns.h"
      6 
      7 int havefork = 0;
      8 
      9 static char **
     10 rcargv(char *s)
     11 {
     12 	int argc;
     13 	char **argv;
     14 	word *p;
     15 
     16 	p = vlook("*")->val;
     17 	argv = malloc((count(p)+6)*sizeof(char*));
     18 	argc = 0;
     19 	argv[argc++] = argv0;
     20 	if(flag['e'])
     21 		argv[argc++] = "-Se";
     22 	else
     23 		argv[argc++] = "-S";
     24 	argv[argc++] = "-c";
     25 	argv[argc++] = s;
     26 	for(p = vlook("*")->val; p; p = p->next)
     27 		argv[argc++] = p->word;
     28 	argv[argc] = 0;
     29 	return argv;
     30 }
     31 
     32 void
     33 Xasync(void)
     34 {
     35 	uint pid;
     36 	char buf[20], **argv;
     37 
     38 	Updenv();
     39 
     40 	argv = rcargv(runq->code[runq->pc].s);
     41 	pid = ForkExecute(argv0, argv, -1, 1, 2);
     42 	free(argv);
     43 
     44 	if(pid == 0) {
     45 		Xerror("proc failed");
     46 		return;
     47 	}
     48 
     49 	runq->pc++;
     50 	sprint(buf, "%d", pid);
     51 	setvar("apid", newword(buf, (word *)0));
     52 }
     53 
     54 char*
     55 erealloc(char *p, long n)
     56 {
     57 	p = realloc(p, n);		/* botch, should be Realloc */
     58 	if(p==0)
     59 		panic("Can't realloc %d bytes\n", n);
     60 	return p;
     61 }
     62 
     63 enum { Stralloc = 100, };
     64 
     65 void
     66 Xbackq(void)
     67 {
     68 	char **argv;
     69 	int c, l;
     70 	char *s, *wd, *ewd, *stop;
     71 	struct io *f;
     72 	var *ifs = vlook("ifs");
     73 	word *v, *nextv;
     74 	int pfd[2];
     75 	int pid;
     76 
     77 	stop = ifs->val?ifs->val->word:"";
     78 	if(pipe(pfd)<0){
     79 		Xerror("can't make pipe");
     80 		return;
     81 	}
     82 
     83 	Updenv();
     84 
     85 	argv = rcargv(runq->code[runq->pc].s);
     86 	pid = ForkExecute(argv0, argv, -1, pfd[1], 2);
     87 	free(argv);
     88 
     89 	close(pfd[1]);
     90 
     91 	if(pid == 0) {
     92 		Xerror("proc failed");
     93 		close(pfd[0]);
     94 		return;
     95 	}
     96 
     97 	f = openfd(pfd[0]);
     98 		s = wd = ewd = 0;
     99 	v = 0;
    100 	while((c=rchr(f))!=EOF){
    101 		if(s==ewd){
    102 			l = s-wd;
    103 			wd = erealloc(wd, l+Stralloc);
    104 			ewd = wd+l+Stralloc-1;
    105 			s = wd+l;
    106 		}
    107 		if(strchr(stop, c)){
    108 			if(s!=wd){
    109 				*s='\0';
    110 				v = newword(wd, v);
    111 				s = wd;
    112 			}
    113 		}
    114 		else *s++=c;
    115 	}
    116 	if(s!=wd){
    117 		*s='\0';
    118 		v=newword(wd, v);
    119 	}
    120 	if(wd)
    121 		efree(wd);
    122 	closeio(f);
    123 	Waitfor(pid, 1);
    124 	/* v points to reversed arglist -- reverse it onto argv */
    125 	while(v){
    126 		nextv=v->next;
    127 		v->next=runq->argv->words;
    128 		runq->argv->words=v;
    129 		v=nextv;
    130 	}
    131 	runq->pc++;
    132 }
    133 
    134 void
    135 Xpipe(void)
    136 {
    137 	thread *p=runq;
    138 	int pc=p->pc, pid;
    139 	int rfd=p->code[pc+1].i;
    140 	int pfd[2];
    141 	char **argv;
    142 
    143 	if(pipe(pfd)<0){
    144 		Xerror1("can't get pipe");
    145 		return;
    146 	}
    147 
    148 	Updenv();
    149 
    150 	argv = rcargv(runq->code[pc+2].s);
    151 	pid = ForkExecute(argv0, argv, 0, pfd[1], 2);
    152 	free(argv);
    153 	close(pfd[1]);
    154 
    155 	if(pid == 0) {
    156 		Xerror("proc failed");
    157 		close(pfd[0]);
    158 		return;
    159 	}
    160 
    161 	start(p->code, pc+4, runq->local);
    162 	pushredir(ROPEN, pfd[0], rfd);
    163 	p->pc=p->code[pc+3].i;
    164 	p->pid=pid;
    165 }
    166 
    167 void
    168 Xpipefd(void)
    169 {
    170 	Abort();
    171 }
    172 
    173 void
    174 Xsubshell(void)
    175 {
    176 	char **argv;
    177 	int pid;
    178 
    179 	Updenv();
    180 
    181 	argv = rcargv(runq->code[runq->pc].s);
    182 	pid = ForkExecute(argv0, argv, -1, 1, 2);
    183 	free(argv);
    184 
    185 	if(pid < 0) {
    186 		Xerror("proc failed");
    187 		return;
    188 	}
    189 
    190 	Waitfor(pid, 1);
    191 	runq->pc++;
    192 }
    193 
    194 /*
    195  *  start a process running the cmd on the stack and return its pid.
    196  */
    197 int
    198 execforkexec(void)
    199 {
    200 	char **argv;
    201 	char file[1024];
    202 	int nc;
    203 	word *path;
    204 	int pid;
    205 
    206 	if(runq->argv->words==0)
    207 		return -1;
    208 	argv = mkargv(runq->argv->words);
    209 
    210 	for(path = searchpath(runq->argv->words->word);path;path = path->next){
    211 		nc = strlen(path->word);
    212 		if(nc < sizeof file - 1){	/* 1 for / */
    213 			strcpy(file, path->word);
    214 			if(file[0]){
    215 				strcat(file, "/");
    216 				nc++;
    217 			}
    218 			if(nc+strlen(argv[1])<sizeof(file)){
    219 				strcat(file, argv[1]);
    220 				pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
    221 				if(pid >= 0){
    222 					free(argv);
    223 					return pid;
    224 				}
    225 			}
    226 		}
    227 	}
    228 	free(argv);
    229 	return -1;
    230 }