Esempio n. 1
0
static void dopipe(Node *n) {
	int i, j, sp, pid, fd_prev, fd_out, pids[512], stats[512], p[2];
	bool intr;
	Node *r;

	fd_prev = fd_out = 1;
	for (r = n, i = 0; r != NULL && r->type == nPipe; r = r->u[2].p, i++) {
		if (i > 500) /* the only hard-wired limit in rc? */
			rc_error("pipe too long");
		if (pipe(p) < 0) {
			uerror("pipe");
			rc_error(NULL);
		}
		if ((pid = rc_fork()) == 0) {
			setsigdefaults(FALSE);
			redirq = NULL; /* clear preredir queue */
			mvfd(p[0], r->u[1].i);
			if (fd_prev != 1)
				mvfd(fd_prev, fd_out);
			close(p[1]);
			walk(r->u[3].p, FALSE);
			exit(getstatus());
		}
		if (fd_prev != 1)
			close(fd_prev); /* parent must close all pipe fd's */
		pids[i] = pid;
		fd_prev = p[1];
		fd_out = r->u[0].i;
		close(p[0]);
	}
	if ((pid = rc_fork()) == 0) {
		setsigdefaults(FALSE);
		mvfd(fd_prev, fd_out);
		walk(r, FALSE);
		exit(getstatus());
		/* NOTREACHED */
	}
	redirq = NULL; /* clear preredir queue */
	close(fd_prev);
	pids[i++] = pid;

	/* collect statuses */

	intr = FALSE;
	for (j = 0; j < i; j++) {
		rc_wait4(pids[j], &sp, TRUE);
		stats[j] = sp;
		intr |= (sp == SIGINT);
	}
	setpipestatus(stats, i);
	sigchk();
}
Esempio n. 2
0
File: glom.c Progetto: muennich/rc3
static List *mkcmdarg(Node *n) {
	int fd;
	char *name;
	Edata efifo;
	Estack *e = enew(Estack);
	List *ret = nnew(List);
	static int fifonumber = 0;

	name = nprint("/tmp/rc%d.%d", getpid(), fifonumber++);
	if (mkfifo(name, 0666) < 0) {
		uerror("mkfifo");
		return NULL;
	}
	if (rc_fork() == 0) {
		setsigdefaults(FALSE);
		fd = rc_open(name, (n->u[0].i != rFrom) ? rFrom : rCreate); /* stupid hack */
		if (fd < 0) {
			uerror("open");
			exit(1);
		}
		if (mvfd(fd, (n->u[0].i == rFrom)) < 0) /* same stupid hack */
			exit(1);
		redirq = NULL;
		walk(n->u[2].p, FALSE);
		exit(getstatus());
	}
	efifo.name = name;
	except(eFifo, efifo, e);
	ret->w = name;
	ret->m = NULL;
	ret->n = NULL;
	return ret;
}
Esempio n. 3
0
File: glom.c Progetto: muennich/rc3
static List *mkcmdarg(Node *n) {
	char *name;
	List *ret = nnew(List);
	Estack *e = nnew(Estack);
	Edata efd;
	int p[2];
	if (pipe(p) < 0) {
		uerror("pipe");
		return NULL;
	}
	if (rc_fork() == 0) {
		setsigdefaults(FALSE);
		if (mvfd(p[n->u[0].i == rFrom], n->u[0].i == rFrom) < 0) /* stupid hack */
			exit(1);
		close(p[n->u[0].i != rFrom]);
		redirq = NULL;
		walk(n->u[2].p, FALSE);
		exit(getstatus());
	}

#if HAVE_DEV_FD
	name = nprint("/dev/fd/%d", p[n->u[0].i != rFrom]);
#else
	name = nprint("/proc/self/fd/%d", p[n->u[0].i != rFrom]);
#endif

	efd.fd = p[n->u[0].i != rFrom];
	except(eFd, efd, e);
	close(p[n->u[0].i == rFrom]);
	ret->w = name;
	ret->m = NULL;
	ret->n = NULL;
	return ret;
}
Esempio n. 4
0
File: glom.c Progetto: muennich/rc3
static List *backq(Node *ifs, Node *n) {
	int p[2], sp;
	pid_t pid;
	List *bq;
	struct termios t;
	if (n == NULL)
		return NULL;
	if (pipe(p) < 0) {
		uerror("pipe");
		rc_error(NULL);
	}
	if (interactive)
		tcgetattr(0, &t);
	if ((pid = rc_fork()) == 0) {
		mvfd(p[1], 1);
		close(p[0]);
		redirq = NULL;
		walk(n, FALSE);
		exit(getstatus());
	}
	close(p[1]);
	bq = bqinput(glom(ifs), p[0]);
	close(p[0]);
	rc_wait4(pid, &sp, TRUE);
	if (interactive && WIFSIGNALED(sp))
		tcsetattr(0, TCSANOW, &t);
	statprint(-1, sp);
	varassign("bqstatus", word(strstatus(sp), NULL), FALSE);
	sigchk();
	return bq;
}
Esempio n. 5
0
extern void doredirs() {
	List *fname;
	int fd, p[2];
	Rq *r;
	for (r = redirq; r != NULL; r = r->n) {
		switch(r->r->type) {
		default:
			panic("unexpected node in doredirs");
			/* NOTREACHED */
		case nRedir:
			if (r->r->u[0].i == rHerestring) {
				fname = flatten(glom(r->r->u[2].p)); /* fname is really a string */
				if (pipe(p) < 0) {
					uerror("pipe");
					rc_error(NULL);
				}
				if (rc_fork() == 0) { /* child writes to pipe */
					setsigdefaults(FALSE);
					close(p[0]);
					if (fname != NULL)
						writeall(p[1], fname->w, strlen(fname->w));
					exit(0);
				} else {
					close(p[1]);
					if (mvfd(p[0], r->r->u[1].i) < 0)
						rc_error(NULL);
				}
			} else {
				fname = glob(glom(r->r->u[2].p));
				if (fname == NULL)
					rc_error("null filename in redirection");
				if (fname->n != NULL)
					rc_error("multi-word filename in redirection");
				switch (r->r->u[0].i) {
				default:
					panic("unexpected node in doredirs");
					/* NOTREACHED */
				case rCreate: case rAppend: case rFrom:
					fd = rc_open(fname->w, r->r->u[0].i);
					break;
				}
				if (fd < 0) {
					uerror(fname->w);
					rc_error(NULL);
				}
				if (mvfd(fd, r->r->u[1].i) < 0)
					rc_error(NULL);
			}
			break;
		case nDup:
			if (r->r->u[2].i == -1)
				close(r->r->u[1].i);
			else if (r->r->u[2].i != r->r->u[1].i) {
				if (dup2(r->r->u[2].i, r->r->u[1].i) < 0) {
					uerror("dup2");
					rc_error(NULL);
				}
			}
		}
	}
	redirq = NULL;
}
Esempio n. 6
0
extern bool walk(Node *n, bool parent) {
top:	sigchk();
	if (n == NULL) {
		if (!parent)
			exit(0);
		set(TRUE);
		return TRUE;
	}
	switch (n->type) {
	case nArgs: case nBackq: case nConcat: case nCount:
	case nFlat: case nLappend: case nRedir: case nVar:
	case nVarsub: case nWord:
		exec(glob(glom(n)), parent);	/* simple command */
		break;
	case nBody:
		walk(n->u[0].p, TRUE);
		WALK(n->u[1].p, parent);
		/* WALK doesn't fall through */
	case nNowait: {
		int pid;
		if ((pid = rc_fork()) == 0) {
#if defined(RC_JOB) && defined(SIGTTOU) && defined(SIGTTIN) && defined(SIGTSTP)
			setsigdefaults(FALSE);
			rc_signal(SIGTTOU, SIG_IGN);	/* Berkeleyized version: put it in a new pgroup. */
			rc_signal(SIGTTIN, SIG_IGN);
			rc_signal(SIGTSTP, SIG_IGN);
			setpgid(0, getpid());
#else
			setsigdefaults(TRUE);		/* ignore SIGINT, SIGQUIT, SIGTERM */
#endif
			mvfd(rc_open("/dev/null", rFrom), 0);
			walk(n->u[0].p, FALSE);
			exit(getstatus());
		}
		if (interactive)
			fprint(2, "%d\n", pid);
		varassign("apid", word(nprint("%d", pid), NULL), FALSE);
		redirq = NULL; /* kill pre-redir queue */
		break;
	}
	case nAndalso: {
		bool oldcond = cond;
		cond = TRUE;
		if (walk(n->u[0].p, TRUE)) {
			cond = oldcond;
			WALK(n->u[1].p, parent);
		} else
			cond = oldcond;
		break;
	}
	case nOrelse: {
		bool oldcond = cond;
		cond = TRUE;
		if (!walk(n->u[0].p, TRUE)) {
			cond = oldcond;
			WALK(n->u[1].p, parent);
		} else
			cond = oldcond;
		break;
	}
	case nBang:
		set(!walk(n->u[0].p, TRUE));
		break;
	case nIf: {
		bool oldcond = cond;
		Node *true_cmd = n->u[1].p, *false_cmd = NULL;
		if (true_cmd != NULL && true_cmd->type == nElse) {
			false_cmd = true_cmd->u[1].p;
			true_cmd = true_cmd->u[0].p;
		}
		cond = TRUE;
		if (!walk(n->u[0].p, TRUE))
			true_cmd = false_cmd; /* run the else clause */
		cond = oldcond;
		WALK(true_cmd, parent);
	}
	case nWhile: {
		Jbwrap j;
		Edata jbreak;
		Estack e1, e2;
		bool testtrue, oldcond = cond;
		cond = TRUE;
		if (!walk(n->u[0].p, TRUE)) { /* prevent spurious breaks inside test */
			cond = oldcond;
			break;
		}
		if (sigsetjmp(j.j, 1))
			break;
		jbreak.jb = &j;
		except(eBreak, jbreak, &e1);
		do {
			Edata block;
			block.b = newblock();
			cond = oldcond;
			except(eArena, block, &e2);
			walk(n->u[1].p, TRUE);
			testtrue = walk(n->u[0].p, TRUE);
			unexcept(); /* eArena */
			cond = TRUE;
		} while (testtrue);
		cond = oldcond;
		unexcept(); /* eBreak */
		break;
	}
	case nForin: {
		List *l, *var = glom(n->u[0].p);
		Jbwrap j;
		Estack e1, e2;
		Edata jbreak;
		if (sigsetjmp(j.j, 1))
			break;
		jbreak.jb = &j;
		except(eBreak, jbreak, &e1);
		for (l = listcpy(glob(glom(n->u[1].p)), nalloc); l != NULL; l = l->n) {
			Edata block;
			assign(var, word(l->w, NULL), FALSE);
			block.b = newblock();
			except(eArena, block, &e2);
			walk(n->u[2].p, TRUE);
			unexcept(); /* eArena */
		}
		unexcept(); /* eBreak */
		break;
	}
	case nSubshell:
		if (dofork(TRUE)) {
			setsigdefaults(FALSE);
			walk(n->u[0].p, FALSE);
			rc_exit(getstatus());
		}
		break;
	case nAssign:
		if (n->u[0].p == NULL)
			rc_error("null variable name");
		assign(glom(n->u[0].p), glob(glom(n->u[1].p)), FALSE);
		set(TRUE);
		break;
	case nPipe:
		dopipe(n);
		break;
	case nNewfn: {
		List *l = glom(n->u[0].p);
		if (l == NULL)
			rc_error("null function name");
		while (l != NULL) {
			if (dashex)
				prettyprint_fn(2, l->w, n->u[1].p);
			fnassign(l->w, n->u[1].p);
			l = l->n;
		}
		set(TRUE);
		break;
	}
	case nRmfn: {
		List *l = glom(n->u[0].p);
		while (l != NULL) {
			if (dashex)
				fprint(2, "fn %S\n", l->w);
			fnrm(l->w);
			l = l->n;
		}
		set(TRUE);
		break;
	}
	case nDup:
		redirq = NULL;
		break; /* Null command */
	case nMatch: {
		List *a = glob(glom(n->u[0].p)), *b = glom(n->u[1].p);
		if (dashex)
			fprint(2, (a != NULL && a->n != NULL) ? "~ (%L) %L\n" : "~ %L %L\n", a, " ", b, " ");
		set(lmatch(a, b));
		break;
	}
	case nSwitch: {
		List *v = glom(n->u[0].p);
		while (1) {
			do {
				n = n->u[1].p;
				if (n == NULL)
					return istrue();
			} while (n->u[0].p == NULL || n->u[0].p->type != nCase);
			if (lmatch(v, glom(n->u[0].p->u[0].p))) {
				for (n = n->u[1].p; n != NULL && (n->u[0].p == NULL || n->u[0].p->type != nCase); n = n->u[1].p)
					walk(n->u[0].p, TRUE);
				break;
			}
		}
		break;
	}
	case nPre: {
		List *v;
		if (n->u[0].p->type == nRedir || n->u[0].p->type == nDup) {
			if (redirq == NULL && !dofork(parent)) /* subshell on first preredir */
				break;
			setsigdefaults(FALSE);
			qredir(n->u[0].p);
			if (!haspreredir(n->u[1].p))
				doredirs(); /* no more preredirs, empty queue */
			walk(n->u[1].p, FALSE);
			rc_exit(getstatus());
			/* NOTREACHED */
		} else if (n->u[0].p->type == nAssign) {
			if (isallpre(n->u[1].p)) {
				walk(n->u[0].p, TRUE);
				WALK(n->u[1].p, parent);
			} else {
				Estack e;
				Edata var;
				v = glom(n->u[0].p->u[0].p);
				assign(v, glob(glom(n->u[0].p->u[1].p)), TRUE);
				var.name = v->w;
				except(eVarstack, var, &e);
				walk(n->u[1].p, parent);
				varrm(v->w, TRUE);
				unexcept(); /* eVarstack */
			}
		} else
			panic("unexpected node in preredir section of walk");
		break;
	}
	case nBrace:
		if (n->u[1].p == NULL) {
			WALK(n->u[0].p, parent);
		} else if (dofork(parent)) {
			setsigdefaults(FALSE);
			walk(n->u[1].p, TRUE); /* Do redirections */
			redirq = NULL;   /* Reset redirection queue */
			walk(n->u[0].p, FALSE); /* Do commands */
			rc_exit(getstatus());
			/* NOTREACHED */
		}
		break;
	case nEpilog:
		qredir(n->u[0].p);
		if (n->u[1].p != NULL) {
			WALK(n->u[1].p, parent); /* Do more redirections. */
		} else {
			doredirs();	/* Okay, we hit the bottom. */
		}
		break;
	case nNmpipe:
		rc_error("named pipes cannot be executed as commands");
		/* NOTREACHED */
	default:
		panic("unknown node in walk");
		/* NOTREACHED */
	}
	return istrue();
}