xref: /openbsd-src/bin/csh/misc.c (revision acdb32028ee917f8269a9fd16c4817e3a7408b91)
1 /*	$OpenBSD: misc.c,v 1.18 2015/12/26 13:48:38 mestre 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 	free(* av);
128     free(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 Char  **
143 blkspl(Char **up, Char **vp)
144 {
145     Char **wp = xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
146 		      sizeof(Char **));
147 
148     (void) blkcpy(wp, up);
149     return (blkcat(wp, vp));
150 }
151 
152 Char
153 lastchr(Char *cp)
154 {
155 
156     if (!cp)
157 	return (0);
158     if (!*cp)
159 	return (0);
160     while (cp[1])
161 	cp++;
162     return (*cp);
163 }
164 
165 /*
166  * This routine is called after an error to close up
167  * any units which may have been left open accidentally.
168  */
169 void
170 closem(void)
171 {
172     int f;
173 
174     for (f = 0; f < sysconf(_SC_OPEN_MAX); f++)
175 	if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
176 	    f != FSHTTY)
177 	    (void) close(f);
178 }
179 
180 void
181 donefds(void)
182 {
183     (void) close(0);
184     (void) close(1);
185     (void) close(2);
186 
187     didfds = 0;
188 }
189 
190 /*
191  * Move descriptor i to j.
192  * If j is -1 then we just want to get i to a safe place,
193  * i.e. to a unit > 2.  This also happens in dcopy.
194  */
195 int
196 dmove(int i, int j)
197 {
198 
199     if (i == j || i < 0)
200 	return (i);
201     if (j >= 0) {
202 	(void) dup2(i, j);
203 	if (j != i)
204 	    (void) close(i);
205 	return (j);
206     }
207     j = dcopy(i, j);
208     if (j != i)
209 	(void) close(i);
210     return (j);
211 }
212 
213 int
214 dcopy(int i, int j)
215 {
216 
217     if (i == j || i < 0 || (j < 0 && i > 2))
218 	return (i);
219     if (j >= 0) {
220 	(void) dup2(i, j);
221 	return (j);
222     }
223     (void) close(j);
224     return (renum(i, j));
225 }
226 
227 static int
228 renum(int i, int j)
229 {
230     int k = dup(i);
231 
232     if (k < 0)
233 	return (-1);
234     if (j == -1 && k > 2)
235 	return (k);
236     if (k != j) {
237 	j = renum(k, j);
238 	(void) close(k);
239 	return (j);
240     }
241     return (k);
242 }
243 
244 /*
245  * Left shift a command argument list, discarding
246  * the first c arguments.  Used in "shift" commands
247  * as well as by commands like "repeat".
248  */
249 void
250 lshift(Char **v, int c)
251 {
252     Char **u;
253 
254     for (u = v; *u && --c >= 0; u++)
255 	free(*u);
256     (void) blkcpy(v, u);
257 }
258 
259 int
260 number(Char *cp)
261 {
262     if (!cp)
263 	return(0);
264     if (*cp == '-') {
265 	cp++;
266 	if (!Isdigit(*cp))
267 	    return (0);
268 	cp++;
269     }
270     while (*cp && Isdigit(*cp))
271 	cp++;
272     return (*cp == 0);
273 }
274 
275 Char  **
276 copyblk(Char **v)
277 {
278     Char  **nv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
279 
280     return (blkcpy(nv, v));
281 }
282 
283 Char   *
284 strip(Char *cp)
285 {
286     Char *dp = cp;
287 
288     if (!cp)
289 	return (cp);
290     while ((*dp++ &= TRIM) != '\0')
291 	continue;
292     return (cp);
293 }
294 
295 Char   *
296 quote(Char *cp)
297 {
298     Char *dp = cp;
299 
300     if (!cp)
301 	return (cp);
302     while (*dp != '\0')
303 	*dp++ |= QUOTE;
304     return (cp);
305 }
306 
307 void
308 udvar(Char *name)
309 {
310 
311     setname(vis_str(name));
312     stderror(ERR_NAME | ERR_UNDVAR);
313 }
314 
315 int
316 prefix(Char *sub, Char *str)
317 {
318 
319     for (;;) {
320 	if (*sub == 0)
321 	    return (1);
322 	if (*str == 0)
323 	    return (0);
324 	if (*sub++ != *str++)
325 	    return (0);
326     }
327 }
328