sh.misc.c revision 145479
1/* $Header: /src/pub/tcsh/sh.misc.c,v 3.34 2005/01/18 20:24:50 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.34 2005/01/18 20:24:50 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    const char *s;
48    Char c;
49{
50    if (!s)
51	return (0);		/* Check for nil pointer */
52    while (*s)
53	if ((Char)*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    const char *s;
72{
73    char   *n, *r;
74    const char *p;
75
76    if (s == NULL)
77	s = "";
78    for (p = s; *p++ != '\0';)
79	continue;
80    r = n = (char *) xmalloc((size_t)((((const char *) p) - s) * sizeof(char)));
81    while ((*n++ = *s++) != '\0')
82	continue;
83    return (r);
84}
85
86static Char  **
87blkend(up)
88    Char **up;
89{
90
91    while (*up)
92	up++;
93    return (up);
94}
95
96
97void
98blkpr(av)
99    Char **av;
100{
101
102    for (; *av; av++) {
103	xprintf("%S", *av);
104	if (av[1])
105	    xprintf(" ");
106    }
107}
108
109void
110blkexpand(av, str)
111    Char **av;
112    Char *str;
113{
114    *str = '\0';
115    for (; *av; av++) {
116	(void) Strcat(str, *av);
117	if (av[1])
118	    (void) Strcat(str, STRspace);
119    }
120}
121
122int
123blklen(av)
124    Char **av;
125{
126    int i = 0;
127
128    while (*av++)
129	i++;
130    return (i);
131}
132
133Char  **
134blkcpy(oav, bv)
135    Char  **oav;
136    Char **bv;
137{
138    Char **av = oav;
139
140    while ((*av++ = *bv++) != NULL)
141	continue;
142    return (oav);
143}
144
145static Char  **
146blkcat(up, vp)
147    Char  **up, **vp;
148{
149
150    (void) blkcpy(blkend(up), vp);
151    return (up);
152}
153
154void
155blkfree(av0)
156    Char  **av0;
157{
158    Char **av = av0;
159
160    if (!av0)
161	return;
162    for (; *av; av++)
163	xfree((ptr_t) * av);
164    xfree((ptr_t) av0);
165}
166
167Char  **
168saveblk(v)
169    Char **v;
170{
171    Char **newv =
172    (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
173    Char  **onewv = newv;
174
175    while (*v)
176	*newv++ = Strsave(*v++);
177    return (onewv);
178}
179
180#ifndef HAVE_STRSTR
181char   *
182strstr(s, t)
183    const char *s, *t;
184{
185    do {
186	const char *ss = s;
187	const char *tt = t;
188
189	do
190	    if (*tt == '\0')
191		return ((char *) s);
192	while (*ss++ == *tt++);
193    } while (*s++ != '\0');
194    return (NULL);
195}
196#endif /* !HAVE_STRSTR */
197
198#ifndef SHORT_STRINGS
199char   *
200strspl(cp, dp)
201    const char *cp, *dp;
202{
203    char   *ep;
204    size_t cl, dl;
205
206    if (!cp)
207	cp = "";
208    if (!dp)
209	dp = "";
210    cl = strlen(cp);
211    dl = strlen(dp);
212    ep = (char *) xmalloc((cl + dl + 1) * sizeof(char));
213    memcpy(ep, cp, cl);
214    memcpy(ep + cl, dp, dl + 1);
215    return (ep);
216}
217
218#endif /* !SHORT_STRINGS */
219
220Char  **
221blkspl(up, vp)
222    Char **up, **vp;
223{
224    Char **wp =
225    (Char **) xcalloc((size_t) (blklen(up) + blklen(vp) + 1),
226		      sizeof(Char **));
227
228    (void) blkcpy(wp, up);
229    return (blkcat(wp, vp));
230}
231
232Char
233lastchr(cp)
234    Char *cp;
235{
236
237    if (!cp)
238	return (0);
239    if (!*cp)
240	return (0);
241    while (cp[1])
242	cp++;
243    return (*cp);
244}
245
246/*
247 * This routine is called after an error to close up
248 * any units which may have been left open accidentally.
249 */
250void
251closem()
252{
253    int f;
254
255#ifdef NLS_BUGS
256#ifdef NLS_CATALOGS
257    nlsclose();
258#endif /* NLS_CATALOGS */
259#endif /* NLS_BUGS */
260#ifdef YPBUGS
261    /* suggested by Justin Bur; thanks to Karl Kleinpaste */
262    fix_yp_bugs();
263#endif /* YPBUGS */
264    for (f = 0; f < NOFILE; f++)
265	if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
266	    f != FSHTTY
267#ifdef MALLOC_TRACE
268	    && f != 25
269#endif /* MALLOC_TRACE */
270	    )
271	  {
272	    (void) close(f);
273#ifdef NISPLUS
274	    if(f < 3)
275		(void) open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
276#endif /* NISPLUS */
277	  }
278#ifdef NLS_BUGS
279#ifdef NLS_CATALOGS
280    nlsinit();
281#endif /* NLS_CATALOGS */
282#endif /* NLS_BUGS */
283}
284
285#ifndef CLOSE_ON_EXEC
286/*
287 * Close files before executing a file.
288 * We could be MUCH more intelligent, since (on a version 7 system)
289 * we need only close files here during a source, the other
290 * shell fd's being in units 16-19 which are closed automatically!
291 */
292void
293closech()
294{
295    int f;
296
297    if (didcch)
298	return;
299    didcch = 1;
300    SHIN = 0;
301    SHOUT = 1;
302    SHDIAG = 2;
303    OLDSTD = 0;
304    isoutatty = isatty(SHOUT);
305    isdiagatty = isatty(SHDIAG);
306    for (f = 3; f < NOFILE; f++)
307	(void) close(f);
308}
309
310#endif /* CLOSE_ON_EXEC */
311
312void
313donefds()
314{
315
316    (void) close(0);
317    (void) close(1);
318    (void) close(2);
319    didfds = 0;
320#ifdef NISPLUS
321    {
322	int fd = open(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
323	(void)dcopy(fd, 1);
324	(void)dcopy(fd, 2);
325	(void)dmove(fd, 0);
326    }
327#endif /*NISPLUS*/
328}
329
330/*
331 * Move descriptor i to j.
332 * If j is -1 then we just want to get i to a safe place,
333 * i.e. to a unit > FSAFE.  This also happens in dcopy.
334 */
335int
336dmove(i, j)
337    int i, j;
338{
339
340    if (i == j || i < 0)
341	return (i);
342#ifdef HAVE_DUP2
343    if (j >= 0) {
344	(void) dup2(i, j);
345	if (j != i)
346	    (void) close(i);
347	return (j);
348    }
349#endif
350    j = dcopy(i, j);
351    if (j != i)
352	(void) close(i);
353    return (j);
354}
355
356int
357dcopy(i, j)
358    int i, j;
359{
360
361    if (i == j || i < 0 || (j < 0 && i > FSAFE))
362	return (i);
363    if (j >= 0) {
364#ifdef HAVE_DUP2
365	(void) dup2(i, j);
366	return (j);
367#else
368	(void) close(j);
369#endif
370    }
371    return (renum(i, j));
372}
373
374static int
375renum(i, j)
376    int i, j;
377{
378    int k = dup(i);
379
380    if (k < 0)
381	return (-1);
382    if (j == -1 && k > FSAFE)
383	return (k);
384    if (k != j) {
385	j = renum(k, j);
386	(void) close(k);
387	return (j);
388    }
389    return (k);
390}
391
392/*
393 * Left shift a command argument list, discarding
394 * the first c arguments.  Used in "shift" commands
395 * as well as by commands like "repeat".
396 */
397void
398lshift(v, c)
399    Char **v;
400    int c;
401{
402    Char **u;
403
404    for (u = v; *u && --c >= 0; u++)
405	xfree((ptr_t) *u);
406    (void) blkcpy(v, u);
407}
408
409int
410number(cp)
411    Char   *cp;
412{
413    if (!cp)
414	return (0);
415    if (*cp == '-') {
416	cp++;
417	if (!Isdigit(*cp))
418	    return (0);
419	cp++;
420    }
421    while (*cp && Isdigit(*cp))
422	cp++;
423    return (*cp == 0);
424}
425
426Char  **
427copyblk(v)
428    Char **v;
429{
430    Char **nv =
431    (Char **) xcalloc((size_t) (blklen(v) + 1), sizeof(Char **));
432
433    return (blkcpy(nv, v));
434}
435
436#ifndef SHORT_STRINGS
437char   *
438strend(cp)
439    char *cp;
440{
441    if (!cp)
442	return (cp);
443    while (*cp)
444	cp++;
445    return (cp);
446}
447
448#endif /* SHORT_STRINGS */
449
450Char   *
451strip(cp)
452    Char   *cp;
453{
454    Char *dp = cp;
455
456    if (!cp)
457	return (cp);
458    while ((*dp++ &= TRIM) != '\0')
459	continue;
460    return (cp);
461}
462
463Char   *
464quote(cp)
465    Char   *cp;
466{
467    Char *dp = cp;
468
469    if (!cp)
470	return (cp);
471    while (*dp != '\0')
472	*dp++ |= QUOTE;
473    return (cp);
474}
475
476Char   *
477quote_meta(d, s)
478    Char   *d;
479    const Char   *s;
480{
481    Char *r = d;
482    while (*s != '\0') {
483	if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
484		*d++ = '\\';
485	*d++ = *s++;
486    }
487    *d = '\0';
488    return r;
489}
490
491void
492udvar(name)
493    Char   *name;
494{
495
496    setname(short2str(name));
497    stderror(ERR_NAME | ERR_UNDVAR);
498}
499
500int
501prefix(sub, str)
502    const Char *sub, *str;
503{
504
505    for (;;) {
506	if (*sub == 0)
507	    return (1);
508	if (*str == 0)
509	    return (0);
510	if ((*sub++ & TRIM) != (*str++ & TRIM))
511	    return (0);
512    }
513}
514