Merge commit '00f1a4f432b3d8aad1aa270e91c44c57f03ef407'
[unleashed.git] / usr / src / cmd / csh / sh.misc.c
blob8f5e087965484c410aa3aff384c7d035509187c5
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley Software License Agreement
12 * specifies the terms and conditions for redistribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
17 #include "sh.h"
18 #include "sh.tconst.h"
19 #include <fcntl.h>
20 #include <unistd.h>
23 * C Shell
25 tchar **blkcat(tchar **, tchar **);
26 tchar **blkend(tchar **);
28 int
29 any(int c, tchar *s)
32 while (s && *s)
33 if (*s++ == c)
34 return (1);
35 return (0);
38 int
39 onlyread(tchar *cp)
41 extern char end[];
43 return ((char *)cp < end);
46 tchar *
47 savestr(tchar *s)
49 tchar *n;
50 tchar *p;
52 if (s == 0)
53 s = S_ /* "" */;
54 #ifndef m32
55 for (p = s; *p++; )
57 n = p = (tchar *)xalloc((unsigned)(p - s)*sizeof (tchar));
58 while (*p++ = *s++)
60 return (n);
61 #else
62 p = (tchar *) xalloc((strlen_(s) + 1)*sizeof (tchar));
63 strcpy_(p, s);
64 return (p);
65 #endif
68 static void *
69 nomem(size_t i)
71 #ifdef debug
72 static tchar *av[2] = {0, 0};
73 #endif
75 child++;
76 #ifndef debug
77 error("Out of memory");
78 #else
79 showall(av);
80 printf("i=%d: Out of memory\n", i);
81 chdir("/usr/bill/cshcore");
82 abort();
83 #endif
84 return (0); /* fool lint */
87 tchar **
88 blkend(tchar **up)
91 while (*up)
92 up++;
93 return (up);
96 void
97 blkpr(tchar **av)
100 for (; *av; av++) {
101 printf("%t", *av);
102 if (av[1])
103 printf(" ");
108 blklen(tchar **av)
110 int i = 0;
112 while (*av++)
113 i++;
114 return (i);
117 tchar **
118 blkcpy(tchar **oav, tchar **bv)
120 tchar **av = oav;
122 while (*av++ = *bv++)
123 continue;
124 return (oav);
127 tchar **
128 blkcat(tchar **up, tchar **vp)
131 (void) blkcpy(blkend(up), vp);
132 return (up);
135 void
136 blkfree(tchar **av0)
138 tchar **av = av0;
140 for (; *av; av++)
141 xfree(*av);
142 xfree(av0);
145 tchar **
146 saveblk(tchar **v)
148 tchar **newv =
149 (tchar **)xcalloc((unsigned)(blklen(v) + 1),
150 sizeof (tchar **));
151 tchar **onewv = newv;
153 while (*v)
154 *newv++ = savestr(*v++);
155 return (onewv);
158 tchar *
159 strspl(tchar *cp, tchar *dp)
161 tchar *ep;
162 tchar *p, *q;
164 #ifndef m32
165 for (p = cp; *p++; )
167 for (q = dp; *q++; )
169 ep = (tchar *) xalloc((unsigned)(((p - cp) +
170 (q - dp) - 1))*sizeof (tchar));
171 for (p = ep, q = cp; *p++ = *q++; )
173 for (p--, q = dp; *p++ = *q++; )
175 #else
176 int len1 = strlen_(cp);
177 int len2 = strlen_(dp);
179 ep = (tchar *)xalloc((unsigned)(len1 + len2 + 1)*sizeof (tchar));
180 strcpy_(ep, cp);
181 strcat_(ep, dp);
182 #endif
183 return (ep);
186 tchar **
187 blkspl(tchar **up, tchar **vp)
189 tchar **wp =
190 (tchar **)xcalloc((unsigned)(blklen(up) + blklen(vp) + 1),
191 sizeof (tchar **));
193 (void) blkcpy(wp, up);
194 return (blkcat(wp, vp));
198 lastchr(tchar *cp)
201 if (!*cp)
202 return (0);
203 while (cp[1])
204 cp++;
205 return (*cp);
208 void
209 donefds(void)
211 (void) close(0);
212 (void) close(1);
213 (void) close(2);
216 * To avoid NIS+ functions to get hold of 0/1/2,
217 * use descriptor 0, and dup it to 1 and 2.
219 open("/dev/null", O_RDONLY);
220 dup(0); dup(0);
221 didfds = 0;
225 * Move descriptor i to j.
226 * If j is -1 then we just want to get i to a safe place,
227 * i.e. to a unit > 2. This also happens in dcopy.
230 dmove(int i, int j)
232 int fd;
234 if (i == j || i < 0)
235 return (i);
236 if (j >= 0) {
237 fd = dup2(i, j);
238 if (fd != -1)
239 setfd(fd);
240 } else
241 j = dcopy(i, j);
242 if (j != i) {
243 (void) close(i);
244 unsetfd(i);
246 return (j);
250 dcopy(int i, int j)
253 int fd;
255 if (i == j || i < 0 || j < 0 && i > 2)
256 return (i);
257 if (j >= 0) {
258 fd = dup2(i, j);
259 if (fd != -1)
260 setfd(fd);
261 return (j);
263 (void) close(j);
264 unsetfd(j);
265 return (renum(i, j));
269 renum(int i, int j)
271 int k = dup(i);
273 if (k < 0)
274 return (-1);
275 if (j == -1 && k > 2) {
276 setfd(k);
277 return (k);
279 if (k != j) {
280 j = renum(k, j);
281 (void) close(k); /* no need ofr unsetfd() */
282 return (j);
284 return (k);
287 #ifndef copy
288 void
289 copy(tchar *to, tchar *from, int size)
292 if (size)
294 *to++ = *from++;
295 while (--size != 0);
297 #endif
300 * Left shift a command argument list, discarding
301 * the first c arguments. Used in "shift" commands
302 * as well as by commands like "repeat".
304 void
305 lshift(tchar **v, int c)
307 tchar **u = v;
309 while (*u && --c >= 0)
310 xfree((char *)*u++);
311 (void) blkcpy(v, u);
315 number(tchar *cp)
318 if (*cp == '-') {
319 cp++;
320 if (!digit(*cp++))
321 return (0);
323 while (*cp && digit(*cp))
324 cp++;
325 return (*cp == 0);
328 tchar **
329 copyblk(tchar **v)
331 tchar **nv =
332 (tchar **)xcalloc((unsigned)(blklen(v) + 1),
333 sizeof (tchar **));
335 return (blkcpy(nv, v));
338 tchar *
339 strend(tchar *cp)
342 while (*cp)
343 cp++;
344 return (cp);
347 tchar *
348 strip(tchar *cp)
350 tchar *dp = cp;
352 while (*dp++ &= TRIM)
353 continue;
354 return (cp);
357 void
358 udvar(tchar *name)
361 setname(name);
362 bferr("Undefined variable");
366 prefix(tchar *sub, tchar *str)
369 for (;;) {
370 if (*sub == 0)
371 return (1);
372 if (*str == 0)
373 return (0);
374 if (*sub++ != *str++)
375 return (0);
380 * blk*_ routines
383 char **
384 blkend_(char **up)
387 while (*up)
388 up++;
389 return (up);
393 blklen_(char **av)
395 int i = 0;
397 while (*av++)
398 i++;
399 return (i);
402 char **
403 blkcpy_(char **oav, char **bv)
405 char **av = oav;
407 while (*av++ = *bv++)
408 continue;
409 return (oav);
412 char **
413 blkcat_(char **up, char **vp)
416 (void) blkcpy_(blkend_(up), vp);
417 return (up);
420 char **
421 blkspl_(char **up, char **vp)
423 char **wp =
424 (char **)xcalloc((unsigned)(blklen_(up) + blklen_(vp) + 1),
425 sizeof (char **));
427 (void) blkcpy_(wp, up);
428 return (blkcat_(wp, vp));
432 * If stack address was passed to free(), we have no good way to see if
433 * they are really in the stack. Therefore, we record the bottom of heap,
434 * and filter out the address not within heap's top(end) and bottom
435 * (xalloc_bottom).
437 extern char end[];
438 static char *xalloc_bottom;
440 void *
441 xalloc(size_t size)
443 char *rptr, *bp;
445 if ((rptr = malloc(size)) == NULL)
446 return (nomem(size));
447 bp = rptr + size;
448 if (bp > xalloc_bottom)
449 xalloc_bottom = bp;
450 return (rptr);
453 void *
454 xrealloc(void *ptr, size_t size)
456 char *rptr = ptr, *bp;
458 if (ptr == NULL)
459 return (xalloc(size));
460 if (rptr < end) {
461 /* data area, but not in heap area. don't touch it */
462 oob:
463 if (size == 0)
464 return (NULL);
465 rptr = xalloc(size);
466 /* copy max size */
467 (void) memcpy(rptr, ptr, size);
468 return (rptr);
470 if (rptr < xalloc_bottom) {
471 /* address in the heap */
472 inb:
473 if (size == 0) {
474 free(ptr);
475 return (NULL);
477 if ((rptr = realloc(ptr, size)) == NULL)
478 return (nomem(size));
479 bp = rptr + size;
480 if (bp > xalloc_bottom)
481 xalloc_bottom = bp;
482 return (rptr);
485 * can be a memory block returned indirectly from
486 * library functions. update bottom, and check it again.
488 xalloc_bottom = sbrk(0);
489 if (rptr <= xalloc_bottom)
490 goto inb;
491 else
492 goto oob;
493 /*NOTREACHED*/
496 void
497 xfree(void *ptr)
499 char *rptr = ptr;
501 if (rptr < end) {
502 return;
504 if (rptr < xalloc_bottom) {
505 free(ptr);
506 return;
508 xalloc_bottom = sbrk(0);
509 if (rptr <= xalloc_bottom) {
510 free(ptr);
514 void *
515 xcalloc(size_t i, size_t j)
517 char *cp;
519 i *= j;
520 cp = xalloc(i);
521 (void) memset(cp, '\0', i);
522 return (cp);