Beispiel #1
0
/*
 * Print termination report for process tp according to signal s.
 * Return a value of 128 + signal s (e) for exit status of tp.
 */
static int
prsig(int s, pid_t tp, pid_t cp)
{
	int e, r;
	char buf[SBUFMM(1)];
	const char *c, *m;

	e = WTERMSIG(s);
	if (e >= NSIGMSG || (e >= 0 && *sigmsg[e] != EOS)) {
		if (e < NSIGMSG)
			m = sigmsg[e];
		else {
			r = snprintf(buf, sizeof(buf), "Sig %u", (unsigned)e);
			m = (r < 0 || r >= (int)sizeof(buf))  ?
			    "prsig: snprintf: Internal error" :
			    buf;
		}
		c = "";
#ifdef	WCOREDUMP
		if (WCOREDUMP(s) != 0)
			c = sigmsg[0];
#endif
		if (tp != cp)
			fd_print(FD2, "%u: %s%s\n", (unsigned)tp, m, c);
		else
			fd_print(FD2, "%s%s\n", m, c);
	} else
		fd_print(FD2, FMT1S, "");

	return 128 + e;
}
Beispiel #2
0
static char *
gcat(const char *src1, const char *src2)
{
	size_t siz;
	char *b, buf[PATHMAX], c, *dst;
	const char *s;

	*buf = EOS;
	b = buf;
	s = src1;
	while ((c = *s++) != EOS) {
		if (b >= &buf[PATHMAX - 1])
			err(SH_ERR, FMT1S, strerror(ENAMETOOLONG));
		if ((c &= ASCII) == EOS) {
			*b++ = SLASH;
			break;
		}
		*b++ = c;
	}

	s = src2;
	do {
		if (b >= &buf[PATHMAX])
			err(SH_ERR, FMT1S, strerror(ENAMETOOLONG));
		*b++ = c = *s++;
	} while (c != EOS);
	b--;

	siz = (b - buf) + 1;
	gavtot += siz;
	if (gavtot > GAVMAX)
		err(SH_ERR, FMT1S, ERR_E2BIG);
#ifdef	DEBUG
#ifdef	DEBUG_GLOB
	fd_print(FD2, "gcat: siz == %zu, (%p < %p) == %s;\n",
	    siz, b, &buf[PATHMAX], (b < &buf[PATHMAX]) ? "true" : "false");
	fd_print(FD2, "    : strlen(buf) == %zu;\n", strlen(buf));
#endif
#endif
	if ((dst = malloc(siz)) == NULL) {
		err(SH_ERR, FMT1S, ERR_NOMEM);
		/*NOTREACHED*/
	}

	(void)memcpy(dst, buf, siz);
	return dst;
}
Beispiel #3
0
/*
 * NAME
 *	sh6 - shell (command interpreter)
 *
 * SYNOPSIS
 *	sh6 [- | -c [string] | -t | file [arg1 ...]]
 *
 * DESCRIPTION
 *	See the sh6(1) manual page for full details.
 */
int
main(int argc, char **argv)
{
	bool dosigs = false;

	sh_init(argv[0]);
	if (argv[0] == NULL || *argv[0] == EOS)
		err(SH_ERR, FMT1S, ERR_ALINVAL);
	if (fd_isdir(FD0))
		goto done;

	if (argc > 1) {
		name = argv[1];
		dolv = &argv[1];
		dolc = argc - 1;
		if (*argv[1] == HYPHEN) {
			dosigs = true;
			if (argv[1][1] == 'c' && argc > 2) {
				dolv  += 1;
				dolc  -= 1;
				argv2p = argv[2];
			} else if (argv[1][1] == 't')
				one_line_flag = 2;
		} else {
			(void)close(FD0);
			if (open(argv[1], O_RDONLY) != FD0)
				err(SH_ERR, FMT2S, argv[1], ERR_OPEN);
			if (fd_isdir(FD0))
				goto done;
		}
	} else {
		dosigs = true;
		if (isatty(FD0) != 0 && isatty(FD2) != 0)
			prompt = (geteuid() != 0) ? "% " : "# ";
	}
	if (dosigs) {
		if (sasignal(SIGINT, SIG_IGN) == SIG_DFL)
			sig_child |= S_SIGINT;
		if (sasignal(SIGQUIT, SIG_IGN) == SIG_DFL)
			sig_child |= S_SIGQUIT;
		if (prompt != NULL)
			if (sasignal(SIGTERM, SIG_IGN) == SIG_DFL)
				sig_child |= S_SIGTERM;
	}
	fd_free();
	sh_magic();

loop:
	if (prompt != NULL)
		fd_print(FD2, "%s", prompt);
	rpx_line();
	goto loop;

done:
	return status;
}
Beispiel #4
0
/*
 * Convert a string value into an int integer value.
 */
bool
strtoint(const char *string, int *integer)
{
	long lint;
	char *lintbad;
	const char *name;

	name = getmyname();

	/*
	 * Fail if the specified string or integer is (or points to) NULL.
	 */
	errno = 0;
	if (string == NULL || integer == NULL) {
		errno = EINVAL;
		fd_print(FD2, FMT3S, name, "strtoint", strerror(errno));
		if (integer != NULL)
			*integer = 0;
		return false;
	}

	lint = strtol(string, &lintbad, 10);
	if (*string == EOS || *lintbad != EOS) {
		errno = EINVAL;
		if (EQUAL(name, "if"))
			fd_print(FD2, FMT3S, name, string, ERR_NOTINTEGER);
		*integer = 0;
		return false;
	}
	if ((errno == ERANGE  && (lint == LONG_MAX || lint == LONG_MIN)) ||
	    (lint  >  INT_MAX ||  lint <  INT_MIN)) {
		errno = ERANGE;
		if (EQUAL(name, "if"))
			fd_print(FD2, FMT3S, name, string, ERR_RANGE);
		*integer = 0;
		return false;
	}
	*integer = (int)lint;
	return true;
}
Beispiel #5
0
/*
 * Handle all error exit scenarios for the shell.  This includes
 * setting the exit status to the appropriate value according to
 * es and causing the shell to exit if appropriate.  This function
 * is called by err() and may or may not return.
 */
static void
sh_errexit(int es)
{

#ifdef	DEBUG
	fd_print(FD2,"sh_errexit: getmypid() == %d, es == %d;\n",getmypid(),es);
#endif

	status = es;
	if (prompt == NULL) {
		(void)lseek(FD0, (off_t)0, SEEK_END);
		EXIT(status);
	}
	if (getpid() != getmypid())
		_exit(status);
}
Beispiel #6
0
/*
 * Execute the shell command tree pointed to by t.
 */
static void
execute(struct tnode *t, int *pin, int *pout)
{
	struct tnode *t1;
	enum tnflags f;
	pid_t cpid;
	int i, pfd[2];
	const char **gav;
	const char *cmd, *p;

	if (t == NULL)
		return;
	switch (t->ntype) {
	case TLIST:
		f = t->nflags & (FFIN | FPIN | FINTR);
		if ((t1 = t->nleft) != NULL)
			t1->nflags |= f;
		execute(t1, NULL, NULL);
		if ((t1 = t->nright) != NULL)
			t1->nflags |= f;
		execute(t1, NULL, NULL);
		return;

	case TPIPE:
		if (pipe(pfd) == -1) {
			err(SH_ERR, FMT1S, ERR_PIPE);
			if (pin != NULL) {
				(void)close(pin[0]);
				(void)close(pin[1]);
			}
			return;
		}
		f = t->nflags;
		if ((t1 = t->nleft) != NULL)
			t1->nflags |= FPOUT | (f & (FFIN|FPIN|FINTR|FPRS));
		execute(t1, pin, pfd);
		if ((t1 = t->nright) != NULL)
			t1->nflags |= FPIN | (f & (FAND|FPOUT|FINTR|FPRS));
		execute(t1, pfd, pout);
		(void)close(pfd[0]);
		(void)close(pfd[1]);
		return;

	case TCOMMAND:
		if (t->nav == NULL || t->nav[0] == NULL) {
			/* should never (but can) be true */
			err(SH_ERR, FMT1S, "execute: Invalid command");
			return;
		}
		cmd = t->nav[0];
		if (EQUAL(cmd, ":")) {
			status = SH_TRUE;
			return;
		}
		if (EQUAL(cmd, "chdir")) {
			ascan(t->nav[1], &trim);
			if (t->nav[1] == NULL)
				err(SH_ERR, FMT2S, cmd, ERR_ARGCOUNT);
			else if (chdir(t->nav[1]) == -1)
				err(SH_ERR, FMT2S, cmd, ERR_BADDIR);
			else
				status = SH_TRUE;
			return;
		}
		if (EQUAL(cmd, "exit")) {
			if (prompt == NULL) {
				(void)lseek(FD0, (off_t)0, SEEK_END);
				EXIT(status);
			}
			return;
		}
		if (EQUAL(cmd, "login") || EQUAL(cmd, "newgrp")) {
			if (prompt != NULL) {
				p = (*cmd == 'l') ? PATH_LOGIN : PATH_NEWGRP;
				vscan(t->nav, &trim);
				(void)sasignal(SIGINT, SIG_DFL);
				(void)sasignal(SIGQUIT, SIG_DFL);
				(void)pexec(p, (char *const *)t->nav);
				(void)sasignal(SIGINT, SIG_IGN);
				(void)sasignal(SIGQUIT, SIG_IGN);
			}
			err(SH_ERR, FMT2S, cmd, ERR_EXEC);
			return;
		}
		if (EQUAL(cmd, "shift")) {
			if (dolc > 1) {
				dolv = &dolv[1];
				dolc--;
				status = SH_TRUE;
				return;
			}
			err(SH_ERR, FMT2S, cmd, ERR_NOARGS);
			return;
		}
		if (EQUAL(cmd, "wait")) {
			pwait(-1);
			return;
		}
		/*FALLTHROUGH*/

	case TSUBSHELL:
		f = t->nflags;
		if ((cpid = ((f & FNOFORK) != 0) ? 0 : fork()) == -1) {
			err(SH_ERR, FMT1S, ERR_FORK);
			return;
		}
		/**** Parent! ****/
		if (cpid != 0) {
			if (pin != NULL && (f & FPIN) != 0) {
				(void)close(pin[0]);
				(void)close(pin[1]);
			}
			if ((f & FPRS) != 0)
				fd_print(FD2, "%u\n", (unsigned)cpid);
			if ((f & FAND) != 0)
				return;
			if ((f & FPOUT) == 0)
				pwait(cpid);
			return;
		}
		/**** Child! ****/
		/*
		 * Redirect (read) input from pipe.
		 */
		if (pin != NULL && (f & FPIN) != 0) {
			if (dup2(pin[0], FD0) == -1)
				err(FC_ERR, FMT1S, strerror(errno));
			(void)close(pin[0]);
			(void)close(pin[1]);
		}
		/*
		 * Redirect (write) output to pipe.
		 */
		if (pout != NULL && (f & FPOUT) != 0) {
			if (dup2(pout[1], FD1) == -1)
				err(FC_ERR, FMT1S, strerror(errno));
			(void)close(pout[0]);
			(void)close(pout[1]);
		}
		/*
		 * Redirect (read) input from file.
		 */
		if (t->nfin != NULL && (f & FPIN) == 0) {
			f |= FFIN;
			ascan(t->nfin, &trim);
			if ((i = open(t->nfin, O_RDONLY)) == -1)
				err(FC_ERR, FMT2S, t->nfin, ERR_OPEN);
			if (dup2(i, FD0) == -1)
				err(FC_ERR, FMT1S, strerror(errno));
			(void)close(i);
		}
		/*
		 * Redirect (write) output to file.
		 */
		if (t->nfout != NULL && (f & FPOUT) == 0) {
			if ((f & FCAT) != 0)
				i = O_WRONLY | O_APPEND | O_CREAT;
			else
				i = O_WRONLY | O_TRUNC | O_CREAT;
			ascan(t->nfout, &trim);
			if ((i = open(t->nfout, i, 0666)) == -1)
				err(FC_ERR, FMT2S, t->nfout, ERR_CREATE);
			if (dup2(i, FD1) == -1)
				err(FC_ERR, FMT1S, strerror(errno));
			(void)close(i);
		}
		/*
		 * Set the action for the SIGINT and SIGQUIT signals, and
		 * redirect input for `&' commands from `/dev/null' if needed.
		 */
		if ((f & FINTR) != 0) {
			(void)sasignal(SIGINT, SIG_IGN);
			(void)sasignal(SIGQUIT, SIG_IGN);
			if (t->nfin == NULL && (f & (FFIN|FPIN|FPRS)) == FPRS) {
				(void)close(FD0);
				if (open("/dev/null", O_RDONLY) != FD0)
					err(FC_ERR,FMT2S,"/dev/null",ERR_OPEN);
			}
		} else {
			if ((sig_child & S_SIGINT) != 0)
				(void)sasignal(SIGINT, SIG_DFL);
			if ((sig_child & S_SIGQUIT) != 0)
				(void)sasignal(SIGQUIT, SIG_DFL);
		}
		/* Set the SIGTERM signal to its default action if needed. */
		if ((sig_child & S_SIGTERM) != 0)
			(void)sasignal(SIGTERM, SIG_DFL);
		if (t->ntype == TSUBSHELL) {
			if ((t1 = t->nsub) != NULL)
				t1->nflags |= (f & (FFIN | FPIN | FINTR));
			execute(t1, NULL, NULL);
			_exit(status);
		}
		glob_flag = false;
		vscan(t->nav, &tglob);
		if (glob_flag) {
			for (i = 0; t->nav[i] != NULL; i++)
				;	/* nothing */
#ifdef	DEBUG
#ifdef	DEBUG_GLOB
			fd_print(FD2, "execute:  i      == %2d;\n", i);
			fd_print(FD2, "       : (i + 2) == %2d;\n", (i + 2));
			fd_print(FD2, "       : (i + 1) == %2d;\n", (i + 1));
#endif
#endif
			gav = xmalloc((i + 2) * sizeof(char *));
			gav[0] = "glob6";
			cmd = gav[0];
			(void)memcpy(&gav[1], t->nav, (i + 1) * sizeof(char *));
#ifdef	DEBUG
#ifdef	DEBUG_GLOB
			for (i = 0; gav[i] != NULL; i++)
				fd_print(FD2, "       : gav[%2d] == %s;\n",
				    i, gav[i]);
			fd_print(FD2, "       : gav[%2d] == NULL;\n", i);
#endif
#endif
			(void)err_pexec(cmd, (char *const *)gav);
		} else {
			vscan(t->nav, &trim);
			cmd = t->nav[0];
			(void)err_pexec(cmd, (char *const *)t->nav);
		}
		/*NOTREACHED*/
	}
}
Beispiel #7
0
/*
 * Execute a file or path name w/ error handling.
 * This function never returns.
 */
void
err_pexec(const char *file, char *const *argv)
{
	long l;
	const char *f, *n;

	(void)pexec(file, argv);
#ifdef	DEBUG
	fd_print(FD2, "err_pexec: strerror(errno) == %s;\n", strerror(errno));
#endif

	f = (file == NULL) ? "(null)" : file;
	n = getmyname();

	if (EQUAL(n, "glob6")) {
		if (errno == ENOEXEC)
			err(SH_ERR, FMT1S, ERR_NOSHELL);
		if (errno == E2BIG)
			err(SH_ERR, FMT1S, ERR_E2BIG);
		err(SH_ERR, FMT1S, ERR_GNOTFOUND);
	} else if (EQUAL(n, "sh6")) {
		if (errno == ENOEXEC)
			err(125, FMT1S, ERR_NOSHELL);
		if (errno == E2BIG)
			err(126, FMT2S, f, ERR_E2BIG);
		if (errno != ENOENT && errno != ENOTDIR)
			err(126, FMT2S, f, ERR_EXEC);
		err(127, FMT2S, f, ERR_NOTFOUND);
	} else {
		l = no_lnum ? -1 : get_lnum();
		if (name != NULL) {
			if (l != -1) {
				if (errno == ENOEXEC)
					err(125,FMT4LS,n,name,l,f, ERR_NOSHELL);
				if (errno == E2BIG)
					err(126,FMT4LS,n,name, l, f, ERR_E2BIG);
				if (errno != ENOENT && errno != ENOTDIR)
					err(126,FMT4LS,n, name, l, f, ERR_EXEC);
				err(127, FMT4LS, n, name, l, f, ERR_NOTFOUND);
			} else {
				if (errno == ENOEXEC)
					err(125,FMT4S, n, name, f, ERR_NOSHELL);
				if (errno == E2BIG)
					err(126, FMT4S, n, name, f, ERR_E2BIG);
				if (errno != ENOENT && errno != ENOTDIR)
					err(126, FMT4S, n, name, f, ERR_EXEC);
				err(127, FMT4S, n, name, f, ERR_NOTFOUND);
			}
		} else {
			if (l != -1) {
				if (errno == ENOEXEC)
					err(125, FMT3LFS, n, l, f, ERR_NOSHELL);
				if (errno == E2BIG)
					err(126, FMT3LFS, n, l, f, ERR_E2BIG);
				if (errno != ENOENT && errno != ENOTDIR)
					err(126, FMT3LFS, n, l, f, ERR_EXEC);
				err(127, FMT3LFS, n, l, f, ERR_NOTFOUND);
			} else {
				if (errno == ENOEXEC)
					err(125, FMT3S, n, f, ERR_NOSHELL);
				if (errno == E2BIG)
					err(126, FMT3S, n, f, ERR_E2BIG);
				if (errno != ENOENT && errno != ENOTDIR)
					err(126, FMT3S, n, f, ERR_EXEC);
				err(127, FMT3S, n, f, ERR_NOTFOUND);
			}
		}
	}
}