Use -s to flag POSIX's "special built-in" utilities in builtins.def. Add a
authorPeter Avalos <pavalos@dragonflybsd.org>
Sun, 7 Jan 2007 01:14:53 +0000 (01:14 +0000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Sun, 7 Jan 2007 01:14:53 +0000 (01:14 +0000)
new member to struct builtincmd and set it to 1 if -s was specified.  This
is done because there are cases where special builtins must be treated
differently from other builtins.

Implement some of the differences between special built-ins and other builtins
demanded by POSIX.
- A redirection error is only fatal (meaning the execution of a shell script is
  terminated) for special built-ins.  Previously it was fatal for all shell
  builtins, causing problems like the one reported in FreeBSD PR 88845.
- Variable assignments remain in effect for special built-ins.
- Option or operand errors are only fatal for special built-ins.

Add the times builtin.  It reports the user and system time for the shell
itself and its children.  Instead of calling times() (as implied by POSIX) this
implementation directly calls getrusage() to get the times because this is more
convenient.

Print pointers with %p rather than casting them to long.

Replace home-grown dup2() implementation with actual dup2() calls.  This
should slightly reduce the number of system calls in critical portions of
the shell, and select a more efficient path through the fdalloc code.

Implement the PS4 variable which is defined by the POSIX User Portability
Utilities option.  Its value is printed at the beginning of the line if tracing
(-x) is active.  PS4 defaults to the string "+ " which is compatible with the
old behaviour to always print "+ ".

Don't crash on "<cmd> | { }".

Remove some white space at EOL.

Add the POSIX options -v and -V to the 'command' builtin.  Both describe the
type of their argument, if it is a shell function, an alias, a builtin, etc.
-V is more verbose than -v.

Do not assume there is only a space between #define and the macro name
when grepping for JOBS in mkbuiltins

Obtained-from:  FreeBSD

bin/sh/builtins.def
bin/sh/eval.c
bin/sh/eval.h
bin/sh/exec.c
bin/sh/exec.h
bin/sh/mkbuiltins
bin/sh/options.c
bin/sh/sh.1
bin/sh/var.c
bin/sh/var.h

index 38b1dc3..323395f 100644 (file)
@@ -1,5 +1,6 @@
 #!/bin/sh -
-#
+
+#-
 # Copyright (c) 1991, 1993
 #      The Regents of the University of California.  All rights reserved.
 #
 #
 #      @(#)builtins.def        8.4 (Berkeley) 5/4/95
 # $FreeBSD: src/bin/sh/builtins.def,v 1.7.2.2 2002/08/27 01:36:28 tjr Exp $
-# $DragonFly: src/bin/sh/builtins.def,v 1.2 2003/06/17 04:22:50 dillon Exp $
+# $DragonFly: src/bin/sh/builtins.def,v 1.3 2007/01/07 01:14:53 pavalos Exp $
 
 #
 # 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!
 
@@ -54,16 +57,16 @@ bltincmd    builtin
 commandcmd     command
 #alloccmd      alloc
 bgcmd -j       bg
-breakcmd       break continue
+breakcmd       -s break -s continue
 #catfcmd       catf
 cdcmd          cd chdir
-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
 histcmd -h     fc
@@ -78,16 +81,17 @@ localcmd    local
 printfcmd      printf
 pwdcmd         pwd
 readcmd                read
-returncmd      return
-setcmd         set
+returncmd      -s return
+setcmd         -s set
 setvarcmd      setvar
-shiftcmd       shift
-trapcmd                trap
-truecmd                : true
+shiftcmd       -s shift
+timescmd       -s times
+trapcmd                -s trap
+truecmd                -s : true
 typecmd                type
 umaskcmd       umask
 unaliascmd     unalias
-unsetcmd       unset
+unsetcmd       -s unset
 waitcmd                wait
 #foocmd                foo
 aliascmd       alias
index 3cd8965..d1c89bc 100644 (file)
  * SUCH DAMAGE.
  *
  * @(#)eval.c  8.9 (Berkeley) 6/8/95
- * $FreeBSD: src/bin/sh/eval.c,v 1.27.2.5 2002/08/27 01:36:28 tjr Exp $
- * $DragonFly: src/bin/sh/eval.c,v 1.9 2006/09/28 22:29:44 pavalos Exp $
+ * $FreeBSD: src/bin/sh/eval.c,v 1.53 2006/06/15 07:57:05 stefanf Exp $
+ * $DragonFly: src/bin/sh/eval.c,v 1.10 2007/01/07 01:14:53 pavalos Exp $
  */
 
+#include <sys/resource.h>
 #include <sys/wait.h> /* For WIFSIGNALED(status) */
 
 #include <errno.h>
@@ -194,7 +195,7 @@ evaltree(union node *n, int flags)
 #ifndef NO_HISTORY
        displayhist = 1;        /* show history substitutions done with fc */
 #endif
-       TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
+       TRACE(("evaltree(%p: %d) called\n", (void *)n, n->type));
        switch (n->type) {
        case NSEMI:
                evaltree(n->nbinary.ch1, flags & ~EV_EXIT);
@@ -462,7 +463,7 @@ evalpipe(union node *n)
        int prevfd;
        int pip[2];
 
-       TRACE(("evalpipe(0x%lx) called\n", (long)n));
+       TRACE(("evalpipe(%p) called\n", (void *)n));
        pipelen = 0;
        for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
                pipelen++;
@@ -482,16 +483,14 @@ evalpipe(union node *n)
                if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
                        INTON;
                        if (prevfd > 0) {
-                               close(0);
-                               copyfd(prevfd, 0);
+                               dup2(prevfd, 0);
                                close(prevfd);
                        }
                        if (pip[1] >= 0) {
                                if (!(prevfd >= 0 && pip[0] == 0))
                                        close(pip[0]);
                                if (pip[1] != 1) {
-                                       close(1);
-                                       copyfd(pip[1], 1);
+                                       dup2(pip[1], 1);
                                        close(pip[1]);
                                }
                        }
@@ -548,8 +547,7 @@ evalbackcmd(union node *n, struct backcmd *result)
                        FORCEINTON;
                        close(pip[0]);
                        if (pip[1] != 1) {
-                               close(1);
-                               copyfd(pip[1], 1);
+                               dup2(pip[1], 1);
                                close(pip[1]);
                        }
                        evaltree(n, EV_EXIT);
@@ -560,7 +558,7 @@ evalbackcmd(union node *n, struct backcmd *result)
        }
 out:
        popstackmark(&smark);
-       TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
+       TRACE(("evalbackcmd done: fd=%d buf=%p nleft=%d jp=%p\n",
                result->fd, result->buf, result->nleft, result->jp));
 }
 
@@ -605,7 +603,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 #endif
 
        /* First expand the arguments. */
-       TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
+       TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags));
        setstackmark(&smark);
        arglist.lastp = &arglist.list;
        varlist.lastp = &varlist.list;
@@ -647,14 +645,19 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 
        /* 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);
@@ -662,8 +665,10 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
 
        /* 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=";
                const char *path = pathval();
@@ -675,15 +680,15 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
                for (sp = varlist.list ; sp ; sp = sp->next)
                        if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
                                path = sp->text + sizeof(PATH) - 1;
-                               /* 
+                               /*
                                 * On `PATH=... command`, we need to make
                                 * sure that the command isn't using the
                                 * non-updated hash table of the outer PATH
-                                * setting and we need to make sure that 
+                                * setting and we need to make sure that
                                 * the hash table isn't filled with items
                                 * from the temporary setting.
                                 *
-                                * It would be better to forbit using and 
+                                * It would be better to forbit using and
                                 * updating the table while this command
                                 * runs, by the command finding mechanism
                                 * is heavily integrated with hash handling,
@@ -691,7 +696,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
                                 * the command runs. Partly deleting like
                                 * changepatch() does doesn't seem worth the
                                 * bookinging effort, since most such runs add
-                                * diretories in front of the new PATH.
+                                * directories in front of the new PATH.
                                 */
                                clearcmdentry(0);
                                do_clearcmdentry = 1;
@@ -709,7 +714,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
                                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);
@@ -745,8 +751,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
                        FORCEINTON;
                        close(pip[0]);
                        if (pip[1] != 1) {
-                               close(1);
-                               copyfd(pip[1], 1);
+                               dup2(pip[1], 1);
                                close(pip[1]);
                        }
                }
@@ -817,7 +822,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
                        memout.bufsize = 64;
                        mode |= REDIR_BACKQ;
                }
-               redirect(cmd->ncmd.redirect, mode);
                savecmdname = commandname;
                cmdenviron = varlist.list;
                e = -1;
@@ -828,6 +832,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
                }
                savehandler = handler;
                handler = &jmploc;
+               redirect(cmd->ncmd.redirect, mode);
+               if (cmdentry.special)
+                       listsetvar(cmdenviron);
                commandname = argv[0];
                argptr = argv + 1;
                optptr = NULL;                  /* initialize nextopt */
@@ -847,14 +854,7 @@ cmddone:
                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;
                }
@@ -916,7 +916,7 @@ prehash(union node *n)
 {
        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());
@@ -930,14 +930,12 @@ prehash(union node *n)
  */
 
 /*
- * 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
@@ -982,6 +980,7 @@ commandcmd(int argc, char **argv)
        struct strlist *sp;
        const char *path;
        int ch;
+       int cmd = -1;
 
 #ifdef __GNUC__
        /* Avoid longjmp clobbering */
@@ -996,11 +995,17 @@ commandcmd(int argc, char **argv)
 
        optind = optreset = 1;
        opterr = 0;
-       while ((ch = getopt(argc, argv, "p")) != -1) {
+       while ((ch = getopt(argc, argv, "pvV")) != -1) {
                switch (ch) {
                case 'p':
                        path = stdpath;
                        break;
+               case 'v':
+                       cmd = TYPECMD_SMALLV;
+                       break;
+               case 'V':
+                       cmd = TYPECMD_BIGV;
+                       break;
                case '?':
                default:
                        error("unknown option: -%c", optopt);
@@ -1009,6 +1014,11 @@ commandcmd(int argc, char **argv)
        argc -= optind;
        argv += optind;
 
+       if (cmd != -1) {
+               if (argc != 1)
+                       error("wrong number of arguments");
+               return typecmd_impl(2, argv - 1, cmd);
+       }
        if (argc != 0) {
                old = handler;
                handler = &loc;
@@ -1079,3 +1089,28 @@ execcmd(int argc, char **argv)
        }
        return 0;
 }
+
+
+int
+timescmd(int argc __unused, char **argv __unused)
+{
+       struct rusage ru;
+       long shumins, shsmins, chumins, chsmins;
+       double shusecs, shssecs, chusecs, chssecs;
+
+       if (getrusage(RUSAGE_SELF, &ru) < 0)
+               return 1;
+       shumins = ru.ru_utime.tv_sec / 60;
+       shusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.;
+       shsmins = ru.ru_stime.tv_sec / 60;
+       shssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.;
+       if (getrusage(RUSAGE_CHILDREN, &ru) < 0)
+               return 1;
+       chumins = ru.ru_utime.tv_sec / 60;
+       chusecs = ru.ru_utime.tv_sec % 60 + ru.ru_utime.tv_usec / 1000000.;
+       chsmins = ru.ru_stime.tv_sec / 60;
+       chssecs = ru.ru_stime.tv_sec % 60 + ru.ru_stime.tv_usec / 1000000.;
+       out1fmt("%ldm%.3fs %ldm%.3fs\n%ldm%.3fs %ldm%.3fs\n", shumins,
+           shusecs, shsmins, shssecs, chumins, chusecs, chsmins, chssecs);
+       return 0;
+}
index 390fe74..04f0e2a 100644 (file)
@@ -34,8 +34,8 @@
  * SUCH DAMAGE.
  *
  *     @(#)eval.h      8.2 (Berkeley) 5/4/95
- * $FreeBSD: src/bin/sh/eval.h,v 1.7.2.2 2002/08/27 01:36:28 tjr Exp $
- * $DragonFly: src/bin/sh/eval.h,v 1.3 2004/03/19 18:39:41 cpressey Exp $
+ * $FreeBSD: src/bin/sh/eval.h,v 1.11 2005/12/04 18:44:21 stefanf Exp $
+ * $DragonFly: src/bin/sh/eval.h,v 1.4 2007/01/07 01:14:53 pavalos Exp $
  */
 
 extern const char *commandname;        /* currently executing command */
@@ -61,6 +61,7 @@ int returncmd(int, char **);
 int falsecmd(int, char **);
 int truecmd(int, char **);
 int execcmd(int, char **);
+int timescmd(int, char **);
 int commandcmd(int, char **);
 
 /* in_function returns nonzero if we are currently evaluating a function */
index bc43ec7..d762ae9 100644 (file)
@@ -34,8 +34,8 @@
  * SUCH DAMAGE.
  *
  * @(#)exec.c  8.4 (Berkeley) 6/8/95
- * $FreeBSD: src/bin/sh/exec.c,v 1.14.2.4 2002/08/27 01:36:28 tjr Exp $
- * $DragonFly: src/bin/sh/exec.c,v 1.9 2007/01/06 03:44:04 pavalos Exp $
+ * $FreeBSD: src/bin/sh/exec.c,v 1.29 2006/04/09 12:21:20 stefanf Exp $
+ * $DragonFly: src/bin/sh/exec.c,v 1.10 2007/01/07 01:14:53 pavalos Exp $
  */
 
 #include <sys/types.h>
@@ -84,6 +84,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 @@ find_command(char *name, struct cmdentry *entry, int printerr, const char *path)
        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 @@ find_command(char *name, struct cmdentry *entry, int printerr, const char *path)
                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 @@ loop:
                idx++;
                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)) {
@@ -432,6 +436,7 @@ success:
                cmdp->rehash = 0;
                entry->cmdtype = cmdp->cmdtype;
                entry->u = cmdp->param;
+               entry->special = cmdp->special;
        } else
                entry->cmdtype = CMDUNKNOWN;
 }
@@ -443,13 +448,15 @@ success:
  */
 
 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;
 }
@@ -708,11 +715,12 @@ unsetfunc(char *name)
 }
 
 /*
- * Locate and print what a word is...
+ * Shared code for the following builtin commands:
+ *    type, command -v, command -V
  */
 
 int
-typecmd(int argc, char **argv)
+typecmd_impl(int argc, char **argv, int cmd)
 {
        struct cmdentry entry;
        struct tblentry *cmdp;
@@ -722,20 +730,28 @@ typecmd(int argc, char **argv)
        int err = 0;
 
        for (i = 1; i < argc; i++) {
-               out1str(argv[i]);
+               if (cmd != TYPECMD_SMALLV)
+                       out1str(argv[i]);
+
                /* First look at the keywords */
                for (pp = parsekwd; *pp; pp++)
                        if (**pp == *argv[i] && equal(*pp, argv[i]))
                                break;
 
                if (*pp) {
-                       out1str(" is a shell keyword\n");
+                       if (cmd == TYPECMD_SMALLV)
+                               out1fmt("%s\n", argv[i]);
+                       else
+                               out1str(" is a shell keyword\n");
                        continue;
                }
 
                /* Then look at the aliases */
                if ((ap = lookupalias(argv[i], 1)) != NULL) {
-                       out1fmt(" is an alias for %s\n", ap->val);
+                       if (cmd == TYPECMD_SMALLV)
+                               out1fmt("alias %s='%s'\n", argv[i], ap->val);
+                       else
+                               out1fmt(" is an alias for %s\n", ap->val);
                        continue;
                }
 
@@ -759,11 +775,19 @@ typecmd(int argc, char **argv)
                                        name = padvance(&path, argv[i]);
                                        stunalloc(name);
                                } while (--j >= 0);
-                               out1fmt(" is%s %s\n",
-                                   cmdp ? " a tracked alias for" : "", name);
+                               if (cmd == TYPECMD_SMALLV)
+                                       out1fmt("%s\n", name);
+                               else
+                                       out1fmt(" is%s %s\n",
+                                           (cmdp && cmd == TYPECMD_TYPE) ?
+                                               " a tracked alias for" : "",
+                                           name);
                        } else {
                                if (access(argv[i], X_OK) == 0) {
-                                       out1fmt(" is %s\n", argv[i]);
+                                       if (cmd == TYPECMD_SMALLV)
+                                               out1fmt("%s\n", argv[i]);
+                                       else
+                                               out1fmt(" is %s\n", argv[i]);
                                }
                                else {
                                        out1fmt(": %s\n", strerror(errno));
@@ -773,18 +797,35 @@ typecmd(int argc, char **argv)
                        break;
                }
                case CMDFUNCTION:
-                       out1str(" is a shell function\n");
+                       if (cmd == TYPECMD_SMALLV)
+                               out1fmt("%s\n", argv[i]);
+                       else
+                               out1str(" is a shell function\n");
                        break;
 
                case CMDBUILTIN:
-                       out1str(" is a shell builtin\n");
+                       if (cmd == TYPECMD_SMALLV)
+                               out1fmt("%s\n", argv[i]);
+                       else
+                               out1str(" is a shell builtin\n");
                        break;
 
                default:
-                       out1str(": not found\n");
+                       if (cmd != TYPECMD_SMALLV)
+                               out1str(": not found\n");
                        err |= 127;
                        break;
                }
        }
        return err;
 }
+
+/*
+ * Locate and print what a word is...
+ */
+
+int
+typecmd(int argc, char **argv)
+{
+       return typecmd_impl(argc, argv, TYPECMD_TYPE);
+}
index 464a72d..3d83ffc 100644 (file)
@@ -34,8 +34,8 @@
  * SUCH DAMAGE.
  *
  *     @(#)exec.h      8.3 (Berkeley) 6/8/95
- * $FreeBSD: src/bin/sh/exec.h,v 1.9.2.1 2002/07/19 04:38:51 tjr Exp $
- * $DragonFly: src/bin/sh/exec.h,v 1.4 2004/03/19 18:39:41 cpressey Exp $
+ * $FreeBSD: src/bin/sh/exec.h,v 1.15 2006/04/09 12:21:20 stefanf Exp $
+ * $DragonFly: src/bin/sh/exec.h,v 1.5 2007/01/07 01:14:53 pavalos Exp $
  */
 
 /* values of cmdtype */
 #define CMDBUILTIN 1           /* command is a shell builtin */
 #define CMDFUNCTION 2          /* command is a shell function */
 
+/* values for typecmd_impl's third parameter */
+enum {
+       TYPECMD_SMALLV,         /* command -v */
+       TYPECMD_BIGV,           /* command -V */
+       TYPECMD_TYPE            /* type */
+};
 
 struct cmdentry {
        int cmdtype;
@@ -51,6 +57,7 @@ struct cmdentry {
                int index;
                union node *func;
        } u;
+       int special;
 };
 
 
@@ -61,12 +68,13 @@ void shellexec(char **, char **, const char *, int);
 char *padvance(const char **, const char *);
 int hashcmd(int, char **);
 void find_command(char *, struct cmdentry *, int, const char *);
-int find_builtin(char *);
+int find_builtin(char *, int *);
 void hashcd(void);
 void changepath(const char *);
 void deletefuncs(void);
 void addcmdentry(char *, struct cmdentry *);
 void defun(char *, union node *);
 int unsetfunc(char *);
+int typecmd_impl(int, char **, int);
 int typecmd(int, char **);
 void clearcmdentry(int);
index 618167b..ae10584 100644 (file)
@@ -1,5 +1,6 @@
 #!/bin/sh -
-#
+
+#-
 # Copyright (c) 1991, 1993
 #      The Regents of the University of California.  All rights reserved.
 #
 # SUCH DAMAGE.
 #
 #      @(#)mkbuiltins  8.2 (Berkeley) 5/4/95
-# $FreeBSD: src/bin/sh/mkbuiltins,v 1.8.2.3 2002/11/30 07:54:49 tjr Exp $
-# $DragonFly: src/bin/sh/mkbuiltins,v 1.3 2004/03/19 18:39:41 cpressey Exp $
+# $FreeBSD: src/bin/sh/mkbuiltins,v 1.16 2006/04/02 18:43:33 stefanf Exp $
+# $DragonFly: src/bin/sh/mkbuiltins,v 1.4 2007/01/07 01:14:53 pavalos Exp $
 
 temp=`/usr/bin/mktemp -t ka`
 havejobs=0
-if grep '^#define JOBS[         ]*1' shell.h > /dev/null
+if grep '^#define[      ]*JOBS[         ]*1' shell.h > /dev/null
 then   havejobs=1
 fi
 havehist=1
@@ -70,9 +71,14 @@ echo '};
 
 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
@@ -89,6 +95,7 @@ echo '
 struct builtincmd {
       const char *name;
       int code;
+      int special;
 };
 
 extern int (*const builtinfunc[])(int, char *[]);
index 84df06c..9b88b4a 100644 (file)
@@ -35,7 +35,7 @@
  *
  * @(#)options.c       8.2 (Berkeley) 5/4/95
  * $FreeBSD: src/bin/sh/options.c,v 1.15.2.2 2002/07/19 04:38:52 tjr Exp $
- * $DragonFly: src/bin/sh/options.c,v 1.5 2006/09/28 22:29:44 pavalos Exp $
+ * $DragonFly: src/bin/sh/options.c,v 1.6 2007/01/07 01:14:53 pavalos Exp $
  */
 
 #include <signal.h>
@@ -326,7 +326,7 @@ shiftcmd(int argc, char **argv)
        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 1ad5f39..1e68e16 100644 (file)
@@ -34,9 +34,9 @@
 .\"
 .\"    from: @(#)sh.1  8.6 (Berkeley) 5/4/95
 .\" $FreeBSD: src/bin/sh/sh.1,v 1.39.2.25 2003/02/13 19:28:08 fanf Exp $
-.\" $DragonFly: src/bin/sh/sh.1,v 1.5 2006/07/20 17:01:22 corecode Exp $
+.\" $DragonFly: src/bin/sh/sh.1,v 1.6 2007/01/07 01:14:53 pavalos Exp $
 .\"
-.Dd May 5, 1995
+.Dd December 4, 2005
 .Dt SH 1
 .Os
 .Sh NAME
@@ -292,8 +292,9 @@ The shell writes its input to standard error
 as it is read.  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
@@ -1798,6 +1799,11 @@ A shift sets the value of $1 to the value of $2,
 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 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
+itself, the second one contains the user and system times for the
+children.
 .It Ic trap Oo Ar action Oc Ar signal ...
 Cause the shell to parse and execute
 .Ar action
index 31b7480..b44b43c 100644 (file)
@@ -35,7 +35,7 @@
  *
  * @(#)var.c   8.3 (Berkeley) 5/4/95
  * $FreeBSD: src/bin/sh/var.c,v 1.15.2.2 2002/08/27 01:36:28 tjr Exp $
- * $DragonFly: src/bin/sh/var.c,v 1.12 2006/09/28 22:29:44 pavalos Exp $
+ * $DragonFly: src/bin/sh/var.c,v 1.13 2007/01/07 01:14:53 pavalos Exp $
  */
 
 #include <unistd.h>
@@ -87,6 +87,7 @@ struct var vpath;
 struct var vppid;
 struct var vps1;
 struct var vps2;
+struct var vps4;
 struct var vvers;
 STATIC struct var voptind;
 
@@ -110,6 +111,8 @@ STATIC const struct varinit varinit[] = {
         */
        { &vps2,        VSTRFIXED|VTEXTFIXED,           "PS2=> ",
          NULL },
+       { &vps4,        VSTRFIXED|VTEXTFIXED,           "PS4=+ ",
+         NULL },
        { &voptind,     VSTRFIXED|VTEXTFIXED,           "OPTIND=1",
          getoptsreset },
        { NULL, 0,                              NULL,
index 987b6e7..812446e 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)var.h       8.2 (Berkeley) 5/4/95
  * $FreeBSD: src/bin/sh/var.h,v 1.8.2.1 2002/07/19 04:38:52 tjr Exp $
- * $DragonFly: src/bin/sh/var.h,v 1.4 2004/10/01 20:30:25 dillon Exp $
+ * $DragonFly: src/bin/sh/var.h,v 1.5 2007/01/07 01:14:53 pavalos Exp $
  */
 
 /*
@@ -79,6 +79,7 @@ extern struct var vpath;
 extern struct var vppid;
 extern struct var vps1;
 extern struct var vps2;
+extern struct var vps4;
 #ifndef NO_HISTORY
 extern struct var vhistsize;
 #endif
@@ -96,6 +97,7 @@ extern struct var vhistsize;
 #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)