sh.misc.c revision 131962
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
35RCSID("$Id: sh.misc.c,v 3.26 2003/03/12 19:14:51 christos Exp $")
36
37static	int	renum	__P((int, int));
38static  Char  **blkend	__P((Char **));
39static  Char  **blkcat	__P((Char **, Char **));
40
41/*
42 * C Shell
43 */
44
45int
46any(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
58void
59setzero(cp, i)
60    char   *cp;
61    int     i;
62{
63    if (i != 0)
64	do
65	    *cp++ = 0;
66	while (--i);
67}
68
69char   *
70strsave(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
87static Char  **
88blkend(up)
89    register Char **up;
90{
91
92    while (*up)
93	up++;
94    return (up);
95}
96
97
98void
99blkpr(av)
100    register Char **av;
101{
102
103    for (; *av; av++) {
104	xprintf("%S", *av);
105	if (av[1])
106	    xprintf(" ");
107    }
108}
109
110void
111blkexpand(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
123int
124blklen(av)
125    register Char **av;
126{
127    register int i = 0;
128
129    while (*av++)
130	i++;
131    return (i);
132}
133
134Char  **
135blkcpy(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
146static Char  **
147blkcat(up, vp)
148    Char  **up, **vp;
149{
150
151    (void) blkcpy(blkend(up), vp);
152    return (up);
153}
154
155void
156blkfree(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
168Char  **
169saveblk(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)
182char   *
183strstr(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
201char   *
202strspl(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
226Char  **
227blkspl(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
238Char
239lastchr(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 */
256void
257closem()
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 */
298void
299closech()
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
318void
319donefds()
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 */
344int
345dmove(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
365int
366dcopy(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
383static int
384renum(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 */
406void
407lshift(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
418int
419number(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
435Char  **
436copyblk(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
446char   *
447strend(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
459Char   *
460strip(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
472Char   *
473quote(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
485Char   *
486quote_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
500void
501udvar(name)
502    Char   *name;
503{
504
505    setname(short2str(name));
506    stderror(ERR_NAME | ERR_UNDVAR);
507}
508
509int
510prefix(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