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