[Midnightbsd-cvs] src: bin/sh: Merge changes from FreeBSD and NetBSD.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun Jun 29 20:40:10 EDT 2008


Log Message:
-----------
Merge changes from FreeBSD and NetBSD.

Support for command -v and -V
Fixes for erre option
A fix for a crash caused by SIGINT
POSIX compliant set +o output
A fix for unalias' exit code.
Man page updates.

Code cleanup, WANRS 3

Modified Files:
--------------
    src/bin/sh:
        builtins.def (r1.2 -> r1.3)
        cd.c (r1.3 -> r1.4)
        eval.c (r1.2 -> r1.3)
        exec.c (r1.2 -> r1.3)
        exec.h (r1.2 -> r1.3)
        expand.c (r1.2 -> r1.3)
        input.c (r1.2 -> r1.3)
        jobs.c (r1.2 -> r1.3)
        jobs.h (r1.2 -> r1.3)
        main.c (r1.2 -> r1.3)
        mkbuiltins (r1.2 -> r1.3)
        options.c (r1.2 -> r1.3)
        parser.c (r1.2 -> r1.3)
        parser.h (r1.2 -> r1.3)
        sh.1 (r1.2 -> r1.3)
        var.c (r1.2 -> r1.3)
        var.h (r1.2 -> r1.3)

-------------- next part --------------
Index: mkbuiltins
===================================================================
RCS file: /home/cvs/src/bin/sh/mkbuiltins,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/mkbuiltins -L bin/sh/mkbuiltins -u -r1.2 -r1.3
--- bin/sh/mkbuiltins
+++ bin/sh/mkbuiltins
@@ -67,9 +67,14 @@
 
 const struct builtincmd builtincmd[] = {'
 awk '{	for (i = 2 ; i <= NF ; i++) {
-		printf "\t{ \"%s\", %d },\n",  $i, NR-1
+		if ($i == "-s") {
+			spc = 1;
+		} else {
+			printf "\t{ \"%s\", %d, %d },\n",  $i, NR-1, spc
+			spc = 0;
+		}
 	}}' $temp
-echo '	{ NULL, 0 }
+echo '	{ NULL, 0, 0 }
 };'
 
 exec > ${objdir}/builtins.h
@@ -86,6 +91,7 @@
 struct builtincmd {
       char *name;
       int code;
+      int special;
 };
 
 extern int (*const builtinfunc[])(int, char **);
Index: expand.c
===================================================================
RCS file: /home/cvs/src/bin/sh/expand.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/expand.c -L bin/sh/expand.c -u -r1.2 -r1.3
--- bin/sh/expand.c
+++ bin/sh/expand.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/expand.c,v 1.47.2.1 2005/11/06 20:39:47 stefanf Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/expand.c,v 1.47.2.3 2006/11/22 00:28:04 stefanf Exp $");
 
 #include <sys/types.h>
 #include <sys/time.h>
@@ -99,7 +99,7 @@
 STATIC int subevalvar(char *, char *, int, int, int, int);
 STATIC char *evalvar(char *, int);
 STATIC int varisset(char *, int);
-STATIC void varvalue(char *, int, int);
+STATIC void varvalue(char *, int, int, int);
 STATIC void recordregion(int, int, int);
 STATIC void removerecordregions(int); 
 STATIC void ifsbreakup(char *, struct arglist *);
@@ -634,7 +634,7 @@
 	int easy;
 	int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
 
-	varflags = *p++;
+	varflags = (unsigned char)*p++;
 	subtype = varflags & VSTYPE;
 	var = p;
 	special = 0;
@@ -670,7 +670,7 @@
 	if (set && subtype != VSPLUS) {
 		/* insert the value of the variable */
 		if (special) {
-			varvalue(var, varflags & VSQUOTE, flag & EXP_FULL);
+			varvalue(var, varflags & VSQUOTE, subtype, flag);
 			if (subtype == VSLENGTH) {
 				varlen = expdest - stackblock() - startloc;
 				STADJUST(-varlen, expdest);
@@ -764,6 +764,11 @@
 			goto record;
 		break;
 
+	case VSERROR:
+		c = p - var - 1;
+		error("${%.*s%s}: Bad substitution", c, var,
+		    (c > 0 && *p != CTLENDVAR) ? "..." : "");
+
 	default:
 		abort();
 	}
@@ -837,7 +842,7 @@
  */
 
 STATIC void
-varvalue(char *name, int quoted, int allow_split)
+varvalue(char *name, int quoted, int subtype, int flag)
 {
 	int num;
 	char *p;
@@ -849,7 +854,7 @@
 
 #define STRTODEST(p) \
 	do {\
-	if (allow_split) { \
+	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \
 		syntax = quoted? DQSYNTAX : BASESYNTAX; \
 		while (*p) { \
 			if (syntax[(int)*p] == CCTL) \
@@ -884,7 +889,7 @@
 		}
 		break;
 	case '@':
-		if (allow_split && quoted) {
+		if (flag & EXP_FULL && quoted) {
 			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
 				STRTODEST(p);
 				if (*ap)
Index: exec.c
===================================================================
RCS file: /home/cvs/src/bin/sh/exec.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/exec.c -L bin/sh/exec.c -u -r1.2 -r1.3
--- bin/sh/exec.c
+++ bin/sh/exec.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/exec.c,v 1.25.2.1 2005/11/06 20:39:47 stefanf Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/exec.c,v 1.25.2.3 2007/02/04 10:42:30 stefanf Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -85,6 +85,7 @@
 struct tblentry {
 	struct tblentry *next;	/* next entry in hash chain */
 	union param param;	/* definition of builtin function */
+	int special;		/* flag for special builtin commands */
 	short cmdtype;		/* index identifying command */
 	char rehash;		/* if set, cd done since entry created */
 	char cmdname[ARB];	/* name of command */
@@ -318,6 +319,7 @@
 	struct stat statb;
 	int e;
 	int i;
+	int spec;
 
 	/* If name contains a slash, don't use the hash table */
 	if (strchr(name, '/') != NULL) {
@@ -331,11 +333,12 @@
 		goto success;
 
 	/* If %builtin not in path, check for builtin next */
-	if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
+	if (builtinloc < 0 && (i = find_builtin(name, &spec)) >= 0) {
 		INTOFF;
 		cmdp = cmdlookup(name, 1);
 		cmdp->cmdtype = CMDBUILTIN;
 		cmdp->param.index = i;
+		cmdp->special = spec;
 		INTON;
 		goto success;
 	}
@@ -357,12 +360,13 @@
 		index++;
 		if (pathopt) {
 			if (prefix("builtin", pathopt)) {
-				if ((i = find_builtin(name)) < 0)
+				if ((i = find_builtin(name, &spec)) < 0)
 					goto loop;
 				INTOFF;
 				cmdp = cmdlookup(name, 1);
 				cmdp->cmdtype = CMDBUILTIN;
 				cmdp->param.index = i;
+				cmdp->special = spec;
 				INTON;
 				goto success;
 			} else if (prefix("func", pathopt)) {
@@ -431,6 +435,7 @@
 	cmdp->rehash = 0;
 	entry->cmdtype = cmdp->cmdtype;
 	entry->u = cmdp->param;
+	entry->special = cmdp->special;
 }
 
 
@@ -440,13 +445,15 @@
  */
 
 int
-find_builtin(char *name)
+find_builtin(char *name, int *special)
 {
 	const struct builtincmd *bp;
 
 	for (bp = builtincmd ; bp->name ; bp++) {
-		if (*bp->name == *name && equal(bp->name, name))
+		if (*bp->name == *name && equal(bp->name, name)) {
+			*special = bp->special;
 			return bp->code;
+		}
 	}
 	return -1;
 }
@@ -774,14 +781,17 @@
 						" a tracked alias for" : "",
 					    name);
 			} else {
-				if (access(argv[i], X_OK) == 0) {
+				if (eaccess(argv[i], X_OK) == 0) {
 					if (cmd == TYPECMD_SMALLV)
 						out1fmt("%s\n", argv[i]);
 					else
 						out1fmt(" is %s\n", argv[i]);
+				} else {
+					if (cmd != TYPECMD_SMALLV)
+						out1fmt(": %s\n",
+						    strerror(errno));
+					error |= 127;
 				}
-				else
-					out1fmt(": %s\n", strerror(errno));
 			}
 			break;
 		}
Index: exec.h
===================================================================
RCS file: /home/cvs/src/bin/sh/exec.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/exec.h -L bin/sh/exec.h -u -r1.2 -r1.3
--- bin/sh/exec.h
+++ bin/sh/exec.h
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)exec.h	8.3 (Berkeley) 6/8/95
- * $FreeBSD: src/bin/sh/exec.h,v 1.12.8.1 2005/11/06 20:39:47 stefanf Exp $
+ * $FreeBSD: src/bin/sh/exec.h,v 1.12.8.2 2006/06/03 15:38:07 stefanf Exp $
  */
 
 /* values of cmdtype */
@@ -53,6 +53,7 @@
 		int index;
 		union node *func;
 	} u;
+	int special;
 };
 
 
@@ -63,7 +64,7 @@
 char *padvance(char **, char *);
 int hashcmd(int, char **);
 void find_command(char *, struct cmdentry *, int, char *);
-int find_builtin(char *);
+int find_builtin(char *, int *);
 void hashcd(void);
 void changepath(const char *);
 void deletefuncs(void);
Index: var.h
===================================================================
RCS file: /home/cvs/src/bin/sh/var.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/var.h -L bin/sh/var.h -u -r1.2 -r1.3
--- bin/sh/var.h
+++ bin/sh/var.h
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)var.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: src/bin/sh/var.h,v 1.12 2004/04/06 20:06:51 markm Exp $
+ * $FreeBSD: src/bin/sh/var.h,v 1.12.8.1 2006/11/22 00:11:11 stefanf Exp $
  */
 
 /*
@@ -75,6 +75,7 @@
 extern struct var vppid;
 extern struct var vps1;
 extern struct var vps2;
+extern struct var vps4;
 #ifndef NO_HISTORY
 extern struct var vhistsize;
 #endif
@@ -92,6 +93,7 @@
 #define pathval()	(vpath.text + 5)
 #define ps1val()	(vps1.text + 4)
 #define ps2val()	(vps2.text + 4)
+#define ps4val()	(vps4.text + 4)
 #define optindval()	(voptind.text + 7)
 #ifndef NO_HISTORY
 #define histsizeval()	(vhistsize.text + 9)
Index: options.c
===================================================================
RCS file: /home/cvs/src/bin/sh/options.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/options.c -L bin/sh/options.c -u -r1.2 -r1.3
--- bin/sh/options.c
+++ bin/sh/options.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.23.2.1 2005/11/06 20:39:48 stefanf Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/options.c,v 1.23.2.2 2006/06/03 15:38:07 stefanf Exp $");
 
 #include <signal.h>
 #include <unistd.h>
@@ -375,7 +375,7 @@
 	if (argc > 1)
 		n = number(argv[1]);
 	if (n > shellparam.nparam)
-		error("can't shift that many");
+		return 1;
 	INTOFF;
 	shellparam.nparam -= n;
 	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
Index: main.c
===================================================================
RCS file: /home/cvs/src/bin/sh/main.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/main.c -L bin/sh/main.c -u -r1.2 -r1.3
--- bin/sh/main.c
+++ bin/sh/main.c
@@ -43,7 +43,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26 2004/04/06 20:06:51 markm Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/main.c,v 1.26.8.2 2006/11/22 00:23:09 stefanf Exp $");
 
 #include <stdio.h>
 #include <signal.h>
@@ -210,7 +210,7 @@
 		inter = 0;
 		if (iflag && top) {
 			inter++;
-			showjobs(1, 0, 0);
+			showjobs(1, SHOWJOBS_DEFAULT);
 			chkmail(0);
 			flushout(&output);
 		}
@@ -315,19 +315,21 @@
 dotcmd(int argc, char **argv)
 {
 	struct strlist *sp;
+	char *fullname;
+
+	if (argc < 2)
+		error("missing filename");
+
 	exitstatus = 0;
 
 	for (sp = cmdenviron; sp ; sp = sp->next)
 		setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
 
-	if (argc >= 2) {		/* That's what SVR2 does */
-		char *fullname = find_dot_file(argv[1]);
-
-		setinputfile(fullname, 1);
-		commandname = fullname;
-		cmdloop(0);
-		popfile();
-	}
+	fullname = find_dot_file(argv[1]);
+	setinputfile(fullname, 1);
+	commandname = fullname;
+	cmdloop(0);
+	popfile();
 	return exitstatus;
 }
 
Index: jobs.h
===================================================================
RCS file: /home/cvs/src/bin/sh/jobs.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/jobs.h -L bin/sh/jobs.h -u -r1.2 -r1.3
--- bin/sh/jobs.h
+++ bin/sh/jobs.h
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
- * $FreeBSD: src/bin/sh/jobs.h,v 1.18 2004/04/06 20:06:51 markm Exp $
+ * $FreeBSD: src/bin/sh/jobs.h,v 1.18.8.1 2006/11/22 00:23:09 stefanf Exp $
  */
 
 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
@@ -75,6 +75,13 @@
 #endif
 };
 
+enum {
+	SHOWJOBS_DEFAULT,	/* job number, status, command */
+	SHOWJOBS_VERBOSE,	/* job number, PID, status, command */
+	SHOWJOBS_PIDS,		/* PID only */
+	SHOWJOBS_PGIDS		/* PID of the group leader only */
+};
+
 extern pid_t backgndpid;	/* pid of last background process */
 extern int job_warning;		/* user was warned about stopped jobs */
 extern int in_waitcmd;		/* are we in waitcmd()? */
@@ -85,7 +92,7 @@
 int fgcmd(int, char **);
 int bgcmd(int, char **);
 int jobscmd(int, char **);
-void showjobs(int, int, int);
+void showjobs(int, int);
 int waitcmd(int, char **);
 int jobidcmd(int, char **);
 struct job *makejob(union node *, int);
Index: eval.c
===================================================================
RCS file: /home/cvs/src/bin/sh/eval.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/eval.c -L bin/sh/eval.c -u -r1.2 -r1.3
--- bin/sh/eval.c
+++ bin/sh/eval.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/eval.c,v 1.42.8.2 2005/12/26 15:43:54 stefanf Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/eval.c,v 1.42.8.6 2007/10/26 10:23:27 stefanf Exp $");
 
 #include <paths.h>
 #include <signal.h>
@@ -368,6 +368,7 @@
 	setstackmark(&smark);
 	arglist.lastp = &arglist.list;
 	oexitstatus = exitstatus;
+	exitstatus = 0;
 	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
 	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
 		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
@@ -644,14 +645,19 @@
 
 	/* Print the command if xflag is set. */
 	if (xflag) {
-		outc('+', &errout);
+		char sep = 0;
+		out2str(ps4val());
 		for (sp = varlist.list ; sp ; sp = sp->next) {
-			outc(' ', &errout);
+			if (sep != 0)
+				outc(' ', &errout);
 			out2str(sp->text);
+			sep = ' ';
 		}
 		for (sp = arglist.list ; sp ; sp = sp->next) {
-			outc(' ', &errout);
+			if (sep != 0)
+				outc(' ', &errout);
 			out2str(sp->text);
+			sep = ' ';
 		}
 		outc('\n', &errout);
 		flushout(&errout);
@@ -659,8 +665,10 @@
 
 	/* Now locate the command. */
 	if (argc == 0) {
+		/* Variable assignment(s) without command */
 		cmdentry.cmdtype = CMDBUILTIN;
 		cmdentry.u.index = BLTINCMD;
+		cmdentry.special = 1;
 	} else {
 		static const char PATH[] = "PATH=";
 		char *path = pathval();
@@ -706,7 +714,8 @@
 				argv++;
 				if (--argc == 0)
 					break;
-				if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
+				if ((cmdentry.u.index = find_builtin(*argv,
+				    &cmdentry.special)) < 0) {
 					outfmt(&errout, "%s: not found\n", *argv);
 					exitstatus = 127;
 					flushout(&errout);
@@ -813,7 +822,6 @@
 			memout.bufsize = 64;
 			mode |= REDIR_BACKQ;
 		}
-		redirect(cmd->ncmd.redirect, mode);
 		savecmdname = commandname;
 		cmdenviron = varlist.list;
 		e = -1;
@@ -824,6 +832,9 @@
 		}
 		savehandler = handler;
 		handler = &jmploc;
+		redirect(cmd->ncmd.redirect, mode);
+		if (cmdentry.special)
+			listsetvar(cmdenviron);
 		commandname = argv[0];
 		argptr = argv + 1;
 		optptr = NULL;			/* initialize nextopt */
@@ -843,14 +854,7 @@
 		handler = savehandler;
 		if (e != -1) {
 			if ((e != EXERROR && e != EXEXEC)
-			   || cmdentry.u.index == BLTINCMD
-			   || cmdentry.u.index == DOTCMD
-			   || cmdentry.u.index == EVALCMD
-#ifndef NO_HISTORY
-			   || cmdentry.u.index == HISTCMD
-#endif
-			   || cmdentry.u.index == EXECCMD
-			   || cmdentry.u.index == COMMANDCMD)
+			    || cmdentry.special)
 				exraise(e);
 			FORCEINTON;
 		}
@@ -912,7 +916,7 @@
 {
 	struct cmdentry entry;
 
-	if (n->type == NCMD && n->ncmd.args)
+	if (n && n->type == NCMD && n->ncmd.args)
 		if (goodname(n->ncmd.args->narg.text))
 			find_command(n->ncmd.args->narg.text, &entry, 0,
 				     pathval());
@@ -926,14 +930,12 @@
  */
 
 /*
- * No command given, or a bltin command with no arguments.  Set the
- * specified variables.
+ * No command given, or a bltin command with no arguments.
  */
 
 int
 bltincmd(int argc __unused, char **argv __unused)
 {
-	listsetvar(cmdenviron);
 	/*
 	 * Preserve exitstatus of a previous possible redirection
 	 * as POSIX mandates
Index: parser.h
===================================================================
RCS file: /home/cvs/src/bin/sh/parser.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/parser.h -L bin/sh/parser.h -u -r1.2 -r1.3
--- bin/sh/parser.h
+++ bin/sh/parser.h
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)parser.h	8.3 (Berkeley) 5/4/95
- * $FreeBSD: src/bin/sh/parser.h,v 1.10 2004/04/06 20:06:51 markm Exp $
+ * $FreeBSD: src/bin/sh/parser.h,v 1.10.8.1 2006/11/22 00:26:06 stefanf Exp $
  */
 
 /* control characters in argument strings */
@@ -61,6 +61,7 @@
 #define VSTRIMRIGHT	0x8		/* ${var%pattern} */
 #define VSTRIMRIGHTMAX 	0x9		/* ${var%%pattern} */
 #define VSLENGTH	0xa		/* ${#var} */
+#define VSERROR		0xb		/* Syntax error, issue when expanded */
 
 
 /*
Index: builtins.def
===================================================================
RCS file: /home/cvs/src/bin/sh/builtins.def,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/builtins.def -L bin/sh/builtins.def -u -r1.2 -r1.3
--- bin/sh/builtins.def
+++ bin/sh/builtins.def
@@ -37,13 +37,15 @@
 
 #
 # This file lists all the builtin commands.  The first column is the name
-# of a C routine.  The -j flag, if present, specifies that this command
-# is to be excluded from systems without job control, and the -h flag,
-# if present specifies that this command is to be excluded from systems
-# based on the NO_HISTORY compile-time symbol.  The rest of the line
-# specifies the command name or names used to run the command.  The entry
-# for bltincmd, which is run when the user does not specify a command, must
-# come first.
+# of a C routine.
+# The -j flag specifies that this command is to be excluded from systems
+# without job control.
+# The -h flag specifies that this command is to be excluded from systems
+# based on the NO_HISTORY compile-time symbol.
+# The -s flag specifies that this is a POSIX 'special built-in' command.
+# The rest of the line specifies the command name or names used to run the
+# command.  The entry for bltincmd, which is run when the user does not specify
+# a command, must come first.
 #
 # NOTE: bltincmd must come first!
 
@@ -51,16 +53,16 @@
 aliascmd	alias
 bgcmd -j	bg
 bindcmd		bind
-breakcmd	break continue
+breakcmd	-s break -s continue
 cdcmd		cd chdir
 commandcmd	command
-dotcmd		.
+dotcmd		-s .
 echocmd		echo
-evalcmd		eval
-execcmd		exec
-exitcmd		exit
+evalcmd		-s eval
+execcmd		-s exec
+exitcmd		-s exit
 expcmd		exp let
-exportcmd	export readonly
+exportcmd	-s export -s readonly
 #exprcmd		expr
 falsecmd	false
 fgcmd -j	fg
@@ -73,18 +75,18 @@
 #printfcmd	printf
 pwdcmd		pwd
 readcmd		read
-returncmd	return
-setcmd		set
+returncmd	-s return
+setcmd		-s set
 setvarcmd	setvar
-shiftcmd	shift
+shiftcmd	-s shift
 testcmd		test [
-timescmd	times
-trapcmd		trap
-truecmd		: true
+timescmd	-s times
+trapcmd		-s trap
+truecmd		-s : true
 typecmd		type
 ulimitcmd	ulimit
 umaskcmd	umask
 unaliascmd	unalias
-unsetcmd	unset
+unsetcmd	-s unset
 waitcmd		wait
 wordexpcmd	wordexp
Index: jobs.c
===================================================================
RCS file: /home/cvs/src/bin/sh/jobs.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/jobs.c -L bin/sh/jobs.c -u -r1.2 -r1.3
--- bin/sh/jobs.c
+++ bin/sh/jobs.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/jobs.c,v 1.68.2.2 2006/01/12 05:24:46 maxim Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/jobs.c,v 1.68.2.3 2006/11/22 00:23:09 stefanf Exp $");
 
 #include <fcntl.h>
 #include <signal.h>
@@ -99,7 +99,7 @@
 STATIC void deljob(struct job *);
 STATIC struct job *getcurjob(struct job *);
 #endif
-STATIC void showjob(struct job *, pid_t, int, int);
+STATIC void showjob(struct job *, pid_t, int);
 
 
 /*
@@ -266,18 +266,21 @@
 jobscmd(int argc, char *argv[])
 {
 	char *id;
-	int ch, sformat, lformat;
+	int ch, mode;
 
 	optind = optreset = 1;
 	opterr = 0;
-	sformat = lformat = 0;
-	while ((ch = getopt(argc, argv, "ls")) != -1) {
+	mode = SHOWJOBS_DEFAULT;
+	while ((ch = getopt(argc, argv, "lps")) != -1) {
 		switch (ch) {
 		case 'l':
-			lformat = 1;
+			mode = SHOWJOBS_VERBOSE;
+			break;
+		case 'p':
+			mode = SHOWJOBS_PGIDS;
 			break;
 		case 's':
-			sformat = 1;
+			mode = SHOWJOBS_PIDS;
 			break;
 		case '?':
 		default:
@@ -288,24 +291,25 @@
 	argv += optind;
 
 	if (argc == 0)
-		showjobs(0, sformat, lformat);
+		showjobs(0, mode);
 	else
 		while ((id = *argv++) != NULL)
-			showjob(getjob(id), 0, sformat, lformat);
+			showjob(getjob(id), 0, mode);
 
 	return (0);
 }
 
 STATIC void
-showjob(struct job *jp, pid_t pid, int sformat, int lformat)
+showjob(struct job *jp, pid_t pid, int mode)
 {
 	char s[64];
 	struct procstat *ps;
 	struct job *j;
 	int col, curr, i, jobno, prev, procno;
+	pid_t ppid;
 	char c;
 
-	procno = jp->nprocs;
+	procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
 	jobno = jp - jobtab + 1;
 	curr = prev = 0;
 #if JOBS
@@ -316,11 +320,13 @@
 	}
 #endif
 	for (ps = jp->ps ; ; ps++) {	/* for each process */
-		if (sformat) {
-			out1fmt("%d\n", (int)ps->pid);
+		if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
+			ppid = (mode == SHOWJOBS_PIDS) ? ps->pid :
+			    getpgid(ps->pid);
+			out1fmt("%d\n", (int)ppid);
 			goto skip;
 		}
-		if (!lformat && ps != jp->ps && pid == 0)
+		if (mode != SHOWJOBS_VERBOSE && ps != jp->ps && pid == 0)
 			goto skip;
 		if (pid != 0 && pid != ps->pid)
 			goto skip;
@@ -336,7 +342,7 @@
 			fmtstr(s, 64, "    %c ", c);
 		out1str(s);
 		col = strlen(s);
-		if (lformat) {
+		if (mode == SHOWJOBS_VERBOSE) {
 			fmtstr(s, 64, "%d ", (int)ps->pid);
 			out1str(s);
 			col += strlen(s);
@@ -389,7 +395,7 @@
  */
 
 void
-showjobs(int change, int sformat, int lformat)
+showjobs(int change, int mode)
 {
 	int jobno;
 	struct job *jp;
@@ -405,7 +411,7 @@
 		}
 		if (change && ! jp->changed)
 			continue;
-		showjob(jp, 0, sformat, lformat);
+		showjob(jp, 0, mode);
 		jp->changed = 0;
 		if (jp->state == JOBDONE) {
 			freejob(jp);
@@ -993,7 +999,7 @@
 					out1str(" (core dumped)");
 				out1c('\n');
 			} else
-				showjob(thisjob, pid, 0, 0);
+				showjob(thisjob, pid, SHOWJOBS_DEFAULT);
 		}
 	} else {
 		TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
Index: parser.c
===================================================================
RCS file: /home/cvs/src/bin/sh/parser.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/parser.c -L bin/sh/parser.c -u -r1.2 -r1.3
--- bin/sh/parser.c
+++ bin/sh/parser.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/parser.c,v 1.52.2.1 2005/11/06 20:39:48 stefanf Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/parser.c,v 1.52.2.3 2006/11/22 00:26:06 stefanf Exp $");
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -953,6 +953,7 @@
 					USTPUTC('\\', out);
 					pungetc();
 				} else if (c == '\n') {
+					plinno++;
 					if (doprompt)
 						setprompt(2);
 					else
@@ -1228,12 +1229,17 @@
 				c = pgetc();
 			}
 		} else {
-			if (! is_special(c))
-badsub:				synerror("Bad substitution");
-			USTPUTC(c, out);
-			c = pgetc();
+			if (! is_special(c)) {
+				subtype = VSERROR;
+				if (c == '}')
+					pungetc();
+				else
+					USTPUTC(c, out);
+			} else {
+				USTPUTC(c, out);
+				c = pgetc();
+			}
 		}
-		STPUTC('=', out);
 		flags = 0;
 		if (subtype == 0) {
 			switch (c) {
@@ -1243,9 +1249,13 @@
 				/*FALLTHROUGH*/
 			default:
 				p = strchr(types, c);
-				if (p == NULL)
-					goto badsub;
-				subtype = p - types + VSNORMAL;
+				if (p == NULL) {
+					if (flags == VSNUL)
+						STPUTC(':', out);
+					STPUTC(c, out);
+					subtype = VSERROR;
+				} else
+					subtype = p - types + VSNORMAL;
 				break;
 			case '%':
 			case '#':
@@ -1261,9 +1271,10 @@
 					break;
 				}
 			}
-		} else {
+		} else if (subtype != VSERROR) {
 			pungetc();
 		}
+		STPUTC('=', out);
 		if (subtype != VSLENGTH && (dblquote || arinest))
 			flags |= VSQUOTE;
 		*(stackblock() + typeloc) = subtype | flags;
Index: sh.1
===================================================================
RCS file: /home/cvs/src/bin/sh/sh.1,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/sh.1 -L bin/sh/sh.1 -u -r1.2 -r1.3
--- bin/sh/sh.1
+++ bin/sh/sh.1
@@ -33,7 +33,7 @@
 .\" $FreeBSD: src/bin/sh/sh.1,v 1.102.2.2 2005/12/26 15:43:54 stefanf Exp $
 .\" $MidnightBSD$
 .\"
-.Dd December 8, 2005
+.Dd June 29, 2008
 .Dt SH 1
 .Os
 .Sh NAME
@@ -306,8 +306,9 @@
 Useful for debugging.
 .It Fl x Li xtrace
 Write each command
-(preceded by
-.Dq Li "+ " )
+(preceded by the value of the 
+.Ev PS4
+variable)
 to standard error before it is executed.
 Useful for debugging.
 .El
@@ -363,6 +364,13 @@
 .It Li <& Ta Li >& Ta Li <<- Ta Li >|
 .El
 .El
+.Pp
+The character
+.Ql #
+introduces a comment if used at the beginning of a word.
+The word starting with
+.Ql #
+and the rest of the line are ignored.
 .Ss Quoting
 Quoting is used to remove the special meaning of certain characters
 or words to the shell, such as operators, whitespace, keywords,
@@ -854,6 +862,10 @@
 separated by
 .Dq Li \&|
 characters.
+The exit code of the
+.Ic case
+command is the exit code of the last command executed in the list or
+zero if no patterns were matched.
 .Ss Grouping Commands Together
 Commands may be grouped by writing either
 .Bd -literal -offset indent
@@ -1354,9 +1366,8 @@
 are built-in because they need to perform some operation
 that cannot be performed by a separate process.
 In addition to
-these, a built-in version of the
-.Xr test 1
-command is provided for efficiency.
+these, built-in versions of essential utilities
+are provided for efficiency.
 .Bl -tag -width indent
 .It Ic \&:
 A null command that returns a 0 (true) exit value.
@@ -1378,6 +1389,9 @@
 If it is not found in the
 .Ev PATH ,
 it is sought in the current working directory.
+.It Ic \&[
+A built-in equivalent of
+.Xr test 1 .
 .It Ic alias Oo Ar name Ns Oo = Ns Ar string Oc ... Oc
 If
 .Ar name Ns = Ns Ar string
@@ -1612,6 +1626,8 @@
 option is specified, the exported variables are printed as
 .Dq Ic export Ar name Ns = Ns Ar value
 lines, suitable for re-input to the shell.
+.It Ic false
+A null command that returns a non-zero (false) exit value.
 .It Ic fc Oo Fl e Ar editor Oc Op Ar first Op Ar last
 .It Ic fc Fl l Oo Fl nr Oc Op Ar first Op Ar last
 .It Ic fc Fl s Oo Ar old Ns = Ns Ar new Oc Op Ar first
@@ -1766,7 +1782,7 @@
 If the
 .Ar job
 argument is omitted, use the current job.
-.It Ic jobs Oo Fl ls Oc Op Ar job ...
+.It Ic jobs Oo Fl lps Oc Op Ar job ...
 Print information about the specified jobs, or all jobs if no
 .Ar job
 argument is given.
@@ -1776,8 +1792,13 @@
 .Fl l
 option is specified, the PID of each job is also printed.
 If the
+.Fl p
+option is specified, only the process IDs for the process group leaders
+are printed, one per line.
+If the
 .Fl s
-option is specified, only the PIDs of the jobs are printed, one per line.
+option is specified, only the PIDs of the job commands are printed, one per
+line.
 .It Ic local Oo Ar variable ... Oc Op Fl
 See the
 .Sx Functions
@@ -1952,6 +1973,9 @@
 the value of $2 to the value of $3, and so on,
 decreasing the value of $# by one.
 If there are zero positional parameters, shifting does not do anything.
+.It Ic test
+A built-in equivalent of
+.Xr test 1 .
 .It Ic times
 Print the amount of time spent executing the shell and its children.
 The first output line shows the user and system times for the shell
@@ -1989,6 +2013,8 @@
 causes the
 .Ic trap
 command to display a list of valid signal names.
+.It Ic true
+A null command that returns a 0 (true) exit value.
 .It Ic type Op Ar name ...
 Interpret each
 .Ar name
@@ -2191,6 +2217,12 @@
 .It Ev PS2
 The secondary prompt string, which defaults to
 .Dq Li "> " .
+.It Ev PS4
+The prefix for the trace output (if
+.Fl x
+is active).
+The default is
+.Dq Li "+ " .
 .It Ev TERM
 The default terminal setting for the shell.
 This is inherited by children of the shell, and is used in the history
@@ -2222,8 +2254,23 @@
 .Sh HISTORY
 A
 .Nm
-command appeared in
+command, the Thompson shell, appeared in
 .At v1 .
+It was superseded in
+.At v7
+by the Bourne shell, which inherited the name
+.Nm .
+.Pp
+This version of
+.Nm
+was rewritten in 1989 under the
+.Bx
+license after the Bourne shell from
+.At V.4 .
+.Sh AUTHORS
+This version of
+.Nm
+was originally written by Kenneth Almquist.
 .Sh BUGS
 The
 .Nm
Index: input.c
===================================================================
RCS file: /home/cvs/src/bin/sh/input.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/input.c -L bin/sh/input.c -u -r1.2 -r1.3
--- bin/sh/input.c
+++ bin/sh/input.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22 2004/04/06 20:06:51 markm Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/input.c,v 1.22.8.1 2006/06/03 15:38:07 stefanf Exp $");
 
 #include <stdio.h>	/* defines BUFSIZ */
 #include <fcntl.h>
@@ -185,14 +185,23 @@
 retry:
 #ifndef NO_HISTORY
 	if (parsefile->fd == 0 && el) {
-		const char *rl_cp;
+		static const char *rl_cp;
+		static int el_len;
 
-		rl_cp = el_gets(el, &nr);
+		if (rl_cp == NULL)
+			rl_cp = el_gets(el, &el_len);
 		if (rl_cp == NULL)
 			nr = 0;
 		else {
-			/* XXX - BUFSIZE should redesign so not necessary */
-			(void) strcpy(parsenextc, rl_cp);
+			nr = el_len;
+			if (nr > BUFSIZ - 1)
+				nr = BUFSIZ - 1;
+			memcpy(parsenextc, rl_cp, nr);
+			if (nr != el_len) {
+				el_len -= nr;
+				rl_cp += nr;
+			} else
+				rl_cp = NULL;
 		}
 	} else
 #endif
Index: cd.c
===================================================================
RCS file: /home/cvs/src/bin/sh/cd.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L bin/sh/cd.c -L bin/sh/cd.c -u -r1.3 -r1.4
--- bin/sh/cd.c
+++ bin/sh/cd.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34 2004/04/06 20:06:51 markm Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/cd.c,v 1.34.8.1 2006/06/28 21:14:23 stefanf Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
Index: var.c
===================================================================
RCS file: /home/cvs/src/bin/sh/var.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L bin/sh/var.c -L bin/sh/var.c -u -r1.2 -r1.3
--- bin/sh/var.c
+++ bin/sh/var.c
@@ -37,7 +37,7 @@
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.27.2.1 2005/11/06 20:39:48 stefanf Exp $");
+__FBSDID("$FreeBSD: src/bin/sh/var.c,v 1.27.2.3 2006/11/22 00:11:11 stefanf Exp $");
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -89,6 +89,7 @@
 struct var vppid;
 struct var vps1;
 struct var vps2;
+struct var vps4;
 struct var vvers;
 STATIC struct var voptind;
 
@@ -112,6 +113,8 @@
 	 */
 	{ &vps2,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",
 	  NULL },
+	{ &vps4,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",
+	  NULL },
 	{ &voptind,	VSTRFIXED|VTEXTFIXED,		"OPTIND=1",
 	  getoptsreset },
 	{ NULL,	0,				NULL,
@@ -480,6 +483,21 @@
 }
 
 
+static int
+var_compare(const void *a, const void *b)
+{
+	const char *const *sa, *const *sb;
+
+	sa = a;
+	sb = b;
+	/*
+	 * This compares two var=value strings which creates a different
+	 * order from what you would probably expect.  POSIX is somewhat
+	 * ambiguous on what should be sorted exactly.
+	 */
+	return strcoll(*sa, *sb);
+}
+
 
 /*
  * Command to list all variables which are set.  Currently this command
@@ -493,18 +511,41 @@
 	struct var **vpp;
 	struct var *vp;
 	const char *s;
+	const char **vars;
+	int i, n;
 
-	for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
-		for (vp = *vpp ; vp ; vp = vp->next) {
-			if (vp->flags & VUNSET)
-				continue;
-			for (s = vp->text; *s != '='; s++)
-				out1c(*s);
-			out1c('=');
-			out1qstr(s + 1);
-			out1c('\n');
+	/*
+	 * POSIX requires us to sort the variables.
+	 */
+	n = 0;
+	for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
+		for (vp = *vpp; vp; vp = vp->next) {
+			if (!(vp->flags & VUNSET))
+				n++;
+		}
+	}
+
+	INTON;
+	vars = ckmalloc(n * sizeof(*vars));
+	i = 0;
+	for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
+		for (vp = *vpp; vp; vp = vp->next) {
+			if (!(vp->flags & VUNSET))
+				vars[i++] = vp->text;
 		}
 	}
+
+	qsort(vars, n, sizeof(*vars), var_compare);
+	for (i = 0; i < n; i++) {
+		for (s = vars[i]; *s != '='; s++)
+			out1c(*s);
+		out1c('=');
+		out1qstr(s + 1);
+		out1c('\n');
+	}
+	ckfree(vars);
+	INTOFF;
+
 	return 0;
 }
 


More information about the Midnightbsd-cvs mailing list