Sat Aug 25 14:48:22 2018 UTC ()
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.c


(martin)
diff -r1.140.2.5 -r1.140.2.6 src/bin/sh/eval.c
diff -r1.19.8.1 -r1.19.8.2 src/bin/sh/eval.h
diff -r1.47.2.3 -r1.47.2.4 src/bin/sh/exec.c

cvs diff -r1.140.2.5 -r1.140.2.6 src/bin/sh/eval.c (expand / switch to unified diff)

--- 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
38static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; 38static 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
699static const char * 699const char *
700syspath(void) 700syspath(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 {

cvs diff -r1.19.8.1 -r1.19.8.2 src/bin/sh/eval.h (expand / switch to unified diff)

--- 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
43struct backcmd { /* result of evalbackcmd */ 43struct 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
50void evalstring(char *, int); 50void evalstring(char *, int);
51union node; /* BLETCH for ansi C */ 51union node; /* BLETCH for ansi C */
52void evaltree(union node *, int); 52void evaltree(union node *, int);
53void evalbackcmd(union node *, struct backcmd *); 53void evalbackcmd(union node *, struct backcmd *);
54 54
 55const 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 */
56int in_function(void); /* return non-zero, if evaluating a function */ 58int 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) */
59enum skipstate { 61enum 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
67enum skipstate current_skipstate(void); 69enum skipstate current_skipstate(void);

cvs diff -r1.47.2.3 -r1.47.2.4 src/bin/sh/exec.c (expand / switch to unified diff)

--- 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
38static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; 38static 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);