summaryrefslogtreecommitdiffstats
path: root/source/ap/ash/patches/ash-builtin.patch
diff options
context:
space:
mode:
Diffstat (limited to 'source/ap/ash/patches/ash-builtin.patch')
-rw-r--r--source/ap/ash/patches/ash-builtin.patch843
1 files changed, 843 insertions, 0 deletions
diff --git a/source/ap/ash/patches/ash-builtin.patch b/source/ap/ash/patches/ash-builtin.patch
new file mode 100644
index 000000000..b812e6375
--- /dev/null
+++ b/source/ap/ash/patches/ash-builtin.patch
@@ -0,0 +1,843 @@
+diff -urN netbsd-sh/builtins.def ash-0.3.7.orig/builtins.def
+--- netbsd-sh/builtins.def Mon Apr 10 13:02:58 2000
++++ ash-0.3.7.orig/builtins.def Mon Apr 23 22:16:46 2001
+@@ -49,12 +49,13 @@
+ #
+ # NOTE: bltincmd must come first!
+
+-bltincmd command
++bltincmd builtin
+ #alloccmd alloc
+ bgcmd -j bg
+ breakcmd break continue
+ #catfcmd catf
+ cdcmd cd chdir
++commandcmd command
+ dotcmd .
+ echocmd echo
+ evalcmd eval
+diff -urN netbsd-sh/eval.c ash-0.3.7.orig/eval.c
+--- netbsd-sh/eval.c Tue May 23 12:03:18 2000
++++ ash-0.3.7.orig/eval.c Mon Apr 23 22:16:46 2001
+@@ -45,7 +45,9 @@
+ #endif
+ #endif /* not lint */
+
++#include <sys/types.h>
+ #include <signal.h>
++#include <malloc.h>
+ #include <unistd.h>
+
+ /*
+@@ -101,6 +103,8 @@
+ STATIC void evalpipe __P((union node *));
+ STATIC void evalcommand __P((union node *, int, struct backcmd *));
+ STATIC void prehash __P((union node *));
++STATIC int is_assignment_builtin __P((const char *));
++STATIC const char *get_standard_path __P((void));
+
+
+ /*
+@@ -257,6 +261,11 @@
+ evalcase(n, flags);
+ break;
+ case NDEFUN:
++ if (is_special_builtin(n->narg.text)) {
++ outfmt(out2, "%s is a special built-in\n", n->narg.text);
++ exitstatus = 1;
++ break;
++ }
+ defun(n->narg.text, n->narg.next);
+ exitstatus = 0;
+ break;
+@@ -497,9 +507,14 @@
+ close(0);
+ copyfd(prevfd, 0);
+ close(prevfd);
++ if (pip[0] == 0) {
++ pip[0] = -1;
++ }
+ }
+ if (pip[1] >= 0) {
+- close(pip[0]);
++ if (pip[0] >= 0) {
++ close(pip[0]);
++ }
+ if (pip[1] != 1) {
+ close(1);
+ copyfd(pip[1], 1);
+@@ -607,6 +622,7 @@
+ int argc;
+ char **envp;
+ int varflag;
++ int pseudovarflag;
+ struct strlist *sp;
+ int mode;
+ int pip[2];
+@@ -619,12 +635,17 @@
+ struct localvar *volatile savelocalvars;
+ volatile int e;
+ char *lastarg;
++ int not_special;
++ const char *path;
++ const char *standard_path;
+ #if __GNUC__
+ /* Avoid longjmp clobbering */
+ (void) &argv;
+ (void) &argc;
+ (void) &lastarg;
+ (void) &flags;
++ (void) &not_special;
++ (void) &standard_path;
+ #endif
+
+ /* First expand the arguments. */
+@@ -632,21 +653,31 @@
+ setstackmark(&smark);
+ arglist.lastp = &arglist.list;
+ varlist.lastp = &varlist.list;
++ arglist.list = 0;
+ varflag = 1;
++ pseudovarflag = 0;
+ oexitstatus = exitstatus;
+ exitstatus = 0;
++ not_special = 0;
++ path = pathval();
++ standard_path = NULL;
+ for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
+ char *p = argp->narg.text;
+- if (varflag && is_name(*p)) {
++ if ((varflag || pseudovarflag) && is_name(*p)) {
+ do {
+ p++;
+ } while (is_in_name(*p));
+ if (*p == '=') {
+- expandarg(argp, &varlist, EXP_VARTILDE);
++ if (varflag)
++ expandarg(argp, &varlist, EXP_VARTILDE);
++ else
++ expandarg(argp, &arglist, EXP_VARTILDE);
+ continue;
+ }
+ }
+ expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
++ if (varflag && arglist.list && is_assignment_builtin(arglist.list->text))
++ pseudovarflag = 1;
+ varflag = 0;
+ }
+ *arglist.lastp = NULL;
+@@ -688,37 +719,75 @@
+ cmdentry.u.index = BLTINCMD;
+ } else {
+ static const char PATH[] = "PATH=";
+- const char *path = pathval();
++ const char *oldpath = NULL;
++ int findflag = DO_ERR;
+
+ /*
+ * Modify the command lookup path, if a PATH= assignment
+ * is present
+ */
+ for (sp = varlist.list ; sp ; sp = sp->next)
+- if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
++ if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
+ path = sp->text + sizeof(PATH) - 1;
+-
+- find_command(argv[0], &cmdentry, DO_ERR, path);
+- if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
+- exitstatus = 127;
+- flushout(&errout);
+- return;
+- }
+- /* implement the bltin builtin here */
+- if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
+- for (;;) {
++ findflag |= DO_BRUTE;
++ }
++ for(;;) {
++ find_command(argv[0], &cmdentry, findflag, path);
++ if (oldpath) {
++ path = oldpath;
++ oldpath = NULL;
++ }
++ if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
++ exitstatus = 127;
++ flushout(&errout);
++ goto out;
++ }
++ /* implement the bltin builtin here */
++ if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
++ not_special = 1;
++ for(;;) {
++ argv++;
++ if (--argc == 0)
++ break;
++ if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
++ outfmt(&errout, "%s: not found\n", *argv);
++ exitstatus = 127;
++ flushout(&errout);
++ goto out;
++ }
++ if (cmdentry.u.index != BLTINCMD)
++ break;
++ }
++ }
++ if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == COMMANDCMD) {
++ not_special = 1;
+ argv++;
+- if (--argc == 0)
+- break;
+- if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
+- outfmt(&errout, "%s: not found\n", *argv);
+- exitstatus = 127;
+- flushout(&errout);
+- return;
++ if (--argc == 0) {
++ exitstatus = 0;
++ goto out;
+ }
+- if (cmdentry.u.index != BLTINCMD)
+- break;
++ if (*argv[0] == '-') {
++ if (!equal(argv[0], "-p")) {
++ argv--;
++ argc++;
++ break;
++ }
++ argv++;
++ if (--argc == 0) {
++ exitstatus = 0;
++ goto out;
++ }
++ if (!standard_path) {
++ standard_path = get_standard_path();
++ }
++ oldpath = path;
++ path = standard_path;
++ findflag |= DO_BRUTE;
++ }
++ findflag |= DO_NOFUN;
++ continue;
+ }
++ break;
+ }
+ }
+
+@@ -756,13 +825,12 @@
+ #ifdef DEBUG
+ trputs("Shell function: "); trargs(argv);
+ #endif
++ exitstatus = oexitstatus;
+ redirect(cmd->ncmd.redirect, REDIR_PUSH);
+ saveparam = shellparam;
+ shellparam.malloc = 0;
+- shellparam.reset = 1;
+ shellparam.nparam = argc - 1;
+ shellparam.p = argv + 1;
+- shellparam.optnext = NULL;
+ INTOFF;
+ savelocalvars = localvars;
+ localvars = NULL;
+@@ -772,6 +840,8 @@
+ freeparam((volatile struct shparam *)
+ &saveparam);
+ } else {
++ saveparam.optind = shellparam.optind;
++ saveparam.optoff = shellparam.optoff;
+ freeparam(&shellparam);
+ shellparam = saveparam;
+ }
+@@ -790,6 +860,8 @@
+ INTOFF;
+ poplocalvars();
+ localvars = savelocalvars;
++ saveparam.optind = shellparam.optind;
++ saveparam.optoff = shellparam.optoff;
+ freeparam(&shellparam);
+ shellparam = saveparam;
+ handler = savehandler;
+@@ -832,6 +908,8 @@
+ out1 = &output;
+ out2 = &errout;
+ freestdout();
++ if (!not_special && is_special_builtin(commandname))
++ listsetvar(cmdenviron);
+ cmdenviron = NULL;
+ if (e != EXSHELLPROC) {
+ commandname = savecmdname;
+@@ -867,7 +953,7 @@
+ for (sp = varlist.list ; sp ; sp = sp->next)
+ setvareq(sp->text, VEXPORT|VSTACK);
+ envp = environment();
+- shellexec(argv, envp, pathval(), cmdentry.u.index);
++ shellexec(argv, envp, path, cmdentry.u.index);
+ }
+ goto out;
+
+@@ -1025,4 +1111,49 @@
+ shellexec(argv + 1, environment(), pathval(), 0);
+ }
+ return 0;
++}
++
++STATIC int
++is_assignment_builtin (command)
++ const char *command;
++{
++ static const char *assignment_builtins[] = {
++ "alias", "declare", "export", "local", "readonly", "typeset",
++ (char *)NULL
++ };
++ int i;
++
++ for (i = 0; assignment_builtins[i]; i++)
++ if (strcmp(command, assignment_builtins[i]) == 0) return 1;
++ return 0;
++}
++
++int
++is_special_builtin(name)
++ const char *name;
++{
++ static const char *special_builtins[] = {
++ "break", ":", ".", "continue", "eval", "exec", "exit",
++ "export", "readonly", "return", "set", "shift", "times",
++ "trap", "unset", (char *)NULL
++ };
++ int i;
++
++ if (!name) return 0;
++ for (i = 0; special_builtins[i]; i++)
++ if (equal(name, special_builtins[i])) return 1;
++ return 0;
++}
++
++STATIC const char *
++get_standard_path()
++{
++ char *p;
++ size_t len;
++
++ len = confstr(_CS_PATH, NULL, 0);
++ p = stalloc(len + 2);
++ *p = '\0';
++ confstr(_CS_PATH, p, len);
++ return p;
+ }
+diff -urN netbsd-sh/eval.h ash-0.3.7.orig/eval.h
+--- netbsd-sh/eval.h Fri Jan 28 13:03:00 2000
++++ ash-0.3.7.orig/eval.h Mon Apr 23 22:16:46 2001
+@@ -61,6 +61,7 @@
+ int falsecmd __P((int, char **));
+ int truecmd __P((int, char **));
+ int execcmd __P((int, char **));
++int is_special_builtin __P((const char *));
+
+ /* in_function returns nonzero if we are currently evaluating a function */
+ #define in_function() funcnest
+diff -urN netbsd-sh/exec.c ash-0.3.7.orig/exec.c
+--- netbsd-sh/exec.c Fri Jan 12 17:50:35 2001
++++ ash-0.3.7.orig/exec.c Mon Apr 23 22:16:46 2001
+@@ -51,6 +51,7 @@
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <stdlib.h>
++#include <sysexits.h>
+
+ /*
+ * When commands are first encountered, they are entered in a hash table.
+@@ -108,6 +109,9 @@
+ STATIC void clearcmdentry __P((int));
+ STATIC struct tblentry *cmdlookup __P((char *, int));
+ STATIC void delete_cmd_entry __P((void));
++STATIC int describe_command __P((char *, int));
++STATIC int path_change __P((const char *, int *));
++STATIC int is_regular_builtin __P((const char *));
+
+
+
+@@ -164,7 +172,7 @@
+ char **envp;
+ {
+ int e;
+-#ifndef BSD
++#if !defined(BSD) && !defined(linux)
+ char *p;
+ #endif
+
+@@ -180,7 +188,7 @@
+ initshellproc();
+ setinputfile(cmd, 0);
+ commandname = arg0 = savestr(argv[0]);
+-#ifndef BSD
++#if !defined(BSD) && !defined(linux)
+ pgetc(); pungetc(); /* fill up input buffer */
+ p = parsenextc;
+ if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
+@@ -195,7 +203,7 @@
+ }
+
+
+-#ifndef BSD
++#if !defined(BSD) && !defined(linux)
+ /*
+ * Execute an interpreter introduced by "#!", for systems where this
+ * feature has not been built into the kernel. If the interpreter is
+@@ -351,27 +359,29 @@
+ if (*argptr == NULL) {
+ for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+ for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+- printentry(cmdp, verbose);
++ if (cmdp->cmdtype != CMDBUILTIN) {
++ printentry(cmdp, verbose);
++ }
+ }
+ }
+ return 0;
+ }
++ c = 0;
+ while ((name = *argptr) != NULL) {
+ if ((cmdp = cmdlookup(name, 0)) != NULL
+ && (cmdp->cmdtype == CMDNORMAL
+ || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
+ delete_cmd_entry();
+ find_command(name, &entry, DO_ERR, pathval());
+- if (verbose) {
+- if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
+- cmdp = cmdlookup(name, 0);
+- printentry(cmdp, verbose);
+- }
++ if (entry.cmdtype == CMDUNKNOWN) c = 1;
++ else if (verbose) {
++ cmdp = cmdlookup(name, 0);
++ if (cmdp) printentry(cmdp, verbose);
+ flushall();
+ }
+ argptr++;
+ }
+- return 0;
++ return c;
+ }
+
+
+@@ -435,6 +445,10 @@
+ struct stat statb;
+ int e;
+ int i;
++ int bltin;
++ int firstchange;
++ int updatetbl;
++ int regular;
+
+ /* If name contains a slash, don't use the hash table */
+ if (strchr(name, '/') != NULL) {
+@@ -459,12 +473,54 @@
+ return;
+ }
+
++ updatetbl = 1;
++ if (act & DO_BRUTE) {
++ firstchange = path_change(path, &bltin);
++ } else {
++ bltin = builtinloc;
++ firstchange = 9999;
++ }
++
+ /* If name is in the table, and not invalidated by cd, we're done */
+- if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
+- goto success;
++ if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
++ if (cmdp->cmdtype == CMDFUNCTION) {
++ if (act & DO_NOFUN) {
++ updatetbl = 0;
++ } else {
++ goto success;
++ }
++ } else if (act & DO_BRUTE) {
++ if ((cmdp->cmdtype == CMDNORMAL &&
++ cmdp->param.index >= firstchange) ||
++ (cmdp->cmdtype == CMDBUILTIN &&
++ ((builtinloc < 0 && bltin >= 0) ?
++ bltin : builtinloc) >= firstchange)) {
++ /* need to recompute the entry */
++ } else {
++ goto success;
++ }
++ } else {
++ goto success;
++ }
++ }
++
++ if ((regular = is_regular_builtin(name))) {
++ if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
++ goto success;
++ }
++ } else if (act & DO_BRUTE) {
++ if (firstchange == 0) {
++ updatetbl = 0;
++ }
++ }
+
+ /* If %builtin not in path, check for builtin next */
+- if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
++ if ((bltin < 0 || regular) && (i = find_builtin(name)) >= 0) {
++ if (!updatetbl) {
++ entry->cmdtype = CMDBUILTIN;
++ entry->u.index = i;
++ return;
++ }
+ INTOFF;
+ cmdp = cmdlookup(name, 1);
+ cmdp->cmdtype = CMDBUILTIN;
+@@ -475,7 +531,7 @@
+
+ /* We have to search path. */
+ prev = -1; /* where to start */
+- if (cmdp) { /* doing a rehash */
++ if (cmdp && cmdp->rehash) { /* doing a rehash */
+ if (cmdp->cmdtype == CMDBUILTIN)
+ prev = builtinloc;
+ else
+@@ -488,26 +544,38 @@
+ while ((fullname = padvance(&path, name)) != NULL) {
+ stunalloc(fullname);
+ idx++;
++ if (idx >= firstchange) {
++ updatetbl = 0;
++ }
+ if (pathopt) {
+ if (prefix("builtin", pathopt)) {
+- if ((i = find_builtin(name)) < 0)
+- goto loop;
+- INTOFF;
+- cmdp = cmdlookup(name, 1);
+- cmdp->cmdtype = CMDBUILTIN;
+- cmdp->param.index = i;
+- INTON;
+- goto success;
+- } else if (prefix("func", pathopt)) {
++ if ((i = find_builtin(name)) >= 0) {
++ if (!updatetbl) {
++ entry->cmdtype = CMDBUILTIN;
++ entry->u.index = i;
++ return;
++ }
++ INTOFF;
++ cmdp = cmdlookup(name, 1);
++ cmdp->cmdtype = CMDBUILTIN;
++ cmdp->param.index = i;
++ INTON;
++ goto success;
++ } else {
++ continue;
++ }
++ } else if (!(act & DO_NOFUN) &&
++ prefix("func", pathopt)) {
+ /* handled below */
+ } else {
+- goto loop; /* ignore unimplemented options */
++ continue; /* ignore unimplemented options */
+ }
+ }
+ /* if rehash, don't redo absolute path names */
+- if (fullname[0] == '/' && idx <= prev) {
++ if (fullname[0] == '/' && idx <= prev &&
++ idx < firstchange) {
+ if (idx < prev)
+- goto loop;
++ continue;
+ TRACE(("searchexec \"%s\": no change\n", name));
+ goto success;
+ }
+@@ -522,7 +590,7 @@
+ }
+ e = EACCES; /* if we fail, this will be the error */
+ if (!S_ISREG(statb.st_mode))
+- goto loop;
++ continue;
+ if (pathopt) { /* this is a %func directory */
+ stalloc(strlen(fullname) + 1);
+ readcmdfile(fullname);
+@@ -544,6 +612,13 @@
+ }
+ #endif
+ TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
++ /* If we aren't called with DO_BRUTE and cmdp is set, it must
++ be a function and we're being called with DO_NOFUN */
++ if (!updatetbl) {
++ entry->cmdtype = CMDNORMAL;
++ entry->u.index = idx;
++ return;
++ }
+ INTOFF;
+ cmdp = cmdlookup(name, 1);
+ cmdp->cmdtype = CMDNORMAL;
+@@ -553,7 +628,7 @@
+ }
+
+ /* We failed. If there was an entry for this command, delete it */
+- if (cmdp)
++ if (cmdp && updatetbl)
+ delete_cmd_entry();
+ if (act & DO_ERR)
+ outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
+@@ -618,37 +693,12 @@
+ changepath(newval)
+ const char *newval;
+ {
+- const char *old, *new;
+- int idx;
+ int firstchange;
+ int bltin;
+
+- old = pathval();
+- new = newval;
+- firstchange = 9999; /* assume no change */
+- idx = 0;
+- bltin = -1;
+- for (;;) {
+- if (*old != *new) {
+- firstchange = idx;
+- if ((*old == '\0' && *new == ':')
+- || (*old == ':' && *new == '\0'))
+- firstchange++;
+- old = new; /* ignore subsequent differences */
+- }
+- if (*new == '\0')
+- break;
+- if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
+- bltin = idx;
+- if (*new == ':') {
+- idx++;
+- }
+- new++, old++;
+- }
++ firstchange = path_change(newval, &bltin);
+ if (builtinloc < 0 && bltin >= 0)
+ builtinloc = bltin; /* zap builtins */
+- if (builtinloc >= 0 && bltin < 0)
+- firstchange = 0;
+ clearcmdentry(firstchange);
+ builtinloc = bltin;
+ }
+@@ -838,11 +888,9 @@
+ {
+ struct cmdentry entry;
+
+- INTOFF;
+ entry.cmdtype = CMDFUNCTION;
+ entry.u.func = copyfunc(func);
+ addcmdentry(name, &entry);
+- INTON;
+ }
+
+
+@@ -944,4 +992,190 @@
+ }
+ }
+ return err;
++}
++
++STATIC int
++describe_command(command, verbose)
++ char *command;
++ int verbose;
++{
++ struct cmdentry entry;
++ struct tblentry *cmdp;
++ char **pp;
++ struct alias *ap;
++ extern char *const parsekwd[];
++
++ for (pp = (char **)parsekwd; *pp; pp++)
++ if (**pp == *command && equal(*pp, command))
++ break;
++
++ if (*pp) {
++ if (verbose) {
++ out1fmt("%s is a reserved word\n", command);
++ } else {
++ out1fmt("%s\n", command);
++ }
++ return 0;
++ }
++
++ /* Then look at the aliases */
++ if ((ap = lookupalias(command, 1)) != NULL) {
++ if (verbose) {
++ out1fmt("%s is aliased to `%s'\n", command, ap->val);
++ } else {
++ out1fmt("alias %s='%s'\n", command, ap->val);
++ }
++ return 0;
++ }
++
++ /* Then check if it is a tracked alias */
++ if ((cmdp = cmdlookup(command, 0)) != NULL) {
++ entry.cmdtype = cmdp->cmdtype;
++ entry.u = cmdp->param;
++ }
++ else {
++ /* Finally use brute force */
++ find_command(command, &entry, DO_ABS, pathval());
++ }
++
++ switch (entry.cmdtype) {
++ case CMDNORMAL: {
++ int j = entry.u.index;
++ const char *path = pathval();
++ char *name;
++ if (j == -1)
++ name = command;
++ else {
++ do {
++ name = padvance(&path, command);
++ stunalloc(name);
++ } while (--j >= 0);
++ }
++ if (verbose) {
++ out1fmt("%s is %s\n", command, name);
++ } else {
++ out1fmt("%s\n", name);
++ }
++ break;
++ }
++ case CMDFUNCTION:
++ if (verbose) {
++ out1fmt("%s is a function\n", command);
++ } else {
++ out1fmt("%s\n", command);
++ }
++ break;
++ case CMDBUILTIN:
++ if (verbose) {
++ if (is_special_builtin(command)) {
++ out1fmt("%s is a special built-in utility\n", command);
++ } else {
++ out1fmt("%s is a built-in utility\n", command);
++ }
++ } else {
++ out1fmt("%s\n", command);
++ }
++ break;
++ default:
++ outfmt(out2, "%s not found\n", command);
++ return 127;
++ }
++
++ return 0;
++}
++
++int
++commandcmd(argc, argv)
++ int argc;
++ char **argv;
++{
++ int c;
++ int default_path = 0;
++ int verify_only = 0;
++ int verbose_verify_only = 0;
++
++ while ((c = nextopt("pvV")) != '\0')
++ switch (c) {
++ case 'p':
++ default_path = 1;
++ break;
++ case 'v':
++ verify_only = 1;
++ break;
++ case 'V':
++ verbose_verify_only = 1;
++ break;
++ default:
++ outfmt(out2,
++"command: nextopt returned character code 0%o\n", c);
++ return EX_SOFTWARE;
++ }
++
++ if (default_path + verify_only + verbose_verify_only > 1 ||
++ !*argptr) {
++ outfmt(out2,
++"command [-p] command [arg ...]\n");
++ outfmt(out2,
++"command {-v|-V} command\n");
++ return EX_USAGE;
++ }
++
++ if (verify_only || verbose_verify_only) {
++ return describe_command(*argptr, verbose_verify_only);
++ }
++
++ return 0;
++}
++
++STATIC int
++path_change(newval, bltin)
++ const char *newval;
++ int *bltin;
++{
++ const char *old, *new;
++ int idx;
++ int firstchange;
++
++ old = pathval();
++ new = newval;
++ firstchange = 9999; /* assume no change */
++ idx = 0;
++ *bltin = -1;
++ for (;;) {
++ if (*old != *new) {
++ firstchange = idx;
++ if ((*old == '\0' && *new == ':')
++ || (*old == ':' && *new == '\0'))
++ firstchange++;
++ old = new; /* ignore subsequent differences */
++ }
++ if (*new == '\0')
++ break;
++ if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
++ *bltin = idx;
++ if (*new == ':') {
++ idx++;
++ }
++ new++, old++;
++ }
++ if (builtinloc >= 0 && *bltin < 0)
++ firstchange = 0;
++ return firstchange;
++}
++
++STATIC int
++is_regular_builtin(name)
++ const char *name;
++{
++ static const char *regular_builtins[] = {
++ "alias", "bg", "cd", "command", "false", "fc", "fg",
++ "getopts", "jobs", "kill", "newgrp", "read", "true",
++ "umask", "unalias", "wait", (char *)NULL
++ };
++ int i;
++
++ if (!name) return 0;
++ for (i = 0; regular_builtins[i]; i++)
++ if (equal(name, regular_builtins[i])) return 1;
++ return 0;
+ }
+diff -urN netbsd-sh/exec.h ash-0.3.7.orig/exec.h
+--- netbsd-sh/exec.h Tue May 23 12:03:19 2000
++++ ash-0.3.7.orig/exec.h Mon Apr 23 22:16:46 2001
+@@ -56,6 +56,8 @@
+
+ #define DO_ERR 1 /* find_command prints errors */
+ #define DO_ABS 2 /* find_command checks absolute paths */
++#define DO_NOFUN 4 /* find_command ignores functions */
++#define DO_BRUTE 8 /* find_command ignores hash table */
+
+ extern const char *pathopt; /* set by padvance */
+ extern int exerrno; /* last exec error */
+@@ -74,3 +76,4 @@
+ void defun __P((char *, union node *));
+ int unsetfunc __P((char *));
+ int typecmd __P((int, char **));
++int commandcmd __P((int, char **));
+