xref: /netbsd-src/bin/csh/misc.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /* $NetBSD: misc.c,v 1.16 2004/01/06 00:20:16 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.16 2004/01/06 00:20:16 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(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(char *s)
67 {
68     char *n, *p;
69 
70     if (s == NULL)
71 	s = "";
72     for (p = s; *p++;)
73 	continue;
74     n = p = (char *)xmalloc((size_t)((p - s) * sizeof(char)));
75     while ((*p++ = *s++) != '\0')
76 	continue;
77     return (n);
78 }
79 
80 Char **
81 blkend(Char **up)
82 {
83     while (*up)
84 	up++;
85     return (up);
86 }
87 
88 
89 void
90 blkpr(FILE *fp, Char **av)
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;
103 
104     i = 0;
105     while (*av++)
106 	i++;
107     return (i);
108 }
109 
110 Char **
111 blkcpy(Char **oav, Char **bv)
112 {
113     Char **av;
114 
115     av = oav;
116     while ((*av++ = *bv++) != NULL)
117 	continue;
118     return (oav);
119 }
120 
121 Char **
122 blkcat(Char **up, Char **vp)
123 {
124     (void)blkcpy(blkend(up), vp);
125     return (up);
126 }
127 
128 void
129 blkfree(Char **av0)
130 {
131     Char **av;
132 
133     av = av0;
134     if (!av0)
135 	return;
136     for (; *av; av++)
137 	xfree((ptr_t) * av);
138     xfree((ptr_t) av0);
139 }
140 
141 Char **
142 saveblk(Char **v)
143 {
144     Char **newv, **onewv;
145 
146     newv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **));
147     onewv = newv;
148     while (*v)
149 	*newv++ = Strsave(*v++);
150     return (onewv);
151 }
152 
153 #ifdef NOTUSED
154 char *
155 strstr(char *s, char *t)
156 {
157     do {
158 	char *ss;
159 	char *tt;
160 
161 	ss = s;
162 	tt = t;
163 
164 	do
165 	    if (*tt == '\0')
166 		return (s);
167 	while (*ss++ == *tt++);
168     } while (*s++ != '\0');
169     return (NULL);
170 }
171 
172 #endif /* NOTUSED */
173 
174 #ifndef SHORT_STRINGS
175 char *
176 strspl(char *cp, char *dp)
177 {
178     char *ep, *p, *q;
179 
180     if (!cp)
181 	cp = "";
182     if (!dp)
183 	dp = "";
184     for (p = cp; *p++;)
185 	continue;
186     for (q = dp; *q++;)
187 	continue;
188     ep = (char *) xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(char)));
189     for (p = ep, q = cp; *p++ = *q++;)
190 	continue;
191     for (p--, q = dp; *p++ = *q++;)
192 	continue;
193     return (ep);
194 }
195 
196 #endif
197 
198 Char **
199 blkspl(Char **up, Char **vp)
200 {
201     Char **wp;
202 
203     wp = (Char **)xcalloc((size_t)(blklen(up) + blklen(vp) + 1),
204         sizeof(Char **));
205     (void)blkcpy(wp, up);
206     return (blkcat(wp, vp));
207 }
208 
209 Char
210 lastchr(Char *cp)
211 {
212     if (!cp)
213 	return (0);
214     if (!*cp)
215 	return (0);
216     while (cp[1])
217 	cp++;
218     return (*cp);
219 }
220 
221 /*
222  * This routine is called after an error to close up
223  * any units which may have been left open accidentally.
224  */
225 void
226 closem(void)
227 {
228     int f;
229     int nofile;
230 
231 #ifdef F_CLOSEM
232     nofile = FOLDSTD + 1;
233     if (fcntl(nofile, F_CLOSEM, 0) == -1)
234 #endif
235 	nofile = NOFILE;
236 
237     for (f = 0; f < nofile; f++)
238 	if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
239 	    f != FSHTTY)
240 	    (void) close(f);
241 }
242 
243 void
244 donefds(void)
245 {
246     (void)close(0);
247     (void)close(1);
248     (void)close(2);
249 
250     didfds = 0;
251 }
252 
253 /*
254  * Move descriptor i to j.
255  * If j is -1 then we just want to get i to a safe place,
256  * i.e. to a unit > 2.  This also happens in dcopy.
257  */
258 int
259 dmove(int i, int j)
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     if (i == j || i < 0 || (j < 0 && i > 2))
279 	return (i);
280     if (j >= 0) {
281 	(void)dup2(i, j);
282 	return (j);
283     }
284     (void)close(j);
285     return (renum(i, j));
286 }
287 
288 static int
289 renum(int i, int j)
290 {
291     int k;
292 
293     k = dup(i);
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;
341 
342     nv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **));
343 
344     return (blkcpy(nv, v));
345 }
346 
347 #ifndef SHORT_STRINGS
348 char *
349 strend(char *cp)
350 {
351     if (!cp)
352 	return (cp);
353     while (*cp)
354 	cp++;
355     return (cp);
356 }
357 
358 #endif /* SHORT_STRINGS */
359 
360 Char *
361 strip(Char *cp)
362 {
363     Char *dp;
364 
365     dp = cp;
366     if (!cp)
367 	return (cp);
368     while ((*dp++ &= TRIM) != '\0')
369 	continue;
370     return (cp);
371 }
372 
373 Char *
374 quote(Char *cp)
375 {
376     Char *dp;
377 
378     dp = cp;
379     if (!cp)
380 	return (cp);
381     while (*dp != '\0')
382 	*dp++ |= QUOTE;
383     return (cp);
384 }
385 
386 void
387 udvar(Char *name)
388 {
389     setname(vis_str(name));
390     stderror(ERR_NAME | ERR_UNDVAR);
391     /* NOTREACHED */
392 }
393 
394 int
395 prefix(Char *sub, Char *str)
396 {
397     for (;;) {
398 	if (*sub == 0)
399 	    return (1);
400 	if (*str == 0)
401 	    return (0);
402 	if (*sub++ != *str++)
403 	    return (0);
404     }
405 }
406