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