[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