Pull up following revision(s) (requested by kre in ticket #989): bin/sh/eval.c: revision 1.156 bin/sh/eval.h: revision 1.20 bin/sh/exec.c: revision 1.53 Fix several bugs in the command / type builtin ( including PR bin/48499 ) 1. Make command -pv (and -pV) work (which is not as easy as the PR suggests it might be (the "check and cause error" was there because it did not work, not in order to prevent it from working). 2. Stop -v and -V being both used (that makes no sense). 3. Stop the "type" builtin inheriting the args (-pvV) that "command" has (which it did, as when -v -or -V is used with command, it and type are implemented using the same code). 4. make "command -v word" DTRT for sh keywords (was treating them as an error). 5. Require at least one arg for "command -[vV]" or "type" else usage & error. Strictly this should also apply to "command" and "command -p" (no -v) but that's handled elsewhere, so perhaps some other time. Perhaps "command -v" (and -V) should be limited to 1 command name (where "type" can have many) as in the POSIX definitions, but I don't think that matters. 6. With "command -V alias", (or "type alias" which is the same thing), (but not "command -v alias") alter the output format, so we get ll is an alias for: ls -al instead of the old ll is an alias for ls -al (and note there was a space, for some reason, after "for") That is, unless the alias value contains any \n characters, in which case (something approximating) the old multi-line format is retained. Also note: that if code wants to parse/use the value of an alias, it should be using the output of "alias name", not command or type. Note that none of the above affects "command [-p] cmd" (no -v or -V options) only "command -[vV]" and "type". Note also that the changes to eval.[ch] are merely to make syspath() visible in exec.c rather than static in eval.cdiff -r1.140.2.5 -r1.140.2.6 src/bin/sh/eval.c
(martin)
--- src/bin/sh/eval.c 2018/08/25 14:22:49 1.140.2.5
+++ src/bin/sh/eval.c 2018/08/25 14:48:22 1.140.2.6
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: eval.c,v 1.140.2.5 2018/08/25 14:22:49 martin Exp $ */ | 1 | /* $NetBSD: eval.c,v 1.140.2.6 2018/08/25 14:48:22 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1993 | 4 | * Copyright (c) 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Kenneth Almquist. | 8 | * Kenneth Almquist. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | 32 | * SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | #include <sys/cdefs.h> | 35 | #include <sys/cdefs.h> | |
36 | #ifndef lint | 36 | #ifndef lint | |
37 | #if 0 | 37 | #if 0 | |
38 | static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; | 38 | static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; | |
39 | #else | 39 | #else | |
40 | __RCSID("$NetBSD: eval.c,v 1.140.2.5 2018/08/25 14:22:49 martin Exp $"); | 40 | __RCSID("$NetBSD: eval.c,v 1.140.2.6 2018/08/25 14:48:22 martin Exp $"); | |
41 | #endif | 41 | #endif | |
42 | #endif /* not lint */ | 42 | #endif /* not lint */ | |
43 | 43 | |||
44 | #include <stdbool.h> | 44 | #include <stdbool.h> | |
45 | #include <stdlib.h> | 45 | #include <stdlib.h> | |
46 | #include <signal.h> | 46 | #include <signal.h> | |
47 | #include <stdio.h> | 47 | #include <stdio.h> | |
48 | #include <string.h> | 48 | #include <string.h> | |
49 | #include <errno.h> | 49 | #include <errno.h> | |
50 | #include <limits.h> | 50 | #include <limits.h> | |
51 | #include <unistd.h> | 51 | #include <unistd.h> | |
52 | #include <sys/fcntl.h> | 52 | #include <sys/fcntl.h> | |
53 | #include <sys/stat.h> | 53 | #include <sys/stat.h> | |
@@ -686,27 +686,27 @@ evalbackcmd(union node *n, struct backcm | @@ -686,27 +686,27 @@ evalbackcmd(union node *n, struct backcm | |||
686 | /* NOTREACHED */ | 686 | /* NOTREACHED */ | |
687 | } | 687 | } | |
688 | close(pip[1]); | 688 | close(pip[1]); | |
689 | result->fd = pip[0]; | 689 | result->fd = pip[0]; | |
690 | result->jp = jp; | 690 | result->jp = jp; | |
691 | INTON; | 691 | INTON; | |
692 | } | 692 | } | |
693 | out: | 693 | out: | |
694 | popstackmark(&smark); | 694 | popstackmark(&smark); | |
695 | CTRACE(DBG_EVAL, ("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", | 695 | CTRACE(DBG_EVAL, ("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", | |
696 | result->fd, result->buf, result->nleft, result->jp)); | 696 | result->fd, result->buf, result->nleft, result->jp)); | |
697 | } | 697 | } | |
698 | 698 | |||
699 | static const char * | 699 | const char * | |
700 | syspath(void) | 700 | syspath(void) | |
701 | { | 701 | { | |
702 | static char *sys_path = NULL; | 702 | static char *sys_path = NULL; | |
703 | static int mib[] = {CTL_USER, USER_CS_PATH}; | 703 | static int mib[] = {CTL_USER, USER_CS_PATH}; | |
704 | static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; | 704 | static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; | |
705 | size_t len; | 705 | size_t len; | |
706 | 706 | |||
707 | if (sys_path == NULL) { | 707 | if (sys_path == NULL) { | |
708 | if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && | 708 | if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && | |
709 | (sys_path = ckmalloc(len + 5)) != NULL && | 709 | (sys_path = ckmalloc(len + 5)) != NULL && | |
710 | sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { | 710 | sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { | |
711 | memcpy(sys_path, "PATH=", 5); | 711 | memcpy(sys_path, "PATH=", 5); | |
712 | } else { | 712 | } else { |
--- src/bin/sh/eval.h 2018/08/25 14:22:49 1.19.8.1
+++ src/bin/sh/eval.h 2018/08/25 14:48:22 1.19.8.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: eval.h,v 1.19.8.1 2018/08/25 14:22:49 martin Exp $ */ | 1 | /* $NetBSD: eval.h,v 1.19.8.2 2018/08/25 14:48:22 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1991, 1993 | 4 | * Copyright (c) 1991, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Kenneth Almquist. | 8 | * Kenneth Almquist. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -42,26 +42,28 @@ extern struct strlist *cmdenviron; /* e | @@ -42,26 +42,28 @@ extern struct strlist *cmdenviron; /* e | |||
42 | 42 | |||
43 | struct backcmd { /* result of evalbackcmd */ | 43 | struct backcmd { /* result of evalbackcmd */ | |
44 | int fd; /* file descriptor to read from */ | 44 | int fd; /* file descriptor to read from */ | |
45 | char *buf; /* buffer */ | 45 | char *buf; /* buffer */ | |
46 | int nleft; /* number of chars in buffer */ | 46 | int nleft; /* number of chars in buffer */ | |
47 | struct job *jp; /* job structure for command */ | 47 | struct job *jp; /* job structure for command */ | |
48 | }; | 48 | }; | |
49 | 49 | |||
50 | void evalstring(char *, int); | 50 | void evalstring(char *, int); | |
51 | union node; /* BLETCH for ansi C */ | 51 | union node; /* BLETCH for ansi C */ | |
52 | void evaltree(union node *, int); | 52 | void evaltree(union node *, int); | |
53 | void evalbackcmd(union node *, struct backcmd *); | 53 | void evalbackcmd(union node *, struct backcmd *); | |
54 | 54 | |||
55 | const char *syspath(void); | |||
56 | ||||
55 | /* in_function returns nonzero if we are currently evaluating a function */ | 57 | /* in_function returns nonzero if we are currently evaluating a function */ | |
56 | int in_function(void); /* return non-zero, if evaluating a function */ | 58 | int in_function(void); /* return non-zero, if evaluating a function */ | |
57 | 59 | |||
58 | /* reasons for skipping commands (see comment on breakcmd routine) */ | 60 | /* reasons for skipping commands (see comment on breakcmd routine) */ | |
59 | enum skipstate { | 61 | enum skipstate { | |
60 | SKIPNONE = 0, /* not skipping */ | 62 | SKIPNONE = 0, /* not skipping */ | |
61 | SKIPBREAK, /* break */ | 63 | SKIPBREAK, /* break */ | |
62 | SKIPCONT, /* continue */ | 64 | SKIPCONT, /* continue */ | |
63 | SKIPFUNC, /* return in a function */ | 65 | SKIPFUNC, /* return in a function */ | |
64 | SKIPFILE /* return in a dot command */ | 66 | SKIPFILE /* return in a dot command */ | |
65 | }; | 67 | }; | |
66 | 68 | |||
67 | enum skipstate current_skipstate(void); | 69 | enum skipstate current_skipstate(void); |
--- src/bin/sh/exec.c 2018/07/13 14:29:15 1.47.2.3
+++ src/bin/sh/exec.c 2018/08/25 14:48:22 1.47.2.4
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: exec.c,v 1.47.2.3 2018/07/13 14:29:15 martin Exp $ */ | 1 | /* $NetBSD: exec.c,v 1.47.2.4 2018/08/25 14:48:22 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1991, 1993 | 4 | * Copyright (c) 1991, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Kenneth Almquist. | 8 | * Kenneth Almquist. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | 32 | * SUCH DAMAGE. | |
33 | */ | 33 | */ | |
34 | 34 | |||
35 | #include <sys/cdefs.h> | 35 | #include <sys/cdefs.h> | |
36 | #ifndef lint | 36 | #ifndef lint | |
37 | #if 0 | 37 | #if 0 | |
38 | static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; | 38 | static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; | |
39 | #else | 39 | #else | |
40 | __RCSID("$NetBSD: exec.c,v 1.47.2.3 2018/07/13 14:29:15 martin Exp $"); | 40 | __RCSID("$NetBSD: exec.c,v 1.47.2.4 2018/08/25 14:48:22 martin Exp $"); | |
41 | #endif | 41 | #endif | |
42 | #endif /* not lint */ | 42 | #endif /* not lint */ | |
43 | 43 | |||
44 | #include <sys/types.h> | 44 | #include <sys/types.h> | |
45 | #include <sys/stat.h> | 45 | #include <sys/stat.h> | |
46 | #include <sys/wait.h> | 46 | #include <sys/wait.h> | |
47 | #include <unistd.h> | 47 | #include <unistd.h> | |
48 | #include <fcntl.h> | 48 | #include <fcntl.h> | |
49 | #include <errno.h> | 49 | #include <errno.h> | |
50 | #include <stdio.h> | 50 | #include <stdio.h> | |
51 | #include <stdlib.h> | 51 | #include <stdlib.h> | |
52 | 52 | |||
53 | /* | 53 | /* | |
@@ -1054,68 +1054,90 @@ typecmd(int argc, char **argv) | @@ -1054,68 +1054,90 @@ typecmd(int argc, char **argv) | |||
1054 | int c; | 1054 | int c; | |
1055 | int V_flag = 0; | 1055 | int V_flag = 0; | |
1056 | int v_flag = 0; | 1056 | int v_flag = 0; | |
1057 | int p_flag = 0; | 1057 | int p_flag = 0; | |
1058 | 1058 | |||
1059 | while ((c = nextopt("vVp")) != 0) { | 1059 | while ((c = nextopt("vVp")) != 0) { | |
1060 | switch (c) { | 1060 | switch (c) { | |
1061 | case 'v': v_flag = 1; break; | 1061 | case 'v': v_flag = 1; break; | |
1062 | case 'V': V_flag = 1; break; | 1062 | case 'V': V_flag = 1; break; | |
1063 | case 'p': p_flag = 1; break; | 1063 | case 'p': p_flag = 1; break; | |
1064 | } | 1064 | } | |
1065 | } | 1065 | } | |
1066 | 1066 | |||
1067 | if (p_flag && (v_flag || V_flag)) | 1067 | if (argv[0][0] != 'c' && v_flag | V_flag | p_flag) | |
1068 | error("cannot specify -p with -v or -V"); | 1068 | error("usage: %s name...", argv[0]); | |
1069 | ||||
1070 | if (v_flag && V_flag) | |||
1071 | error("-v and -V cannot both be specified"); | |||
1072 | ||||
1073 | if (*argptr == NULL) | |||
1074 | error("usage: %s%s name ...", argv[0], | |||
1075 | argv[0][0] == 'c' ? " [-p] [-v|-V]" : ""); | |||
1069 | 1076 | |||
1070 | while ((arg = *argptr++)) { | 1077 | while ((arg = *argptr++)) { | |
1071 | if (!v_flag) | 1078 | if (!v_flag) | |
1072 | out1str(arg); | 1079 | out1str(arg); | |
1073 | /* First look at the keywords */ | 1080 | /* First look at the keywords */ | |
1074 | for (pp = parsekwd; *pp; pp++) | 1081 | for (pp = parsekwd; *pp; pp++) | |
1075 | if (**pp == *arg && equal(*pp, arg)) | 1082 | if (**pp == *arg && equal(*pp, arg)) | |
1076 | break; | 1083 | break; | |
1077 | 1084 | |||
1078 | if (*pp) { | 1085 | if (*pp) { | |
1079 | if (v_flag) | 1086 | if (v_flag) | |
1080 | err = 1; | 1087 | out1fmt("%s\n", arg); | |
1081 | else | 1088 | else | |
1082 | out1str(" is a shell keyword\n"); | 1089 | out1str(" is a shell keyword\n"); | |
1083 | continue; | 1090 | continue; | |
1084 | } | 1091 | } | |
1085 | 1092 | |||
1086 | /* Then look at the aliases */ | 1093 | /* Then look at the aliases */ | |
1087 | if ((ap = lookupalias(arg, 1)) != NULL) { | 1094 | if ((ap = lookupalias(arg, 1)) != NULL) { | |
1088 | if (!v_flag) | 1095 | int ml = 0; | |
1089 | out1fmt(" is an alias for \n"); | 1096 | ||
1097 | if (!v_flag) { | |||
1098 | out1str(" is an alias "); | |||
1099 | if (strchr(ap->val, '\n')) { | |||
1100 | out1str("(multiline)...\n"); | |||
1101 | ml = 1; | |||
1102 | } else | |||
1103 | out1str("for: "); | |||
1104 | } | |||
1090 | out1fmt("%s\n", ap->val); | 1105 | out1fmt("%s\n", ap->val); | |
1106 | if (ml && *argptr != NULL) | |||
1107 | out1c('\n'); | |||
1091 | continue; | 1108 | continue; | |
1092 | } | 1109 | } | |
1093 | 1110 | |||
1094 | /* Then check if it is a tracked alias */ | 1111 | /* Then check if it is a tracked alias */ | |
1095 | if ((cmdp = cmdlookup(arg, 0)) != NULL) { | 1112 | if (!p_flag && (cmdp = cmdlookup(arg, 0)) != NULL) { | |
1096 | entry.cmdtype = cmdp->cmdtype; | 1113 | entry.cmdtype = cmdp->cmdtype; | |
1097 | entry.u = cmdp->param; | 1114 | entry.u = cmdp->param; | |
1098 | } else { | 1115 | } else { | |
1116 | cmdp = NULL; | |||
1099 | /* Finally use brute force */ | 1117 | /* Finally use brute force */ | |
1100 | find_command(arg, &entry, DO_ABS, pathval()); | 1118 | find_command(arg, &entry, DO_ABS, | |
1119 | p_flag ? syspath() + 5 : pathval()); | |||
1101 | } | 1120 | } | |
1102 | 1121 | |||
1103 | switch (entry.cmdtype) { | 1122 | switch (entry.cmdtype) { | |
1104 | case CMDNORMAL: { | 1123 | case CMDNORMAL: { | |
1105 | if (strchr(arg, '/') == NULL) { | 1124 | if (strchr(arg, '/') == NULL) { | |
1106 | const char *path = pathval(); | 1125 | const char *path; | |
1107 | char *name; | 1126 | char *name; | |
1108 | int j = entry.u.index; | 1127 | int j = entry.u.index; | |
1128 | ||||
1129 | path = p_flag ? syspath() + 5 : pathval(); | |||
1130 | ||||
1109 | do { | 1131 | do { | |
1110 | name = padvance(&path, arg, 1); | 1132 | name = padvance(&path, arg, 1); | |
1111 | stunalloc(name); | 1133 | stunalloc(name); | |
1112 | } while (--j >= 0); | 1134 | } while (--j >= 0); | |
1113 | if (!v_flag) | 1135 | if (!v_flag) | |
1114 | out1fmt(" is%s ", | 1136 | out1fmt(" is%s ", | |
1115 | cmdp ? " a tracked alias for" : ""); | 1137 | cmdp ? " a tracked alias for" : ""); | |
1116 | out1fmt("%s\n", name); | 1138 | out1fmt("%s\n", name); | |
1117 | } else { | 1139 | } else { | |
1118 | if (access(arg, X_OK) == 0) { | 1140 | if (access(arg, X_OK) == 0) { | |
1119 | if (!v_flag) | 1141 | if (!v_flag) | |
1120 | out1fmt(" is "); | 1142 | out1fmt(" is "); | |
1121 | out1fmt("%s\n", arg); | 1143 | out1fmt("%s\n", arg); |