Merge from vendor branch FILE:
[dragonfly.git] / contrib / tcsh / sh.misc.c
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 }