summaryrefslogtreecommitdiff
path: root/package/busybox/patches/903-ash.patch
blob: efc1bc34395fce209c326cf81eceb1faa276b9bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1569,14 +1569,14 @@
 static char *optptr;                   /* used by nextopt */
 
 /*
- * XXX - should get rid of.  have all builtins use getopt(3).  the
- * library getopt must have the BSD extension static variable "optreset"
- * otherwise it can't be used within the shell safely.
+ * XXX - should get rid of. Have all builtins use getopt(3).
+ * The library getopt must have the BSD extension static variable
+ * "optreset", otherwise it can't be used within the shell safely.
  *
- * Standard option processing (a la getopt) for builtin routines.  The
- * only argument that is passed to nextopt is the option string; the
- * other arguments are unnecessary.  It return the character, or '\0' on
- * end of input.
+ * Standard option processing (a la getopt) for builtin routines.
+ * The only argument that is passed to nextopt is the option string;
+ * the other arguments are unnecessary. It returns the character,
+ * or '\0' on end of input.
  */
 static int
 nextopt(const char *optstring)
@@ -1587,13 +1587,20 @@
 
 	p = optptr;
 	if (p == NULL || *p == '\0') {
+		/* We ate entire "-param", take next one */
 		p = *argptr;
-		if (p == NULL || *p != '-' || *++p == '\0')
+		if (p == NULL)
+			return '\0';
+		if (*p != '-')
+			return '\0';
+		if (*++p == '\0') /* just "-" ? */
 			return '\0';
 		argptr++;
-		if (LONE_DASH(p))        /* check for "--" */
+		if (LONE_DASH(p)) /* "--" ? */
 			return '\0';
+		/* p => next "-param" */
 	}
+	/* p => some option char in the middle of a "-param" */
 	c = *p++;
 	for (q = optstring; *q != c;) {
 		if (*q == '\0')
@@ -1602,8 +1609,11 @@
 			q++;
 	}
 	if (*++q == ':') {
-		if (*p == '\0' && (p = *argptr++) == NULL)
-			ash_msg_and_raise_error("no arg for -%c option", c);
+		if (*p == '\0') {
+			p = *argptr++;
+			if (p == NULL)
+				ash_msg_and_raise_error("no arg for -%c option", c);
+		}
 		optionarg = p;
 		p = NULL;
 	}
@@ -7428,8 +7438,10 @@
 		else if (c != 'p')
 			abort();
 #endif
-	if (verify)
+	/* Mimic bash: just "command -v" doesn't complain, it's a nop */
+	if (verify && (*argptr != NULL)) {
 		return describe_command(*argptr, verify - VERIFY_BRIEF);
+	}
 
 	return 0;
 }
@@ -7788,16 +7800,33 @@
 static void
 evaltree(union node *n, int flags)
 {
+
+	struct jmploc *volatile savehandler = exception_handler;
+	struct jmploc jmploc;
 	int checkexit = 0;
 	void (*evalfn)(union node *, int);
-	unsigned isor;
 	int status;
+
 	if (n == NULL) {
 		TRACE(("evaltree(NULL) called\n"));
-		goto out;
+		goto out1;
 	}
 	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
 			getpid(), n, n->type, flags));
+
+	exception_handler = &jmploc;
+	{
+		int err = setjmp(jmploc.loc);
+		if (err) {
+			/* if it was a signal, check for trap handlers */
+			if (exception == EXSIG)
+				goto out;
+			/* continue on the way out */
+			exception_handler = savehandler;
+			longjmp(exception_handler->loc, err);
+		}
+	}
+
 	switch (n->type) {
 	default:
 #if DEBUG
@@ -7843,19 +7872,20 @@
 		goto calleval;
 	case NAND:
 	case NOR:
-	case NSEMI:
+	case NSEMI: {
+
 #if NAND + 1 != NOR
 #error NAND + 1 != NOR
 #endif
 #if NOR + 1 != NSEMI
 #error NOR + 1 != NSEMI
 #endif
-		isor = n->type - NAND;
+		unsigned is_or = n->type - NAND;
 		evaltree(
 			n->nbinary.ch1,
-			(flags | ((isor >> 1) - 1)) & EV_TESTED
+			(flags | ((is_or >> 1) - 1)) & EV_TESTED
 		);
-		if (!exitstatus == isor)
+		if (!exitstatus == is_or)
 			break;
 		if (!evalskip) {
 			n = n->nbinary.ch2;
@@ -7866,6 +7896,7 @@
 			break;
 		}
 		break;
+	}
 	case NIF:
 		evaltree(n->nif.test, EV_TESTED);
 		if (evalskip)
@@ -7886,8 +7917,11 @@
 		exitstatus = status;
 		break;
 	}
+
  out:
-	if ((checkexit & exitstatus))
+	exception_handler = savehandler;
+ out1:
+	if (checkexit & exitstatus)
 		evalskip |= SKIPEVAL;
 	else if (pendingsig && dotrap())
 		goto exexit;