jobs.c revision 254767
11553Srgrimes/*-
21553Srgrimes * Copyright (c) 1991, 1993
31553Srgrimes *	The Regents of the University of California.  All rights reserved.
41553Srgrimes *
51553Srgrimes * This code is derived from software contributed to Berkeley by
61553Srgrimes * Kenneth Almquist.
71553Srgrimes *
81553Srgrimes * Redistribution and use in source and binary forms, with or without
91553Srgrimes * modification, are permitted provided that the following conditions
101553Srgrimes * are met:
111553Srgrimes * 1. Redistributions of source code must retain the above copyright
121553Srgrimes *    notice, this list of conditions and the following disclaimer.
131553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141553Srgrimes *    notice, this list of conditions and the following disclaimer in the
151553Srgrimes *    documentation and/or other materials provided with the distribution.
161553Srgrimes * 4. Neither the name of the University nor the names of its contributors
171553Srgrimes *    may be used to endorse or promote products derived from this software
181553Srgrimes *    without specific prior written permission.
191553Srgrimes *
201553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231553Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301553Srgrimes * SUCH DAMAGE.
311553Srgrimes */
321553Srgrimes
331553Srgrimes#ifndef lint
341553Srgrimes#if 0
3515648Sjoergstatic char sccsid[] = "@(#)jobs.c	8.5 (Berkeley) 5/4/95";
361553Srgrimes#endif
371553Srgrimes#endif /* not lint */
381553Srgrimes#include <sys/cdefs.h>
391553Srgrimes__FBSDID("$FreeBSD: head/bin/sh/jobs.c 254767 2013-08-24 09:57:32Z jilles $");
401553Srgrimes
411553Srgrimes#include <sys/ioctl.h>
421553Srgrimes#include <sys/param.h>
431553Srgrimes#include <sys/resource.h>
441553Srgrimes#include <sys/time.h>
451553Srgrimes#include <sys/wait.h>
461553Srgrimes#include <errno.h>
471553Srgrimes#include <fcntl.h>
481553Srgrimes#include <paths.h>
491553Srgrimes#include <signal.h>
501553Srgrimes#include <stddef.h>
511553Srgrimes#include <stdlib.h>
521553Srgrimes#include <unistd.h>
531553Srgrimes
541553Srgrimes#include "shell.h"
551553Srgrimes#if JOBS
561553Srgrimes#include <termios.h>
571553Srgrimes#undef CEOF			/* syntax.h redefines this */
581553Srgrimes#endif
591553Srgrimes#include "redir.h"
601553Srgrimes#include "exec.h"
611553Srgrimes#include "show.h"
621553Srgrimes#include "main.h"
631553Srgrimes#include "parser.h"
641553Srgrimes#include "nodes.h"
651553Srgrimes#include "jobs.h"
661553Srgrimes#include "options.h"
671553Srgrimes#include "trap.h"
681553Srgrimes#include "syntax.h"
691553Srgrimes#include "input.h"
701553Srgrimes#include "output.h"
711553Srgrimes#include "memalloc.h"
721553Srgrimes#include "error.h"
731553Srgrimes#include "mystring.h"
741553Srgrimes#include "var.h"
751553Srgrimes#include "builtins.h"
761553Srgrimes
771553Srgrimes
781553Srgrimesstatic struct job *jobtab;	/* array of jobs */
791553Srgrimesstatic int njobs;		/* size of array */
801553Srgrimesstatic pid_t backgndpid = -1;	/* pid of last background process */
811553Srgrimesstatic struct job *bgjob = NULL; /* last background process */
821553Srgrimes#if JOBS
831553Srgrimesstatic struct job *jobmru;	/* most recently used job list */
841553Srgrimesstatic pid_t initialpgrp;	/* pgrp of shell on invocation */
851553Srgrimes#endif
861553Srgrimesint in_waitcmd = 0;		/* are we in waitcmd()? */
871553Srgrimesvolatile sig_atomic_t breakwaitcmd = 0;	/* should wait be terminated? */
881553Srgrimesstatic int ttyfd = -1;
891553Srgrimes
901553Srgrimes/* mode flags for dowait */
911553Srgrimes#define DOWAIT_BLOCK	0x1 /* wait until a child exits */
921553Srgrimes#define DOWAIT_SIG	0x2 /* if DOWAIT_BLOCK, abort on signals */
931553Srgrimes
941553Srgrimes#if JOBS
951553Srgrimesstatic void restartjob(struct job *);
961553Srgrimes#endif
971553Srgrimesstatic void freejob(struct job *);
981553Srgrimesstatic int waitcmdloop(struct job *);
991553Srgrimesstatic struct job *getjob_nonotfound(char *);
1001553Srgrimesstatic struct job *getjob(char *);
1011553Srgrimespid_t getjobpgrp(char *);
1021553Srgrimesstatic pid_t dowait(int, struct job *);
1031553Srgrimesstatic void checkzombies(void);
1041553Srgrimesstatic void cmdtxt(union node *);
1051553Srgrimesstatic void cmdputs(const char *);
1061553Srgrimes#if JOBS
1071553Srgrimesstatic void setcurjob(struct job *);
1081553Srgrimesstatic void deljob(struct job *);
1091553Srgrimesstatic struct job *getcurjob(struct job *);
1101553Srgrimes#endif
1111553Srgrimesstatic void printjobcmd(struct job *);
1121553Srgrimesstatic void showjob(struct job *, int);
1131553Srgrimes
1141553Srgrimes
1151553Srgrimes/*
1161553Srgrimes * Turn job control on and off.
1171553Srgrimes */
1181553Srgrimes
1191553Srgrimesstatic int jobctl;
1201553Srgrimes
1211553Srgrimes#if JOBS
1221553Srgrimesvoid
1231553Srgrimessetjobctl(int on)
1241553Srgrimes{
1251553Srgrimes	int i;
1261553Srgrimes
1271553Srgrimes	if (on == jobctl || rootshell == 0)
1281553Srgrimes		return;
1291553Srgrimes	if (on) {
1301553Srgrimes		if (ttyfd != -1)
1311553Srgrimes			close(ttyfd);
1321553Srgrimes		if ((ttyfd = open(_PATH_TTY, O_RDWR | O_CLOEXEC)) < 0) {
1331553Srgrimes			i = 0;
1341553Srgrimes			while (i <= 2 && !isatty(i))
1351553Srgrimes				i++;
1361553Srgrimes			if (i > 2 ||
1371553Srgrimes			    (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0)
1381553Srgrimes				goto out;
1391553Srgrimes		}
1401553Srgrimes		if (ttyfd < 10) {
1411553Srgrimes			/*
1421553Srgrimes			 * Keep our TTY file descriptor out of the way of
1431553Srgrimes			 * the user's redirections.
1441553Srgrimes			 */
1451553Srgrimes			if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
1461553Srgrimes				close(ttyfd);
1471553Srgrimes				ttyfd = -1;
1481553Srgrimes				goto out;
1491553Srgrimes			}
1501553Srgrimes			close(ttyfd);
1511553Srgrimes			ttyfd = i;
1521553Srgrimes		}
1531553Srgrimes		do { /* while we are in the background */
1541553Srgrimes			initialpgrp = tcgetpgrp(ttyfd);
1551553Srgrimes			if (initialpgrp < 0) {
1561553Srgrimesout:				out2fmt_flush("sh: can't access tty; job control turned off\n");
1571553Srgrimes				mflag = 0;
1581553Srgrimes				return;
1591553Srgrimes			}
1601553Srgrimes			if (initialpgrp != getpgrp()) {
1611553Srgrimes				kill(0, SIGTTIN);
1621553Srgrimes				continue;
1631553Srgrimes			}
1641553Srgrimes		} while (0);
1651553Srgrimes		setsignal(SIGTSTP);
1661553Srgrimes		setsignal(SIGTTOU);
1671553Srgrimes		setsignal(SIGTTIN);
1681553Srgrimes		setpgid(0, rootpid);
1691553Srgrimes		tcsetpgrp(ttyfd, rootpid);
1701553Srgrimes	} else { /* turning job control off */
1711553Srgrimes		setpgid(0, initialpgrp);
1721553Srgrimes		tcsetpgrp(ttyfd, initialpgrp);
1731553Srgrimes		close(ttyfd);
1741553Srgrimes		ttyfd = -1;
1751553Srgrimes		setsignal(SIGTSTP);
1761553Srgrimes		setsignal(SIGTTOU);
1771553Srgrimes		setsignal(SIGTTIN);
1781553Srgrimes	}
1791553Srgrimes	jobctl = on;
1801553Srgrimes}
1811553Srgrimes#endif
1821553Srgrimes
1831553Srgrimes
1841553Srgrimes#if JOBS
1851553Srgrimesint
1861553Srgrimesfgcmd(int argc __unused, char **argv __unused)
1871553Srgrimes{
1881553Srgrimes	struct job *jp;
1891553Srgrimes	pid_t pgrp;
1901553Srgrimes	int status;
1911553Srgrimes
1921553Srgrimes	nextopt("");
1931553Srgrimes	jp = getjob(*argptr);
1941553Srgrimes	if (jp->jobctl == 0)
1951553Srgrimes		error("job not created under job control");
1961553Srgrimes	printjobcmd(jp);
1971553Srgrimes	flushout(&output);
1981553Srgrimes	pgrp = jp->ps[0].pid;
1991553Srgrimes	tcsetpgrp(ttyfd, pgrp);
2001553Srgrimes	restartjob(jp);
2011553Srgrimes	jp->foreground = 1;
2021553Srgrimes	INTOFF;
2031553Srgrimes	status = waitforjob(jp, (int *)NULL);
2041553Srgrimes	INTON;
2051553Srgrimes	return status;
2061553Srgrimes}
2071553Srgrimes
2081553Srgrimes
2091553Srgrimesint
2101553Srgrimesbgcmd(int argc, char **argv)
2111553Srgrimes{
2121553Srgrimes	struct job *jp;
2131553Srgrimes
2141553Srgrimes	nextopt("");
2151553Srgrimes	do {
2161553Srgrimes		jp = getjob(*argptr);
2171553Srgrimes		if (jp->jobctl == 0)
2181553Srgrimes			error("job not created under job control");
2191553Srgrimes		if (jp->state == JOBDONE)
2201553Srgrimes			continue;
2211553Srgrimes		restartjob(jp);
2221553Srgrimes		jp->foreground = 0;
2231553Srgrimes		out1fmt("[%td] ", jp - jobtab + 1);
2241553Srgrimes		printjobcmd(jp);
2251553Srgrimes	} while (*argptr != NULL && *++argptr != NULL);
2261553Srgrimes	return 0;
2271553Srgrimes}
2281553Srgrimes
2291553Srgrimes
2301553Srgrimesstatic void
2311553Srgrimesrestartjob(struct job *jp)
2321553Srgrimes{
2331553Srgrimes	struct procstat *ps;
2341553Srgrimes	int i;
2351553Srgrimes
2361553Srgrimes	if (jp->state == JOBDONE)
2371553Srgrimes		return;
2381553Srgrimes	setcurjob(jp);
2391553Srgrimes	INTOFF;
2401553Srgrimes	kill(-jp->ps[0].pid, SIGCONT);
2411553Srgrimes	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
2421553Srgrimes		if (WIFSTOPPED(ps->status)) {
2431553Srgrimes			ps->status = -1;
2441553Srgrimes			jp->state = 0;
2451553Srgrimes		}
2461553Srgrimes	}
2471553Srgrimes	INTON;
2481553Srgrimes}
2491553Srgrimes#endif
2501553Srgrimes
2511553Srgrimes
2521553Srgrimesint
2531553Srgrimesjobscmd(int argc __unused, char *argv[] __unused)
2541553Srgrimes{
2551553Srgrimes	char *id;
2561553Srgrimes	int ch, mode;
2571553Srgrimes
2581553Srgrimes	mode = SHOWJOBS_DEFAULT;
2591553Srgrimes	while ((ch = nextopt("lps")) != '\0') {
2601553Srgrimes		switch (ch) {
2611553Srgrimes		case 'l':
2621553Srgrimes			mode = SHOWJOBS_VERBOSE;
2631553Srgrimes			break;
2641553Srgrimes		case 'p':
2651553Srgrimes			mode = SHOWJOBS_PGIDS;
2661553Srgrimes			break;
2671553Srgrimes		case 's':
2681553Srgrimes			mode = SHOWJOBS_PIDS;
2691553Srgrimes			break;
2701553Srgrimes		}
2711553Srgrimes	}
2721553Srgrimes
2731553Srgrimes	if (*argptr == NULL)
2741553Srgrimes		showjobs(0, mode);
2751553Srgrimes	else
2761553Srgrimes		while ((id = *argptr++) != NULL)
2771553Srgrimes			showjob(getjob(id), mode);
2781553Srgrimes
2791553Srgrimes	return (0);
2801553Srgrimes}
2811553Srgrimes
2821553Srgrimesstatic void
2831553Srgrimesprintjobcmd(struct job *jp)
2841553Srgrimes{
2851553Srgrimes	struct procstat *ps;
2861553Srgrimes	int i;
2871553Srgrimes
2881553Srgrimes	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
2891553Srgrimes		out1str(ps->cmd);
2901553Srgrimes		if (i > 0)
2911553Srgrimes			out1str(" | ");
2921553Srgrimes	}
2931553Srgrimes	out1c('\n');
2941553Srgrimes}
29515648Sjoerg
2961553Srgrimesstatic void
2971553Srgrimesshowjob(struct job *jp, int mode)
2981553Srgrimes{
2991553Srgrimes	char s[64];
3001553Srgrimes	char statestr[64];
3011553Srgrimes	const char *sigstr;
3021553Srgrimes	struct procstat *ps;
3031553Srgrimes	struct job *j;
3041553Srgrimes	int col, curr, i, jobno, prev, procno;
3051553Srgrimes	char c;
3061553Srgrimes
3071553Srgrimes	procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
3081553Srgrimes	jobno = jp - jobtab + 1;
3091553Srgrimes	curr = prev = 0;
3101553Srgrimes#if JOBS
3111553Srgrimes	if ((j = getcurjob(NULL)) != NULL) {
3121553Srgrimes		curr = j - jobtab + 1;
3131553Srgrimes		if ((j = getcurjob(j)) != NULL)
3141553Srgrimes			prev = j - jobtab + 1;
3151553Srgrimes	}
31615648Sjoerg#endif
3171553Srgrimes	ps = jp->ps + jp->nprocs - 1;
3181553Srgrimes	if (jp->state == 0) {
3191553Srgrimes		strcpy(statestr, "Running");
3201553Srgrimes#if JOBS
3211553Srgrimes	} else if (jp->state == JOBSTOPPED) {
3221553Srgrimes		while (!WIFSTOPPED(ps->status) && ps > jp->ps)
3231553Srgrimes			ps--;
3241553Srgrimes		if (WIFSTOPPED(ps->status))
3251553Srgrimes			i = WSTOPSIG(ps->status);
3261553Srgrimes		else
3271553Srgrimes			i = -1;
3281553Srgrimes		sigstr = strsignal(i);
3291553Srgrimes		if (sigstr != NULL)
3301553Srgrimes			strcpy(statestr, sigstr);
3311553Srgrimes		else
3321553Srgrimes			strcpy(statestr, "Suspended");
3331553Srgrimes#endif
3341553Srgrimes	} else if (WIFEXITED(ps->status)) {
3351553Srgrimes		if (WEXITSTATUS(ps->status) == 0)
3361553Srgrimes			strcpy(statestr, "Done");
3371553Srgrimes		else
3381553Srgrimes			fmtstr(statestr, 64, "Done(%d)",
3391553Srgrimes			    WEXITSTATUS(ps->status));
340	} else {
341		i = WTERMSIG(ps->status);
342		sigstr = strsignal(i);
343		if (sigstr != NULL)
344			strcpy(statestr, sigstr);
345		else
346			strcpy(statestr, "Unknown signal");
347		if (WCOREDUMP(ps->status))
348			strcat(statestr, " (core dumped)");
349	}
350
351	for (ps = jp->ps ; ; ps++) {	/* for each process */
352		if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
353			out1fmt("%d\n", (int)ps->pid);
354			goto skip;
355		}
356		if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
357			goto skip;
358		if (jobno == curr && ps == jp->ps)
359			c = '+';
360		else if (jobno == prev && ps == jp->ps)
361			c = '-';
362		else
363			c = ' ';
364		if (ps == jp->ps)
365			fmtstr(s, 64, "[%d] %c ", jobno, c);
366		else
367			fmtstr(s, 64, "    %c ", c);
368		out1str(s);
369		col = strlen(s);
370		if (mode == SHOWJOBS_VERBOSE) {
371			fmtstr(s, 64, "%d ", (int)ps->pid);
372			out1str(s);
373			col += strlen(s);
374		}
375		if (ps == jp->ps) {
376			out1str(statestr);
377			col += strlen(statestr);
378		}
379		do {
380			out1c(' ');
381			col++;
382		} while (col < 30);
383		if (mode == SHOWJOBS_VERBOSE) {
384			out1str(ps->cmd);
385			out1c('\n');
386		} else
387			printjobcmd(jp);
388skip:		if (--procno <= 0)
389			break;
390	}
391}
392
393/*
394 * Print a list of jobs.  If "change" is nonzero, only print jobs whose
395 * statuses have changed since the last call to showjobs.
396 *
397 * If the shell is interrupted in the process of creating a job, the
398 * result may be a job structure containing zero processes.  Such structures
399 * will be freed here.
400 */
401
402void
403showjobs(int change, int mode)
404{
405	int jobno;
406	struct job *jp;
407
408	TRACE(("showjobs(%d) called\n", change));
409	checkzombies();
410	for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
411		if (! jp->used)
412			continue;
413		if (jp->nprocs == 0) {
414			freejob(jp);
415			continue;
416		}
417		if (change && ! jp->changed)
418			continue;
419		showjob(jp, mode);
420		if (mode == SHOWJOBS_DEFAULT || mode == SHOWJOBS_VERBOSE) {
421			jp->changed = 0;
422			/* Hack: discard jobs for which $! has not been
423			 * referenced in interactive mode when they terminate.
424			 */
425			if (jp->state == JOBDONE && !jp->remembered &&
426					(iflag || jp != bgjob)) {
427				freejob(jp);
428			}
429		}
430	}
431}
432
433
434/*
435 * Mark a job structure as unused.
436 */
437
438static void
439freejob(struct job *jp)
440{
441	struct procstat *ps;
442	int i;
443
444	INTOFF;
445	if (bgjob == jp)
446		bgjob = NULL;
447	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
448		if (ps->cmd != nullstr)
449			ckfree(ps->cmd);
450	}
451	if (jp->ps != &jp->ps0)
452		ckfree(jp->ps);
453	jp->used = 0;
454#if JOBS
455	deljob(jp);
456#endif
457	INTON;
458}
459
460
461
462int
463waitcmd(int argc __unused, char **argv __unused)
464{
465	struct job *job;
466	int retval;
467
468	nextopt("");
469	if (*argptr == NULL)
470		return (waitcmdloop(NULL));
471
472	do {
473		job = getjob_nonotfound(*argptr);
474		if (job == NULL)
475			retval = 127;
476		else
477			retval = waitcmdloop(job);
478		argptr++;
479	} while (*argptr != NULL);
480
481	return (retval);
482}
483
484static int
485waitcmdloop(struct job *job)
486{
487	int status, retval;
488	struct job *jp;
489
490	/*
491	 * Loop until a process is terminated or stopped, or a SIGINT is
492	 * received.
493	 */
494
495	in_waitcmd++;
496	do {
497		if (job != NULL) {
498			if (job->state == JOBDONE) {
499				status = job->ps[job->nprocs - 1].status;
500				if (WIFEXITED(status))
501					retval = WEXITSTATUS(status);
502				else
503					retval = WTERMSIG(status) + 128;
504				if (! iflag || ! job->changed)
505					freejob(job);
506				else {
507					job->remembered = 0;
508					if (job == bgjob)
509						bgjob = NULL;
510				}
511				in_waitcmd--;
512				return retval;
513			}
514		} else {
515			for (jp = jobtab ; jp < jobtab + njobs; jp++)
516				if (jp->used && jp->state == JOBDONE) {
517					if (! iflag || ! jp->changed)
518						freejob(jp);
519					else {
520						jp->remembered = 0;
521						if (jp == bgjob)
522							bgjob = NULL;
523					}
524				}
525			for (jp = jobtab ; ; jp++) {
526				if (jp >= jobtab + njobs) {	/* no running procs */
527					in_waitcmd--;
528					return 0;
529				}
530				if (jp->used && jp->state == 0)
531					break;
532			}
533		}
534	} while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, (struct job *)NULL) != -1);
535	in_waitcmd--;
536
537	return pendingsig + 128;
538}
539
540
541
542int
543jobidcmd(int argc __unused, char **argv __unused)
544{
545	struct job *jp;
546	int i;
547
548	nextopt("");
549	jp = getjob(*argptr);
550	for (i = 0 ; i < jp->nprocs ; ) {
551		out1fmt("%d", (int)jp->ps[i].pid);
552		out1c(++i < jp->nprocs? ' ' : '\n');
553	}
554	return 0;
555}
556
557
558
559/*
560 * Convert a job name to a job structure.
561 */
562
563static struct job *
564getjob_nonotfound(char *name)
565{
566	int jobno;
567	struct job *found, *jp;
568	pid_t pid;
569	int i;
570
571	if (name == NULL) {
572#if JOBS
573currentjob:	if ((jp = getcurjob(NULL)) == NULL)
574			error("No current job");
575		return (jp);
576#else
577		error("No current job");
578#endif
579	} else if (name[0] == '%') {
580		if (is_digit(name[1])) {
581			jobno = number(name + 1);
582			if (jobno > 0 && jobno <= njobs
583			 && jobtab[jobno - 1].used != 0)
584				return &jobtab[jobno - 1];
585#if JOBS
586		} else if (name[1] == '%' && name[2] == '\0') {
587			goto currentjob;
588		} else if (name[1] == '+' && name[2] == '\0') {
589			goto currentjob;
590		} else if (name[1] == '-' && name[2] == '\0') {
591			if ((jp = getcurjob(NULL)) == NULL ||
592			    (jp = getcurjob(jp)) == NULL)
593				error("No previous job");
594			return (jp);
595#endif
596		} else if (name[1] == '?') {
597			found = NULL;
598			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
599				if (jp->used && jp->nprocs > 0
600				 && strstr(jp->ps[0].cmd, name + 2) != NULL) {
601					if (found)
602						error("%s: ambiguous", name);
603					found = jp;
604				}
605			}
606			if (found != NULL)
607				return (found);
608		} else {
609			found = NULL;
610			for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
611				if (jp->used && jp->nprocs > 0
612				 && prefix(name + 1, jp->ps[0].cmd)) {
613					if (found)
614						error("%s: ambiguous", name);
615					found = jp;
616				}
617			}
618			if (found)
619				return found;
620		}
621	} else if (is_number(name)) {
622		pid = (pid_t)number(name);
623		for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
624			if (jp->used && jp->nprocs > 0
625			 && jp->ps[jp->nprocs - 1].pid == pid)
626				return jp;
627		}
628	}
629	return NULL;
630}
631
632
633static struct job *
634getjob(char *name)
635{
636	struct job *jp;
637
638	jp = getjob_nonotfound(name);
639	if (jp == NULL)
640		error("No such job: %s", name);
641	return (jp);
642}
643
644
645pid_t
646getjobpgrp(char *name)
647{
648	struct job *jp;
649
650	jp = getjob(name);
651	return -jp->ps[0].pid;
652}
653
654/*
655 * Return a new job structure,
656 */
657
658struct job *
659makejob(union node *node __unused, int nprocs)
660{
661	int i;
662	struct job *jp;
663
664	for (i = njobs, jp = jobtab ; ; jp++) {
665		if (--i < 0) {
666			INTOFF;
667			if (njobs == 0) {
668				jobtab = ckmalloc(4 * sizeof jobtab[0]);
669#if JOBS
670				jobmru = NULL;
671#endif
672			} else {
673				jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
674				memcpy(jp, jobtab, njobs * sizeof jp[0]);
675#if JOBS
676				/* Relocate `next' pointers and list head */
677				if (jobmru != NULL)
678					jobmru = &jp[jobmru - jobtab];
679				for (i = 0; i < njobs; i++)
680					if (jp[i].next != NULL)
681						jp[i].next = &jp[jp[i].next -
682						    jobtab];
683#endif
684				if (bgjob != NULL)
685					bgjob = &jp[bgjob - jobtab];
686				/* Relocate `ps' pointers */
687				for (i = 0; i < njobs; i++)
688					if (jp[i].ps == &jobtab[i].ps0)
689						jp[i].ps = &jp[i].ps0;
690				ckfree(jobtab);
691				jobtab = jp;
692			}
693			jp = jobtab + njobs;
694			for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0)
695				;
696			INTON;
697			break;
698		}
699		if (jp->used == 0)
700			break;
701	}
702	INTOFF;
703	jp->state = 0;
704	jp->used = 1;
705	jp->changed = 0;
706	jp->nprocs = 0;
707	jp->foreground = 0;
708	jp->remembered = 0;
709#if JOBS
710	jp->jobctl = jobctl;
711	jp->next = NULL;
712#endif
713	if (nprocs > 1) {
714		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
715	} else {
716		jp->ps = &jp->ps0;
717	}
718	INTON;
719	TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node, nprocs,
720	    jp - jobtab + 1));
721	return jp;
722}
723
724#if JOBS
725static void
726setcurjob(struct job *cj)
727{
728	struct job *jp, *prev;
729
730	for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
731		if (jp == cj) {
732			if (prev != NULL)
733				prev->next = jp->next;
734			else
735				jobmru = jp->next;
736			jp->next = jobmru;
737			jobmru = cj;
738			return;
739		}
740	}
741	cj->next = jobmru;
742	jobmru = cj;
743}
744
745static void
746deljob(struct job *j)
747{
748	struct job *jp, *prev;
749
750	for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
751		if (jp == j) {
752			if (prev != NULL)
753				prev->next = jp->next;
754			else
755				jobmru = jp->next;
756			return;
757		}
758	}
759}
760
761/*
762 * Return the most recently used job that isn't `nj', and preferably one
763 * that is stopped.
764 */
765static struct job *
766getcurjob(struct job *nj)
767{
768	struct job *jp;
769
770	/* Try to find a stopped one.. */
771	for (jp = jobmru; jp != NULL; jp = jp->next)
772		if (jp->used && jp != nj && jp->state == JOBSTOPPED)
773			return (jp);
774	/* Otherwise the most recently used job that isn't `nj' */
775	for (jp = jobmru; jp != NULL; jp = jp->next)
776		if (jp->used && jp != nj)
777			return (jp);
778
779	return (NULL);
780}
781
782#endif
783
784/*
785 * Fork of a subshell.  If we are doing job control, give the subshell its
786 * own process group.  Jp is a job structure that the job is to be added to.
787 * N is the command that will be evaluated by the child.  Both jp and n may
788 * be NULL.  The mode parameter can be one of the following:
789 *	FORK_FG - Fork off a foreground process.
790 *	FORK_BG - Fork off a background process.
791 *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
792 *		     process group even if job control is on.
793 *
794 * When job control is turned off, background processes have their standard
795 * input redirected to /dev/null (except for the second and later processes
796 * in a pipeline).
797 */
798
799pid_t
800forkshell(struct job *jp, union node *n, int mode)
801{
802	pid_t pid;
803	pid_t pgrp;
804
805	TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n,
806	    mode));
807	INTOFF;
808	if (mode == FORK_BG && (jp == NULL || jp->nprocs == 0))
809		checkzombies();
810	flushall();
811	pid = fork();
812	if (pid == -1) {
813		TRACE(("Fork failed, errno=%d\n", errno));
814		INTON;
815		error("Cannot fork: %s", strerror(errno));
816	}
817	if (pid == 0) {
818		struct job *p;
819		int wasroot;
820		int i;
821
822		TRACE(("Child shell %d\n", (int)getpid()));
823		wasroot = rootshell;
824		rootshell = 0;
825		handler = &main_handler;
826		closescript();
827		INTON;
828		forcelocal = 0;
829		clear_traps();
830#if JOBS
831		jobctl = 0;		/* do job control only in root shell */
832		if (wasroot && mode != FORK_NOJOB && mflag) {
833			if (jp == NULL || jp->nprocs == 0)
834				pgrp = getpid();
835			else
836				pgrp = jp->ps[0].pid;
837			if (setpgid(0, pgrp) == 0 && mode == FORK_FG) {
838				/*** this causes superfluous TIOCSPGRPS ***/
839				if (tcsetpgrp(ttyfd, pgrp) < 0)
840					error("tcsetpgrp failed, errno=%d", errno);
841			}
842			setsignal(SIGTSTP);
843			setsignal(SIGTTOU);
844		} else if (mode == FORK_BG) {
845			ignoresig(SIGINT);
846			ignoresig(SIGQUIT);
847			if ((jp == NULL || jp->nprocs == 0) &&
848			    ! fd0_redirected_p ()) {
849				close(0);
850				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
851					error("cannot open %s: %s",
852					    _PATH_DEVNULL, strerror(errno));
853			}
854		}
855#else
856		if (mode == FORK_BG) {
857			ignoresig(SIGINT);
858			ignoresig(SIGQUIT);
859			if ((jp == NULL || jp->nprocs == 0) &&
860			    ! fd0_redirected_p ()) {
861				close(0);
862				if (open(_PATH_DEVNULL, O_RDONLY) != 0)
863					error("cannot open %s: %s",
864					    _PATH_DEVNULL, strerror(errno));
865			}
866		}
867#endif
868		INTOFF;
869		for (i = njobs, p = jobtab ; --i >= 0 ; p++)
870			if (p->used)
871				freejob(p);
872		INTON;
873		if (wasroot && iflag) {
874			setsignal(SIGINT);
875			setsignal(SIGQUIT);
876			setsignal(SIGTERM);
877		}
878		return pid;
879	}
880	if (rootshell && mode != FORK_NOJOB && mflag) {
881		if (jp == NULL || jp->nprocs == 0)
882			pgrp = pid;
883		else
884			pgrp = jp->ps[0].pid;
885		setpgid(pid, pgrp);
886	}
887	if (mode == FORK_BG) {
888		if (bgjob != NULL && bgjob->state == JOBDONE &&
889		    !bgjob->remembered && !iflag)
890			freejob(bgjob);
891		backgndpid = pid;		/* set $! */
892		bgjob = jp;
893	}
894	if (jp) {
895		struct procstat *ps = &jp->ps[jp->nprocs++];
896		ps->pid = pid;
897		ps->status = -1;
898		ps->cmd = nullstr;
899		if (iflag && rootshell && n)
900			ps->cmd = commandtext(n);
901		jp->foreground = mode == FORK_FG;
902#if JOBS
903		setcurjob(jp);
904#endif
905	}
906	INTON;
907	TRACE(("In parent shell:  child = %d\n", (int)pid));
908	return pid;
909}
910
911
912pid_t
913vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int idx, int pip[2])
914{
915	pid_t pid;
916	struct jmploc jmploc;
917	struct jmploc *savehandler;
918
919	TRACE(("vforkexecshell(%%%td, %s, %p) called\n", jp - jobtab, argv[0],
920	    (void *)pip));
921	INTOFF;
922	flushall();
923	savehandler = handler;
924	pid = vfork();
925	if (pid == -1) {
926		TRACE(("Vfork failed, errno=%d\n", errno));
927		INTON;
928		error("Cannot fork: %s", strerror(errno));
929	}
930	if (pid == 0) {
931		TRACE(("Child shell %d\n", (int)getpid()));
932		if (setjmp(jmploc.loc))
933			_exit(exception == EXEXEC ? exerrno : 2);
934		if (pip != NULL) {
935			close(pip[0]);
936			if (pip[1] != 1) {
937				dup2(pip[1], 1);
938				close(pip[1]);
939			}
940		}
941		handler = &jmploc;
942		shellexec(argv, envp, path, idx);
943	}
944	handler = savehandler;
945	if (jp) {
946		struct procstat *ps = &jp->ps[jp->nprocs++];
947		ps->pid = pid;
948		ps->status = -1;
949		ps->cmd = nullstr;
950		jp->foreground = 1;
951#if JOBS
952		setcurjob(jp);
953#endif
954	}
955	INTON;
956	TRACE(("In parent shell:  child = %d\n", (int)pid));
957	return pid;
958}
959
960
961/*
962 * Wait for job to finish.
963 *
964 * Under job control we have the problem that while a child process is
965 * running interrupts generated by the user are sent to the child but not
966 * to the shell.  This means that an infinite loop started by an inter-
967 * active user may be hard to kill.  With job control turned off, an
968 * interactive user may place an interactive program inside a loop.  If
969 * the interactive program catches interrupts, the user doesn't want
970 * these interrupts to also abort the loop.  The approach we take here
971 * is to have the shell ignore interrupt signals while waiting for a
972 * foreground process to terminate, and then send itself an interrupt
973 * signal if the child process was terminated by an interrupt signal.
974 * Unfortunately, some programs want to do a bit of cleanup and then
975 * exit on interrupt; unless these processes terminate themselves by
976 * sending a signal to themselves (instead of calling exit) they will
977 * confuse this approach.
978 */
979
980int
981waitforjob(struct job *jp, int *origstatus)
982{
983#if JOBS
984	pid_t mypgrp = getpgrp();
985	int propagate_int = jp->jobctl && jp->foreground;
986#endif
987	int status;
988	int st;
989
990	INTOFF;
991	TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
992	while (jp->state == 0)
993		if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG : 0), jp) == -1)
994			dotrap();
995#if JOBS
996	if (jp->jobctl) {
997		if (tcsetpgrp(ttyfd, mypgrp) < 0)
998			error("tcsetpgrp failed, errno=%d\n", errno);
999	}
1000	if (jp->state == JOBSTOPPED)
1001		setcurjob(jp);
1002#endif
1003	status = jp->ps[jp->nprocs - 1].status;
1004	if (origstatus != NULL)
1005		*origstatus = status;
1006	/* convert to 8 bits */
1007	if (WIFEXITED(status))
1008		st = WEXITSTATUS(status);
1009#if JOBS
1010	else if (WIFSTOPPED(status))
1011		st = WSTOPSIG(status) + 128;
1012#endif
1013	else
1014		st = WTERMSIG(status) + 128;
1015	if (! JOBS || jp->state == JOBDONE)
1016		freejob(jp);
1017	if (int_pending()) {
1018		if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGINT)
1019			CLEAR_PENDING_INT;
1020	}
1021#if JOBS
1022	else if (rootshell && iflag && propagate_int &&
1023			WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
1024		kill(getpid(), SIGINT);
1025#endif
1026	INTON;
1027	return st;
1028}
1029
1030
1031static void
1032dummy_handler(int sig __unused)
1033{
1034}
1035
1036/*
1037 * Wait for a process to terminate.
1038 */
1039
1040static pid_t
1041dowait(int mode, struct job *job)
1042{
1043	struct sigaction sa, osa;
1044	sigset_t mask, omask;
1045	pid_t pid;
1046	int status;
1047	struct procstat *sp;
1048	struct job *jp;
1049	struct job *thisjob;
1050	const char *sigstr;
1051	int done;
1052	int stopped;
1053	int sig;
1054	int coredump;
1055	int wflags;
1056	int restore_sigchld;
1057
1058	TRACE(("dowait(%d, %p) called\n", mode, job));
1059	restore_sigchld = 0;
1060	if ((mode & DOWAIT_SIG) != 0) {
1061		sigfillset(&mask);
1062		sigprocmask(SIG_BLOCK, &mask, &omask);
1063		INTOFF;
1064		if (!issigchldtrapped()) {
1065			restore_sigchld = 1;
1066			sa.sa_handler = dummy_handler;
1067			sa.sa_flags = 0;
1068			sigemptyset(&sa.sa_mask);
1069			sigaction(SIGCHLD, &sa, &osa);
1070		}
1071	}
1072	do {
1073#if JOBS
1074		if (iflag)
1075			wflags = WUNTRACED | WCONTINUED;
1076		else
1077#endif
1078			wflags = 0;
1079		if ((mode & (DOWAIT_BLOCK | DOWAIT_SIG)) != DOWAIT_BLOCK)
1080			wflags |= WNOHANG;
1081		pid = wait3(&status, wflags, (struct rusage *)NULL);
1082		TRACE(("wait returns %d, status=%d\n", (int)pid, status));
1083		if (pid == 0 && (mode & DOWAIT_SIG) != 0) {
1084			sigsuspend(&omask);
1085			pid = -1;
1086			if (int_pending())
1087				break;
1088		}
1089	} while (pid == -1 && errno == EINTR && breakwaitcmd == 0);
1090	if (pid == -1 && errno == ECHILD && job != NULL)
1091		job->state = JOBDONE;
1092	if ((mode & DOWAIT_SIG) != 0) {
1093		if (restore_sigchld)
1094			sigaction(SIGCHLD, &osa, NULL);
1095		sigprocmask(SIG_SETMASK, &omask, NULL);
1096		INTON;
1097	}
1098	if (breakwaitcmd != 0) {
1099		breakwaitcmd = 0;
1100		if (pid <= 0)
1101			return -1;
1102	}
1103	if (pid <= 0)
1104		return pid;
1105	INTOFF;
1106	thisjob = NULL;
1107	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
1108		if (jp->used && jp->nprocs > 0) {
1109			done = 1;
1110			stopped = 1;
1111			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
1112				if (sp->pid == -1)
1113					continue;
1114				if (sp->pid == pid) {
1115					TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
1116						   (int)pid, sp->status,
1117						   status));
1118					if (WIFCONTINUED(status)) {
1119						sp->status = -1;
1120						jp->state = 0;
1121					} else
1122						sp->status = status;
1123					thisjob = jp;
1124				}
1125				if (sp->status == -1)
1126					stopped = 0;
1127				else if (WIFSTOPPED(sp->status))
1128					done = 0;
1129			}
1130			if (stopped) {		/* stopped or done */
1131				int state = done? JOBDONE : JOBSTOPPED;
1132				if (jp->state != state) {
1133					TRACE(("Job %td: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
1134					jp->state = state;
1135					if (jp != job) {
1136						if (done && !jp->remembered &&
1137						    !iflag && jp != bgjob)
1138							freejob(jp);
1139#if JOBS
1140						else if (done)
1141							deljob(jp);
1142#endif
1143					}
1144				}
1145			}
1146		}
1147	}
1148	INTON;
1149	if (!thisjob || thisjob->state == 0)
1150		;
1151	else if ((!rootshell || !iflag || thisjob == job) &&
1152	    thisjob->foreground && thisjob->state != JOBSTOPPED) {
1153		sig = 0;
1154		coredump = 0;
1155		for (sp = thisjob->ps; sp < thisjob->ps + thisjob->nprocs; sp++)
1156			if (WIFSIGNALED(sp->status)) {
1157				sig = WTERMSIG(sp->status);
1158				coredump = WCOREDUMP(sp->status);
1159			}
1160		if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
1161			sigstr = strsignal(sig);
1162			if (sigstr != NULL)
1163				out2str(sigstr);
1164			else
1165				out2str("Unknown signal");
1166			if (coredump)
1167				out2str(" (core dumped)");
1168			out2c('\n');
1169			flushout(out2);
1170		}
1171	} else {
1172		TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
1173		thisjob->changed = 1;
1174	}
1175	return pid;
1176}
1177
1178
1179
1180/*
1181 * return 1 if there are stopped jobs, otherwise 0
1182 */
1183int job_warning = 0;
1184int
1185stoppedjobs(void)
1186{
1187	int jobno;
1188	struct job *jp;
1189
1190	if (job_warning)
1191		return (0);
1192	for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
1193		if (jp->used == 0)
1194			continue;
1195		if (jp->state == JOBSTOPPED) {
1196			out2fmt_flush("You have stopped jobs.\n");
1197			job_warning = 2;
1198			return (1);
1199		}
1200	}
1201
1202	return (0);
1203}
1204
1205
1206static void
1207checkzombies(void)
1208{
1209	while (njobs > 0 && dowait(0, NULL) > 0)
1210		;
1211}
1212
1213
1214int
1215backgndpidset(void)
1216{
1217	return backgndpid != -1;
1218}
1219
1220
1221pid_t
1222backgndpidval(void)
1223{
1224	if (bgjob != NULL && !forcelocal)
1225		bgjob->remembered = 1;
1226	return backgndpid;
1227}
1228
1229/*
1230 * Return a string identifying a command (to be printed by the
1231 * jobs command.
1232 */
1233
1234static char *cmdnextc;
1235static int cmdnleft;
1236#define MAXCMDTEXT	200
1237
1238char *
1239commandtext(union node *n)
1240{
1241	char *name;
1242
1243	cmdnextc = name = ckmalloc(MAXCMDTEXT);
1244	cmdnleft = MAXCMDTEXT - 4;
1245	cmdtxt(n);
1246	*cmdnextc = '\0';
1247	return name;
1248}
1249
1250
1251static void
1252cmdtxt(union node *n)
1253{
1254	union node *np;
1255	struct nodelist *lp;
1256	const char *p;
1257	int i;
1258	char s[2];
1259
1260	if (n == NULL)
1261		return;
1262	switch (n->type) {
1263	case NSEMI:
1264		cmdtxt(n->nbinary.ch1);
1265		cmdputs("; ");
1266		cmdtxt(n->nbinary.ch2);
1267		break;
1268	case NAND:
1269		cmdtxt(n->nbinary.ch1);
1270		cmdputs(" && ");
1271		cmdtxt(n->nbinary.ch2);
1272		break;
1273	case NOR:
1274		cmdtxt(n->nbinary.ch1);
1275		cmdputs(" || ");
1276		cmdtxt(n->nbinary.ch2);
1277		break;
1278	case NPIPE:
1279		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
1280			cmdtxt(lp->n);
1281			if (lp->next)
1282				cmdputs(" | ");
1283		}
1284		break;
1285	case NSUBSHELL:
1286		cmdputs("(");
1287		cmdtxt(n->nredir.n);
1288		cmdputs(")");
1289		break;
1290	case NREDIR:
1291	case NBACKGND:
1292		cmdtxt(n->nredir.n);
1293		break;
1294	case NIF:
1295		cmdputs("if ");
1296		cmdtxt(n->nif.test);
1297		cmdputs("; then ");
1298		cmdtxt(n->nif.ifpart);
1299		cmdputs("...");
1300		break;
1301	case NWHILE:
1302		cmdputs("while ");
1303		goto until;
1304	case NUNTIL:
1305		cmdputs("until ");
1306until:
1307		cmdtxt(n->nbinary.ch1);
1308		cmdputs("; do ");
1309		cmdtxt(n->nbinary.ch2);
1310		cmdputs("; done");
1311		break;
1312	case NFOR:
1313		cmdputs("for ");
1314		cmdputs(n->nfor.var);
1315		cmdputs(" in ...");
1316		break;
1317	case NCASE:
1318		cmdputs("case ");
1319		cmdputs(n->ncase.expr->narg.text);
1320		cmdputs(" in ...");
1321		break;
1322	case NDEFUN:
1323		cmdputs(n->narg.text);
1324		cmdputs("() ...");
1325		break;
1326	case NNOT:
1327		cmdputs("! ");
1328		cmdtxt(n->nnot.com);
1329		break;
1330	case NCMD:
1331		for (np = n->ncmd.args ; np ; np = np->narg.next) {
1332			cmdtxt(np);
1333			if (np->narg.next)
1334				cmdputs(" ");
1335		}
1336		for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
1337			cmdputs(" ");
1338			cmdtxt(np);
1339		}
1340		break;
1341	case NARG:
1342		cmdputs(n->narg.text);
1343		break;
1344	case NTO:
1345		p = ">";  i = 1;  goto redir;
1346	case NAPPEND:
1347		p = ">>";  i = 1;  goto redir;
1348	case NTOFD:
1349		p = ">&";  i = 1;  goto redir;
1350	case NCLOBBER:
1351		p = ">|"; i = 1; goto redir;
1352	case NFROM:
1353		p = "<";  i = 0;  goto redir;
1354	case NFROMTO:
1355		p = "<>";  i = 0;  goto redir;
1356	case NFROMFD:
1357		p = "<&";  i = 0;  goto redir;
1358redir:
1359		if (n->nfile.fd != i) {
1360			s[0] = n->nfile.fd + '0';
1361			s[1] = '\0';
1362			cmdputs(s);
1363		}
1364		cmdputs(p);
1365		if (n->type == NTOFD || n->type == NFROMFD) {
1366			if (n->ndup.dupfd >= 0)
1367				s[0] = n->ndup.dupfd + '0';
1368			else
1369				s[0] = '-';
1370			s[1] = '\0';
1371			cmdputs(s);
1372		} else {
1373			cmdtxt(n->nfile.fname);
1374		}
1375		break;
1376	case NHERE:
1377	case NXHERE:
1378		cmdputs("<<...");
1379		break;
1380	default:
1381		cmdputs("???");
1382		break;
1383	}
1384}
1385
1386
1387
1388static void
1389cmdputs(const char *s)
1390{
1391	const char *p;
1392	char *q;
1393	char c;
1394	int subtype = 0;
1395
1396	if (cmdnleft <= 0)
1397		return;
1398	p = s;
1399	q = cmdnextc;
1400	while ((c = *p++) != '\0') {
1401		if (c == CTLESC)
1402			*q++ = *p++;
1403		else if (c == CTLVAR) {
1404			*q++ = '$';
1405			if (--cmdnleft > 0)
1406				*q++ = '{';
1407			subtype = *p++;
1408			if ((subtype & VSTYPE) == VSLENGTH && --cmdnleft > 0)
1409				*q++ = '#';
1410		} else if (c == '=' && subtype != 0) {
1411			*q = "}-+?=##%%\0X"[(subtype & VSTYPE) - VSNORMAL];
1412			if (*q)
1413				q++;
1414			else
1415				cmdnleft++;
1416			if (((subtype & VSTYPE) == VSTRIMLEFTMAX ||
1417			    (subtype & VSTYPE) == VSTRIMRIGHTMAX) &&
1418			    --cmdnleft > 0)
1419				*q = q[-1], q++;
1420			subtype = 0;
1421		} else if (c == CTLENDVAR) {
1422			*q++ = '}';
1423		} else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE) {
1424			cmdnleft -= 5;
1425			if (cmdnleft > 0) {
1426				*q++ = '$';
1427				*q++ = '(';
1428				*q++ = '.';
1429				*q++ = '.';
1430				*q++ = '.';
1431				*q++ = ')';
1432			}
1433		} else if (c == CTLARI) {
1434			cmdnleft -= 2;
1435			if (cmdnleft > 0) {
1436				*q++ = '$';
1437				*q++ = '(';
1438				*q++ = '(';
1439			}
1440			p++;
1441		} else if (c == CTLENDARI) {
1442			if (--cmdnleft > 0) {
1443				*q++ = ')';
1444				*q++ = ')';
1445			}
1446		} else if (c == CTLQUOTEMARK || c == CTLQUOTEEND)
1447			cmdnleft++; /* ignore */
1448		else
1449			*q++ = c;
1450		if (--cmdnleft <= 0) {
1451			*q++ = '.';
1452			*q++ = '.';
1453			*q++ = '.';
1454			break;
1455		}
1456	}
1457	cmdnextc = q;
1458}
1459