0
|
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 "@(#)sh.misc.c 1.19 05/09/15 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
|
|
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
|
|
39 onlyread(tchar *cp)
|
|
40 {
|
|
41 extern char end[];
|
|
42
|
|
43 return ((char *)cp < end);
|
|
44 }
|
|
45
|
|
46 tchar *
|
|
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 *
|
|
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 **
|
|
91 blkend(tchar **up)
|
|
92 {
|
|
93
|
|
94 while (*up)
|
|
95 up++;
|
|
96 return (up);
|
|
97 }
|
|
98
|
|
99 void
|
|
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
|
|
111 blklen(tchar **av)
|
|
112 {
|
|
113 int i = 0;
|
|
114
|
|
115 while (*av++)
|
|
116 i++;
|
|
117 return (i);
|
|
118 }
|
|
119
|
|
120 tchar **
|
|
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 **
|
|
131 blkcat(tchar **up, tchar **vp)
|
|
132 {
|
|
133
|
|
134 (void) blkcpy(blkend(up), vp);
|
|
135 return (up);
|
|
136 }
|
|
137
|
|
138 void
|
|
139 blkfree(tchar **av0)
|
|
140 {
|
|
141 tchar **av = av0;
|
|
142
|
|
143 for (; *av; av++)
|
|
144 xfree(*av);
|
|
145 xfree(av0);
|
|
146 }
|
|
147
|
|
148 tchar **
|
|
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 *
|
|
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 **
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 **
|
|
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 *
|
|
342 strend(tchar *cp)
|
|
343 {
|
|
344
|
|
345 while (*cp)
|
|
346 cp++;
|
|
347 return (cp);
|
|
348 }
|
|
349
|
|
350 tchar *
|
|
351 strip(tchar *cp)
|
|
352 {
|
|
353 tchar *dp = cp;
|
|
354
|
|
355 while (*dp++ &= TRIM)
|
|
356 continue;
|
|
357 return (cp);
|
|
358 }
|
|
359
|
|
360 void
|
|
361 udvar(tchar *name)
|
|
362 {
|
|
363
|
|
364 setname(name);
|
|
365 bferr("Undefined variable");
|
|
366 }
|
|
367
|
|
368 int
|
|
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 **
|
|
387 blkend_(char **up)
|
|
388 {
|
|
389
|
|
390 while (*up)
|
|
391 up++;
|
|
392 return (up);
|
|
393 }
|
|
394
|
|
395 int
|
|
396 blklen_(char **av)
|
|
397 {
|
|
398 int i = 0;
|
|
399
|
|
400 while (*av++)
|
|
401 i++;
|
|
402 return (i);
|
|
403 }
|
|
404
|
|
405 char **
|
|
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 **
|
|
416 blkcat_(char **up, char **vp)
|
|
417 {
|
|
418
|
|
419 (void) blkcpy_(blkend_(up), vp);
|
|
420 return (up);
|
|
421 }
|
|
422
|
|
423 char **
|
|
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 *
|
|
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 *
|
|
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
|
|
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 *
|
|
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 }
|