2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1997-2005
5 * Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/types.h>
46 * When commands are first encountered, they are entered in a hash table.
47 * This ensures that a full path search will not have to be done for them
50 * We should investigate converting to a linear search, even though that
51 * would make the command name "hash" a misnomer.
76 #define CMDTABLESIZE 31 /* should be prime */
77 #define ARB 1 /* actual size determined at run time */
82 struct tblentry
*next
; /* next entry in hash chain */
83 union param param
; /* definition of builtin function */
84 short cmdtype
; /* index identifying command */
85 char rehash
; /* if set, cd done since entry created */
86 char cmdname
[ARB
]; /* name of command */
90 STATIC
struct tblentry
*cmdtable
[CMDTABLESIZE
];
91 STATIC
int builtinloc
= -1; /* index in path of %builtin, or -1 */
94 STATIC
void tryexec(char *, char **, char **);
95 STATIC
void printentry(struct tblentry
*);
96 STATIC
void clearcmdentry(void);
97 STATIC
struct tblentry
*cmdlookup(const char *, int);
98 STATIC
void delete_cmd_entry(void);
99 STATIC
void addcmdentry(char *, struct cmdentry
*);
100 STATIC
int describe_command(struct output
*, char *, const char *, int);
104 * Exec a program. Never returns. If you change this routine, you may
105 * have to change the find_command routine as well.
109 shellexec(char **argv
, const char *path
, int idx
)
116 envp
= environment();
117 if (strchr(argv
[0], '/') != NULL
) {
118 tryexec(argv
[0], argv
, envp
);
122 while (padvance(&path
, argv
[0]) >= 0) {
123 cmdname
= stackblock();
124 if (--idx
< 0 && pathopt
== NULL
) {
125 tryexec(cmdname
, argv
, envp
);
126 if (errno
!= ENOENT
&& errno
!= ENOTDIR
)
132 /* Map to POSIX errors */
144 exitstatus
= exerrno
;
145 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
146 argv
[0], e
, suppressint
));
147 exerror(EXEND
, "%s: %s", argv
[0], errmsg(e
, E_EXEC
));
153 tryexec(char *cmd
, char **argv
, char **envp
)
155 char *const path_bshell
= _PATH_BSHELL
;
160 execve(cmd
, argv
, envp
);
161 } while (errno
== EINTR
);
163 execve(cmd
, argv
, envp
);
165 if (cmd
!= path_bshell
&& errno
== ENOEXEC
) {
167 *argv
= cmd
= path_bshell
;
172 static const char *legal_pathopt(const char *opt
, const char *term
, int magic
)
180 opt
= prefix(opt
, "builtin") ?: prefix(opt
, "func");
184 opt
+= strcspn(opt
, term
);
188 if (opt
&& *opt
== '%')
195 * Do a path search. The variable path (passed by reference) should be
196 * set to the start of the path before the first call; padvance will update
197 * this value as it proceeds. Successive calls to padvance will return
198 * the possible path expansions in sequence. If an option (indicated by
199 * a percent sign) appears in the path entry then the global variable
200 * pathopt will be set to point to it; otherwise pathopt will be set to
203 * If magic is 0 then pathopt recognition will be disabled. If magic is
204 * 1 we shall recognise %builtin/%func. Otherwise we shall accept any
210 int padvance_magic(const char **path
, const char *name
, int magic
)
212 const char *term
= "%:";
213 const char *lpathopt
;
226 if (*start
== '%' && (p
= legal_pathopt(start
+ 1, term
, magic
))) {
227 lpathopt
= start
+ 1;
232 len
= strcspn(start
, term
);
236 size_t extra
= strchrnul(p
, ':') - p
;
238 if (legal_pathopt(p
+ 1, term
, magic
))
247 *path
= *p
== ':' ? p
+ 1 : NULL
;
249 /* "2" is for '/' and '\0' */
250 qlen
= len
+ strlen(name
) + 2;
251 q
= growstackto(qlen
);
254 q
= mempcpy(q
, start
, len
);
264 /*** Command hashing code ***/
268 hashcmd(int argc
, char **argv
)
270 struct tblentry
**pp
;
271 struct tblentry
*cmdp
;
273 struct cmdentry entry
;
278 while ((c
= nextopt("r")) != '\0')
285 if (*argptr
== NULL
) {
286 for (pp
= cmdtable
; pp
< &cmdtable
[CMDTABLESIZE
] ; pp
++) {
287 for (cmdp
= *pp
; cmdp
; cmdp
= cmdp
->next
) {
288 if (cmdp
->cmdtype
== CMDNORMAL
)
295 while ((name
= *argptr
) != NULL
) {
296 if ((cmdp
= cmdlookup(name
, 0)) &&
297 (cmdp
->cmdtype
== CMDNORMAL
||
298 (cmdp
->cmdtype
== CMDBUILTIN
&&
299 !(cmdp
->param
.cmd
->flags
& BUILTIN_REGULAR
) &&
302 find_command(name
, &entry
, DO_ERR
, pathval());
303 if (entry
.cmdtype
== CMDUNKNOWN
)
312 printentry(struct tblentry
*cmdp
)
318 idx
= cmdp
->param
.index
;
321 padvance(&path
, cmdp
->cmdname
);
322 } while (--idx
>= 0);
325 out1fmt(snlfmt
, cmdp
->rehash
? "*" : nullstr
);
328 static int test_exec(const char *fullname
, struct stat64
*statb
)
330 if (!S_ISREG(statb
->st_mode
))
333 if ((statb
->st_mode
& 0111) != 0111 &&
334 #ifdef HAVE_FACCESSAT
335 !test_file_access(fullname
, X_OK
)
337 !test_access(statb
, X_OK
)
346 * Resolve a command name. If you change this routine, you may have to
347 * change the shellexec routine as well.
351 find_command(char *name
, struct cmdentry
*entry
, int act
, const char *path
)
353 struct tblentry
*cmdp
;
360 struct builtincmd
*bcmd
;
363 /* If name contains a slash, don't use PATH or hash table */
364 if (strchr(name
, '/') != NULL
) {
367 while (stat64(name
, &statb
) < 0) {
373 entry
->cmdtype
= CMDUNKNOWN
;
376 if (!test_exec(name
, &statb
))
379 entry
->cmdtype
= CMDNORMAL
;
383 updatetbl
= (path
== pathval());
387 /* If name is in the table, check answer will be ok */
388 if ((cmdp
= cmdlookup(name
, 0)) != NULL
) {
391 switch (cmdp
->cmdtype
) {
397 bit
= DO_ALTPATH
| DO_REGBLTIN
;
403 bit
= cmdp
->param
.cmd
->flags
& BUILTIN_REGULAR
?
408 if (act
& bit
& DO_REGBLTIN
)
413 } else if (cmdp
->rehash
== 0)
414 /* if not invalidated by cd, we're done */
418 /* If %builtin not in path, check for builtin next */
419 bcmd
= find_builtin(name
);
420 if (bcmd
&& ((bcmd
->flags
& BUILTIN_REGULAR
) | (act
& DO_ALTPATH
) |
422 goto builtin_success
;
424 if (act
& DO_REGBLTIN
)
427 /* We have to search path. */
428 prev
= -1; /* where to start */
429 if (cmdp
&& cmdp
->rehash
) { /* doing a rehash */
430 if (cmdp
->cmdtype
== CMDBUILTIN
)
433 prev
= cmdp
->param
.index
;
439 while ((len
= padvance(&path
, name
)) >= 0) {
440 const char *lpathopt
= pathopt
;
442 fullname
= stackblock();
445 if (*lpathopt
== 'b') {
447 goto builtin_success
;
449 } else if (!(act
& DO_NOFUNC
)) {
452 /* ignore unimplemented options */
456 /* if rehash, don't redo absolute path names */
457 if (fullname
[0] == '/' && idx
<= prev
) {
460 TRACE(("searchexec \"%s\": no change\n", name
));
463 while (stat64(fullname
, &statb
) < 0) {
468 if (errno
!= ENOENT
&& errno
!= ENOTDIR
)
472 if (lpathopt
) { /* this is a %func directory */
474 readcmdfile(fullname
);
475 if ((cmdp
= cmdlookup(name
, 0)) == NULL
||
476 cmdp
->cmdtype
!= CMDFUNCTION
)
477 sh_error("%s not defined in %s", name
,
482 e
= EACCES
; /* if we fail, this will be the error */
483 if (!test_exec(fullname
, &statb
))
485 TRACE(("searchexec \"%s\" returns \"%s\"\n", name
, fullname
));
487 entry
->cmdtype
= CMDNORMAL
;
488 entry
->u
.index
= idx
;
492 cmdp
= cmdlookup(name
, 1);
493 cmdp
->cmdtype
= CMDNORMAL
;
494 cmdp
->param
.index
= idx
;
499 /* We failed. If there was an entry for this command, delete it */
500 if (cmdp
&& updatetbl
)
503 sh_warnx("%s: %s", name
, errmsg(e
, E_EXEC
));
505 entry
->cmdtype
= CMDUNKNOWN
;
510 entry
->cmdtype
= CMDBUILTIN
;
515 cmdp
= cmdlookup(name
, 1);
516 cmdp
->cmdtype
= CMDBUILTIN
;
517 cmdp
->param
.cmd
= bcmd
;
521 entry
->cmdtype
= cmdp
->cmdtype
;
522 entry
->u
= cmdp
->param
;
528 * Search the table of builtin commands.
532 find_builtin(const char *name
)
534 struct builtincmd
*bp
;
537 &name
, builtincmd
, NUMBUILTINS
, sizeof(struct builtincmd
),
546 * Called when a cd is done. Marks all commands so the next time they
547 * are executed they will be rehashed.
553 struct tblentry
**pp
;
554 struct tblentry
*cmdp
;
556 for (pp
= cmdtable
; pp
< &cmdtable
[CMDTABLESIZE
] ; pp
++) {
557 for (cmdp
= *pp
; cmdp
; cmdp
= cmdp
->next
) {
558 if (cmdp
->cmdtype
== CMDNORMAL
|| (
559 cmdp
->cmdtype
== CMDBUILTIN
&&
560 !(cmdp
->param
.cmd
->flags
& BUILTIN_REGULAR
) &&
571 * Fix command hash table when PATH changed.
572 * Called before PATH is changed. The argument is the new value of PATH;
573 * pathval() still returns the old value at this point.
574 * Called with interrupts off.
578 changepath(const char *newval
)
588 if (*new == '%' && prefix(new + 1, "builtin")) {
592 new = strchr(new, ':');
604 * Clear out command entries. The argument specifies the first entry in
605 * PATH which has changed.
611 struct tblentry
**tblp
;
612 struct tblentry
**pp
;
613 struct tblentry
*cmdp
;
616 for (tblp
= cmdtable
; tblp
< &cmdtable
[CMDTABLESIZE
] ; tblp
++) {
618 while ((cmdp
= *pp
) != NULL
) {
619 if (cmdp
->cmdtype
== CMDNORMAL
||
620 (cmdp
->cmdtype
== CMDBUILTIN
&&
621 !(cmdp
->param
.cmd
->flags
& BUILTIN_REGULAR
) &&
636 * Locate a command in the command hash table. If "add" is nonzero,
637 * add the command to the table if it is not already present. The
638 * variable "lastcmdentry" is set to point to the address of the link
639 * pointing to the entry, so that delete_cmd_entry can delete the
642 * Interrupts must be off if called with add != 0.
645 struct tblentry
**lastcmdentry
;
648 STATIC
struct tblentry
*
649 cmdlookup(const char *name
, int add
)
651 unsigned int hashval
;
653 struct tblentry
*cmdp
;
654 struct tblentry
**pp
;
657 hashval
= (unsigned char)*p
<< 4;
659 hashval
+= (unsigned char)*p
++;
661 pp
= &cmdtable
[hashval
% CMDTABLESIZE
];
662 for (cmdp
= *pp
; cmdp
; cmdp
= cmdp
->next
) {
663 if (equal(cmdp
->cmdname
, name
))
667 if (add
&& cmdp
== NULL
) {
668 cmdp
= *pp
= ckmalloc(sizeof (struct tblentry
) - ARB
671 cmdp
->cmdtype
= CMDUNKNOWN
;
672 strcpy(cmdp
->cmdname
, name
);
679 * Delete the command entry returned on the last lookup.
683 delete_cmd_entry(void)
685 struct tblentry
*cmdp
;
688 cmdp
= *lastcmdentry
;
689 *lastcmdentry
= cmdp
->next
;
690 if (cmdp
->cmdtype
== CMDFUNCTION
)
691 freefunc(cmdp
->param
.func
);
700 getcmdentry(char *name
, struct cmdentry
*entry
)
702 struct tblentry
*cmdp
= cmdlookup(name
, 0);
705 entry
->u
= cmdp
->param
;
706 entry
->cmdtype
= cmdp
->cmdtype
;
708 entry
->cmdtype
= CMDUNKNOWN
;
716 * Add a new command entry, replacing any existing command entry for
717 * the same name - except special builtins.
721 addcmdentry(char *name
, struct cmdentry
*entry
)
723 struct tblentry
*cmdp
;
725 cmdp
= cmdlookup(name
, 1);
726 if (cmdp
->cmdtype
== CMDFUNCTION
) {
727 freefunc(cmdp
->param
.func
);
729 cmdp
->cmdtype
= entry
->cmdtype
;
730 cmdp
->param
= entry
->u
;
736 * Define a shell function.
740 defun(union node
*func
)
742 struct cmdentry entry
;
745 entry
.cmdtype
= CMDFUNCTION
;
746 entry
.u
.func
= copyfunc(func
);
747 addcmdentry(func
->ndefun
.text
, &entry
);
753 * Delete a function if it exists.
757 unsetfunc(const char *name
)
759 struct tblentry
*cmdp
;
761 if ((cmdp
= cmdlookup(name
, 0)) != NULL
&&
762 cmdp
->cmdtype
== CMDFUNCTION
)
767 * Locate and print what a word is...
771 typecmd(int argc
, char **argv
)
777 err
|= describe_command(out1
, *argptr
++, NULL
, 1);
782 static int describe_command(struct output
*out
, char *command
,
783 const char *path
, int verbose
)
785 struct cmdentry entry
;
786 struct tblentry
*cmdp
;
787 const struct alias
*ap
;
790 outstr(command
, out
);
793 /* First look at the keywords */
794 if (findkwd(command
)) {
795 outstr(verbose
? " is a shell keyword" : command
, out
);
799 /* Then look at the aliases */
800 if ((ap
= lookupalias(command
, 0)) != NULL
) {
802 outfmt(out
, " is an alias for %s", ap
->val
);
804 outstr("alias ", out
);
811 /* Then if the standard search path is used, check if it is
816 cmdp
= cmdlookup(command
, 0);
822 entry
.cmdtype
= cmdp
->cmdtype
;
823 entry
.u
= cmdp
->param
;
825 /* Finally use brute force */
826 find_command(command
, &entry
, DO_ABS
, path
);
829 switch (entry
.cmdtype
) {
831 int j
= entry
.u
.index
;
837 padvance(&path
, command
);
844 cmdp
? " a tracked alias for" : nullstr
, p
854 outstr(" is a shell function", out
);
856 outstr(command
, out
);
863 out
, " is a %sshell builtin",
864 entry
.u
.cmd
->flags
& BUILTIN_SPECIAL
?
868 outstr(command
, out
);
874 outstr(": not found\n", out
);
884 int commandcmd(int argc
, char **argv
)
892 const char *path
= NULL
;
894 while ((c
= nextopt("pvV")) != '\0')
896 verify
|= VERIFY_VERBOSE
;
898 verify
|= VERIFY_BRIEF
;
908 return describe_command(out1
, cmd
, path
, verify
- VERIFY_BRIEF
);