1 diff -urN netbsd-sh/builtins.def ash-0.3.7.orig/builtins.def
2 --- netbsd-sh/builtins.def Mon Apr 10 13:02:58 2000
3 +++ ash-0.3.7.orig/builtins.def Mon Apr 23 22:16:46 2001
6 # NOTE: bltincmd must come first!
12 breakcmd break continue
19 diff -urN netbsd-sh/eval.c ash-0.3.7.orig/eval.c
20 --- netbsd-sh/eval.c Tue May 23 12:03:18 2000
21 +++ ash-0.3.7.orig/eval.c Mon Apr 23 22:16:46 2001
26 +#include <sys/types.h>
33 STATIC void evalpipe __P((union node *));
34 STATIC void evalcommand __P((union node *, int, struct backcmd *));
35 STATIC void prehash __P((union node *));
36 +STATIC int is_assignment_builtin __P((const char *));
37 +STATIC const char *get_standard_path __P((void));
45 + if (is_special_builtin(n->narg.text)) {
46 + outfmt(out2, "%s is a special built-in\n", n->narg.text);
50 defun(n->narg.text, n->narg.next);
78 struct localvar *volatile savelocalvars;
83 + const char *standard_path;
85 /* Avoid longjmp clobbering */
90 + (void) ¬_special;
91 + (void) &standard_path;
94 /* First expand the arguments. */
97 arglist.lastp = &arglist.list;
98 varlist.lastp = &varlist.list;
102 oexitstatus = exitstatus;
106 + standard_path = NULL;
107 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
108 char *p = argp->narg.text;
109 - if (varflag && is_name(*p)) {
110 + if ((varflag || pseudovarflag) && is_name(*p)) {
113 } while (is_in_name(*p));
115 - expandarg(argp, &varlist, EXP_VARTILDE);
117 + expandarg(argp, &varlist, EXP_VARTILDE);
119 + expandarg(argp, &arglist, EXP_VARTILDE);
123 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
124 + if (varflag && arglist.list && is_assignment_builtin(arglist.list->text))
128 *arglist.lastp = NULL;
129 @@ -688,37 +719,75 @@
130 cmdentry.u.index = BLTINCMD;
132 static const char PATH[] = "PATH=";
133 - const char *path = pathval();
134 + const char *oldpath = NULL;
135 + int findflag = DO_ERR;
138 * Modify the command lookup path, if a PATH= assignment
141 for (sp = varlist.list ; sp ; sp = sp->next)
142 - if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
143 + if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
144 path = sp->text + sizeof(PATH) - 1;
146 - find_command(argv[0], &cmdentry, DO_ERR, path);
147 - if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
152 - /* implement the bltin builtin here */
153 - if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
155 + findflag |= DO_BRUTE;
158 + find_command(argv[0], &cmdentry, findflag, path);
163 + if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
168 + /* implement the bltin builtin here */
169 + if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
175 + if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
176 + outfmt(&errout, "%s: not found\n", *argv);
181 + if (cmdentry.u.index != BLTINCMD)
185 + if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == COMMANDCMD) {
190 - if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
191 - outfmt(&errout, "%s: not found\n", *argv);
199 - if (cmdentry.u.index != BLTINCMD)
201 + if (*argv[0] == '-') {
202 + if (!equal(argv[0], "-p")) {
212 + if (!standard_path) {
213 + standard_path = get_standard_path();
216 + path = standard_path;
217 + findflag |= DO_BRUTE;
219 + findflag |= DO_NOFUN;
226 @@ -756,13 +825,12 @@
228 trputs("Shell function: "); trargs(argv);
230 + exitstatus = oexitstatus;
231 redirect(cmd->ncmd.redirect, REDIR_PUSH);
232 saveparam = shellparam;
233 shellparam.malloc = 0;
234 - shellparam.reset = 1;
235 shellparam.nparam = argc - 1;
236 shellparam.p = argv + 1;
237 - shellparam.optnext = NULL;
239 savelocalvars = localvars;
242 freeparam((volatile struct shparam *)
245 + saveparam.optind = shellparam.optind;
246 + saveparam.optoff = shellparam.optoff;
247 freeparam(&shellparam);
248 shellparam = saveparam;
253 localvars = savelocalvars;
254 + saveparam.optind = shellparam.optind;
255 + saveparam.optoff = shellparam.optoff;
256 freeparam(&shellparam);
257 shellparam = saveparam;
258 handler = savehandler;
263 + if (!not_special && is_special_builtin(commandname))
264 + listsetvar(cmdenviron);
266 if (e != EXSHELLPROC) {
267 commandname = savecmdname;
269 for (sp = varlist.list ; sp ; sp = sp->next)
270 setvareq(sp->text, VEXPORT|VSTACK);
271 envp = environment();
272 - shellexec(argv, envp, pathval(), cmdentry.u.index);
273 + shellexec(argv, envp, path, cmdentry.u.index);
277 @@ -1025,4 +1111,49 @@
278 shellexec(argv + 1, environment(), pathval(), 0);
284 +is_assignment_builtin (command)
285 + const char *command;
287 + static const char *assignment_builtins[] = {
288 + "alias", "declare", "export", "local", "readonly", "typeset",
293 + for (i = 0; assignment_builtins[i]; i++)
294 + if (strcmp(command, assignment_builtins[i]) == 0) return 1;
299 +is_special_builtin(name)
302 + static const char *special_builtins[] = {
303 + "break", ":", ".", "continue", "eval", "exec", "exit",
304 + "export", "readonly", "return", "set", "shift", "times",
305 + "trap", "unset", (char *)NULL
309 + if (!name) return 0;
310 + for (i = 0; special_builtins[i]; i++)
311 + if (equal(name, special_builtins[i])) return 1;
321 + len = confstr(_CS_PATH, NULL, 0);
322 + p = stalloc(len + 2);
324 + confstr(_CS_PATH, p, len);
327 diff -urN netbsd-sh/eval.h ash-0.3.7.orig/eval.h
328 --- netbsd-sh/eval.h Fri Jan 28 13:03:00 2000
329 +++ ash-0.3.7.orig/eval.h Mon Apr 23 22:16:46 2001
331 int falsecmd __P((int, char **));
332 int truecmd __P((int, char **));
333 int execcmd __P((int, char **));
334 +int is_special_builtin __P((const char *));
336 /* in_function returns nonzero if we are currently evaluating a function */
337 #define in_function() funcnest
338 diff -urN netbsd-sh/exec.c ash-0.3.7.orig/exec.c
339 --- netbsd-sh/exec.c Fri Jan 12 17:50:35 2001
340 +++ ash-0.3.7.orig/exec.c Mon Apr 23 22:16:46 2001
345 +#include <sysexits.h>
348 * When commands are first encountered, they are entered in a hash table.
350 STATIC void clearcmdentry __P((int));
351 STATIC struct tblentry *cmdlookup __P((char *, int));
352 STATIC void delete_cmd_entry __P((void));
353 +STATIC int describe_command __P((char *, int));
354 +STATIC int path_change __P((const char *, int *));
355 +STATIC int is_regular_builtin __P((const char *));
364 +#if !defined(BSD) && !defined(linux)
370 setinputfile(cmd, 0);
371 commandname = arg0 = savestr(argv[0]);
373 +#if !defined(BSD) && !defined(linux)
374 pgetc(); pungetc(); /* fill up input buffer */
376 if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
382 +#if !defined(BSD) && !defined(linux)
384 * Execute an interpreter introduced by "#!", for systems where this
385 * feature has not been built into the kernel. If the interpreter is
386 @@ -351,27 +359,29 @@
387 if (*argptr == NULL) {
388 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
389 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
390 - printentry(cmdp, verbose);
391 + if (cmdp->cmdtype != CMDBUILTIN) {
392 + printentry(cmdp, verbose);
399 while ((name = *argptr) != NULL) {
400 if ((cmdp = cmdlookup(name, 0)) != NULL
401 && (cmdp->cmdtype == CMDNORMAL
402 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
404 find_command(name, &entry, DO_ERR, pathval());
406 - if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
407 - cmdp = cmdlookup(name, 0);
408 - printentry(cmdp, verbose);
410 + if (entry.cmdtype == CMDUNKNOWN) c = 1;
411 + else if (verbose) {
412 + cmdp = cmdlookup(name, 0);
413 + if (cmdp) printentry(cmdp, verbose);
432 /* If name contains a slash, don't use the hash table */
433 if (strchr(name, '/') != NULL) {
434 @@ -459,12 +473,54 @@
439 + if (act & DO_BRUTE) {
440 + firstchange = path_change(path, &bltin);
442 + bltin = builtinloc;
443 + firstchange = 9999;
446 /* If name is in the table, and not invalidated by cd, we're done */
447 - if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
449 + if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
450 + if (cmdp->cmdtype == CMDFUNCTION) {
451 + if (act & DO_NOFUN) {
456 + } else if (act & DO_BRUTE) {
457 + if ((cmdp->cmdtype == CMDNORMAL &&
458 + cmdp->param.index >= firstchange) ||
459 + (cmdp->cmdtype == CMDBUILTIN &&
460 + ((builtinloc < 0 && bltin >= 0) ?
461 + bltin : builtinloc) >= firstchange)) {
462 + /* need to recompute the entry */
471 + if ((regular = is_regular_builtin(name))) {
472 + if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
475 + } else if (act & DO_BRUTE) {
476 + if (firstchange == 0) {
481 /* If %builtin not in path, check for builtin next */
482 - if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
483 + if ((bltin < 0 || regular) && (i = find_builtin(name)) >= 0) {
485 + entry->cmdtype = CMDBUILTIN;
486 + entry->u.index = i;
490 cmdp = cmdlookup(name, 1);
491 cmdp->cmdtype = CMDBUILTIN;
494 /* We have to search path. */
495 prev = -1; /* where to start */
496 - if (cmdp) { /* doing a rehash */
497 + if (cmdp && cmdp->rehash) { /* doing a rehash */
498 if (cmdp->cmdtype == CMDBUILTIN)
501 @@ -488,26 +544,38 @@
502 while ((fullname = padvance(&path, name)) != NULL) {
505 + if (idx >= firstchange) {
509 if (prefix("builtin", pathopt)) {
510 - if ((i = find_builtin(name)) < 0)
513 - cmdp = cmdlookup(name, 1);
514 - cmdp->cmdtype = CMDBUILTIN;
515 - cmdp->param.index = i;
518 - } else if (prefix("func", pathopt)) {
519 + if ((i = find_builtin(name)) >= 0) {
521 + entry->cmdtype = CMDBUILTIN;
522 + entry->u.index = i;
526 + cmdp = cmdlookup(name, 1);
527 + cmdp->cmdtype = CMDBUILTIN;
528 + cmdp->param.index = i;
534 + } else if (!(act & DO_NOFUN) &&
535 + prefix("func", pathopt)) {
538 - goto loop; /* ignore unimplemented options */
539 + continue; /* ignore unimplemented options */
542 /* if rehash, don't redo absolute path names */
543 - if (fullname[0] == '/' && idx <= prev) {
544 + if (fullname[0] == '/' && idx <= prev &&
545 + idx < firstchange) {
549 TRACE(("searchexec \"%s\": no change\n", name));
554 e = EACCES; /* if we fail, this will be the error */
555 if (!S_ISREG(statb.st_mode))
558 if (pathopt) { /* this is a %func directory */
559 stalloc(strlen(fullname) + 1);
560 readcmdfile(fullname);
564 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
565 + /* If we aren't called with DO_BRUTE and cmdp is set, it must
566 + be a function and we're being called with DO_NOFUN */
568 + entry->cmdtype = CMDNORMAL;
569 + entry->u.index = idx;
573 cmdp = cmdlookup(name, 1);
574 cmdp->cmdtype = CMDNORMAL;
578 /* We failed. If there was an entry for this command, delete it */
580 + if (cmdp && updatetbl)
583 outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
584 @@ -618,37 +693,12 @@
588 - const char *old, *new;
595 - firstchange = 9999; /* assume no change */
599 - if (*old != *new) {
601 - if ((*old == '\0' && *new == ':')
602 - || (*old == ':' && *new == '\0'))
604 - old = new; /* ignore subsequent differences */
608 - if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
615 + firstchange = path_change(newval, &bltin);
616 if (builtinloc < 0 && bltin >= 0)
617 builtinloc = bltin; /* zap builtins */
618 - if (builtinloc >= 0 && bltin < 0)
620 clearcmdentry(firstchange);
625 struct cmdentry entry;
628 entry.cmdtype = CMDFUNCTION;
629 entry.u.func = copyfunc(func);
630 addcmdentry(name, &entry);
635 @@ -944,4 +992,190 @@
642 +describe_command(command, verbose)
646 + struct cmdentry entry;
647 + struct tblentry *cmdp;
650 + extern char *const parsekwd[];
652 + for (pp = (char **)parsekwd; *pp; pp++)
653 + if (**pp == *command && equal(*pp, command))
658 + out1fmt("%s is a reserved word\n", command);
660 + out1fmt("%s\n", command);
665 + /* Then look at the aliases */
666 + if ((ap = lookupalias(command, 1)) != NULL) {
668 + out1fmt("%s is aliased to `%s'\n", command, ap->val);
670 + out1fmt("alias %s='%s'\n", command, ap->val);
675 + /* Then check if it is a tracked alias */
676 + if ((cmdp = cmdlookup(command, 0)) != NULL) {
677 + entry.cmdtype = cmdp->cmdtype;
678 + entry.u = cmdp->param;
681 + /* Finally use brute force */
682 + find_command(command, &entry, DO_ABS, pathval());
685 + switch (entry.cmdtype) {
687 + int j = entry.u.index;
688 + const char *path = pathval();
694 + name = padvance(&path, command);
696 + } while (--j >= 0);
699 + out1fmt("%s is %s\n", command, name);
701 + out1fmt("%s\n", name);
707 + out1fmt("%s is a function\n", command);
709 + out1fmt("%s\n", command);
714 + if (is_special_builtin(command)) {
715 + out1fmt("%s is a special built-in utility\n", command);
717 + out1fmt("%s is a built-in utility\n", command);
720 + out1fmt("%s\n", command);
724 + outfmt(out2, "%s not found\n", command);
732 +commandcmd(argc, argv)
737 + int default_path = 0;
738 + int verify_only = 0;
739 + int verbose_verify_only = 0;
741 + while ((c = nextopt("pvV")) != '\0')
750 + verbose_verify_only = 1;
754 +"command: nextopt returned character code 0%o\n", c);
755 + return EX_SOFTWARE;
758 + if (default_path + verify_only + verbose_verify_only > 1 ||
761 +"command [-p] command [arg ...]\n");
763 +"command {-v|-V} command\n");
767 + if (verify_only || verbose_verify_only) {
768 + return describe_command(*argptr, verbose_verify_only);
775 +path_change(newval, bltin)
776 + const char *newval;
779 + const char *old, *new;
785 + firstchange = 9999; /* assume no change */
789 + if (*old != *new) {
791 + if ((*old == '\0' && *new == ':')
792 + || (*old == ':' && *new == '\0'))
794 + old = new; /* ignore subsequent differences */
798 + if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
805 + if (builtinloc >= 0 && *bltin < 0)
807 + return firstchange;
811 +is_regular_builtin(name)
814 + static const char *regular_builtins[] = {
815 + "alias", "bg", "cd", "command", "false", "fc", "fg",
816 + "getopts", "jobs", "kill", "newgrp", "read", "true",
817 + "umask", "unalias", "wait", (char *)NULL
821 + if (!name) return 0;
822 + for (i = 0; regular_builtins[i]; i++)
823 + if (equal(name, regular_builtins[i])) return 1;
826 diff -urN netbsd-sh/exec.h ash-0.3.7.orig/exec.h
827 --- netbsd-sh/exec.h Tue May 23 12:03:19 2000
828 +++ ash-0.3.7.orig/exec.h Mon Apr 23 22:16:46 2001
831 #define DO_ERR 1 /* find_command prints errors */
832 #define DO_ABS 2 /* find_command checks absolute paths */
833 +#define DO_NOFUN 4 /* find_command ignores functions */
834 +#define DO_BRUTE 8 /* find_command ignores hash table */
836 extern const char *pathopt; /* set by padvance */
837 extern int exerrno; /* last exec error */
839 void defun __P((char *, union node *));
840 int unsetfunc __P((char *));
841 int typecmd __P((int, char **));
842 +int commandcmd __P((int, char **));