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