xref: /freebsd/contrib/tcsh/sh.misc.c (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
1 /* $Header: /src/pub/tcsh/sh.misc.c,v 3.26 2003/03/12 19:14:51 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.26 2003/03/12 19:14:51 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 NLS_BUGS
262 #ifdef NLS_CATALOGS
263     (void)catclose(catd);
264 #endif /* NLS_CATALOGS */
265 #endif /* NLS_BUGS */
266 #ifdef YPBUGS
267     /* suggested by Justin Bur; thanks to Karl Kleinpaste */
268     fix_yp_bugs();
269 #endif /* YPBUGS */
270     for (f = 0; f < NOFILE; f++)
271 	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
272 	    f != FSHTTY
273 #ifdef MALLOC_TRACE
274 	    && f != 25
275 #endif /* MALLOC_TRACE */
276 	    )
277 	  {
278 	    (void) close(f);
279 #ifdef NISPLUS
280 	    if(f < 3)
281 		(void) open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
282 #endif /* NISPLUS */
283 	  }
284 #ifdef NLS_BUGS
285 #ifdef NLS_CATALOGS
286     nlsinit();
287 #endif /* NLS_CATALOGS */
288 #endif /* NLS_BUGS */
289 }
290 
291 #ifndef CLOSE_ON_EXEC
292 /*
293  * Close files before executing a file.
294  * We could be MUCH more intelligent, since (on a version 7 system)
295  * we need only close files here during a source, the other
296  * shell fd's being in units 16-19 which are closed automatically!
297  */
298 void
299 closech()
300 {
301     register int f;
302 
303     if (didcch)
304 	return;
305     didcch = 1;
306     SHIN = 0;
307     SHOUT = 1;
308     SHDIAG = 2;
309     OLDSTD = 0;
310     isoutatty = isatty(SHOUT);
311     isdiagatty = isatty(SHDIAG);
312     for (f = 3; f < NOFILE; f++)
313 	(void) close(f);
314 }
315 
316 #endif /* CLOSE_ON_EXEC */
317 
318 void
319 donefds()
320 {
321 
322     (void) close(0);
323     (void) close(1);
324     (void) close(2);
325     didfds = 0;
326 #ifdef NISPLUS
327     {
328 	int fd = open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
329 	(void) dup2(fd, 1);
330 	(void) dup2(fd, 2);
331 	if (fd != 0) {
332 	    (void) dup2(fd, 0);
333 	    (void) close(fd);
334 	}
335     }
336 #endif /*NISPLUS*/
337 }
338 
339 /*
340  * Move descriptor i to j.
341  * If j is -1 then we just want to get i to a safe place,
342  * i.e. to a unit > 2.  This also happens in dcopy.
343  */
344 int
345 dmove(i, j)
346     register int i, j;
347 {
348 
349     if (i == j || i < 0)
350 	return (i);
351 #ifdef HAVEDUP2
352     if (j >= 0) {
353 	(void) dup2(i, j);
354 	if (j != i)
355 	    (void) close(i);
356 	return (j);
357     }
358 #endif
359     j = dcopy(i, j);
360     if (j != i)
361 	(void) close(i);
362     return (j);
363 }
364 
365 int
366 dcopy(i, j)
367     register int i, j;
368 {
369 
370     if (i == j || i < 0 || (j < 0 && i > 2))
371 	return (i);
372     if (j >= 0) {
373 #ifdef HAVEDUP2
374 	(void) dup2(i, j);
375 	return (j);
376 #else
377 	(void) close(j);
378 #endif
379     }
380     return (renum(i, j));
381 }
382 
383 static int
384 renum(i, j)
385     register int i, j;
386 {
387     register int k = dup(i);
388 
389     if (k < 0)
390 	return (-1);
391     if (j == -1 && k > 2)
392 	return (k);
393     if (k != j) {
394 	j = renum(k, j);
395 	(void) close(k);
396 	return (j);
397     }
398     return (k);
399 }
400 
401 /*
402  * Left shift a command argument list, discarding
403  * the first c arguments.  Used in "shift" commands
404  * as well as by commands like "repeat".
405  */
406 void
407 lshift(v, c)
408     register Char **v;
409     register int c;
410 {
411     register Char **u;
412 
413     for (u = v; *u && --c >= 0; u++)
414 	xfree((ptr_t) *u);
415     (void) blkcpy(v, u);
416 }
417 
418 int
419 number(cp)
420     Char   *cp;
421 {
422     if (!cp)
423 	return (0);
424     if (*cp == '-') {
425 	cp++;
426 	if (!Isdigit(*cp))
427 	    return (0);
428 	cp++;
429     }
430     while (*cp && Isdigit(*cp))
431 	cp++;
432     return (*cp == 0);
433 }
434 
435 Char  **
436 copyblk(v)
437     register Char **v;
438 {
439     register Char **nv =
440     (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
441 
442     return (blkcpy(nv, v));
443 }
444 
445 #ifndef SHORT_STRINGS
446 char   *
447 strend(cp)
448     register char *cp;
449 {
450     if (!cp)
451 	return (cp);
452     while (*cp)
453 	cp++;
454     return (cp);
455 }
456 
457 #endif /* SHORT_STRINGS */
458 
459 Char   *
460 strip(cp)
461     Char   *cp;
462 {
463     register Char *dp = cp;
464 
465     if (!cp)
466 	return (cp);
467     while ((*dp++ &= TRIM) != '\0')
468 	continue;
469     return (cp);
470 }
471 
472 Char   *
473 quote(cp)
474     Char   *cp;
475 {
476     register Char *dp = cp;
477 
478     if (!cp)
479 	return (cp);
480     while (*dp != '\0')
481 	*dp++ |= QUOTE;
482     return (cp);
483 }
484 
485 Char   *
486 quote_meta(d, s)
487     Char   *d;
488     const Char   *s;
489 {
490     Char *r = d;
491     while (*s != '\0') {
492 	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
493 		*d++ = '\\';
494 	*d++ = *s++;
495     }
496     *d = '\0';
497     return r;
498 }
499 
500 void
501 udvar(name)
502     Char   *name;
503 {
504 
505     setname(short2str(name));
506     stderror(ERR_NAME | ERR_UNDVAR);
507 }
508 
509 int
510 prefix(sub, str)
511     register Char *sub, *str;
512 {
513 
514     for (;;) {
515 	if (*sub == 0)
516 	    return (1);
517 	if (*str == 0)
518 	    return (0);
519 	if ((*sub++ & TRIM) != (*str++ & TRIM))
520 	    return (0);
521     }
522 }
523