xref: /netbsd-src/bin/csh/misc.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /* $NetBSD: misc.c,v 1.19 2006/03/18 06:24:26 christos Exp $ */
2 
3 /*-
4  * Copyright (c) 1980, 1991, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)misc.c	8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: misc.c,v 1.19 2006/03/18 06:24:26 christos Exp $");
38 #endif
39 #endif /* not lint */
40 
41 #include <sys/param.h>
42 
43 #include <stdarg.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 
49 #include "csh.h"
50 #include "extern.h"
51 
52 static int renum(int, int);
53 
54 int
55 any(const char *s, int c)
56 {
57     if (!s)
58 	return (0);		/* Check for nil pointer */
59     while (*s)
60 	if (*s++ == c)
61 	    return (1);
62     return (0);
63 }
64 
65 char *
66 strsave(const char *s)
67 {
68     const char *n;
69     char *p, *r;
70 
71     if (s == NULL)
72 	s = "";
73     for (n = s; *n++;)
74 	continue;
75     r = p = (char *)xmalloc((size_t)((n - s) * sizeof(char)));
76     while ((*p++ = *s++) != '\0')
77 	continue;
78     return (r);
79 }
80 
81 Char **
82 blkend(Char **up)
83 {
84     while (*up)
85 	up++;
86     return (up);
87 }
88 
89 
90 void
91 blkpr(FILE *fp, Char **av)
92 {
93     for (; *av; av++) {
94 	(void)fprintf(fp, "%s", vis_str(*av));
95 	if (av[1])
96 	    (void)fprintf(fp, " ");
97     }
98 }
99 
100 int
101 blklen(Char **av)
102 {
103     int i;
104 
105     i = 0;
106     while (*av++)
107 	i++;
108     return (i);
109 }
110 
111 Char **
112 blkcpy(Char **oav, Char **bv)
113 {
114     Char **av;
115 
116     av = oav;
117     while ((*av++ = *bv++) != NULL)
118 	continue;
119     return (oav);
120 }
121 
122 Char **
123 blkcat(Char **up, Char **vp)
124 {
125     (void)blkcpy(blkend(up), vp);
126     return (up);
127 }
128 
129 void
130 blkfree(Char **av0)
131 {
132     Char **av;
133 
134     av = av0;
135     if (!av0)
136 	return;
137     for (; *av; av++)
138 	xfree((ptr_t) * av);
139     xfree((ptr_t) av0);
140 }
141 
142 Char **
143 saveblk(Char **v)
144 {
145     Char **newv, **onewv;
146 
147     if (v == NULL)
148 	return NULL;
149 
150     newv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **));
151     onewv = newv;
152     while (*v)
153 	*newv++ = Strsave(*v++);
154     return (onewv);
155 }
156 
157 #ifdef NOTUSED
158 char *
159 strstr(char *s, char *t)
160 {
161     do {
162 	char *ss;
163 	char *tt;
164 
165 	ss = s;
166 	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, *p, *q;
183 
184     if (!cp)
185 	cp = "";
186     if (!dp)
187 	dp = "";
188     for (p = cp; *p++;)
189 	continue;
190     for (q = dp; *q++;)
191 	continue;
192     ep = (char *) xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(char)));
193     for (p = ep, q = cp; *p++ = *q++;)
194 	continue;
195     for (p--, q = dp; *p++ = *q++;)
196 	continue;
197     return (ep);
198 }
199 
200 #endif
201 
202 Char **
203 blkspl(Char **up, Char **vp)
204 {
205     Char **wp;
206 
207     wp = (Char **)xcalloc((size_t)(blklen(up) + blklen(vp) + 1),
208         sizeof(Char **));
209     (void)blkcpy(wp, up);
210     return (blkcat(wp, vp));
211 }
212 
213 Char
214 lastchr(Char *cp)
215 {
216     if (!cp)
217 	return (0);
218     if (!*cp)
219 	return (0);
220     while (cp[1])
221 	cp++;
222     return (*cp);
223 }
224 
225 /*
226  * This routine is called after an error to close up
227  * any units which may have been left open accidentally.
228  */
229 void
230 closem(void)
231 {
232     int f;
233     int nofile;
234 
235 #ifdef F_CLOSEM
236     nofile = FOLDSTD + 1;
237     if (fcntl(nofile, F_CLOSEM, 0) == -1)
238 #endif
239 	nofile = NOFILE;
240 
241     for (f = 0; f < nofile; f++)
242 	if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
243 	    f != FSHTTY)
244 	    (void) close(f);
245 }
246 
247 void
248 donefds(void)
249 {
250     (void)close(0);
251     (void)close(1);
252     (void)close(2);
253 
254     didfds = 0;
255 }
256 
257 /*
258  * Move descriptor i to j.
259  * If j is -1 then we just want to get i to a safe place,
260  * i.e. to a unit > 2.  This also happens in dcopy.
261  */
262 int
263 dmove(int i, int j)
264 {
265     if (i == j || i < 0)
266 	return (i);
267     if (j >= 0) {
268 	(void)dup2(i, j);
269 	if (j != i)
270 	    (void)close(i);
271 	return (j);
272     }
273     j = dcopy(i, j);
274     if (j != i)
275 	(void)close(i);
276     return (j);
277 }
278 
279 int
280 dcopy(int i, int j)
281 {
282     if (i == j || i < 0 || (j < 0 && i > 2))
283 	return (i);
284     if (j >= 0) {
285 	(void)dup2(i, j);
286 	return (j);
287     }
288     return (renum(i, j));
289 }
290 
291 static int
292 renum(int i, int j)
293 {
294     int k;
295 
296     k = dup(i);
297     if (k < 0)
298 	return (-1);
299     if (j == -1 && k > 2)
300 	return (k);
301     if (k != j) {
302 	j = renum(k, j);
303 	(void)close(k);
304 	return (j);
305     }
306     return (k);
307 }
308 
309 /*
310  * Left shift a command argument list, discarding
311  * the first c arguments.  Used in "shift" commands
312  * as well as by commands like "repeat".
313  */
314 void
315 lshift(Char **v, int c)
316 {
317     Char **u;
318 
319     for (u = v; *u && --c >= 0; u++)
320 	xfree((ptr_t) *u);
321     (void)blkcpy(v, u);
322 }
323 
324 int
325 number(Char *cp)
326 {
327     if (!cp)
328 	return(0);
329     if (*cp == '-') {
330 	cp++;
331 	if (!Isdigit(*cp))
332 	    return (0);
333 	cp++;
334     }
335     while (*cp && Isdigit(*cp))
336 	cp++;
337     return (*cp == 0);
338 }
339 
340 Char **
341 copyblk(Char **v)
342 {
343     Char **nv;
344 
345     nv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **));
346 
347     return (blkcpy(nv, v));
348 }
349 
350 #ifndef SHORT_STRINGS
351 char *
352 strend(char *cp)
353 {
354     if (!cp)
355 	return (cp);
356     while (*cp)
357 	cp++;
358     return (cp);
359 }
360 
361 #endif /* SHORT_STRINGS */
362 
363 Char *
364 strip(Char *cp)
365 {
366     Char *dp;
367 
368     dp = cp;
369     if (!cp)
370 	return (cp);
371     while ((*dp++ &= TRIM) != '\0')
372 	continue;
373     return (cp);
374 }
375 
376 Char *
377 quote(Char *cp)
378 {
379     Char *dp;
380 
381     dp = cp;
382     if (!cp)
383 	return (cp);
384     while (*dp != '\0')
385 	*dp++ |= QUOTE;
386     return (cp);
387 }
388 
389 void
390 udvar(Char *name)
391 {
392     setname(vis_str(name));
393     stderror(ERR_NAME | ERR_UNDVAR);
394     /* NOTREACHED */
395 }
396 
397 int
398 prefix(Char *sub, Char *str)
399 {
400     for (;;) {
401 	if (*sub == 0)
402 	    return (1);
403 	if (*str == 0)
404 	    return (0);
405 	if (*sub++ != *str++)
406 	    return (0);
407     }
408 }
409