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);
57 - if ((flags & EV_EXIT) || (eflag && exitstatus && !(flags & EV_TESTED)))
58 + if (flags & EV_EXIT)
59 exitshell(exitstatus);
87 struct localvar *volatile savelocalvars;
92 + const char *standard_path;
94 /* Avoid longjmp clobbering */
99 + (void) ¬_special;
100 + (void) &standard_path;
103 /* First expand the arguments. */
104 @@ -632,21 +653,31 @@
105 setstackmark(&smark);
106 arglist.lastp = &arglist.list;
107 varlist.lastp = &varlist.list;
111 oexitstatus = exitstatus;
115 + standard_path = NULL;
116 for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
117 char *p = argp->narg.text;
118 - if (varflag && is_name(*p)) {
119 + if ((varflag || pseudovarflag) && is_name(*p)) {
122 } while (is_in_name(*p));
124 - expandarg(argp, &varlist, EXP_VARTILDE);
126 + expandarg(argp, &varlist, EXP_VARTILDE);
128 + expandarg(argp, &arglist, EXP_VARTILDE);
132 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
133 + if (varflag && arglist.list && is_assignment_builtin(arglist.list->text))
137 *arglist.lastp = NULL;
138 @@ -688,37 +719,75 @@
139 cmdentry.u.index = BLTINCMD;
141 static const char PATH[] = "PATH=";
142 - const char *path = pathval();
143 + const char *oldpath = NULL;
144 + int findflag = DO_ERR;
147 * Modify the command lookup path, if a PATH= assignment
150 for (sp = varlist.list ; sp ; sp = sp->next)
151 - if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0)
152 + if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) {
153 path = sp->text + sizeof(PATH) - 1;
155 - find_command(argv[0], &cmdentry, DO_ERR, path);
156 - if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
161 - /* implement the bltin builtin here */
162 - if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
164 + findflag |= DO_BRUTE;
167 + find_command(argv[0], &cmdentry, findflag, path);
172 + if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
177 + /* implement the bltin builtin here */
178 + if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) {
184 + if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
185 + outfmt(&errout, "%s: not found\n", *argv);
190 + if (cmdentry.u.index != BLTINCMD)
194 + if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == COMMANDCMD) {
199 - if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
200 - outfmt(&errout, "%s: not found\n", *argv);
208 - if (cmdentry.u.index != BLTINCMD)
210 + if (*argv[0] == '-') {
211 + if (!equal(argv[0], "-p")) {
221 + if (!standard_path) {
222 + standard_path = get_standard_path();
225 + path = standard_path;
226 + findflag |= DO_BRUTE;
228 + findflag |= DO_NOFUN;
235 @@ -756,13 +825,12 @@
237 trputs("Shell function: "); trargs(argv);
239 + exitstatus = oexitstatus;
240 redirect(cmd->ncmd.redirect, REDIR_PUSH);
241 saveparam = shellparam;
242 shellparam.malloc = 0;
243 - shellparam.reset = 1;
244 shellparam.nparam = argc - 1;
245 shellparam.p = argv + 1;
246 - shellparam.optnext = NULL;
248 savelocalvars = localvars;
251 freeparam((volatile struct shparam *)
254 + saveparam.optind = shellparam.optind;
255 + saveparam.optoff = shellparam.optoff;
256 freeparam(&shellparam);
257 shellparam = saveparam;
262 localvars = savelocalvars;
263 + saveparam.optind = shellparam.optind;
264 + saveparam.optoff = shellparam.optoff;
265 freeparam(&shellparam);
266 shellparam = saveparam;
267 handler = savehandler;
272 + if (!not_special && is_special_builtin(commandname))
273 + listsetvar(cmdenviron);
275 if (e != EXSHELLPROC) {
276 commandname = savecmdname;
278 for (sp = varlist.list ; sp ; sp = sp->next)
279 setvareq(sp->text, VEXPORT|VSTACK);
280 envp = environment();
281 - shellexec(argv, envp, pathval(), cmdentry.u.index);
282 + shellexec(argv, envp, path, cmdentry.u.index);
286 @@ -1025,4 +1111,49 @@
287 shellexec(argv + 1, environment(), pathval(), 0);
293 +is_assignment_builtin (command)
294 + const char *command;
296 + static const char *assignment_builtins[] = {
297 + "alias", "declare", "export", "local", "readonly", "typeset",
302 + for (i = 0; assignment_builtins[i]; i++)
303 + if (strcmp(command, assignment_builtins[i]) == 0) return 1;
308 +is_special_builtin(name)
311 + static const char *special_builtins[] = {
312 + "break", ":", ".", "continue", "eval", "exec", "exit",
313 + "export", "readonly", "return", "set", "shift", "times",
314 + "trap", "unset", (char *)NULL
318 + if (!name) return 0;
319 + for (i = 0; special_builtins[i]; i++)
320 + if (equal(name, special_builtins[i])) return 1;
330 + len = confstr(_CS_PATH, NULL, 0);
331 + p = stalloc(len + 2);
333 + confstr(_CS_PATH, p, len);
336 diff -urN netbsd-sh/eval.h ash-0.3.7.orig/eval.h
337 --- netbsd-sh/eval.h Fri Jan 28 13:03:00 2000
338 +++ ash-0.3.7.orig/eval.h Mon Apr 23 22:16:46 2001
340 int falsecmd __P((int, char **));
341 int truecmd __P((int, char **));
342 int execcmd __P((int, char **));
343 +int is_special_builtin __P((const char *));
345 /* in_function returns nonzero if we are currently evaluating a function */
346 #define in_function() funcnest
347 diff -urN netbsd-sh/exec.c ash-0.3.7.orig/exec.c
348 --- netbsd-sh/exec.c Fri Jan 12 17:50:35 2001
349 +++ ash-0.3.7.orig/exec.c Mon Apr 23 22:16:46 2001
354 +#include <sysexits.h>
357 * When commands are first encountered, they are entered in a hash table.
359 STATIC void clearcmdentry __P((int));
360 STATIC struct tblentry *cmdlookup __P((char *, int));
361 STATIC void delete_cmd_entry __P((void));
362 +STATIC int describe_command __P((char *, int));
363 +STATIC int path_change __P((const char *, int *));
364 +STATIC int is_regular_builtin __P((const char *));
373 +#if !defined(BSD) && !defined(linux)
379 setinputfile(cmd, 0);
380 commandname = arg0 = savestr(argv[0]);
382 +#if !defined(BSD) && !defined(linux)
383 pgetc(); pungetc(); /* fill up input buffer */
385 if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
391 +#if !defined(BSD) && !defined(linux)
393 * Execute an interpreter introduced by "#!", for systems where this
394 * feature has not been built into the kernel. If the interpreter is
395 @@ -351,27 +359,29 @@
396 if (*argptr == NULL) {
397 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
398 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
399 - printentry(cmdp, verbose);
400 + if (cmdp->cmdtype != CMDBUILTIN) {
401 + printentry(cmdp, verbose);
408 while ((name = *argptr) != NULL) {
409 if ((cmdp = cmdlookup(name, 0)) != NULL
410 && (cmdp->cmdtype == CMDNORMAL
411 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
413 find_command(name, &entry, DO_ERR, pathval());
415 - if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */
416 - cmdp = cmdlookup(name, 0);
417 - printentry(cmdp, verbose);
419 + if (entry.cmdtype == CMDUNKNOWN) c = 1;
420 + else if (verbose) {
421 + cmdp = cmdlookup(name, 0);
422 + if (cmdp) printentry(cmdp, verbose);
441 /* If name contains a slash, don't use the hash table */
442 if (strchr(name, '/') != NULL) {
443 @@ -459,12 +473,54 @@
448 + if (act & DO_BRUTE) {
449 + firstchange = path_change(path, &bltin);
451 + bltin = builtinloc;
452 + firstchange = 9999;
455 /* If name is in the table, and not invalidated by cd, we're done */
456 - if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0)
458 + if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
459 + if (cmdp->cmdtype == CMDFUNCTION) {
460 + if (act & DO_NOFUN) {
465 + } else if (act & DO_BRUTE) {
466 + if ((cmdp->cmdtype == CMDNORMAL &&
467 + cmdp->param.index >= firstchange) ||
468 + (cmdp->cmdtype == CMDBUILTIN &&
469 + ((builtinloc < 0 && bltin >= 0) ?
470 + bltin : builtinloc) >= firstchange)) {
471 + /* need to recompute the entry */
480 + if ((regular = is_regular_builtin(name))) {
481 + if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
484 + } else if (act & DO_BRUTE) {
485 + if (firstchange == 0) {
490 /* If %builtin not in path, check for builtin next */
491 - if (builtinloc < 0 && (i = find_builtin(name)) >= 0) {
492 + if ((bltin < 0 || regular) && (i = find_builtin(name)) >= 0) {
494 + entry->cmdtype = CMDBUILTIN;
495 + entry->u.index = i;
499 cmdp = cmdlookup(name, 1);
500 cmdp->cmdtype = CMDBUILTIN;
503 /* We have to search path. */
504 prev = -1; /* where to start */
505 - if (cmdp) { /* doing a rehash */
506 + if (cmdp && cmdp->rehash) { /* doing a rehash */
507 if (cmdp->cmdtype == CMDBUILTIN)
510 @@ -488,26 +544,38 @@
511 while ((fullname = padvance(&path, name)) != NULL) {
514 + if (idx >= firstchange) {
518 if (prefix("builtin", pathopt)) {
519 - if ((i = find_builtin(name)) < 0)
522 - cmdp = cmdlookup(name, 1);
523 - cmdp->cmdtype = CMDBUILTIN;
524 - cmdp->param.index = i;
527 - } else if (prefix("func", pathopt)) {
528 + if ((i = find_builtin(name)) >= 0) {
530 + entry->cmdtype = CMDBUILTIN;
531 + entry->u.index = i;
535 + cmdp = cmdlookup(name, 1);
536 + cmdp->cmdtype = CMDBUILTIN;
537 + cmdp->param.index = i;
543 + } else if (!(act & DO_NOFUN) &&
544 + prefix("func", pathopt)) {
547 - goto loop; /* ignore unimplemented options */
548 + continue; /* ignore unimplemented options */
551 /* if rehash, don't redo absolute path names */
552 - if (fullname[0] == '/' && idx <= prev) {
553 + if (fullname[0] == '/' && idx <= prev &&
554 + idx < firstchange) {
558 TRACE(("searchexec \"%s\": no change\n", name));
563 e = EACCES; /* if we fail, this will be the error */
564 if (!S_ISREG(statb.st_mode))
567 if (pathopt) { /* this is a %func directory */
568 stalloc(strlen(fullname) + 1);
569 readcmdfile(fullname);
573 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
574 + /* If we aren't called with DO_BRUTE and cmdp is set, it must
575 + be a function and we're being called with DO_NOFUN */
577 + entry->cmdtype = CMDNORMAL;
578 + entry->u.index = idx;
582 cmdp = cmdlookup(name, 1);
583 cmdp->cmdtype = CMDNORMAL;
587 /* We failed. If there was an entry for this command, delete it */
589 + if (cmdp && updatetbl)
592 outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC));
593 @@ -618,37 +693,12 @@
597 - const char *old, *new;
604 - firstchange = 9999; /* assume no change */
608 - if (*old != *new) {
610 - if ((*old == '\0' && *new == ':')
611 - || (*old == ':' && *new == '\0'))
613 - old = new; /* ignore subsequent differences */
617 - if (*new == '%' && bltin < 0 && prefix("builtin", new + 1))
624 + firstchange = path_change(newval, &bltin);
625 if (builtinloc < 0 && bltin >= 0)
626 builtinloc = bltin; /* zap builtins */
627 - if (builtinloc >= 0 && bltin < 0)
629 clearcmdentry(firstchange);
634 struct cmdentry entry;
637 entry.cmdtype = CMDFUNCTION;
638 entry.u.func = copyfunc(func);
639 addcmdentry(name, &entry);
644 @@ -944,4 +992,190 @@
651 +describe_command(command, verbose)
655 + struct cmdentry entry;
656 + struct tblentry *cmdp;
659 + extern char *const parsekwd[];
661 + for (pp = (char **)parsekwd; *pp; pp++)
662 + if (**pp == *command && equal(*pp, command))
667 + out1fmt("%s is a reserved word\n", command);
669 + out1fmt("%s\n", command);
674 + /* Then look at the aliases */
675 + if ((ap = lookupalias(command, 1)) != NULL) {
677 + out1fmt("%s is aliased to `%s'\n", command, ap->val);
679 + out1fmt("alias %s='%s'\n", command, ap->val);
684 + /* Then check if it is a tracked alias */
685 + if ((cmdp = cmdlookup(command, 0)) != NULL) {
686 + entry.cmdtype = cmdp->cmdtype;
687 + entry.u = cmdp->param;
690 + /* Finally use brute force */
691 + find_command(command, &entry, DO_ABS, pathval());
694 + switch (entry.cmdtype) {
696 + int j = entry.u.index;
697 + const char *path = pathval();
703 + name = padvance(&path, command);
705 + } while (--j >= 0);
708 + out1fmt("%s is %s\n", command, name);
710 + out1fmt("%s\n", name);
716 + out1fmt("%s is a function\n", command);
718 + out1fmt("%s\n", command);
723 + if (is_special_builtin(command)) {
724 + out1fmt("%s is a special built-in utility\n", command);
726 + out1fmt("%s is a built-in utility\n", command);
729 + out1fmt("%s\n", command);
733 + outfmt(out2, "%s not found\n", command);
741 +commandcmd(argc, argv)
746 + int default_path = 0;
747 + int verify_only = 0;
748 + int verbose_verify_only = 0;
750 + while ((c = nextopt("pvV")) != '\0')
759 + verbose_verify_only = 1;
763 +"command: nextopt returned character code 0%o\n", c);
764 + return EX_SOFTWARE;
767 + if (default_path + verify_only + verbose_verify_only > 1 ||
770 +"command [-p] command [arg ...]\n");
772 +"command {-v|-V} command\n");
776 + if (verify_only || verbose_verify_only) {
777 + return describe_command(*argptr, verbose_verify_only);
784 +path_change(newval, bltin)
785 + const char *newval;
788 + const char *old, *new;
794 + firstchange = 9999; /* assume no change */
798 + if (*old != *new) {
800 + if ((*old == '\0' && *new == ':')
801 + || (*old == ':' && *new == '\0'))
803 + old = new; /* ignore subsequent differences */
807 + if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
814 + if (builtinloc >= 0 && *bltin < 0)
816 + return firstchange;
820 +is_regular_builtin(name)
823 + static const char *regular_builtins[] = {
824 + "alias", "bg", "cd", "command", "false", "fc", "fg",
825 + "getopts", "jobs", "kill", "newgrp", "read", "true",
826 + "umask", "unalias", "wait", (char *)NULL
830 + if (!name) return 0;
831 + for (i = 0; regular_builtins[i]; i++)
832 + if (equal(name, regular_builtins[i])) return 1;
835 diff -urN netbsd-sh/exec.h ash-0.3.7.orig/exec.h
836 --- netbsd-sh/exec.h Tue May 23 12:03:19 2000
837 +++ ash-0.3.7.orig/exec.h Mon Apr 23 22:16:46 2001
840 #define DO_ERR 1 /* find_command prints errors */
841 #define DO_ABS 2 /* find_command checks absolute paths */
842 +#define DO_NOFUN 4 /* find_command ignores functions */
843 +#define DO_BRUTE 8 /* find_command ignores hash table */
845 extern const char *pathopt; /* set by padvance */
846 extern int exerrno; /* last exec error */
848 void defun __P((char *, union node *));
849 int unsetfunc __P((char *));
850 int typecmd __P((int, char **));
851 +int commandcmd __P((int, char **));