xref: /openbsd-src/bin/csh/misc.c (revision c7e8ea31cd41a963f06f0a8ba93948b06aa6b4a4)
1 /*	$OpenBSD: misc.c,v 1.20 2017/06/20 16:44:06 anton 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
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   *
56 strsave(char *s)
57 {
58     char   *n;
59     char *p;
60 
61     if (s == NULL)
62 	s = "";
63     for (p = s; *p++;)
64 	continue;
65     n = p = xreallocarray(NULL, (p - s), sizeof(char));
66     while ((*p++ = *s++) != '\0')
67 	continue;
68     return (n);
69 }
70 
71 Char  **
72 blkend(Char **up)
73 {
74 
75     while (*up)
76 	up++;
77     return (up);
78 }
79 
80 
81 void
82 blkpr(FILE *fp, Char **av)
83 {
84 
85     for (; *av; av++) {
86 	(void) fprintf(fp, "%s", vis_str(*av));
87 	if (av[1])
88 	    (void) fprintf(fp, " ");
89     }
90 }
91 
92 int
93 blklen(Char **av)
94 {
95     int i = 0;
96 
97     while (*av++)
98 	i++;
99     return (i);
100 }
101 
102 Char  **
103 blkcpy(Char **oav, Char **bv)
104 {
105     Char **av = oav;
106 
107     while ((*av++ = *bv++) != NULL)
108 	continue;
109     return (oav);
110 }
111 
112 Char  **
113 blkcat(Char **up, Char **vp)
114 {
115 
116     (void) blkcpy(blkend(up), vp);
117     return (up);
118 }
119 
120 void
121 blkfree(Char **av0)
122 {
123     Char **av = av0;
124 
125     if (!av0)
126 	return;
127     for (; *av; av++)
128 	free(* av);
129     free(av0);
130 }
131 
132 Char  **
133 saveblk(Char **v)
134 {
135     Char **newv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
136     Char  **onewv = newv;
137 
138     while (*v)
139 	*newv++ = Strsave(*v++);
140     return (onewv);
141 }
142 
143 Char  **
144 blkspl(Char **up, Char **vp)
145 {
146     Char **wp = xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
147 		      sizeof(Char **));
148 
149     (void) blkcpy(wp, up);
150     return (blkcat(wp, vp));
151 }
152 
153 Char
154 lastchr(Char *cp)
155 {
156 
157     if (!cp)
158 	return (0);
159     if (!*cp)
160 	return (0);
161     while (cp[1])
162 	cp++;
163     return (*cp);
164 }
165 
166 /*
167  * Returns 0 if fd is in use, 1 if fd is greater than the largest used file
168  * descriptor and -1 otherwise.
169  */
170 static int
171 fdcmp(int fd)
172 {
173     int fds[] = { SHIN, SHOUT, SHERR, OLDSTD, FSHTTY };
174     int i, max;
175 
176     max = -1;
177     for (i = 0; i < sizeof(fds)/sizeof(fds[0]); i++) {
178 	if (fd == fds[i])
179 	    return (0);
180 	if (fds[i] > max)
181 	    max = fds[i];
182     }
183     if (fd > max)
184 	return (1);
185 
186     return (-1);
187 }
188 
189 /*
190  * This routine is called after an error to close up
191  * any units which may have been left open accidentally.
192  */
193 void
194 closem(void)
195 {
196     int f;
197     int max = sysconf(_SC_OPEN_MAX);
198 
199     for (f = 0; f < max; f++)
200 	switch (fdcmp(f)) {
201 	case 0:
202 	    continue;
203 	case 1:
204 	    closefrom(f);
205 	    return;
206 	default:
207 	    close(f);
208 	}
209 }
210 
211 void
212 donefds(void)
213 {
214     (void) close(0);
215     (void) close(1);
216     (void) close(2);
217 
218     didfds = 0;
219 }
220 
221 /*
222  * Move descriptor i to j.
223  * If j is -1 then we just want to get i to a safe place,
224  * i.e. to a unit > 2.  This also happens in dcopy.
225  */
226 int
227 dmove(int i, int j)
228 {
229 
230     if (i == j || i < 0)
231 	return (i);
232     if (j >= 0) {
233 	(void) dup2(i, j);
234 	if (j != i)
235 	    (void) close(i);
236 	return (j);
237     }
238     j = dcopy(i, j);
239     if (j != i)
240 	(void) close(i);
241     return (j);
242 }
243 
244 int
245 dcopy(int i, int j)
246 {
247 
248     if (i == j || i < 0 || (j < 0 && i > 2))
249 	return (i);
250     if (j >= 0) {
251 	(void) dup2(i, j);
252 	return (j);
253     }
254     (void) close(j);
255     return (renum(i, j));
256 }
257 
258 static int
259 renum(int i, int j)
260 {
261     int k = dup(i);
262 
263     if (k < 0)
264 	return (-1);
265     if (j == -1 && k > 2)
266 	return (k);
267     if (k != j) {
268 	j = renum(k, j);
269 	(void) close(k);
270 	return (j);
271     }
272     return (k);
273 }
274 
275 /*
276  * Left shift a command argument list, discarding
277  * the first c arguments.  Used in "shift" commands
278  * as well as by commands like "repeat".
279  */
280 void
281 lshift(Char **v, int c)
282 {
283     Char **u;
284 
285     for (u = v; *u && --c >= 0; u++)
286 	free(*u);
287     (void) blkcpy(v, u);
288 }
289 
290 int
291 number(Char *cp)
292 {
293     if (!cp)
294 	return(0);
295     if (*cp == '-') {
296 	cp++;
297 	if (!Isdigit(*cp))
298 	    return (0);
299 	cp++;
300     }
301     while (*cp && Isdigit(*cp))
302 	cp++;
303     return (*cp == 0);
304 }
305 
306 Char  **
307 copyblk(Char **v)
308 {
309     Char  **nv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
310 
311     return (blkcpy(nv, v));
312 }
313 
314 Char   *
315 strip(Char *cp)
316 {
317     Char *dp = cp;
318 
319     if (!cp)
320 	return (cp);
321     while ((*dp++ &= TRIM) != '\0')
322 	continue;
323     return (cp);
324 }
325 
326 Char   *
327 quote(Char *cp)
328 {
329     Char *dp = cp;
330 
331     if (!cp)
332 	return (cp);
333     while (*dp != '\0')
334 	*dp++ |= QUOTE;
335     return (cp);
336 }
337 
338 void
339 udvar(Char *name)
340 {
341 
342     setname(vis_str(name));
343     stderror(ERR_NAME | ERR_UNDVAR);
344 }
345 
346 int
347 prefix(Char *sub, Char *str)
348 {
349 
350     for (;;) {
351 	if (*sub == 0)
352 	    return (1);
353 	if (*str == 0)
354 	    return (0);
355 	if (*sub++ != *str++)
356 	    return (0);
357     }
358 }
359