shithub: riscv

ref: 3ba1197aeb382e1750cbb0f2567794bd4482e1e2
dir: /sys/src/cmd/rc/haventfork.c/

View raw version
#include "rc.h"
#include "getflags.h"
#include "exec.h"
#include "io.h"
#include "fns.h"

int havefork = 0;

static char **
rcargv(char *s)
{
	int argc;
	char **argv;
	word *p;

	p = vlook("*")->val;
	argv = emalloc((count(p)+6)*sizeof(char*));
	argc = 0;
	argv[argc++] = argv0;
	if(flag['e'])
		argv[argc++] = "-Se";
	else
		argv[argc++] = "-S";
	argv[argc++] = "-c";
	argv[argc++] = s;
	for(p = vlook("*")->val; p; p = p->next)
		argv[argc++] = p->word;
	argv[argc] = 0;
	return argv;
}

void
Xasync(void)
{
	uint pid;
	char buf[20], **argv;

	Updenv();

	argv = rcargv(runq->code[runq->pc].s);
	pid = ForkExecute(argv0, argv, -1, 1, 2);
	free(argv);

	if(pid == 0) {
		Xerror("proc failed");
		return;
	}

	runq->pc++;
	sprint(buf, "%d", pid);
	setvar("apid", newword(buf, (word *)0));
}

enum { Stralloc = 100, };

void
Xbackq(void)
{
	char **argv;
	int c, l;
	char *s, *wd, *ewd, *stop;
	struct io *f;
	var *ifs = vlook("ifs");
	word *v, *nextv;
	int pfd[2];
	int pid;

	stop = ifs->val?ifs->val->word:"";
	if(pipe(pfd)<0){
		Xerror("can't make pipe");
		return;
	}

	Updenv();

	argv = rcargv(runq->code[runq->pc].s);
	pid = ForkExecute(argv0, argv, -1, pfd[1], 2);
	free(argv);

	close(pfd[1]);

	if(pid == 0) {
		Xerror("proc failed");
		close(pfd[0]);
		return;
	}

	f = openfd(pfd[0]);
		s = wd = ewd = 0;
	v = 0;
	while((c=rchr(f))!=EOF){
		if(s==ewd){
			l = s-wd;
			wd = erealloc(wd, l+Stralloc);
			ewd = wd+l+Stralloc-1;
			s = wd+l;
		}
		if(strchr(stop, c)){
			if(s!=wd){
				*s='\0';
				v = newword(wd, v);
				s = wd;
			}
		}
		else *s++=c;
	}
	if(s!=wd){
		*s='\0';
		v=newword(wd, v);
	}
	free(wd);
	closeio(f);
	Waitfor(pid, 1);
	/* v points to reversed arglist -- reverse it onto argv */
	while(v){
		nextv=v->next;
		v->next=runq->argv->words;
		runq->argv->words=v;
		v=nextv;
	}
	runq->pc++;
}

void
Xpipe(void)
{
	thread *p=runq;
	int pc=p->pc, pid;
	int rfd=p->code[pc+1].i;
	int pfd[2];
	char **argv;

	if(pipe(pfd)<0){
		Xerror1("can't get pipe");
		return;
	}

	Updenv();

	argv = rcargv(runq->code[pc+2].s);
	pid = ForkExecute(argv0, argv, 0, pfd[1], 2);
	free(argv);
	close(pfd[1]);

	if(pid == 0) {
		Xerror("proc failed");
		close(pfd[0]);
		return;
	}

	start(p->code, pc+4, runq->local);
	pushredir(ROPEN, pfd[0], rfd);
	p->pc=p->code[pc+3].i;
	p->pid=pid;
}

void
Xpipefd(void)
{
	Abort();
}

void
Xsubshell(void)
{
	char **argv;
	int pid;

	Updenv();

	argv = rcargv(runq->code[runq->pc].s);
	pid = ForkExecute(argv0, argv, -1, 1, 2);
	free(argv);

	if(pid < 0) {
		Xerror("proc failed");
		return;
	}

	Waitfor(pid, 1);
	runq->pc++;
}

/*
 *  start a process running the cmd on the stack and return its pid.
 */
int
execforkexec(void)
{
	char **argv;
	char file[1024];
	int nc, mc;
	word *path;
	int pid;

	if(runq->argv->words==0)
		return -1;
	argv = mkargv(runq->argv->words);
	mc = strlen(argv[1])+1;
	for(path = searchpath(runq->argv->words->word);path;path = path->next){
		nc = strlen(path->word);
		if(nc + mc >= sizeof file - 1)	/* 1 for / */
			continue;
		if(nc > 0){
			memmove(file, path->word, nc);
			file[nc++] = '/';
		}
		memmove(file+nc, argv[1], mc);
		pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
		if(pid >= 0){
			free(argv);
			return pid;
		}
	}
	free(argv);
	return -1;
}