1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
8
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.
13 */
14
15 #pragma ident "%Z%%M% %I% %E% SMI"
16
17 #include "sh.h"
18 #include "sh.tconst.h"
19 #include <fcntl.h>
20 #include <unistd.h>
21
22 /*
23 * C Shell
24 */
25 tchar **blkcat(tchar **, tchar **);
26 tchar **blkend(tchar **);
27
28 int
any(int c,tchar * s)29 any(int c, tchar *s)
30 {
31
32 while (s && *s)
33 if (*s++ == c)
34 return (1);
35 return (0);
36 }
37
38 int
onlyread(tchar * cp)39 onlyread(tchar *cp)
40 {
41 extern char end[];
42
43 return ((char *)cp < end);
44 }
45
46 tchar *
savestr(tchar * s)47 savestr(tchar *s)
48 {
49 tchar *n;
50 tchar *p;
51
52 if (s == 0)
53 s = S_ /* "" */;
54 #ifndef m32
55 for (p = s; *p++; )
56 ;
57 n = p = (tchar *)xalloc((unsigned)(p - s)*sizeof (tchar));
58 while (*p++ = *s++)
59 ;
60 return (n);
61 #else
62 p = (tchar *) xalloc((strlen_(s) + 1)*sizeof (tchar));
63 strcpy_(p, s);
64 return (p);
65 #endif
66 }
67
68 static void *
nomem(size_t i)69 nomem(size_t i)
70 {
71 #ifdef debug
72 static tchar *av[2] = {0, 0};
73 #endif
74
75 child++;
76 #ifndef debug
77 error("Out of memory");
78 #ifdef lint
79 i = i;
80 #endif
81 #else
82 showall(av);
83 printf("i=%d: Out of memory\n", i);
84 chdir("/usr/bill/cshcore");
85 abort();
86 #endif
87 return (0); /* fool lint */
88 }
89
90 tchar **
blkend(tchar ** up)91 blkend(tchar **up)
92 {
93
94 while (*up)
95 up++;
96 return (up);
97 }
98
99 void
blkpr(tchar ** av)100 blkpr(tchar **av)
101 {
102
103 for (; *av; av++) {
104 printf("%t", *av);
105 if (av[1])
106 printf(" ");
107 }
108 }
109
110 int
blklen(tchar ** av)111 blklen(tchar **av)
112 {
113 int i = 0;
114
115 while (*av++)
116 i++;
117 return (i);
118 }
119
120 tchar **
blkcpy(tchar ** oav,tchar ** bv)121 blkcpy(tchar **oav, tchar **bv)
122 {
123 tchar **av = oav;
124
125 while (*av++ = *bv++)
126 continue;
127 return (oav);
128 }
129
130 tchar **
blkcat(tchar ** up,tchar ** vp)131 blkcat(tchar **up, tchar **vp)
132 {
133
134 (void) blkcpy(blkend(up), vp);
135 return (up);
136 }
137
138 void
blkfree(tchar ** av0)139 blkfree(tchar **av0)
140 {
141 tchar **av = av0;
142
143 for (; *av; av++)
144 xfree(*av);
145 xfree(av0);
146 }
147
148 tchar **
saveblk(tchar ** v)149 saveblk(tchar **v)
150 {
151 tchar **newv =
152 (tchar **)xcalloc((unsigned)(blklen(v) + 1),
153 sizeof (tchar **));
154 tchar **onewv = newv;
155
156 while (*v)
157 *newv++ = savestr(*v++);
158 return (onewv);
159 }
160
161 tchar *
strspl(tchar * cp,tchar * dp)162 strspl(tchar *cp, tchar *dp)
163 {
164 tchar *ep;
165 tchar *p, *q;
166
167 #ifndef m32
168 for (p = cp; *p++; )
169 ;
170 for (q = dp; *q++; )
171 ;
172 ep = (tchar *) xalloc((unsigned)(((p - cp) +
173 (q - dp) - 1))*sizeof (tchar));
174 for (p = ep, q = cp; *p++ = *q++; )
175 ;
176 for (p--, q = dp; *p++ = *q++; )
177 ;
178 #else
179 int len1 = strlen_(cp);
180 int len2 = strlen_(dp);
181
182 ep = (tchar *)xalloc((unsigned)(len1 + len2 + 1)*sizeof (tchar));
183 strcpy_(ep, cp);
184 strcat_(ep, dp);
185 #endif
186 return (ep);
187 }
188
189 tchar **
blkspl(tchar ** up,tchar ** vp)190 blkspl(tchar **up, tchar **vp)
191 {
192 tchar **wp =
193 (tchar **)xcalloc((unsigned)(blklen(up) + blklen(vp) + 1),
194 sizeof (tchar **));
195
196 (void) blkcpy(wp, up);
197 return (blkcat(wp, vp));
198 }
199
200 int
lastchr(tchar * cp)201 lastchr(tchar *cp)
202 {
203
204 if (!*cp)
205 return (0);
206 while (cp[1])
207 cp++;
208 return (*cp);
209 }
210
211 void
donefds(void)212 donefds(void)
213 {
214 (void) close(0);
215 (void) close(1);
216 (void) close(2);
217
218 /*
219 * To avoid NIS+ functions to get hold of 0/1/2,
220 * use descriptor 0, and dup it to 1 and 2.
221 */
222 open("/dev/null", 0);
223 dup(0); dup(0);
224 didfds = 0;
225 }
226
227 /*
228 * Move descriptor i to j.
229 * If j is -1 then we just want to get i to a safe place,
230 * i.e. to a unit > 2. This also happens in dcopy.
231 */
232 int
dmove(int i,int j)233 dmove(int i, int j)
234 {
235 int fd;
236
237 if (i == j || i < 0)
238 return (i);
239 if (j >= 0) {
240 fd = dup2(i, j);
241 if (fd != -1)
242 setfd(fd);
243 } else
244 j = dcopy(i, j);
245 if (j != i) {
246 (void) close(i);
247 unsetfd(i);
248 }
249 return (j);
250 }
251
252 int
dcopy(int i,int j)253 dcopy(int i, int j)
254 {
255
256 int fd;
257
258 if (i == j || i < 0 || j < 0 && i > 2)
259 return (i);
260 if (j >= 0) {
261 fd = dup2(i, j);
262 if (fd != -1)
263 setfd(fd);
264 return (j);
265 }
266 (void) close(j);
267 unsetfd(j);
268 return (renum(i, j));
269 }
270
271 int
renum(int i,int j)272 renum(int i, int j)
273 {
274 int k = dup(i);
275
276 if (k < 0)
277 return (-1);
278 if (j == -1 && k > 2) {
279 setfd(k);
280 return (k);
281 }
282 if (k != j) {
283 j = renum(k, j);
284 (void) close(k); /* no need ofr unsetfd() */
285 return (j);
286 }
287 return (k);
288 }
289
290 #ifndef copy
291 void
copy(tchar * to,tchar * from,int size)292 copy(tchar *to, tchar *from, int size)
293 {
294
295 if (size)
296 do
297 *to++ = *from++;
298 while (--size != 0);
299 }
300 #endif
301
302 /*
303 * Left shift a command argument list, discarding
304 * the first c arguments. Used in "shift" commands
305 * as well as by commands like "repeat".
306 */
307 void
lshift(tchar ** v,int c)308 lshift(tchar **v, int c)
309 {
310 tchar **u = v;
311
312 while (*u && --c >= 0)
313 xfree((char *)*u++);
314 (void) blkcpy(v, u);
315 }
316
317 int
number(tchar * cp)318 number(tchar *cp)
319 {
320
321 if (*cp == '-') {
322 cp++;
323 if (!digit(*cp++))
324 return (0);
325 }
326 while (*cp && digit(*cp))
327 cp++;
328 return (*cp == 0);
329 }
330
331 tchar **
copyblk(tchar ** v)332 copyblk(tchar **v)
333 {
334 tchar **nv =
335 (tchar **)xcalloc((unsigned)(blklen(v) + 1),
336 sizeof (tchar **));
337
338 return (blkcpy(nv, v));
339 }
340
341 tchar *
strend(tchar * cp)342 strend(tchar *cp)
343 {
344
345 while (*cp)
346 cp++;
347 return (cp);
348 }
349
350 tchar *
strip(tchar * cp)351 strip(tchar *cp)
352 {
353 tchar *dp = cp;
354
355 while (*dp++ &= TRIM)
356 continue;
357 return (cp);
358 }
359
360 void
udvar(tchar * name)361 udvar(tchar *name)
362 {
363
364 setname(name);
365 bferr("Undefined variable");
366 }
367
368 int
prefix(tchar * sub,tchar * str)369 prefix(tchar *sub, tchar *str)
370 {
371
372 for (;;) {
373 if (*sub == 0)
374 return (1);
375 if (*str == 0)
376 return (0);
377 if (*sub++ != *str++)
378 return (0);
379 }
380 }
381
382 /*
383 * blk*_ routines
384 */
385
386 char **
blkend_(char ** up)387 blkend_(char **up)
388 {
389
390 while (*up)
391 up++;
392 return (up);
393 }
394
395 int
blklen_(char ** av)396 blklen_(char **av)
397 {
398 int i = 0;
399
400 while (*av++)
401 i++;
402 return (i);
403 }
404
405 char **
blkcpy_(char ** oav,char ** bv)406 blkcpy_(char **oav, char **bv)
407 {
408 char **av = oav;
409
410 while (*av++ = *bv++)
411 continue;
412 return (oav);
413 }
414
415 char **
blkcat_(char ** up,char ** vp)416 blkcat_(char **up, char **vp)
417 {
418
419 (void) blkcpy_(blkend_(up), vp);
420 return (up);
421 }
422
423 char **
blkspl_(char ** up,char ** vp)424 blkspl_(char **up, char **vp)
425 {
426 char **wp =
427 (char **)xcalloc((unsigned)(blklen_(up) + blklen_(vp) + 1),
428 sizeof (char **));
429
430 (void) blkcpy_(wp, up);
431 return (blkcat_(wp, vp));
432 }
433
434 /*
435 * If stack address was passed to free(), we have no good way to see if
436 * they are really in the stack. Therefore, we record the bottom of heap,
437 * and filter out the address not within heap's top(end) and bottom
438 * (xalloc_bottom).
439 */
440 extern char end[];
441 static char *xalloc_bottom;
442
443 void *
xalloc(size_t size)444 xalloc(size_t size)
445 {
446 char *rptr, *bp;
447
448 if ((rptr = malloc(size)) == NULL)
449 return (nomem(size));
450 bp = rptr + size;
451 if (bp > xalloc_bottom)
452 xalloc_bottom = bp;
453 return (rptr);
454 }
455
456 void *
xrealloc(void * ptr,size_t size)457 xrealloc(void *ptr, size_t size)
458 {
459 char *rptr = ptr, *bp;
460
461 if (ptr == NULL)
462 return (xalloc(size));
463 if (rptr < end) {
464 /* data area, but not in heap area. don't touch it */
465 oob:
466 if (size == 0)
467 return (NULL);
468 rptr = xalloc(size);
469 /* copy max size */
470 (void) memcpy(rptr, ptr, size);
471 return (rptr);
472 }
473 if (rptr < xalloc_bottom) {
474 /* address in the heap */
475 inb:
476 if (size == 0) {
477 free(ptr);
478 return (NULL);
479 }
480 if ((rptr = realloc(ptr, size)) == NULL)
481 return (nomem(size));
482 bp = rptr + size;
483 if (bp > xalloc_bottom)
484 xalloc_bottom = bp;
485 return (rptr);
486 }
487 #if defined(__sparc)
488 if (rptr > (char *)&rptr) {
489 /* in the stack frame */
490 goto oob;
491 }
492 #endif
493 /*
494 * can be a memory block returned indirectly from
495 * library functions. update bottom, and check it again.
496 */
497 xalloc_bottom = sbrk(0);
498 if (rptr <= xalloc_bottom)
499 goto inb;
500 else
501 goto oob;
502 /*NOTREACHED*/
503 }
504
505 void
xfree(void * ptr)506 xfree(void *ptr)
507 {
508 char *rptr = ptr;
509
510 if (rptr < end) {
511 return;
512 }
513 if (rptr < xalloc_bottom) {
514 free(ptr);
515 return;
516 }
517 #if defined(__sparc)
518 if (rptr > (char *)&rptr) {
519 /* in the stack frame */
520 return;
521 }
522 #endif
523 xalloc_bottom = sbrk(0);
524 if (rptr <= xalloc_bottom) {
525 free(ptr);
526 }
527 }
528
529 void *
xcalloc(size_t i,size_t j)530 xcalloc(size_t i, size_t j)
531 {
532 char *cp;
533
534 i *= j;
535 cp = xalloc(i);
536 (void) memset(cp, '\0', i);
537 return (cp);
538 }
539