]>
Commit | Line | Data |
---|---|---|
cf7098dd MM |
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 | |
4 | @@ -49,12 +49,13 @@ | |
5 | # | |
6 | # NOTE: bltincmd must come first! | |
7 | ||
8 | -bltincmd command | |
9 | +bltincmd builtin | |
10 | #alloccmd alloc | |
11 | bgcmd -j bg | |
12 | breakcmd break continue | |
13 | #catfcmd catf | |
14 | cdcmd cd chdir | |
15 | +commandcmd command | |
16 | dotcmd . | |
17 | echocmd echo | |
18 | evalcmd eval | |
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 | |
22 | @@ -45,7 +45,9 @@ | |
23 | #endif | |
24 | #endif /* not lint */ | |
25 | ||
26 | +#include <sys/types.h> | |
27 | #include <signal.h> | |
28 | +#include <malloc.h> | |
29 | #include <unistd.h> | |
30 | ||
31 | /* | |
32 | @@ -101,6 +103,8 @@ | |
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)); | |
38 | ||
39 | ||
40 | /* | |
41 | @@ -257,6 +261,11 @@ | |
42 | evalcase(n, flags); | |
43 | break; | |
44 | case NDEFUN: | |
45 | + if (is_special_builtin(n->narg.text)) { | |
46 | + outfmt(out2, "%s is a special built-in\n", n->narg.text); | |
47 | + exitstatus = 1; | |
48 | + break; | |
49 | + } | |
50 | defun(n->narg.text, n->narg.next); | |
51 | exitstatus = 0; | |
52 | break; | |
53 | @@ -279,7 +288,7 @@ | |
54 | out: | |
55 | if (pendingsigs) | |
56 | dotrap(); | |
57 | - if ((flags & EV_EXIT) || (eflag && exitstatus && !(flags & EV_TESTED))) | |
58 | + if (flags & EV_EXIT) | |
59 | exitshell(exitstatus); | |
60 | } | |
61 | ||
62 | @@ -497,9 +507,14 @@ | |
63 | close(0); | |
64 | copyfd(prevfd, 0); | |
65 | close(prevfd); | |
66 | + if (pip[0] == 0) { | |
67 | + pip[0] = -1; | |
68 | + } | |
69 | } | |
70 | if (pip[1] >= 0) { | |
71 | - close(pip[0]); | |
72 | + if (pip[0] >= 0) { | |
73 | + close(pip[0]); | |
74 | + } | |
75 | if (pip[1] != 1) { | |
76 | close(1); | |
77 | copyfd(pip[1], 1); | |
78 | @@ -607,6 +622,7 @@ | |
79 | int argc; | |
80 | char **envp; | |
81 | int varflag; | |
82 | + int pseudovarflag; | |
83 | struct strlist *sp; | |
84 | int mode; | |
85 | int pip[2]; | |
86 | @@ -619,12 +635,17 @@ | |
87 | struct localvar *volatile savelocalvars; | |
88 | volatile int e; | |
89 | char *lastarg; | |
90 | + int not_special; | |
91 | + const char *path; | |
92 | + const char *standard_path; | |
93 | #if __GNUC__ | |
94 | /* Avoid longjmp clobbering */ | |
95 | (void) &argv; | |
96 | (void) &argc; | |
97 | (void) &lastarg; | |
98 | (void) &flags; | |
99 | + (void) ¬_special; | |
100 | + (void) &standard_path; | |
101 | #endif | |
102 | ||
103 | /* First expand the arguments. */ | |
104 | @@ -632,21 +653,31 @@ | |
105 | setstackmark(&smark); | |
106 | arglist.lastp = &arglist.list; | |
107 | varlist.lastp = &varlist.list; | |
108 | + arglist.list = 0; | |
109 | varflag = 1; | |
110 | + pseudovarflag = 0; | |
111 | oexitstatus = exitstatus; | |
112 | exitstatus = 0; | |
113 | + not_special = 0; | |
114 | + path = pathval(); | |
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)) { | |
120 | do { | |
121 | p++; | |
122 | } while (is_in_name(*p)); | |
123 | if (*p == '=') { | |
124 | - expandarg(argp, &varlist, EXP_VARTILDE); | |
125 | + if (varflag) | |
126 | + expandarg(argp, &varlist, EXP_VARTILDE); | |
127 | + else | |
128 | + expandarg(argp, &arglist, EXP_VARTILDE); | |
129 | continue; | |
130 | } | |
131 | } | |
132 | expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); | |
133 | + if (varflag && arglist.list && is_assignment_builtin(arglist.list->text)) | |
134 | + pseudovarflag = 1; | |
135 | varflag = 0; | |
136 | } | |
137 | *arglist.lastp = NULL; | |
138 | @@ -688,37 +719,75 @@ | |
139 | cmdentry.u.index = BLTINCMD; | |
140 | } else { | |
141 | static const char PATH[] = "PATH="; | |
142 | - const char *path = pathval(); | |
143 | + const char *oldpath = NULL; | |
144 | + int findflag = DO_ERR; | |
145 | ||
146 | /* | |
147 | * Modify the command lookup path, if a PATH= assignment | |
148 | * is present | |
149 | */ | |
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; | |
154 | - | |
155 | - find_command(argv[0], &cmdentry, DO_ERR, path); | |
156 | - if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ | |
157 | - exitstatus = 127; | |
158 | - flushout(&errout); | |
159 | - return; | |
160 | - } | |
161 | - /* implement the bltin builtin here */ | |
162 | - if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) { | |
163 | - for (;;) { | |
164 | + findflag |= DO_BRUTE; | |
165 | + } | |
166 | + for(;;) { | |
167 | + find_command(argv[0], &cmdentry, findflag, path); | |
168 | + if (oldpath) { | |
169 | + path = oldpath; | |
170 | + oldpath = NULL; | |
171 | + } | |
172 | + if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ | |
173 | + exitstatus = 127; | |
174 | + flushout(&errout); | |
175 | + goto out; | |
176 | + } | |
177 | + /* implement the bltin builtin here */ | |
178 | + if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) { | |
179 | + not_special = 1; | |
180 | + for(;;) { | |
181 | + argv++; | |
182 | + if (--argc == 0) | |
183 | + break; | |
184 | + if ((cmdentry.u.index = find_builtin(*argv)) < 0) { | |
185 | + outfmt(&errout, "%s: not found\n", *argv); | |
186 | + exitstatus = 127; | |
187 | + flushout(&errout); | |
188 | + goto out; | |
189 | + } | |
190 | + if (cmdentry.u.index != BLTINCMD) | |
191 | + break; | |
192 | + } | |
193 | + } | |
194 | + if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == COMMANDCMD) { | |
195 | + not_special = 1; | |
196 | argv++; | |
197 | - if (--argc == 0) | |
198 | - break; | |
199 | - if ((cmdentry.u.index = find_builtin(*argv)) < 0) { | |
200 | - outfmt(&errout, "%s: not found\n", *argv); | |
201 | - exitstatus = 127; | |
202 | - flushout(&errout); | |
203 | - return; | |
204 | + if (--argc == 0) { | |
205 | + exitstatus = 0; | |
206 | + goto out; | |
207 | } | |
208 | - if (cmdentry.u.index != BLTINCMD) | |
209 | - break; | |
210 | + if (*argv[0] == '-') { | |
211 | + if (!equal(argv[0], "-p")) { | |
212 | + argv--; | |
213 | + argc++; | |
214 | + break; | |
215 | + } | |
216 | + argv++; | |
217 | + if (--argc == 0) { | |
218 | + exitstatus = 0; | |
219 | + goto out; | |
220 | + } | |
221 | + if (!standard_path) { | |
222 | + standard_path = get_standard_path(); | |
223 | + } | |
224 | + oldpath = path; | |
225 | + path = standard_path; | |
226 | + findflag |= DO_BRUTE; | |
227 | + } | |
228 | + findflag |= DO_NOFUN; | |
229 | + continue; | |
230 | } | |
231 | + break; | |
232 | } | |
233 | } | |
234 | ||
235 | @@ -756,13 +825,12 @@ | |
236 | #ifdef DEBUG | |
237 | trputs("Shell function: "); trargs(argv); | |
238 | #endif | |
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; | |
247 | INTOFF; | |
248 | savelocalvars = localvars; | |
249 | localvars = NULL; | |
250 | @@ -772,6 +840,8 @@ | |
251 | freeparam((volatile struct shparam *) | |
252 | &saveparam); | |
253 | } else { | |
254 | + saveparam.optind = shellparam.optind; | |
255 | + saveparam.optoff = shellparam.optoff; | |
256 | freeparam(&shellparam); | |
257 | shellparam = saveparam; | |
258 | } | |
259 | @@ -790,6 +860,8 @@ | |
260 | INTOFF; | |
261 | poplocalvars(); | |
262 | localvars = savelocalvars; | |
263 | + saveparam.optind = shellparam.optind; | |
264 | + saveparam.optoff = shellparam.optoff; | |
265 | freeparam(&shellparam); | |
266 | shellparam = saveparam; | |
267 | handler = savehandler; | |
268 | @@ -832,6 +908,8 @@ | |
269 | out1 = &output; | |
270 | out2 = &errout; | |
271 | freestdout(); | |
272 | + if (!not_special && is_special_builtin(commandname)) | |
273 | + listsetvar(cmdenviron); | |
274 | cmdenviron = NULL; | |
275 | if (e != EXSHELLPROC) { | |
276 | commandname = savecmdname; | |
277 | @@ -867,7 +953,7 @@ | |
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); | |
283 | } | |
284 | goto out; | |
285 | ||
286 | @@ -1025,4 +1111,49 @@ | |
287 | shellexec(argv + 1, environment(), pathval(), 0); | |
288 | } | |
289 | return 0; | |
290 | +} | |
291 | + | |
292 | +STATIC int | |
293 | +is_assignment_builtin (command) | |
294 | + const char *command; | |
295 | +{ | |
296 | + static const char *assignment_builtins[] = { | |
297 | + "alias", "declare", "export", "local", "readonly", "typeset", | |
298 | + (char *)NULL | |
299 | + }; | |
300 | + int i; | |
301 | + | |
302 | + for (i = 0; assignment_builtins[i]; i++) | |
303 | + if (strcmp(command, assignment_builtins[i]) == 0) return 1; | |
304 | + return 0; | |
305 | +} | |
306 | + | |
307 | +int | |
308 | +is_special_builtin(name) | |
309 | + const char *name; | |
310 | +{ | |
311 | + static const char *special_builtins[] = { | |
312 | + "break", ":", ".", "continue", "eval", "exec", "exit", | |
313 | + "export", "readonly", "return", "set", "shift", "times", | |
314 | + "trap", "unset", (char *)NULL | |
315 | + }; | |
316 | + int i; | |
317 | + | |
318 | + if (!name) return 0; | |
319 | + for (i = 0; special_builtins[i]; i++) | |
320 | + if (equal(name, special_builtins[i])) return 1; | |
321 | + return 0; | |
322 | +} | |
323 | + | |
324 | +STATIC const char * | |
325 | +get_standard_path() | |
326 | +{ | |
327 | + char *p; | |
328 | + size_t len; | |
329 | + | |
330 | + len = confstr(_CS_PATH, NULL, 0); | |
331 | + p = stalloc(len + 2); | |
332 | + *p = '\0'; | |
333 | + confstr(_CS_PATH, p, len); | |
334 | + return p; | |
335 | } | |
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 | |
339 | @@ -61,6 +61,7 @@ | |
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 *)); | |
344 | ||
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 | |
350 | @@ -51,6 +51,7 @@ | |
351 | #include <fcntl.h> | |
352 | #include <errno.h> | |
353 | #include <stdlib.h> | |
354 | +#include <sysexits.h> | |
355 | ||
356 | /* | |
357 | * When commands are first encountered, they are entered in a hash table. | |
358 | @@ -108,6 +109,9 @@ | |
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 *)); | |
365 | ||
366 | ||
367 | ||
368 | @@ -164,7 +172,7 @@ | |
369 | char **envp; | |
370 | { | |
371 | int e; | |
372 | -#ifndef BSD | |
373 | +#if !defined(BSD) && !defined(linux) | |
374 | char *p; | |
375 | #endif | |
376 | ||
377 | @@ -180,7 +188,7 @@ | |
378 | initshellproc(); | |
379 | setinputfile(cmd, 0); | |
380 | commandname = arg0 = savestr(argv[0]); | |
381 | -#ifndef BSD | |
382 | +#if !defined(BSD) && !defined(linux) | |
383 | pgetc(); pungetc(); /* fill up input buffer */ | |
384 | p = parsenextc; | |
385 | if (parsenleft > 2 && p[0] == '#' && p[1] == '!') { | |
386 | @@ -195,7 +203,7 @@ | |
387 | } | |
388 | ||
389 | ||
390 | -#ifndef BSD | |
391 | +#if !defined(BSD) && !defined(linux) | |
392 | /* | |
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); | |
402 | + } | |
403 | } | |
404 | } | |
405 | return 0; | |
406 | } | |
407 | + c = 0; | |
408 | while ((name = *argptr) != NULL) { | |
409 | if ((cmdp = cmdlookup(name, 0)) != NULL | |
410 | && (cmdp->cmdtype == CMDNORMAL | |
411 | || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))) | |
412 | delete_cmd_entry(); | |
413 | find_command(name, &entry, DO_ERR, pathval()); | |
414 | - if (verbose) { | |
415 | - if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */ | |
416 | - cmdp = cmdlookup(name, 0); | |
417 | - printentry(cmdp, verbose); | |
418 | - } | |
419 | + if (entry.cmdtype == CMDUNKNOWN) c = 1; | |
420 | + else if (verbose) { | |
421 | + cmdp = cmdlookup(name, 0); | |
422 | + if (cmdp) printentry(cmdp, verbose); | |
423 | flushall(); | |
424 | } | |
425 | argptr++; | |
426 | } | |
427 | - return 0; | |
428 | + return c; | |
429 | } | |
430 | ||
431 | ||
432 | @@ -435,6 +445,10 @@ | |
433 | struct stat statb; | |
434 | int e; | |
435 | int i; | |
436 | + int bltin; | |
437 | + int firstchange; | |
438 | + int updatetbl; | |
439 | + int regular; | |
440 | ||
441 | /* If name contains a slash, don't use the hash table */ | |
442 | if (strchr(name, '/') != NULL) { | |
443 | @@ -459,12 +473,54 @@ | |
444 | return; | |
445 | } | |
446 | ||
447 | + updatetbl = 1; | |
448 | + if (act & DO_BRUTE) { | |
449 | + firstchange = path_change(path, &bltin); | |
450 | + } else { | |
451 | + bltin = builtinloc; | |
452 | + firstchange = 9999; | |
453 | + } | |
454 | + | |
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) | |
457 | - goto success; | |
458 | + if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) { | |
459 | + if (cmdp->cmdtype == CMDFUNCTION) { | |
460 | + if (act & DO_NOFUN) { | |
461 | + updatetbl = 0; | |
462 | + } else { | |
463 | + goto success; | |
464 | + } | |
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 */ | |
472 | + } else { | |
473 | + goto success; | |
474 | + } | |
475 | + } else { | |
476 | + goto success; | |
477 | + } | |
478 | + } | |
479 | + | |
480 | + if ((regular = is_regular_builtin(name))) { | |
481 | + if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) { | |
482 | + goto success; | |
483 | + } | |
484 | + } else if (act & DO_BRUTE) { | |
485 | + if (firstchange == 0) { | |
486 | + updatetbl = 0; | |
487 | + } | |
488 | + } | |
489 | ||
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) { | |
493 | + if (!updatetbl) { | |
494 | + entry->cmdtype = CMDBUILTIN; | |
495 | + entry->u.index = i; | |
496 | + return; | |
497 | + } | |
498 | INTOFF; | |
499 | cmdp = cmdlookup(name, 1); | |
500 | cmdp->cmdtype = CMDBUILTIN; | |
501 | @@ -475,7 +531,7 @@ | |
502 | ||
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) | |
508 | prev = builtinloc; | |
509 | else | |
510 | @@ -488,26 +544,38 @@ | |
511 | while ((fullname = padvance(&path, name)) != NULL) { | |
512 | stunalloc(fullname); | |
513 | idx++; | |
514 | + if (idx >= firstchange) { | |
515 | + updatetbl = 0; | |
516 | + } | |
517 | if (pathopt) { | |
518 | if (prefix("builtin", pathopt)) { | |
519 | - if ((i = find_builtin(name)) < 0) | |
520 | - goto loop; | |
521 | - INTOFF; | |
522 | - cmdp = cmdlookup(name, 1); | |
523 | - cmdp->cmdtype = CMDBUILTIN; | |
524 | - cmdp->param.index = i; | |
525 | - INTON; | |
526 | - goto success; | |
527 | - } else if (prefix("func", pathopt)) { | |
528 | + if ((i = find_builtin(name)) >= 0) { | |
529 | + if (!updatetbl) { | |
530 | + entry->cmdtype = CMDBUILTIN; | |
531 | + entry->u.index = i; | |
532 | + return; | |
533 | + } | |
534 | + INTOFF; | |
535 | + cmdp = cmdlookup(name, 1); | |
536 | + cmdp->cmdtype = CMDBUILTIN; | |
537 | + cmdp->param.index = i; | |
538 | + INTON; | |
539 | + goto success; | |
540 | + } else { | |
541 | + continue; | |
542 | + } | |
543 | + } else if (!(act & DO_NOFUN) && | |
544 | + prefix("func", pathopt)) { | |
545 | /* handled below */ | |
546 | } else { | |
547 | - goto loop; /* ignore unimplemented options */ | |
548 | + continue; /* ignore unimplemented options */ | |
549 | } | |
550 | } | |
551 | /* if rehash, don't redo absolute path names */ | |
552 | - if (fullname[0] == '/' && idx <= prev) { | |
553 | + if (fullname[0] == '/' && idx <= prev && | |
554 | + idx < firstchange) { | |
555 | if (idx < prev) | |
556 | - goto loop; | |
557 | + continue; | |
558 | TRACE(("searchexec \"%s\": no change\n", name)); | |
559 | goto success; | |
560 | } | |
561 | @@ -522,7 +590,7 @@ | |
562 | } | |
563 | e = EACCES; /* if we fail, this will be the error */ | |
564 | if (!S_ISREG(statb.st_mode)) | |
565 | - goto loop; | |
566 | + continue; | |
567 | if (pathopt) { /* this is a %func directory */ | |
568 | stalloc(strlen(fullname) + 1); | |
569 | readcmdfile(fullname); | |
570 | @@ -544,6 +612,13 @@ | |
571 | } | |
572 | #endif | |
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 */ | |
576 | + if (!updatetbl) { | |
577 | + entry->cmdtype = CMDNORMAL; | |
578 | + entry->u.index = idx; | |
579 | + return; | |
580 | + } | |
581 | INTOFF; | |
582 | cmdp = cmdlookup(name, 1); | |
583 | cmdp->cmdtype = CMDNORMAL; | |
584 | @@ -553,7 +628,7 @@ | |
585 | } | |
586 | ||
587 | /* We failed. If there was an entry for this command, delete it */ | |
588 | - if (cmdp) | |
589 | + if (cmdp && updatetbl) | |
590 | delete_cmd_entry(); | |
591 | if (act & DO_ERR) | |
592 | outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC)); | |
593 | @@ -618,37 +693,12 @@ | |
594 | changepath(newval) | |
595 | const char *newval; | |
596 | { | |
597 | - const char *old, *new; | |
598 | - int idx; | |
599 | int firstchange; | |
600 | int bltin; | |
601 | ||
602 | - old = pathval(); | |
603 | - new = newval; | |
604 | - firstchange = 9999; /* assume no change */ | |
605 | - idx = 0; | |
606 | - bltin = -1; | |
607 | - for (;;) { | |
608 | - if (*old != *new) { | |
609 | - firstchange = idx; | |
610 | - if ((*old == '\0' && *new == ':') | |
611 | - || (*old == ':' && *new == '\0')) | |
612 | - firstchange++; | |
613 | - old = new; /* ignore subsequent differences */ | |
614 | - } | |
615 | - if (*new == '\0') | |
616 | - break; | |
617 | - if (*new == '%' && bltin < 0 && prefix("builtin", new + 1)) | |
618 | - bltin = idx; | |
619 | - if (*new == ':') { | |
620 | - idx++; | |
621 | - } | |
622 | - new++, old++; | |
623 | - } | |
624 | + firstchange = path_change(newval, &bltin); | |
625 | if (builtinloc < 0 && bltin >= 0) | |
626 | builtinloc = bltin; /* zap builtins */ | |
627 | - if (builtinloc >= 0 && bltin < 0) | |
628 | - firstchange = 0; | |
629 | clearcmdentry(firstchange); | |
630 | builtinloc = bltin; | |
631 | } | |
632 | @@ -838,11 +888,9 @@ | |
633 | { | |
634 | struct cmdentry entry; | |
635 | ||
636 | - INTOFF; | |
637 | entry.cmdtype = CMDFUNCTION; | |
638 | entry.u.func = copyfunc(func); | |
639 | addcmdentry(name, &entry); | |
640 | - INTON; | |
641 | } | |
642 | ||
643 | ||
644 | @@ -944,4 +992,190 @@ | |
645 | } | |
646 | } | |
647 | return err; | |
648 | +} | |
649 | + | |
650 | +STATIC int | |
651 | +describe_command(command, verbose) | |
652 | + char *command; | |
653 | + int verbose; | |
654 | +{ | |
655 | + struct cmdentry entry; | |
656 | + struct tblentry *cmdp; | |
657 | + char **pp; | |
658 | + struct alias *ap; | |
659 | + extern char *const parsekwd[]; | |
660 | + | |
661 | + for (pp = (char **)parsekwd; *pp; pp++) | |
662 | + if (**pp == *command && equal(*pp, command)) | |
663 | + break; | |
664 | + | |
665 | + if (*pp) { | |
666 | + if (verbose) { | |
667 | + out1fmt("%s is a reserved word\n", command); | |
668 | + } else { | |
669 | + out1fmt("%s\n", command); | |
670 | + } | |
671 | + return 0; | |
672 | + } | |
673 | + | |
674 | + /* Then look at the aliases */ | |
675 | + if ((ap = lookupalias(command, 1)) != NULL) { | |
676 | + if (verbose) { | |
677 | + out1fmt("%s is aliased to `%s'\n", command, ap->val); | |
678 | + } else { | |
679 | + out1fmt("alias %s='%s'\n", command, ap->val); | |
680 | + } | |
681 | + return 0; | |
682 | + } | |
683 | + | |
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; | |
688 | + } | |
689 | + else { | |
690 | + /* Finally use brute force */ | |
691 | + find_command(command, &entry, DO_ABS, pathval()); | |
692 | + } | |
693 | + | |
694 | + switch (entry.cmdtype) { | |
695 | + case CMDNORMAL: { | |
696 | + int j = entry.u.index; | |
697 | + const char *path = pathval(); | |
698 | + char *name; | |
699 | + if (j == -1) | |
700 | + name = command; | |
701 | + else { | |
702 | + do { | |
703 | + name = padvance(&path, command); | |
704 | + stunalloc(name); | |
705 | + } while (--j >= 0); | |
706 | + } | |
707 | + if (verbose) { | |
708 | + out1fmt("%s is %s\n", command, name); | |
709 | + } else { | |
710 | + out1fmt("%s\n", name); | |
711 | + } | |
712 | + break; | |
713 | + } | |
714 | + case CMDFUNCTION: | |
715 | + if (verbose) { | |
716 | + out1fmt("%s is a function\n", command); | |
717 | + } else { | |
718 | + out1fmt("%s\n", command); | |
719 | + } | |
720 | + break; | |
721 | + case CMDBUILTIN: | |
722 | + if (verbose) { | |
723 | + if (is_special_builtin(command)) { | |
724 | + out1fmt("%s is a special built-in utility\n", command); | |
725 | + } else { | |
726 | + out1fmt("%s is a built-in utility\n", command); | |
727 | + } | |
728 | + } else { | |
729 | + out1fmt("%s\n", command); | |
730 | + } | |
731 | + break; | |
732 | + default: | |
733 | + outfmt(out2, "%s not found\n", command); | |
734 | + return 127; | |
735 | + } | |
736 | + | |
737 | + return 0; | |
738 | +} | |
739 | + | |
740 | +int | |
741 | +commandcmd(argc, argv) | |
742 | + int argc; | |
743 | + char **argv; | |
744 | +{ | |
745 | + int c; | |
746 | + int default_path = 0; | |
747 | + int verify_only = 0; | |
748 | + int verbose_verify_only = 0; | |
749 | + | |
750 | + while ((c = nextopt("pvV")) != '\0') | |
751 | + switch (c) { | |
752 | + case 'p': | |
753 | + default_path = 1; | |
754 | + break; | |
755 | + case 'v': | |
756 | + verify_only = 1; | |
757 | + break; | |
758 | + case 'V': | |
759 | + verbose_verify_only = 1; | |
760 | + break; | |
761 | + default: | |
762 | + outfmt(out2, | |
763 | +"command: nextopt returned character code 0%o\n", c); | |
764 | + return EX_SOFTWARE; | |
765 | + } | |
766 | + | |
767 | + if (default_path + verify_only + verbose_verify_only > 1 || | |
768 | + !*argptr) { | |
769 | + outfmt(out2, | |
770 | +"command [-p] command [arg ...]\n"); | |
771 | + outfmt(out2, | |
772 | +"command {-v|-V} command\n"); | |
773 | + return EX_USAGE; | |
774 | + } | |
775 | + | |
776 | + if (verify_only || verbose_verify_only) { | |
777 | + return describe_command(*argptr, verbose_verify_only); | |
778 | + } | |
779 | + | |
780 | + return 0; | |
781 | +} | |
782 | + | |
783 | +STATIC int | |
784 | +path_change(newval, bltin) | |
785 | + const char *newval; | |
786 | + int *bltin; | |
787 | +{ | |
788 | + const char *old, *new; | |
789 | + int idx; | |
790 | + int firstchange; | |
791 | + | |
792 | + old = pathval(); | |
793 | + new = newval; | |
794 | + firstchange = 9999; /* assume no change */ | |
795 | + idx = 0; | |
796 | + *bltin = -1; | |
797 | + for (;;) { | |
798 | + if (*old != *new) { | |
799 | + firstchange = idx; | |
800 | + if ((*old == '\0' && *new == ':') | |
801 | + || (*old == ':' && *new == '\0')) | |
802 | + firstchange++; | |
803 | + old = new; /* ignore subsequent differences */ | |
804 | + } | |
805 | + if (*new == '\0') | |
806 | + break; | |
807 | + if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1)) | |
808 | + *bltin = idx; | |
809 | + if (*new == ':') { | |
810 | + idx++; | |
811 | + } | |
812 | + new++, old++; | |
813 | + } | |
814 | + if (builtinloc >= 0 && *bltin < 0) | |
815 | + firstchange = 0; | |
816 | + return firstchange; | |
817 | +} | |
818 | + | |
819 | +STATIC int | |
820 | +is_regular_builtin(name) | |
821 | + const char *name; | |
822 | +{ | |
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 | |
827 | + }; | |
828 | + int i; | |
829 | + | |
830 | + if (!name) return 0; | |
831 | + for (i = 0; regular_builtins[i]; i++) | |
832 | + if (equal(name, regular_builtins[i])) return 1; | |
833 | + return 0; | |
834 | } | |
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 | |
838 | @@ -56,6 +56,8 @@ | |
839 | ||
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 */ | |
844 | ||
845 | extern const char *pathopt; /* set by padvance */ | |
846 | extern int exerrno; /* last exec error */ | |
847 | @@ -74,3 +76,4 @@ | |
848 | void defun __P((char *, union node *)); | |
849 | int unsetfunc __P((char *)); | |
850 | int typecmd __P((int, char **)); | |
851 | +int commandcmd __P((int, char **)); | |
852 |