Пример #1
0
extern void *erealloc(void *p, size_t n) {
	extern void *realloc(void *, size_t);
	if ((p = realloc(p, n)) == NULL) {
		uerror("realloc");
		rc_exit(1);
	}
	return p;
}
Пример #2
0
extern void *ealloc(size_t n) {
	extern void *malloc(size_t);
	void *p = malloc(n);
	if (p == NULL) {
		uerror("malloc");
		rc_exit(1);
	}
	return p;
}
Пример #3
0
extern char *which(char *name, bool verbose) {
	static char *test = NULL;
	static size_t testlen = 0;
	List *path;
	int len;
	if (name == NULL)	/* no filename? can happen with "> foo" as a command */
		return NULL;
	if (!initialized) {
		initialized = TRUE;
		uid = geteuid();
		gid = getegid();
#if HAVE_GETGROUPS
#if HAVE_POSIX_GETGROUPS
		ngroups = getgroups(0, (GETGROUPS_T *)0);
		if (ngroups < 0) {
			uerror("getgroups");
			rc_exit(1);
		}
#else
		ngroups = NGROUPS;
#endif
		if (ngroups) {	
			gidset = ealloc(ngroups * sizeof(GETGROUPS_T));
			getgroups(ngroups, gidset);
		}
#endif
	}
	if (isabsolute(name)) /* absolute pathname? */
		return rc_access(name, verbose) ? name : NULL;
	len = strlen(name);
	for (path = varlookup("path"); path != NULL; path = path->n) {
		size_t need = strlen(path->w) + len + 2; /* one for null terminator, one for the '/' */
		if (testlen < need) {
			efree(test);
			test = ealloc(testlen = need);
		}
		if (*path->w == '\0') {
			strcpy(test, name);
		} else {
			strcpy(test, path->w);
			if (!streq(test, "/")) /* "//" is special to POSIX */
				strcat(test, "/");
			strcat(test, name);
		}
		if (rc_access(test, FALSE))
			return test;
	}
	if (verbose) {
		char *n = protect(name);
		fprint(2, RC "cannot find `%s'\n", n);
		efree(n);
	}
	return NULL;
}
Пример #4
0
extern void statprint(int pid, int i) {
	if (i & 0xff) {
		char *msg = ((i & 0x7f) < NUMOFSIGNALS ? signals[i & 0x7f].msg : "");
		if (pid != -1)
			fprint(2, "%d: ", pid);
		if (i & 0x80) {
			if (*msg == '\0')
				fprint(2, "core dumped\n");
			else
				fprint(2, "%s--core dumped\n", msg);
		} else if (*msg != '\0')
			fprint(2, "%s\n", msg);
	}
	if (i != 0 && dashee && !cond)
		rc_exit(getstatus());
}
Пример #5
0
extern void rc_raise(ecodes e) {
	if (e == eError && rc_pid != getpid())
		exit(1); /* child processes exit on an error/signal */
	for (; estack != NULL; estack = estack->prev)
		if (estack->e != e) {
			if (e == eBreak && estack->e != eArena && estack->e != eVarstack)
				rc_error("break outside of loop");
			else if (e == eReturn && estack->e == eError) /* can return from loops inside functions */
				rc_error("return outside of function");
			switch (estack->e) {
			default:
				break;
			case eVarstack:
				varrm(estack->data.name, TRUE);
				break;
			case eArena:
				restoreblock(estack->data.b);
				break;
			case eFifo:
				unlink(estack->data.name);
				break;
			case eFd:
				close(estack->data.fd);
				break;
			}
		} else {
			if (e == eError && !estack->interactive) {
				popinput();
			} else {
				Jbwrap *j = estack->data.jb;

				interactive = estack->interactive;
				estack = estack->prev;
				siglongjmp(j->j, 1);
			}
		}
	rc_exit(1); /* top of exception stack */
}
Пример #6
0
extern int main(int argc, char *argv[], char *envp[]) {
	char *dashsee[2], *dollarzero, *null[1];
	int c;
	initprint();
	dashsee[0] = dashsee[1] = NULL;
	dollarzero = argv[0];
	rc_pid = getpid();
	dashell = (*argv[0] == '-'); /* Unix tradition */
	while ((c = rc_getopt(argc, argv, "c:deiIlnopsvx")) != -1)
		switch (c) {
		case 'c':
			dashsee[0] = rc_optarg;
			goto quitopts;
		case 'd':
			dashdee = TRUE;
			break;
		case 'e':
			dashee = TRUE;
			break;
		case 'I':
			dashEYE = TRUE;
			interactive = FALSE;
			break;
		case 'i':
			dasheye = interactive = TRUE;
			break;
		case 'l':
			dashell = TRUE;
			break;
		case 'n':
			dashen = TRUE;
			break;
		case 'o':
			dashoh = TRUE;
			break;
		case 'p':
			dashpee = TRUE;
			break;
		case 's':
			dashess = TRUE;
			break;
		case 'v':
			dashvee = TRUE;
			break;
		case 'x':
			dashex = TRUE;
			break;
		case '?':
			exit(1);
		}
quitopts:
	argv += rc_optind;
	/* use isatty() iff neither -i nor -I is set, and iff the input is not from a script or -c flags */
	if (!dasheye && !dashEYE && dashsee[0] == NULL && (dashess || *argv == NULL))
		interactive = isatty(0);
	if (!dashoh) {
		checkfd(0, rFrom);
		checkfd(1, rCreate);
		checkfd(2, rCreate);
	}
	initsignal();
	inithash();
	initparse();
	assigndefault("ifs", " ", "\t", "\n", (void *)0);
#ifdef DEFAULTPATH
	assigndefault("path", DEFAULTPATH, (void *)0);
#endif
	assigndefault("pid", nprint("%d", rc_pid), (void *)0);
	assigndefault("prompt", "; ", "", (void *)0);
	assigndefault("version", VERSION, "$Release: @(#)" PACKAGE " " VERSION " " RELDATE " $", (void *)0);
	initenv(envp);
	initinput();
	null[0] = NULL;
	starassign(dollarzero, null, FALSE); /* assign $0 to $* */
	inithandler();

	if (dashell) {
		char *rcrc;
		int fd;

		rcrc = concat(varlookup("home"), word("/.rcrc", NULL))->w;
		fd = rc_open(rcrc, rFrom);
		if (fd == -1) {
			if (errno != ENOENT)
				uerror(rcrc);
		} else {
			bool push_interactive;

			pushfd(fd);
			push_interactive = interactive;
			interactive = FALSE;
			doit(TRUE);
			interactive = push_interactive;
			close(fd);
		}
	}

	if (dashsee[0] != NULL || dashess) {	/* input from  -c or -s? */
		if (*argv != NULL)
			starassign(dollarzero, argv, FALSE);
		if (dashess)
			pushfd(0);
		else
			pushstring(dashsee, TRUE);
	} else if (*argv != NULL) {	/* else from a file? */
		b_dot(--argv);
		rc_exit(getstatus());
	} else {			/* else stdin */
		pushfd(0);
	}
	dasheye = FALSE;
	doit(TRUE);
	rc_exit(getstatus());
	return 0; /* Never really reached. */
}
Пример #7
0
extern void exec(List *s, bool parent) {
	char **av, **ev = NULL;
	int pid, stat;
	builtin_t *b;
	char *path = NULL;
	bool didfork, returning, saw_exec, saw_builtin;
	av = list2array(s, dashex);
	saw_builtin = saw_exec = FALSE;
	do {
		if (*av == NULL	|| isabsolute(*av))
			b = NULL;
		else if (!saw_builtin && fnlookup(*av) != NULL)
			b = funcall;
		else
			b = isbuiltin(*av);

		/*
		   a builtin applies only to the immmediately following
		   command, e.g., builtin exec echo hi
		*/
		saw_builtin = FALSE;

		if (b == b_exec) {
			av++;
			saw_exec = TRUE;
			parent = FALSE;
		} else if (b == b_builtin) {
			av++;
			saw_builtin = TRUE;
		}
	} while (b == b_exec || b == b_builtin);
	if (*av == NULL && saw_exec) { /* do redirs and return on a null exec */
		doredirs();
		return;
	}
	/* force an exit on exec with any rc_error, but not for null commands as above */
	if (saw_exec)
		rc_pid = -1;
	if (b == NULL) {
		path = which(*av, TRUE);
		if (path == NULL && *av != NULL) { /* perform null commands for redirections */
			set(FALSE);
			redirq = NULL;
			if (parent)
				return;
			rc_exit(1);
		}
		ev = makeenv(); /* environment only needs to be built for execve() */
	}
	/*
	   If parent & the redirq is nonnull, builtin or not it has to fork.
	   If the fifoq is nonnull, then it must be emptied at the end so we
	   must fork no matter what.
	 */
	if ((parent && (b == NULL || redirq != NULL)) || outstanding_cmdarg()) {
		pid = rc_fork();
		didfork = TRUE;
	} else {
		pid = 0;
		didfork = FALSE;
	}
	returning = (!didfork && parent);
	switch (pid) {
	case -1:
		uerror("fork");
		rc_error(NULL);
		/* NOTREACHED */
	case 0:
		if (!returning)
			setsigdefaults(FALSE);
		pop_cmdarg(FALSE);
		doredirs();

		/* null commands performed for redirections */
		if (*av == NULL || b != NULL) {
			if (b != NULL)
				(*b)(av);
			if (returning)
				return;
			rc_exit(getstatus());
		}
		execve(path, (char * const *) av, (char * const *) ev);
		uerror(*av);
		rc_exit(1);
		/* NOTREACHED */
	default:
		redirq = NULL;
		rc_wait4(pid, &stat, TRUE);
		setstatus(-1, stat);
		if ((stat & 0xff) == 0)
			nl_on_intr = FALSE;
		SIGCHK;
		nl_on_intr = TRUE;
		pop_cmdarg(TRUE);
	}
}
Пример #8
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();
}
Пример #9
0
static void b_exit(char **av) {
	if (*++av != NULL)
		ssetstatus(av);
	rc_exit(getstatus());
}