Пример #1
0
STATIC void
minus_o(char *name, int val)
{
	size_t i;

	if (name == NULL) {
		if (val) {
			out1str("Current option settings\n");
			for (i = 0; i < NOPTS; i++) {
				out1fmt("%-16s%s\n", optlist[i].name,
					optlist[i].val ? "on" : "off");
			}
		} else {
			out1str("set");
			for (i = 0; i < NOPTS; i++) {
				out1fmt(" %co %s",
					"+-"[optlist[i].val], optlist[i].name);
			}
			out1str("\n");
		}
	} else {
		for (i = 0; i < NOPTS; i++)
			if (equal(name, optlist[i].name)) {
				set_opt_val(i, val);
				return;
			}
		error("Illegal option -o %s", name);
	}
}
Пример #2
0
/*
 * The trap builtin.
 */
int
trapcmd(int argc __unused, char **argv)
{
	char *action;
	int signo;
	int errors = 0;
	int i;

	while ((i = nextopt("l")) != '\0') {
		switch (i) {
		case 'l':
			printsignals();
			return (0);
		}
	}
	argv = argptr;

	if (*argv == NULL) {
		for (signo = 0 ; signo < sys_nsig ; signo++) {
			if (signo < NSIG && trap[signo] != NULL) {
				out1str("trap -- ");
				out1qstr(trap[signo]);
				if (signo == 0) {
					out1str(" EXIT\n");
				} else if (sys_signame[signo]) {
					out1fmt(" %s\n", sys_signame[signo]);
				} else {
					out1fmt(" %d\n", signo);
				}
			}
		}
		return 0;
	}
	action = NULL;
	if (*argv && sigstring_to_signum(*argv) == -1) {
		if (strcmp(*argv, "-") == 0)
			argv++;
		else {
			action = *argv;
			argv++;
		}
	}
	for (; *argv; argv++) {
		if ((signo = sigstring_to_signum(*argv)) == -1) {
			warning("bad signal %s", *argv);
			errors = 1;
			continue;
		}
		INTOFF;
		if (action)
			action = savestr(action);
		if (trap[signo])
			ckfree(trap[signo]);
		trap[signo] = action;
		if (signo != 0)
			setsignal(signo);
		INTON;
	}
	return errors;
}
Пример #3
0
static void
printjobcmd(struct job *jp)
{
	struct procstat *ps;
	int i;

	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
		out1str(ps->cmd);
		if (i > 0)
			out1str(" | ");
	}
	out1c('\n');
}
Пример #4
0
/*
 * Print a list of valid signal names
 */
static void
printsignals(void)
{
	int n;

	out1str("EXIT ");

	for (n = 1; n < NSIG; n++) {
		out1fmt("%s", sys_signame[n]);
		if ((n == NSIG/2) ||  n == (NSIG - 1))
			out1str("\n");
		else
			out1c(' ');
	}
}
Пример #5
0
static void
minus_o(char *name, int val)
{
	int i;
	const unsigned char *on;
	size_t len;

	if (name == NULL) {
		if (val) {
			/* "Pretty" output. */
			out1str("Current option settings\n");
			for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1)
				out1fmt("%-16.*s%s\n", *on, on + 1,
					optval[i] ? "on" : "off");
		} else {
			/* Output suitable for re-input to shell. */
			for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1)
				out1fmt("%s %co %.*s%s",
				    i % 6 == 0 ? "set" : "",
				    optval[i] ? '-' : '+',
				    *on, on + 1,
				    i % 6 == 5 || i == NOPTS - 1 ? "\n" : "");
		}
	} else {
		len = strlen(name);
		for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1)
			if (*on == len && memcmp(on + 1, name, len) == 0) {
				setoptionbyindex(i, val);
				return;
			}
		error("Illegal option -o %s", name);
	}
}
Пример #6
0
static void
minus_o(char *name, int val)
{
	int i;

	if (name == NULL) {
		if (val) {
			/* "Pretty" output. */
			out1str("Current option settings\n");
			for (i = 0; i < NOPTS; i++)
				out1fmt("%-16s%s\n", optlist[i].name,
					optlist[i].val ? "on" : "off");
		} else {
			/* Output suitable for re-input to shell. */
			for (i = 0; i < NOPTS; i++)
				out1fmt("%s %co %s%s",
				    i % 6 == 0 ? "set" : "",
				    optlist[i].val ? '-' : '+',
				    optlist[i].name,
				    i % 6 == 5 || i == NOPTS - 1 ? "\n" : "");
		}
	} else {
		for (i = 0; i < NOPTS; i++)
			if (equal(name, optlist[i].name)) {
				setoption(optlist[i].letter, val);
				return;
			}
		error("Illegal option -o %s", name);
	}
}
Пример #7
0
STATIC void
minus_o(char *name, int val)
{
	int i;

	if (name == NULL) {
		if (val) {
			out1str("Current option settings\n");
			for (i = 0; i < NOPTS; i++)
				out1fmt("%-16s%s\n", optnames[i],
					optlist[i] ? "on" : "off");
		} else {
			for (i = 0; i < NOPTS; i++)
				out1fmt("set %s %s\n",
					optlist[i] ? "-o" : "+o",
					optnames[i]);

		}
	} else {
		for (i = 0; i < NOPTS; i++)
			if (equal(name, optnames[i])) {
				optlist[i] = val;
				return;
			}
		sh_error("Illegal option -o %s", name);
	}
}
Пример #8
0
static void put_prompt(void)
{
	out1str(cmdedit_prompt);
	cmdedit_x = cmdedit_prmt_len;   /* count real x terminal position */
	cursor = 0;
	cmdedit_y = 0;                  /* new quasireal y */
}
Пример #9
0
static void put_prompt(void)
{
	out1str(cmdedit_prompt);
	cmdedit_x = cmdedit_prmt_len;
	cursor = 0;
// Huh? what if cmdedit_prmt_len >= width?
	cmdedit_y = 0;                  /* new quasireal y */
}
Пример #10
0
/*
 * Print a list of valid signal names
 */
static void
printsignals(void)
{
	int n;

	out1str("EXIT ");
#ifndef HAVE_SYS_SIGNAME
	init_sys_signame();
#endif

	for (n = 1; n < NSIG; n++) {
		out1fmt("%s", sys_signame[n]);
		if ((n == NSIG/2) ||  n == (NSIG - 1))
			out1str("\n");
		else
			out1c(' ');
	}
}
Пример #11
0
int
bgcmd(int argc, char **argv)
{
	char s[64];
	struct job *jp;

	do {
		jp = getjob(*++argv);
		if (jp->jobctl == 0)
			error("job not created under job control");
		if (jp->state == JOBDONE)
			continue;
		restartjob(jp);
		jp->foreground = 0;
		fmtstr(s, 64, "[%td] ", jp - jobtab + 1);
		out1str(s);
		out1str(jp->ps[0].cmd);
		out1c('\n');
	} while (--argc > 1);
	return 0;
}
Пример #12
0
STATIC void
minus_o(char *name, int val)
{
	int doneset, i;

	if (name == NULL) {
		if (val) {
			/* "Pretty" output. */
			out1str("Current option settings\n");
			for (i = 0; i < NOPTS; i++)
				out1fmt("%-16s%s\n", optlist[i].name,
					optlist[i].val ? "on" : "off");
		} else {
			/* Output suitable for re-input to shell. */
			for (doneset = i = 0; i < NOPTS; i++)
				if (optlist[i].val) {
					if (!doneset) {
						out1str("set");
						doneset = 1;
					}
					out1fmt(" -o %s", optlist[i].name);
				}
			if (doneset)
				out1c('\n');
		}
	} else {
		for (i = 0; i < NOPTS; i++)
			if (equal(name, optlist[i].name)) {
				if (!val && privileged && equal(name, "privileged")) {
					(void) setuid(getuid());
					(void) setgid(getgid());
				}
				setoption(optlist[i].letter, val);
				return;
			}
		error("Illegal option -o %s", name);
	}
}
Пример #13
0
int
wordexpcmd(int argc, char **argv)
{
	size_t len;
	int i;

	out1fmt("%08x", argc - 1);
	for (i = 1, len = 0; i < argc; i++)
		len += strlen(argv[i]);
	out1fmt("%08x", (int)len);
	for (i = 1; i < argc; i++) {
		out1str(argv[i]);
		out1c('\0');
	}
        return (0);
}
Пример #14
0
int
wordexpcmd(shinstance *psh, int argc, char **argv)
{
	size_t len;
	int i;

	out1fmt(psh, "%d", argc - 1);
	out1c(psh, '\0');
	for (i = 1, len = 0; i < argc; i++)
		len += strlen(argv[i]);
	out1fmt(psh, "%zd", len);
	out1c(psh, '\0');
	for (i = 1; i < argc; i++) {
		out1str(psh, argv[i]);
		out1c(psh, '\0');
	}
	return (0);
}
Пример #15
0
int
fgcmd(int argc __unused, char **argv)
{
	struct job *jp;
	pid_t pgrp;
	int status;

	jp = getjob(argv[1]);
	if (jp->jobctl == 0)
		error("job not created under job control");
	out1str(jp->ps[0].cmd);
	out1c('\n');
	flushout(&output);
	pgrp = jp->ps[0].pid;
	tcsetpgrp(ttyfd, pgrp);
	restartjob(jp);
	jp->foreground = 1;
	INTOFF;
	status = waitforjob(jp, (int *)NULL);
	INTON;
	return status;
}
Пример #16
0
/*
 * Print a list of valid signal names.
 */
static void
printsignals(void)
{
	int n, outlen;

	outlen = 0;
	for (n = 1; n < sys_nsig; n++) {
		if (sys_signame[n]) {
			out1fmt("%s", sys_signame[n]);
			outlen += strlen(sys_signame[n]);
		} else {
			out1fmt("%d", n);
			outlen += 3;	/* good enough */
		}
		++outlen;
		if (outlen > 71 || n == sys_nsig - 1) {
			out1str("\n");
			outlen = 0;
		} else {
			out1c(' ');
		}
	}
}
Пример #17
0
/*
 * Print a list of valid signal names.
 */
static void
printsignals(void)
{
	int n, outlen;

	outlen = 0;
	for (n = 1; n < _NSIG; n++) {
		if (strsigname(n)) {
			out1fmt("%s", strsigname(n));
			outlen += strlen(strsigname(n));
		} else {
			out1fmt("%d", n);
			outlen += 3;	/* good enough */
		}
		++outlen;
		if (outlen > 70 || n == _NSIG - 1) {
			out1str("\n");
			outlen = 0;
		} else {
			out1c(' ');
		}
	}
}
Пример #18
0
STATIC void
showjob(struct job *jp, pid_t pid, int sformat, int lformat)
{
	char s[64];
	struct procstat *ps;
	struct job *j;
	int col, curr, i, jobno, prev, procno;
	char c;

	procno = jp->nprocs;
	jobno = jp - jobtab + 1;
	curr = prev = 0;
#if JOBS
	if ((j = getcurjob(NULL)) != NULL) {
		curr = j - jobtab + 1;
		if ((j = getcurjob(j)) != NULL)
			prev = j - jobtab + 1;
	}
#endif
	for (ps = jp->ps ; ; ps++) {	/* for each process */
		if (sformat) {
			out1fmt("%d\n", (int)ps->pid);
			goto skip;
		}
		if (!lformat && ps != jp->ps && pid == 0)
			goto skip;
		if (pid != 0 && pid != ps->pid)
			goto skip;
		if (jobno == curr && ps == jp->ps)
			c = '+';
		else if (jobno == prev && ps == jp->ps)
			c = '-';
		else
			c = ' ';
		if (ps == jp->ps)
			fmtstr(s, 64, "[%d] %c ", jobno, c);
		else
			fmtstr(s, 64, "    %c ", c);
		out1str(s);
		col = strlen(s);
		if (lformat) {
			fmtstr(s, 64, "%d ", (int)ps->pid);
			out1str(s);
			col += strlen(s);
		}
		s[0] = '\0';
		if (ps != jp->ps) {
			*s = '\0';
		} else if (ps->status == -1) {
			strcpy(s, "Running");
		} else if (WIFEXITED(ps->status)) {
			if (WEXITSTATUS(ps->status) == 0)
				strcpy(s, "Done");
			else
				fmtstr(s, 64, "Done (%d)",
				    WEXITSTATUS(ps->status));
		} else {
#if JOBS
			if (WIFSTOPPED(ps->status)) 
				i = WSTOPSIG(ps->status);
			else
#endif
				i = WTERMSIG(ps->status);
			if ((i & 0x7F) < _NSIG && strsiglist(i & 0x7F))
				scopy(strsiglist(i & 0x7F), s);
			else
				fmtstr(s, 64, "Signal %d", i & 0x7F);
			if (WCOREDUMP(ps->status))
				strcat(s, " (core dumped)");
		}
		out1str(s);
		col += strlen(s);
		do {
			out1c(' ');
			col++;
		} while (col < 30);
		out1str(ps->cmd);
		out1c('\n');
skip:		if (--procno <= 0)
			break;
	}
}
Пример #19
0
/*
 *  This command is provided since POSIX decided to standardize
 *  the Korn shell fc command.  Oh well...
 */
int
histcmd(volatile int argc, char ** volatile argv)
{
	int ch;
	const char * volatile editor = NULL;
	HistEvent he;
	volatile int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
	int i, retval;
	const char *firststr, *laststr;
	int first, last, direction;
	char * volatile pat = NULL, * volatile repl;	/* ksh "fc old=new" crap */
	static int active = 0;
	struct jmploc jmploc;
	struct jmploc *volatile savehandler;
	char editfile[MAXPATHLEN + 1];
	FILE * volatile efp;
#ifdef __GNUC__
	repl = NULL;	/* XXX gcc4 */
	efp = NULL;	/* XXX gcc4 */
#endif

	if (hist == NULL)
		error("history not active");

	if (argc == 1)
		error("missing history argument");

	optreset = 1; optind = 1; /* initialize getopt */
	while (not_fcnumber(argv[optind]) &&
	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
		switch ((char)ch) {
		case 'e':
			editor = optionarg;
			break;
		case 'l':
			lflg = 1;
			break;
		case 'n':
			nflg = 1;
			break;
		case 'r':
			rflg = 1;
			break;
		case 's':
			sflg = 1;
			break;
		case ':':
			error("option -%c expects argument", optopt);
			/* NOTREACHED */
		case '?':
		default:
			error("unknown option: -%c", optopt);
			/* NOTREACHED */
		}
	argc -= optind, argv += optind;

	/*
	 * If executing...
	 */
	if (lflg == 0 || editor || sflg) {
		lflg = 0;	/* ignore */
		editfile[0] = '\0';
		/*
		 * Catch interrupts to reset active counter and
		 * cleanup temp files.
		 */
		savehandler = handler;
		if (setjmp(jmploc.loc)) {
			active = 0;
			if (*editfile)
				unlink(editfile);
			handler = savehandler;
			longjmp(handler->loc, 1);
		}
		handler = &jmploc;
		if (++active > MAXHISTLOOPS) {
			active = 0;
			displayhist = 0;
			error("called recursively too many times");
		}
		/*
		 * Set editor.
		 */
		if (sflg == 0) {
			if (editor == NULL &&
			    (editor = bltinlookup("FCEDIT", 1)) == NULL &&
			    (editor = bltinlookup("EDITOR", 1)) == NULL)
				editor = DEFEDITOR;
			if (editor[0] == '-' && editor[1] == '\0') {
				sflg = 1;	/* no edit */
				editor = NULL;
			}
		}
	}

	/*
	 * If executing, parse [old=new] now
	 */
	if (lflg == 0 && argc > 0 &&
	     ((repl = strchr(argv[0], '=')) != NULL)) {
		pat = argv[0];
		*repl++ = '\0';
		argc--, argv++;
	}

	/*
	 * If -s is specified, accept only one operand
	 */
	if (sflg && argc >= 2)
		error("too many args");

	/*
	 * determine [first] and [last]
	 */
	switch (argc) {
	case 0:
		firststr = lflg ? "-16" : "-1";
		laststr = "-1";
		break;
	case 1:
		firststr = argv[0];
		laststr = lflg ? "-1" : argv[0];
		break;
	case 2:
		firststr = argv[0];
		laststr = argv[1];
		break;
	default:
		error("too many args");
		/* NOTREACHED */
	}
	/*
	 * Turn into event numbers.
	 */
	first = str_to_event(firststr, 0);
	last = str_to_event(laststr, 1);

	if (rflg) {
		i = last;
		last = first;
		first = i;
	}
	/*
	 * XXX - this should not depend on the event numbers
	 * always increasing.  Add sequence numbers or offset
	 * to the history element in next (diskbased) release.
	 */
	direction = first < last ? H_PREV : H_NEXT;

	/*
	 * If editing, grab a temp file.
	 */
	if (editor) {
		int fd;
		INTOFF;		/* easier */
		snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP);
		if ((fd = mkstemp(editfile)) < 0)
			error("can't create temporary file %s", editfile);
		if ((efp = fdopen(fd, "w")) == NULL) {
			close(fd);
			error("can't allocate stdio buffer for temp");
		}
	}

	/*
	 * Loop through selected history events.  If listing or executing,
	 * do it now.  Otherwise, put into temp file and call the editor
	 * after.
	 *
	 * The history interface needs rethinking, as the following
	 * convolutions will demonstrate.
	 */
	history(hist, &he, H_FIRST);
	retval = history(hist, &he, H_NEXT_EVENT, first);
	for (;retval != -1; retval = history(hist, &he, direction)) {
		if (lflg) {
			if (!nflg)
				out1fmt("%5d ", he.num);
			out1str(he.str);
		} else {
			const char *s = pat ?
			   fc_replace(he.str, pat, repl) : he.str;

			if (sflg) {
				if (displayhist) {
					out2str(s);
				}

				evalstring(strcpy(stalloc(strlen(s) + 1), s), 0);
				if (displayhist && hist) {
					/*
					 *  XXX what about recursive and
					 *  relative histnums.
					 */
					history(hist, &he, H_ENTER, s);
				}

				break;
			} else
				fputs(s, efp);
		}
		/*
		 * At end?  (if we were to lose last, we'd sure be
		 * messed up).
		 */
		if (he.num == last)
			break;
	}
	if (editor) {
		char *editcmd;
		size_t cmdlen;

		fclose(efp);
		cmdlen = strlen(editor) + strlen(editfile) + 2;
		editcmd = stalloc(cmdlen);
		snprintf(editcmd, cmdlen, "%s %s", editor, editfile);
		evalstring(editcmd, 0);	/* XXX - should use no JC command */
		INTON;
		readcmdfile(editfile);	/* XXX - should read back - quick tst */
		unlink(editfile);
	}

	if (lflg == 0 && active > 0)
		--active;
	if (displayhist)
		displayhist = 0;
	return 0;
}
Пример #20
0
static void
showjob(struct job *jp, int mode)
{
	char s[64];
	char statestr[64];
	struct procstat *ps;
	struct job *j;
	int col, curr, i, jobno, prev, procno;
	char c;

	procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
	jobno = jp - jobtab + 1;
	curr = prev = 0;
#if JOBS
	if ((j = getcurjob(NULL)) != NULL) {
		curr = j - jobtab + 1;
		if ((j = getcurjob(j)) != NULL)
			prev = j - jobtab + 1;
	}
#endif
	ps = jp->ps + jp->nprocs - 1;
	if (jp->state == 0) {
		strcpy(statestr, "Running");
#if JOBS
	} else if (jp->state == JOBSTOPPED) {
		while (!WIFSTOPPED(ps->status) && ps > jp->ps)
			ps--;
		if (WIFSTOPPED(ps->status))
			i = WSTOPSIG(ps->status);
		else
			i = -1;
		if (i > 0 && i < sys_nsig && sys_siglist[i])
			strcpy(statestr, sys_siglist[i]);
		else
			strcpy(statestr, "Suspended");
#endif
	} else if (WIFEXITED(ps->status)) {
		if (WEXITSTATUS(ps->status) == 0)
			strcpy(statestr, "Done");
		else
			fmtstr(statestr, 64, "Done(%d)",
			    WEXITSTATUS(ps->status));
	} else {
		i = WTERMSIG(ps->status);
		if (i > 0 && i < sys_nsig && sys_siglist[i])
			strcpy(statestr, sys_siglist[i]);
		else
			fmtstr(statestr, 64, "Signal %d", i);
		if (WCOREDUMP(ps->status))
			strcat(statestr, " (core dumped)");
	}

	for (ps = jp->ps ; ; ps++) {	/* for each process */
		if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
			out1fmt("%d\n", (int)ps->pid);
			goto skip;
		}
		if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
			goto skip;
		if (jobno == curr && ps == jp->ps)
			c = '+';
		else if (jobno == prev && ps == jp->ps)
			c = '-';
		else
			c = ' ';
		if (ps == jp->ps)
			fmtstr(s, 64, "[%d] %c ", jobno, c);
		else
			fmtstr(s, 64, "    %c ", c);
		out1str(s);
		col = strlen(s);
		if (mode == SHOWJOBS_VERBOSE) {
			fmtstr(s, 64, "%d ", (int)ps->pid);
			out1str(s);
			col += strlen(s);
		}
		if (ps == jp->ps) {
			out1str(statestr);
			col += strlen(statestr);
		}
		do {
			out1c(' ');
			col++;
		} while (col < 30);
		if (mode == SHOWJOBS_VERBOSE) {
			out1str(ps->cmd);
			out1c('\n');
		} else
			printjobcmd(jp);
skip:		if (--procno <= 0)
			break;
	}
}
Пример #21
0
int
trapcmd(int argc, char **argv)
{
	char *action;
	char **ap;
	int signo;
	int errs = 0;
	int printonly = 0;

	ap = argv + 1;

	if (argc == 2 && strcmp(*ap, "-l") == 0) {
		printsignals();
		return 0;
	}
	if (argc == 2 && strcmp(*ap, "-") == 0) {
		for (signo = 0; signo < NSIG; signo++) {
			if (trap[signo] == NULL)
				continue;
			INTOFF;
			ckfree(trap[signo]);
			trap[signo] = NULL;
			if (signo != 0)
				setsignal(signo, 0);
			INTON;
		}
		return 0;
	}
	if (argc >= 2 && strcmp(*ap, "-p") == 0) {
		printonly = 1;
		ap++;
		argc--;
	}

	if (argc > 1 && strcmp(*ap, "--") == 0) {
		argc--;
		ap++;
	}

	if (argc <= 1) {
		int count;

		if (printonly) {
			for (count = 0, signo = 0 ; signo < NSIG ; signo++)
				if (trap[signo] == NULL) {
					if (count == 0)
						out1str("trap -- -");
					out1fmt(" %s", trap_signame(signo));
					/* oh! unlucky 13 */
					if (++count >= 13) {
						out1str("\n");
						count = 0;
					}
				}
			if (count)
				out1str("\n");
		}

		for (count = 0, signo = 0 ; signo < NSIG ; signo++)
			if (trap[signo] != NULL && trap[signo][0] == '\0') {
				if (count == 0)
					out1str("trap -- ''");
				out1fmt(" %s", trap_signame(signo));
				/*
				 * the prefix is 10 bytes, with 4 byte
				 * signal names (common) we have room in
				 * the 70 bytes left on a normal line for
				 * 70/(4+1) signals, that's 14, but to
				 * allow for the occasional longer sig name
				 * we output one less...
				 */
				if (++count >= 13) {
					out1str("\n");
					count = 0;
				}
			}
		if (count)
			out1str("\n");

		for (signo = 0 ; signo < NSIG ; signo++)
			if (trap[signo] != NULL && trap[signo][0] != '\0') {
				out1str("trap -- ");
				print_quoted(trap[signo]);
				out1fmt(" %s\n", trap_signame(signo));
			}

		return 0;
	}

	action = NULL;

	if (!printonly && !is_number(*ap)) {
		if ((*ap)[0] == '-' && (*ap)[1] == '\0')
			ap++;			/* reset to default */
		else
			action = *ap++;		/* can be '' for "ignore" */
		argc--;
	}

	if (argc < 2) {		/* there must be at least 1 condition */
		out2str("Usage: trap [-l]\n"
			"       trap -p [condition ...]\n"
			"       trap action condition ...\n"
			"       trap N condition ...\n");
		return 2;
	}


	while (*ap) {
		signo = signame_to_signum(*ap);

		if (signo < 0 || signo >= NSIG) {
			/* This is not a fatal error, so sayeth posix */
			outfmt(out2, "trap: '%s' bad condition\n", *ap);
			errs = 1;
			ap++;
			continue;
		}
		ap++;

		if (printonly) {
			out1str("trap -- ");
			if (trap[signo] == NULL)
				out1str("-");
			else
				print_quoted(trap[signo]);
			out1fmt(" %s\n", trap_signame(signo));
			continue;
		}

		INTOFF;
		if (action)
			action = savestr(action);

		if (trap[signo])
			ckfree(trap[signo]);

		trap[signo] = action;

		if (signo != 0)
			setsignal(signo, 0);
		INTON;
	}
	return errs;
}