xref: /openbsd/bin/csh/misc.c (revision d95322bb)
1 /*	$OpenBSD: misc.c,v 1.25 2018/10/24 06:01:03 martijn 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	fdcmp(int);
42 static int	renum(int, int);
43 
44 int
any(char * s,int c)45 any(char *s, int c)
46 {
47     if (!s)
48 	return (0);		/* Check for nil pointer */
49     while (*s)
50 	if (*s++ == c)
51 	    return (1);
52     return (0);
53 }
54 
55 Char  **
blkend(Char ** up)56 blkend(Char **up)
57 {
58 
59     while (*up)
60 	up++;
61     return (up);
62 }
63 
64 
65 void
blkpr(FILE * fp,Char ** av)66 blkpr(FILE *fp, Char **av)
67 {
68 
69     for (; *av; av++) {
70 	(void) fprintf(fp, "%s", vis_str(*av));
71 	if (av[1])
72 	    (void) fprintf(fp, " ");
73     }
74 }
75 
76 int
blklen(Char ** av)77 blklen(Char **av)
78 {
79     int i = 0;
80 
81     while (*av++)
82 	i++;
83     return (i);
84 }
85 
86 Char  **
blkcpy(Char ** oav,Char ** bv)87 blkcpy(Char **oav, Char **bv)
88 {
89     Char **av = oav;
90 
91     while ((*av++ = *bv++) != NULL)
92 	continue;
93     return (oav);
94 }
95 
96 Char  **
blkcat(Char ** up,Char ** vp)97 blkcat(Char **up, Char **vp)
98 {
99 
100     (void) blkcpy(blkend(up), vp);
101     return (up);
102 }
103 
104 void
blkfree(Char ** av0)105 blkfree(Char **av0)
106 {
107     Char **av = av0;
108 
109     if (!av0)
110 	return;
111     for (; *av; av++)
112 	free(* av);
113     free(av0);
114 }
115 
116 Char  **
saveblk(Char ** v)117 saveblk(Char **v)
118 {
119     Char **newv = xcalloc(blklen(v) + 1, sizeof(*newv));
120     Char  **onewv = newv;
121 
122     while (*v)
123 	*newv++ = Strsave(*v++);
124     return (onewv);
125 }
126 
127 Char  **
blkspl(Char ** up,Char ** vp)128 blkspl(Char **up, Char **vp)
129 {
130     Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(*wp));
131 
132     (void) blkcpy(wp, up);
133     return (blkcat(wp, vp));
134 }
135 
136 Char
lastchr(Char * cp)137 lastchr(Char *cp)
138 {
139 
140     if (!cp)
141 	return (0);
142     if (!*cp)
143 	return (0);
144     while (cp[1])
145 	cp++;
146     return (*cp);
147 }
148 
149 /*
150  * Returns 0 if fd is in use, 1 if fd is greater than the largest used file
151  * descriptor and -1 otherwise.
152  */
153 static int
fdcmp(int fd)154 fdcmp(int fd)
155 {
156     int fds[] = { SHIN, SHOUT, SHERR, OLDSTD, FSHTTY };
157     int i, max;
158 
159     max = -1;
160     for (i = 0; i < sizeof(fds)/sizeof(fds[0]); i++) {
161 	if (fd == fds[i])
162 	    return (0);
163 	if (fds[i] > max)
164 	    max = fds[i];
165     }
166     if (fd > max)
167 	return (1);
168 
169     return (-1);
170 }
171 
172 /*
173  * This routine is called after an error to close up
174  * any units which may have been left open accidentally.
175  */
176 void
closem(void)177 closem(void)
178 {
179     int f;
180     int max = sysconf(_SC_OPEN_MAX);
181 
182     for (f = 0; f < max; f++)
183 	switch (fdcmp(f)) {
184 	case 0:
185 	    continue;
186 	case 1:
187 	    closefrom(f);
188 	    return;
189 	default:
190 	    close(f);
191 	}
192 }
193 
194 void
donefds(void)195 donefds(void)
196 {
197     (void) close(0);
198     (void) close(1);
199     (void) close(2);
200 
201     didfds = 0;
202 }
203 
204 /*
205  * Move descriptor i to j.
206  * If j is -1 then we just want to get i to a safe place,
207  * i.e. to a unit > 2.  This also happens in dcopy.
208  */
209 int
dmove(int i,int j)210 dmove(int i, int j)
211 {
212 
213     if (i == j || i < 0)
214 	return (i);
215     if (j >= 0) {
216 	(void) dup2(i, j);
217 	if (j != i)
218 	    (void) close(i);
219 	return (j);
220     }
221     j = dcopy(i, j);
222     if (j != i)
223 	(void) close(i);
224     return (j);
225 }
226 
227 int
dcopy(int i,int j)228 dcopy(int i, int j)
229 {
230 
231     if (i == j || i < 0 || (j < 0 && i > 2))
232 	return (i);
233     if (j >= 0) {
234 	(void) dup2(i, j);
235 	return (j);
236     }
237     (void) close(j);
238     return (renum(i, j));
239 }
240 
241 static int
renum(int i,int j)242 renum(int i, int j)
243 {
244     int k = dup(i);
245 
246     if (k < 0)
247 	return (-1);
248     if (j == -1 && k > 2)
249 	return (k);
250     if (k != j) {
251 	j = renum(k, j);
252 	(void) close(k);
253 	return (j);
254     }
255     return (k);
256 }
257 
258 /*
259  * Left shift a command argument list, discarding
260  * the first c arguments.  Used in "shift" commands
261  * as well as by commands like "repeat".
262  */
263 void
lshift(Char ** v,int c)264 lshift(Char **v, int c)
265 {
266     Char **u;
267 
268     for (u = v; *u && --c >= 0; u++)
269 	free(*u);
270     (void) blkcpy(v, u);
271 }
272 
273 int
number(Char * cp)274 number(Char *cp)
275 {
276     if (!cp)
277 	return(0);
278     if (*cp == '-') {
279 	cp++;
280 	if (!Isdigit(*cp))
281 	    return (0);
282 	cp++;
283     }
284     while (*cp && Isdigit(*cp))
285 	cp++;
286     return (*cp == 0);
287 }
288 
289 Char  **
copyblk(Char ** v)290 copyblk(Char **v)
291 {
292     Char  **nv = xcalloc(blklen(v) + 1, sizeof(*nv));
293 
294     return (blkcpy(nv, v));
295 }
296 
297 Char   *
strip(Char * cp)298 strip(Char *cp)
299 {
300     Char *dp = cp;
301 
302     if (!cp)
303 	return (cp);
304     while ((*dp++ &= TRIM) != '\0')
305 	continue;
306     return (cp);
307 }
308 
309 Char   *
quote(Char * cp)310 quote(Char *cp)
311 {
312     Char *dp = cp;
313 
314     if (!cp)
315 	return (cp);
316     while (*dp != '\0')
317 	*dp++ |= QUOTE;
318     return (cp);
319 }
320 
321 void
udvar(Char * name)322 udvar(Char *name)
323 {
324 
325     setname(vis_str(name));
326     stderror(ERR_NAME | ERR_UNDVAR);
327 }
328 
329 int
prefix(Char * sub,Char * str)330 prefix(Char *sub, Char *str)
331 {
332 
333     for (;;) {
334 	if (*sub == 0)
335 	    return (1);
336 	if (*str == 0)
337 	    return (0);
338 	if (*sub++ != *str++)
339 	    return (0);
340     }
341 }
342