xref: /openbsd-src/bin/csh/misc.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: misc.c,v 1.9 2003/06/11 21:09:50 deraadt 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 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)misc.c	8.1 (Berkeley) 5/31/93";
36 #else
37 static char rcsid[] = "$OpenBSD: misc.c,v 1.9 2003/06/11 21:09:50 deraadt Exp $";
38 #endif
39 #endif /* not lint */
40 
41 #include <sys/param.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <stdarg.h>
45 
46 #include "csh.h"
47 #include "extern.h"
48 
49 static int	renum(int, int);
50 
51 int
52 any(char *s, int c)
53 {
54     if (!s)
55 	return (0);		/* Check for nil pointer */
56     while (*s)
57 	if (*s++ == c)
58 	    return (1);
59     return (0);
60 }
61 
62 void
63 setzero(char *cp, int i)
64 {
65     if (i != 0)
66 	do
67 	    *cp++ = 0;
68 	while (--i);
69 }
70 
71 char   *
72 strsave(char *s)
73 {
74     char   *n;
75     char *p;
76 
77     if (s == NULL)
78 	s = "";
79     for (p = s; *p++;)
80 	continue;
81     n = p = (char *) xmalloc((size_t) ((p - s) * sizeof(char)));
82     while ((*p++ = *s++) != '\0')
83 	continue;
84     return (n);
85 }
86 
87 Char  **
88 blkend(Char **up)
89 {
90 
91     while (*up)
92 	up++;
93     return (up);
94 }
95 
96 
97 void
98 blkpr(FILE *fp, Char **av)
99 {
100 
101     for (; *av; av++) {
102 	(void) fprintf(fp, "%s", vis_str(*av));
103 	if (av[1])
104 	    (void) fprintf(fp, " ");
105     }
106 }
107 
108 int
109 blklen(Char **av)
110 {
111     int i = 0;
112 
113     while (*av++)
114 	i++;
115     return (i);
116 }
117 
118 Char  **
119 blkcpy(Char **oav, Char **bv)
120 {
121     Char **av = oav;
122 
123     while ((*av++ = *bv++) != NULL)
124 	continue;
125     return (oav);
126 }
127 
128 Char  **
129 blkcat(Char **up, Char **vp)
130 {
131 
132     (void) blkcpy(blkend(up), vp);
133     return (up);
134 }
135 
136 void
137 blkfree(Char **av0)
138 {
139     Char **av = av0;
140 
141     if (!av0)
142 	return;
143     for (; *av; av++)
144 	xfree((ptr_t) * av);
145     xfree((ptr_t) av0);
146 }
147 
148 Char  **
149 saveblk(Char **v)
150 {
151     Char **newv =
152     (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
153     Char  **onewv = newv;
154 
155     while (*v)
156 	*newv++ = Strsave(*v++);
157     return (onewv);
158 }
159 
160 #ifdef NOTUSED
161 char   *
162 strstr(char *s, char *t)
163 {
164     do {
165 	char *ss = s;
166 	char *tt = t;
167 
168 	do
169 	    if (*tt == '\0')
170 		return (s);
171 	while (*ss++ == *tt++);
172     } while (*s++ != '\0');
173     return (NULL);
174 }
175 
176 #endif /* NOTUSED */
177 
178 #ifndef SHORT_STRINGS
179 char   *
180 strspl(char *cp, char *dp)
181 {
182     char   *ep;
183     char *p, *q;
184 
185     if (!cp)
186 	cp = "";
187     if (!dp)
188 	dp = "";
189     for (p = cp; *p++;)
190 	continue;
191     for (q = dp; *q++;)
192 	continue;
193     ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char)));
194     for (p = ep, q = cp; *p++ = *q++;)
195 	continue;
196     for (p--, q = dp; *p++ = *q++;)
197 	continue;
198     return (ep);
199 }
200 
201 #endif
202 
203 Char  **
204 blkspl(Char **up, Char **vp)
205 {
206     Char **wp =
207     (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
208 		      sizeof(Char **));
209 
210     (void) blkcpy(wp, up);
211     return (blkcat(wp, vp));
212 }
213 
214 Char
215 lastchr(Char *cp)
216 {
217 
218     if (!cp)
219 	return (0);
220     if (!*cp)
221 	return (0);
222     while (cp[1])
223 	cp++;
224     return (*cp);
225 }
226 
227 /*
228  * This routine is called after an error to close up
229  * any units which may have been left open accidentally.
230  */
231 void
232 closem(void)
233 {
234     int f;
235 
236     for (f = 0; f < sysconf(_SC_OPEN_MAX); f++)
237 	if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
238 	    f != FSHTTY)
239 	    (void) close(f);
240 }
241 
242 void
243 donefds(void)
244 {
245     (void) close(0);
246     (void) close(1);
247     (void) close(2);
248 
249     didfds = 0;
250 }
251 
252 /*
253  * Move descriptor i to j.
254  * If j is -1 then we just want to get i to a safe place,
255  * i.e. to a unit > 2.  This also happens in dcopy.
256  */
257 int
258 dmove(int i, int j)
259 {
260 
261     if (i == j || i < 0)
262 	return (i);
263     if (j >= 0) {
264 	(void) dup2(i, j);
265 	if (j != i)
266 	    (void) close(i);
267 	return (j);
268     }
269     j = dcopy(i, j);
270     if (j != i)
271 	(void) close(i);
272     return (j);
273 }
274 
275 int
276 dcopy(int i, int j)
277 {
278 
279     if (i == j || i < 0 || (j < 0 && i > 2))
280 	return (i);
281     if (j >= 0) {
282 	(void) dup2(i, j);
283 	return (j);
284     }
285     (void) close(j);
286     return (renum(i, j));
287 }
288 
289 static int
290 renum(int i, int j)
291 {
292     int k = dup(i);
293 
294     if (k < 0)
295 	return (-1);
296     if (j == -1 && k > 2)
297 	return (k);
298     if (k != j) {
299 	j = renum(k, j);
300 	(void) close(k);
301 	return (j);
302     }
303     return (k);
304 }
305 
306 /*
307  * Left shift a command argument list, discarding
308  * the first c arguments.  Used in "shift" commands
309  * as well as by commands like "repeat".
310  */
311 void
312 lshift(Char **v, int c)
313 {
314     Char **u;
315 
316     for (u = v; *u && --c >= 0; u++)
317 	xfree((ptr_t) *u);
318     (void) blkcpy(v, u);
319 }
320 
321 int
322 number(Char *cp)
323 {
324     if (!cp)
325 	return(0);
326     if (*cp == '-') {
327 	cp++;
328 	if (!Isdigit(*cp))
329 	    return (0);
330 	cp++;
331     }
332     while (*cp && Isdigit(*cp))
333 	cp++;
334     return (*cp == 0);
335 }
336 
337 Char  **
338 copyblk(Char **v)
339 {
340     Char  **nv = (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
341 
342     return (blkcpy(nv, v));
343 }
344 
345 #ifndef SHORT_STRINGS
346 char   *
347 strend(char *cp)
348 {
349     if (!cp)
350 	return (cp);
351     while (*cp)
352 	cp++;
353     return (cp);
354 }
355 
356 #endif /* SHORT_STRINGS */
357 
358 Char   *
359 strip(Char *cp)
360 {
361     Char *dp = cp;
362 
363     if (!cp)
364 	return (cp);
365     while ((*dp++ &= TRIM) != '\0')
366 	continue;
367     return (cp);
368 }
369 
370 Char   *
371 quote(Char *cp)
372 {
373     Char *dp = cp;
374 
375     if (!cp)
376 	return (cp);
377     while (*dp != '\0')
378 	*dp++ |= QUOTE;
379     return (cp);
380 }
381 
382 void
383 udvar(Char *name)
384 {
385 
386     setname(vis_str(name));
387     stderror(ERR_NAME | ERR_UNDVAR);
388 }
389 
390 int
391 prefix(Char *sub, Char *str)
392 {
393 
394     for (;;) {
395 	if (*sub == 0)
396 	    return (1);
397 	if (*str == 0)
398 	    return (0);
399 	if (*sub++ != *str++)
400 	    return (0);
401     }
402 }
403