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