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