1 /* $OpenBSD: misc.c,v 1.25 2018/10/24 06:01:03 martijn Exp $ */
2 /* $NetBSD: misc.c,v 1.6 1995/03/21 09:03:09 cgd Exp $ */
3
4 /*-
5 * Copyright (c) 1980, 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/types.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <stdarg.h>
37
38 #include "csh.h"
39 #include "extern.h"
40
41 static int fdcmp(int);
42 static int renum(int, int);
43
44 int
any(char * s,int c)45 any(char *s, int c)
46 {
47 if (!s)
48 return (0); /* Check for nil pointer */
49 while (*s)
50 if (*s++ == c)
51 return (1);
52 return (0);
53 }
54
55 Char **
blkend(Char ** up)56 blkend(Char **up)
57 {
58
59 while (*up)
60 up++;
61 return (up);
62 }
63
64
65 void
blkpr(FILE * fp,Char ** av)66 blkpr(FILE *fp, Char **av)
67 {
68
69 for (; *av; av++) {
70 (void) fprintf(fp, "%s", vis_str(*av));
71 if (av[1])
72 (void) fprintf(fp, " ");
73 }
74 }
75
76 int
blklen(Char ** av)77 blklen(Char **av)
78 {
79 int i = 0;
80
81 while (*av++)
82 i++;
83 return (i);
84 }
85
86 Char **
blkcpy(Char ** oav,Char ** bv)87 blkcpy(Char **oav, Char **bv)
88 {
89 Char **av = oav;
90
91 while ((*av++ = *bv++) != NULL)
92 continue;
93 return (oav);
94 }
95
96 Char **
blkcat(Char ** up,Char ** vp)97 blkcat(Char **up, Char **vp)
98 {
99
100 (void) blkcpy(blkend(up), vp);
101 return (up);
102 }
103
104 void
blkfree(Char ** av0)105 blkfree(Char **av0)
106 {
107 Char **av = av0;
108
109 if (!av0)
110 return;
111 for (; *av; av++)
112 free(* av);
113 free(av0);
114 }
115
116 Char **
saveblk(Char ** v)117 saveblk(Char **v)
118 {
119 Char **newv = xcalloc(blklen(v) + 1, sizeof(*newv));
120 Char **onewv = newv;
121
122 while (*v)
123 *newv++ = Strsave(*v++);
124 return (onewv);
125 }
126
127 Char **
blkspl(Char ** up,Char ** vp)128 blkspl(Char **up, Char **vp)
129 {
130 Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(*wp));
131
132 (void) blkcpy(wp, up);
133 return (blkcat(wp, vp));
134 }
135
136 Char
lastchr(Char * cp)137 lastchr(Char *cp)
138 {
139
140 if (!cp)
141 return (0);
142 if (!*cp)
143 return (0);
144 while (cp[1])
145 cp++;
146 return (*cp);
147 }
148
149 /*
150 * Returns 0 if fd is in use, 1 if fd is greater than the largest used file
151 * descriptor and -1 otherwise.
152 */
153 static int
fdcmp(int fd)154 fdcmp(int fd)
155 {
156 int fds[] = { SHIN, SHOUT, SHERR, OLDSTD, FSHTTY };
157 int i, max;
158
159 max = -1;
160 for (i = 0; i < sizeof(fds)/sizeof(fds[0]); i++) {
161 if (fd == fds[i])
162 return (0);
163 if (fds[i] > max)
164 max = fds[i];
165 }
166 if (fd > max)
167 return (1);
168
169 return (-1);
170 }
171
172 /*
173 * This routine is called after an error to close up
174 * any units which may have been left open accidentally.
175 */
176 void
closem(void)177 closem(void)
178 {
179 int f;
180 int max = sysconf(_SC_OPEN_MAX);
181
182 for (f = 0; f < max; f++)
183 switch (fdcmp(f)) {
184 case 0:
185 continue;
186 case 1:
187 closefrom(f);
188 return;
189 default:
190 close(f);
191 }
192 }
193
194 void
donefds(void)195 donefds(void)
196 {
197 (void) close(0);
198 (void) close(1);
199 (void) close(2);
200
201 didfds = 0;
202 }
203
204 /*
205 * Move descriptor i to j.
206 * If j is -1 then we just want to get i to a safe place,
207 * i.e. to a unit > 2. This also happens in dcopy.
208 */
209 int
dmove(int i,int j)210 dmove(int i, int j)
211 {
212
213 if (i == j || i < 0)
214 return (i);
215 if (j >= 0) {
216 (void) dup2(i, j);
217 if (j != i)
218 (void) close(i);
219 return (j);
220 }
221 j = dcopy(i, j);
222 if (j != i)
223 (void) close(i);
224 return (j);
225 }
226
227 int
dcopy(int i,int j)228 dcopy(int i, int j)
229 {
230
231 if (i == j || i < 0 || (j < 0 && i > 2))
232 return (i);
233 if (j >= 0) {
234 (void) dup2(i, j);
235 return (j);
236 }
237 (void) close(j);
238 return (renum(i, j));
239 }
240
241 static int
renum(int i,int j)242 renum(int i, int j)
243 {
244 int k = dup(i);
245
246 if (k < 0)
247 return (-1);
248 if (j == -1 && k > 2)
249 return (k);
250 if (k != j) {
251 j = renum(k, j);
252 (void) close(k);
253 return (j);
254 }
255 return (k);
256 }
257
258 /*
259 * Left shift a command argument list, discarding
260 * the first c arguments. Used in "shift" commands
261 * as well as by commands like "repeat".
262 */
263 void
lshift(Char ** v,int c)264 lshift(Char **v, int c)
265 {
266 Char **u;
267
268 for (u = v; *u && --c >= 0; u++)
269 free(*u);
270 (void) blkcpy(v, u);
271 }
272
273 int
number(Char * cp)274 number(Char *cp)
275 {
276 if (!cp)
277 return(0);
278 if (*cp == '-') {
279 cp++;
280 if (!Isdigit(*cp))
281 return (0);
282 cp++;
283 }
284 while (*cp && Isdigit(*cp))
285 cp++;
286 return (*cp == 0);
287 }
288
289 Char **
copyblk(Char ** v)290 copyblk(Char **v)
291 {
292 Char **nv = xcalloc(blklen(v) + 1, sizeof(*nv));
293
294 return (blkcpy(nv, v));
295 }
296
297 Char *
strip(Char * cp)298 strip(Char *cp)
299 {
300 Char *dp = cp;
301
302 if (!cp)
303 return (cp);
304 while ((*dp++ &= TRIM) != '\0')
305 continue;
306 return (cp);
307 }
308
309 Char *
quote(Char * cp)310 quote(Char *cp)
311 {
312 Char *dp = cp;
313
314 if (!cp)
315 return (cp);
316 while (*dp != '\0')
317 *dp++ |= QUOTE;
318 return (cp);
319 }
320
321 void
udvar(Char * name)322 udvar(Char *name)
323 {
324
325 setname(vis_str(name));
326 stderror(ERR_NAME | ERR_UNDVAR);
327 }
328
329 int
prefix(Char * sub,Char * str)330 prefix(Char *sub, Char *str)
331 {
332
333 for (;;) {
334 if (*sub == 0)
335 return (1);
336 if (*str == 0)
337 return (0);
338 if (*sub++ != *str++)
339 return (0);
340 }
341 }
342