xref: /openbsd/bin/csh/misc.c (revision 9b7c3dbb)
1 /*	$OpenBSD: misc.c,v 1.19 2016/08/14 19:45:24 guenther 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     int max = sysconf(_SC_OPEN_MAX);
174 
175     for (f = 0; f < max; f++)
176 	if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD &&
177 	    f != FSHTTY)
178 	    (void) close(f);
179 }
180 
181 void
182 donefds(void)
183 {
184     (void) close(0);
185     (void) close(1);
186     (void) close(2);
187 
188     didfds = 0;
189 }
190 
191 /*
192  * Move descriptor i to j.
193  * If j is -1 then we just want to get i to a safe place,
194  * i.e. to a unit > 2.  This also happens in dcopy.
195  */
196 int
197 dmove(int i, int j)
198 {
199 
200     if (i == j || i < 0)
201 	return (i);
202     if (j >= 0) {
203 	(void) dup2(i, j);
204 	if (j != i)
205 	    (void) close(i);
206 	return (j);
207     }
208     j = dcopy(i, j);
209     if (j != i)
210 	(void) close(i);
211     return (j);
212 }
213 
214 int
215 dcopy(int i, int j)
216 {
217 
218     if (i == j || i < 0 || (j < 0 && i > 2))
219 	return (i);
220     if (j >= 0) {
221 	(void) dup2(i, j);
222 	return (j);
223     }
224     (void) close(j);
225     return (renum(i, j));
226 }
227 
228 static int
229 renum(int i, int j)
230 {
231     int k = dup(i);
232 
233     if (k < 0)
234 	return (-1);
235     if (j == -1 && k > 2)
236 	return (k);
237     if (k != j) {
238 	j = renum(k, j);
239 	(void) close(k);
240 	return (j);
241     }
242     return (k);
243 }
244 
245 /*
246  * Left shift a command argument list, discarding
247  * the first c arguments.  Used in "shift" commands
248  * as well as by commands like "repeat".
249  */
250 void
251 lshift(Char **v, int c)
252 {
253     Char **u;
254 
255     for (u = v; *u && --c >= 0; u++)
256 	free(*u);
257     (void) blkcpy(v, u);
258 }
259 
260 int
261 number(Char *cp)
262 {
263     if (!cp)
264 	return(0);
265     if (*cp == '-') {
266 	cp++;
267 	if (!Isdigit(*cp))
268 	    return (0);
269 	cp++;
270     }
271     while (*cp && Isdigit(*cp))
272 	cp++;
273     return (*cp == 0);
274 }
275 
276 Char  **
277 copyblk(Char **v)
278 {
279     Char  **nv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
280 
281     return (blkcpy(nv, v));
282 }
283 
284 Char   *
285 strip(Char *cp)
286 {
287     Char *dp = cp;
288 
289     if (!cp)
290 	return (cp);
291     while ((*dp++ &= TRIM) != '\0')
292 	continue;
293     return (cp);
294 }
295 
296 Char   *
297 quote(Char *cp)
298 {
299     Char *dp = cp;
300 
301     if (!cp)
302 	return (cp);
303     while (*dp != '\0')
304 	*dp++ |= QUOTE;
305     return (cp);
306 }
307 
308 void
309 udvar(Char *name)
310 {
311 
312     setname(vis_str(name));
313     stderror(ERR_NAME | ERR_UNDVAR);
314 }
315 
316 int
317 prefix(Char *sub, Char *str)
318 {
319 
320     for (;;) {
321 	if (*sub == 0)
322 	    return (1);
323 	if (*str == 0)
324 	    return (0);
325 	if (*sub++ != *str++)
326 	    return (0);
327     }
328 }
329