xref: /freebsd/contrib/tcsh/sh.misc.c (revision c4f02a891fe62fe1277c89859922804ea2c27bcd)
1 /* $Header: /src/pub/tcsh/sh.misc.c,v 3.24 2002/03/08 17:36:46 christos Exp $ */
2 /*
3  * sh.misc.c: Miscelaneous functions
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 #include "sh.h"
34 
35 RCSID("$Id: sh.misc.c,v 3.24 2002/03/08 17:36:46 christos Exp $")
36 
37 static	int	renum	__P((int, int));
38 static  Char  **blkend	__P((Char **));
39 static  Char  **blkcat	__P((Char **, Char **));
40 
41 /*
42  * C Shell
43  */
44 
45 int
46 any(s, c)
47     register char *s;
48     register int c;
49 {
50     if (!s)
51 	return (0);		/* Check for nil pointer */
52     while (*s)
53 	if (*s++ == c)
54 	    return (1);
55     return (0);
56 }
57 
58 void
59 setzero(cp, i)
60     char   *cp;
61     int     i;
62 {
63     if (i != 0)
64 	do
65 	    *cp++ = 0;
66 	while (--i);
67 }
68 
69 char   *
70 strsave(s)
71     register const char *s;
72 {
73     char   *n;
74     register char *p;
75 
76     if (s == NULL)
77 	s = (const char *) "";
78     for (p = (char *) s; *p++ != '\0';)
79 	continue;
80     n = p = (char *) xmalloc((size_t)
81 			     ((((const char *) p) - s) * sizeof(char)));
82     while ((*p++ = *s++) != '\0')
83 	continue;
84     return (n);
85 }
86 
87 static Char  **
88 blkend(up)
89     register Char **up;
90 {
91 
92     while (*up)
93 	up++;
94     return (up);
95 }
96 
97 
98 void
99 blkpr(av)
100     register Char **av;
101 {
102 
103     for (; *av; av++) {
104 	xprintf("%S", *av);
105 	if (av[1])
106 	    xprintf(" ");
107     }
108 }
109 
110 void
111 blkexpand(av, str)
112     register Char **av;
113     Char *str;
114 {
115     *str = '\0';
116     for (; *av; av++) {
117 	(void) Strcat(str, *av);
118 	if (av[1])
119 	    (void) Strcat(str, STRspace);
120     }
121 }
122 
123 int
124 blklen(av)
125     register Char **av;
126 {
127     register int i = 0;
128 
129     while (*av++)
130 	i++;
131     return (i);
132 }
133 
134 Char  **
135 blkcpy(oav, bv)
136     Char  **oav;
137     register Char **bv;
138 {
139     register Char **av = oav;
140 
141     while ((*av++ = *bv++) != NULL)
142 	continue;
143     return (oav);
144 }
145 
146 static Char  **
147 blkcat(up, vp)
148     Char  **up, **vp;
149 {
150 
151     (void) blkcpy(blkend(up), vp);
152     return (up);
153 }
154 
155 void
156 blkfree(av0)
157     Char  **av0;
158 {
159     register Char **av = av0;
160 
161     if (!av0)
162 	return;
163     for (; *av; av++)
164 	xfree((ptr_t) * av);
165     xfree((ptr_t) av0);
166 }
167 
168 Char  **
169 saveblk(v)
170     register Char **v;
171 {
172     register Char **newv =
173     (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
174     Char  **onewv = newv;
175 
176     while (*v)
177 	*newv++ = Strsave(*v++);
178     return (onewv);
179 }
180 
181 #if !defined(SHORT_STRINGS) && !defined(POSIX)
182 char   *
183 strstr(s, t)
184     register const char *s, *t;
185 {
186     do {
187 	register const char *ss = s;
188 	register const char *tt = t;
189 
190 	do
191 	    if (*tt == '\0')
192 		return ((char *) s);
193 	while (*ss++ == *tt++);
194     } while (*s++ != '\0');
195     return (NULL);
196 }
197 
198 #endif /* !SHORT_STRINGS && !POSIX */
199 
200 #ifndef SHORT_STRINGS
201 char   *
202 strspl(cp, dp)
203     char   *cp, *dp;
204 {
205     char   *ep;
206     register char *p, *q;
207 
208     if (!cp)
209 	cp = "";
210     if (!dp)
211 	dp = "";
212     for (p = cp; *p++ != '\0';)
213 	continue;
214     for (q = dp; *q++ != '\0';)
215 	continue;
216     ep = (char *) xmalloc((size_t) (((p - cp) + (q - dp) - 1) * sizeof(char)));
217     for (p = ep, q = cp; (*p++ = *q++) != '\0';)
218 	continue;
219     for (p--, q = dp; (*p++ = *q++) != '\0';)
220 	continue;
221     return (ep);
222 }
223 
224 #endif /* !SHORT_STRINGS */
225 
226 Char  **
227 blkspl(up, vp)
228     register Char **up, **vp;
229 {
230     register Char **wp =
231     (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
232 		      sizeof(Char **));
233 
234     (void) blkcpy(wp, up);
235     return (blkcat(wp, vp));
236 }
237 
238 Char
239 lastchr(cp)
240     register Char *cp;
241 {
242 
243     if (!cp)
244 	return (0);
245     if (!*cp)
246 	return (0);
247     while (cp[1])
248 	cp++;
249     return (*cp);
250 }
251 
252 /*
253  * This routine is called after an error to close up
254  * any units which may have been left open accidentally.
255  */
256 void
257 closem()
258 {
259     register int f;
260 
261 #ifdef YPBUGS
262     /* suggested by Justin Bur; thanks to Karl Kleinpaste */
263     fix_yp_bugs();
264 #endif /* YPBUGS */
265     for (f = 0; f < NOFILE; f++)
266 	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
267 	    f != FSHTTY
268 #ifdef MALLOC_TRACE
269 	    && f != 25
270 #endif /* MALLOC_TRACE */
271 	    )
272 	  {
273 	    (void) close(f);
274 #ifdef NISPLUS
275 	    if(f < 3)
276 		(void) open(_PATH_DEVNULL, O_RDONLY);
277 #endif /* NISPLUS */
278 	  }
279 }
280 
281 #ifndef CLOSE_ON_EXEC
282 /*
283  * Close files before executing a file.
284  * We could be MUCH more intelligent, since (on a version 7 system)
285  * we need only close files here during a source, the other
286  * shell fd's being in units 16-19 which are closed automatically!
287  */
288 void
289 closech()
290 {
291     register int f;
292 
293     if (didcch)
294 	return;
295     didcch = 1;
296     SHIN = 0;
297     SHOUT = 1;
298     SHDIAG = 2;
299     OLDSTD = 0;
300     isoutatty = isatty(SHOUT);
301     isdiagatty = isatty(SHDIAG);
302     for (f = 3; f < NOFILE; f++)
303 	(void) close(f);
304 }
305 
306 #endif /* CLOSE_ON_EXEC */
307 
308 void
309 donefds()
310 {
311 
312     (void) close(0);
313     (void) close(1);
314     (void) close(2);
315     didfds = 0;
316 #ifdef NISPLUS
317     {
318 	int fd = open(_PATH_DEVNULL, O_RDONLY);
319 	(void) dup2(fd, 1);
320 	(void) dup2(fd, 2);
321 	if (fd != 0) {
322 	    (void) dup2(fd, 0);
323 	    (void) close(fd);
324 	}
325     }
326 #endif /*NISPLUS*/
327 }
328 
329 /*
330  * Move descriptor i to j.
331  * If j is -1 then we just want to get i to a safe place,
332  * i.e. to a unit > 2.  This also happens in dcopy.
333  */
334 int
335 dmove(i, j)
336     register int i, j;
337 {
338 
339     if (i == j || i < 0)
340 	return (i);
341 #ifdef HAVEDUP2
342     if (j >= 0) {
343 	(void) dup2(i, j);
344 	if (j != i)
345 	    (void) close(i);
346 	return (j);
347     }
348 #endif
349     j = dcopy(i, j);
350     if (j != i)
351 	(void) close(i);
352     return (j);
353 }
354 
355 int
356 dcopy(i, j)
357     register int i, j;
358 {
359 
360     if (i == j || i < 0 || (j < 0 && i > 2))
361 	return (i);
362     if (j >= 0) {
363 #ifdef HAVEDUP2
364 	(void) dup2(i, j);
365 	return (j);
366 #else
367 	(void) close(j);
368 #endif
369     }
370     return (renum(i, j));
371 }
372 
373 static int
374 renum(i, j)
375     register int i, j;
376 {
377     register int k = dup(i);
378 
379     if (k < 0)
380 	return (-1);
381     if (j == -1 && k > 2)
382 	return (k);
383     if (k != j) {
384 	j = renum(k, j);
385 	(void) close(k);
386 	return (j);
387     }
388     return (k);
389 }
390 
391 /*
392  * Left shift a command argument list, discarding
393  * the first c arguments.  Used in "shift" commands
394  * as well as by commands like "repeat".
395  */
396 void
397 lshift(v, c)
398     register Char **v;
399     register int c;
400 {
401     register Char **u;
402 
403     for (u = v; *u && --c >= 0; u++)
404 	xfree((ptr_t) *u);
405     (void) blkcpy(v, u);
406 }
407 
408 int
409 number(cp)
410     Char   *cp;
411 {
412     if (!cp)
413 	return (0);
414     if (*cp == '-') {
415 	cp++;
416 	if (!Isdigit(*cp))
417 	    return (0);
418 	cp++;
419     }
420     while (*cp && Isdigit(*cp))
421 	cp++;
422     return (*cp == 0);
423 }
424 
425 Char  **
426 copyblk(v)
427     register Char **v;
428 {
429     register Char **nv =
430     (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
431 
432     return (blkcpy(nv, v));
433 }
434 
435 #ifndef SHORT_STRINGS
436 char   *
437 strend(cp)
438     register char *cp;
439 {
440     if (!cp)
441 	return (cp);
442     while (*cp)
443 	cp++;
444     return (cp);
445 }
446 
447 #endif /* SHORT_STRINGS */
448 
449 Char   *
450 strip(cp)
451     Char   *cp;
452 {
453     register Char *dp = cp;
454 
455     if (!cp)
456 	return (cp);
457     while ((*dp++ &= TRIM) != '\0')
458 	continue;
459     return (cp);
460 }
461 
462 Char   *
463 quote(cp)
464     Char   *cp;
465 {
466     register Char *dp = cp;
467 
468     if (!cp)
469 	return (cp);
470     while (*dp != '\0')
471 	*dp++ |= QUOTE;
472     return (cp);
473 }
474 
475 Char   *
476 quote_meta(d, s)
477     Char   *d;
478     const Char   *s;
479 {
480     Char *r = d;
481     while (*s != '\0') {
482 	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
483 		*d++ = '\\';
484 	*d++ = *s++;
485     }
486     *d = '\0';
487     return r;
488 }
489 
490 void
491 udvar(name)
492     Char   *name;
493 {
494 
495     setname(short2str(name));
496     stderror(ERR_NAME | ERR_UNDVAR);
497 }
498 
499 int
500 prefix(sub, str)
501     register Char *sub, *str;
502 {
503 
504     for (;;) {
505 	if (*sub == 0)
506 	    return (1);
507 	if (*str == 0)
508 	    return (0);
509 	if ((*sub++ & TRIM) != (*str++ & TRIM))
510 	    return (0);
511     }
512 }
513