10Sstevel@tonic-gate /* 2*356Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 70Sstevel@tonic-gate /* All Rights Reserved */ 80Sstevel@tonic-gate 90Sstevel@tonic-gate /* 100Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 110Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 120Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 130Sstevel@tonic-gate */ 140Sstevel@tonic-gate 150Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 160Sstevel@tonic-gate 170Sstevel@tonic-gate #include "sh.h" 180Sstevel@tonic-gate #include "sh.tconst.h" 190Sstevel@tonic-gate #include <fcntl.h> 200Sstevel@tonic-gate #include <unistd.h> 210Sstevel@tonic-gate 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * C Shell 240Sstevel@tonic-gate */ 25*356Smuffin tchar **blkcat(tchar **, tchar **); 26*356Smuffin tchar **blkend(tchar **); 270Sstevel@tonic-gate 28*356Smuffin int 29*356Smuffin any(int c, tchar *s) 300Sstevel@tonic-gate { 310Sstevel@tonic-gate 320Sstevel@tonic-gate while (s && *s) 330Sstevel@tonic-gate if (*s++ == c) 340Sstevel@tonic-gate return (1); 350Sstevel@tonic-gate return (0); 360Sstevel@tonic-gate } 370Sstevel@tonic-gate 38*356Smuffin int 39*356Smuffin onlyread(tchar *cp) 400Sstevel@tonic-gate { 410Sstevel@tonic-gate extern char end[]; 420Sstevel@tonic-gate 430Sstevel@tonic-gate return ((char *)cp < end); 440Sstevel@tonic-gate } 450Sstevel@tonic-gate 460Sstevel@tonic-gate 470Sstevel@tonic-gate /* 480Sstevel@tonic-gate * WARNING: changes here also need to occur in the XFREE macro in sh.h. 490Sstevel@tonic-gate */ 50*356Smuffin void 51*356Smuffin xfree(char *cp) 520Sstevel@tonic-gate { 530Sstevel@tonic-gate extern char end[]; 540Sstevel@tonic-gate 550Sstevel@tonic-gate #if defined(sparc) 560Sstevel@tonic-gate if ((char *)cp >= end && (char *)cp < (char *)&cp) 570Sstevel@tonic-gate free(cp); 580Sstevel@tonic-gate #elif defined(i386) 590Sstevel@tonic-gate if ((char *)cp >= end) 600Sstevel@tonic-gate free(cp); 610Sstevel@tonic-gate #else 620Sstevel@tonic-gate #error xfree function is machine dependent and no machine type is recognized 630Sstevel@tonic-gate #endif 640Sstevel@tonic-gate } 650Sstevel@tonic-gate 660Sstevel@tonic-gate tchar * 67*356Smuffin savestr(tchar *s) 680Sstevel@tonic-gate { 690Sstevel@tonic-gate tchar *n; 70*356Smuffin tchar *p; 710Sstevel@tonic-gate 720Sstevel@tonic-gate if (s == 0) 730Sstevel@tonic-gate s = S_ /* "" */; 740Sstevel@tonic-gate #ifndef m32 750Sstevel@tonic-gate for (p = s; *p++; ) 760Sstevel@tonic-gate ; 770Sstevel@tonic-gate n = p = (tchar *)xalloc((unsigned) (p - s)*sizeof (tchar)); 780Sstevel@tonic-gate while (*p++ = *s++) 790Sstevel@tonic-gate ; 800Sstevel@tonic-gate return (n); 810Sstevel@tonic-gate #else 820Sstevel@tonic-gate p = (tchar *) xalloc((strlen_(s) + 1)*sizeof (tchar)); 830Sstevel@tonic-gate strcpy_(p, s); 840Sstevel@tonic-gate return (p); 850Sstevel@tonic-gate #endif 860Sstevel@tonic-gate } 870Sstevel@tonic-gate 880Sstevel@tonic-gate void * 89*356Smuffin calloc(size_t i, size_t j) 900Sstevel@tonic-gate { 91*356Smuffin char *cp; 920Sstevel@tonic-gate 930Sstevel@tonic-gate i *= j; 940Sstevel@tonic-gate cp = (char *)xalloc(i); 950Sstevel@tonic-gate bzero(cp, (int)i); 960Sstevel@tonic-gate return (cp); 970Sstevel@tonic-gate } 980Sstevel@tonic-gate 99*356Smuffin int 100*356Smuffin nomem(unsigned i) 1010Sstevel@tonic-gate { 1020Sstevel@tonic-gate #ifdef debug 1030Sstevel@tonic-gate static tchar *av[2] = {0, 0}; 1040Sstevel@tonic-gate #endif 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate child++; 1070Sstevel@tonic-gate #ifndef debug 1080Sstevel@tonic-gate error("Out of memory"); 1090Sstevel@tonic-gate #ifdef lint 1100Sstevel@tonic-gate i = i; 1110Sstevel@tonic-gate #endif 1120Sstevel@tonic-gate #else 1130Sstevel@tonic-gate showall(av); 1140Sstevel@tonic-gate printf("i=%d: Out of memory\n", i); 1150Sstevel@tonic-gate chdir("/usr/bill/cshcore"); 1160Sstevel@tonic-gate abort(); 1170Sstevel@tonic-gate #endif 1180Sstevel@tonic-gate return (0); /* fool lint */ 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate tchar ** 122*356Smuffin blkend(tchar **up) 1230Sstevel@tonic-gate { 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate while (*up) 1260Sstevel@tonic-gate up++; 1270Sstevel@tonic-gate return (up); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 130*356Smuffin void 131*356Smuffin blkpr(tchar **av) 1320Sstevel@tonic-gate { 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate for (; *av; av++) { 1350Sstevel@tonic-gate printf("%t", *av); 1360Sstevel@tonic-gate if (av[1]) 1370Sstevel@tonic-gate printf(" "); 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 141*356Smuffin int 142*356Smuffin blklen(tchar **av) 1430Sstevel@tonic-gate { 144*356Smuffin int i = 0; 1450Sstevel@tonic-gate 1460Sstevel@tonic-gate while (*av++) 1470Sstevel@tonic-gate i++; 1480Sstevel@tonic-gate return (i); 1490Sstevel@tonic-gate } 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate tchar ** 152*356Smuffin blkcpy(tchar **oav, tchar **bv) 1530Sstevel@tonic-gate { 154*356Smuffin tchar **av = oav; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate while (*av++ = *bv++) 1570Sstevel@tonic-gate continue; 1580Sstevel@tonic-gate return (oav); 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate tchar ** 162*356Smuffin blkcat(tchar **up, tchar **vp) 1630Sstevel@tonic-gate { 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate (void) blkcpy(blkend(up), vp); 1660Sstevel@tonic-gate return (up); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 169*356Smuffin void 170*356Smuffin blkfree(tchar **av0) 1710Sstevel@tonic-gate { 172*356Smuffin tchar **av = av0; 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate for (; *av; av++) 1750Sstevel@tonic-gate XFREE(*av) 1760Sstevel@tonic-gate XFREE((tchar *)av0) 1770Sstevel@tonic-gate } 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate tchar ** 180*356Smuffin saveblk(tchar **v) 1810Sstevel@tonic-gate { 182*356Smuffin tchar **newv = 1830Sstevel@tonic-gate (tchar **) calloc((unsigned) (blklen(v) + 1), 1840Sstevel@tonic-gate sizeof (tchar **)); 1850Sstevel@tonic-gate tchar **onewv = newv; 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate while (*v) 1880Sstevel@tonic-gate *newv++ = savestr(*v++); 1890Sstevel@tonic-gate return (onewv); 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate tchar * 193*356Smuffin strspl(tchar *cp, tchar *dp) 1940Sstevel@tonic-gate { 1950Sstevel@tonic-gate tchar *ep; 196*356Smuffin tchar *p, *q; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate #ifndef m32 1990Sstevel@tonic-gate for (p = cp; *p++; ) 2000Sstevel@tonic-gate ; 2010Sstevel@tonic-gate for (q = dp; *q++; ) 2020Sstevel@tonic-gate ; 2030Sstevel@tonic-gate ep = (tchar *) xalloc((unsigned) (((p - cp) + 2040Sstevel@tonic-gate (q - dp) - 1))*sizeof (tchar)); 2050Sstevel@tonic-gate for (p = ep, q = cp; *p++ = *q++; ) 2060Sstevel@tonic-gate ; 2070Sstevel@tonic-gate for (p--, q = dp; *p++ = *q++; ) 2080Sstevel@tonic-gate ; 2090Sstevel@tonic-gate #else 2100Sstevel@tonic-gate int len1 = strlen_(cp); 2110Sstevel@tonic-gate int len2 = strlen_(dp); 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate ep = (tchar *)xalloc((unsigned) (len1 + len2 + 1)*sizeof (tchar)); 2140Sstevel@tonic-gate strcpy_(ep, cp); 2150Sstevel@tonic-gate strcat_(ep, dp); 2160Sstevel@tonic-gate #endif 2170Sstevel@tonic-gate return (ep); 2180Sstevel@tonic-gate } 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate tchar ** 221*356Smuffin blkspl(tchar **up, tchar **vp) 2220Sstevel@tonic-gate { 223*356Smuffin tchar **wp = 2240Sstevel@tonic-gate (tchar **) calloc((unsigned) (blklen(up) + blklen(vp) + 1), 2250Sstevel@tonic-gate sizeof (tchar **)); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate (void) blkcpy(wp, up); 2280Sstevel@tonic-gate return (blkcat(wp, vp)); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 231*356Smuffin int 232*356Smuffin lastchr(tchar *cp) 2330Sstevel@tonic-gate { 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate if (!*cp) 2360Sstevel@tonic-gate return (0); 2370Sstevel@tonic-gate while (cp[1]) 2380Sstevel@tonic-gate cp++; 2390Sstevel@tonic-gate return (*cp); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 242*356Smuffin void 243*356Smuffin donefds(void) 2440Sstevel@tonic-gate { 2450Sstevel@tonic-gate (void) close(0); 2460Sstevel@tonic-gate (void) close(1); 2470Sstevel@tonic-gate (void) close(2); 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate /* 2500Sstevel@tonic-gate * To avoid NIS+ functions to get hold of 0/1/2, 2510Sstevel@tonic-gate * use descriptor 0, and dup it to 1 and 2. 2520Sstevel@tonic-gate */ 2530Sstevel@tonic-gate open("/dev/null", 0); 2540Sstevel@tonic-gate dup(0); dup(0); 2550Sstevel@tonic-gate didfds = 0; 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate /* 2590Sstevel@tonic-gate * Move descriptor i to j. 2600Sstevel@tonic-gate * If j is -1 then we just want to get i to a safe place, 2610Sstevel@tonic-gate * i.e. to a unit > 2. This also happens in dcopy. 2620Sstevel@tonic-gate */ 263*356Smuffin int 264*356Smuffin dmove(int i, int j) 2650Sstevel@tonic-gate { 2660Sstevel@tonic-gate int fd; 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate if (i == j || i < 0) 2690Sstevel@tonic-gate return (i); 2700Sstevel@tonic-gate if (j >= 0) { 2710Sstevel@tonic-gate fd = dup2(i, j); 2720Sstevel@tonic-gate if (fd != -1) 2730Sstevel@tonic-gate setfd(fd); 2740Sstevel@tonic-gate } else 2750Sstevel@tonic-gate j = dcopy(i, j); 2760Sstevel@tonic-gate if (j != i) { 2770Sstevel@tonic-gate (void) close(i); 2780Sstevel@tonic-gate unsetfd(i); 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate return (j); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate 283*356Smuffin int 284*356Smuffin dcopy(int i, int j) 2850Sstevel@tonic-gate { 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate int fd; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate if (i == j || i < 0 || j < 0 && i > 2) 2900Sstevel@tonic-gate return (i); 2910Sstevel@tonic-gate if (j >= 0) { 2920Sstevel@tonic-gate fd = dup2(i, j); 2930Sstevel@tonic-gate if (fd != -1) 2940Sstevel@tonic-gate setfd(fd); 2950Sstevel@tonic-gate return (j); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate (void) close(j); 2980Sstevel@tonic-gate unsetfd(j); 2990Sstevel@tonic-gate return (renum(i, j)); 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate 302*356Smuffin int 303*356Smuffin renum(int i, int j) 3040Sstevel@tonic-gate { 305*356Smuffin int k = dup(i); 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate if (k < 0) 3080Sstevel@tonic-gate return (-1); 3090Sstevel@tonic-gate if (j == -1 && k > 2) { 3100Sstevel@tonic-gate setfd(k); 3110Sstevel@tonic-gate return (k); 3120Sstevel@tonic-gate } 3130Sstevel@tonic-gate if (k != j) { 3140Sstevel@tonic-gate j = renum(k, j); 3150Sstevel@tonic-gate (void) close(k); /* no need ofr unsetfd() */ 3160Sstevel@tonic-gate return (j); 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate return (k); 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate #ifndef copy 322*356Smuffin void 323*356Smuffin copy(tchar *to, tchar *from, int size) 3240Sstevel@tonic-gate { 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate if (size) 3270Sstevel@tonic-gate do 3280Sstevel@tonic-gate *to++ = *from++; 3290Sstevel@tonic-gate while (--size != 0); 3300Sstevel@tonic-gate } 3310Sstevel@tonic-gate #endif 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate /* 3340Sstevel@tonic-gate * Left shift a command argument list, discarding 3350Sstevel@tonic-gate * the first c arguments. Used in "shift" commands 3360Sstevel@tonic-gate * as well as by commands like "repeat". 3370Sstevel@tonic-gate */ 338*356Smuffin void 339*356Smuffin lshift(tchar **v, int c) 3400Sstevel@tonic-gate { 341*356Smuffin tchar **u = v; 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate while (*u && --c >= 0) 344*356Smuffin xfree((char *)*u++); 3450Sstevel@tonic-gate (void) blkcpy(v, u); 3460Sstevel@tonic-gate } 3470Sstevel@tonic-gate 348*356Smuffin int 349*356Smuffin number(tchar *cp) 3500Sstevel@tonic-gate { 3510Sstevel@tonic-gate 3520Sstevel@tonic-gate if (*cp == '-') { 3530Sstevel@tonic-gate cp++; 3540Sstevel@tonic-gate if (!digit(*cp++)) 3550Sstevel@tonic-gate return (0); 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate while (*cp && digit(*cp)) 3580Sstevel@tonic-gate cp++; 3590Sstevel@tonic-gate return (*cp == 0); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate tchar ** 363*356Smuffin copyblk(tchar **v) 3640Sstevel@tonic-gate { 365*356Smuffin tchar **nv = 3660Sstevel@tonic-gate (tchar **) calloc((unsigned) (blklen(v) + 1), 3670Sstevel@tonic-gate sizeof (tchar **)); 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate return (blkcpy(nv, v)); 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate tchar * 373*356Smuffin strend(tchar *cp) 3740Sstevel@tonic-gate { 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate while (*cp) 3770Sstevel@tonic-gate cp++; 3780Sstevel@tonic-gate return (cp); 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate tchar * 382*356Smuffin strip(tchar *cp) 3830Sstevel@tonic-gate { 384*356Smuffin tchar *dp = cp; 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate while (*dp++ &= TRIM) 3870Sstevel@tonic-gate continue; 3880Sstevel@tonic-gate return (cp); 3890Sstevel@tonic-gate } 3900Sstevel@tonic-gate 391*356Smuffin void 392*356Smuffin udvar(tchar *name) 3930Sstevel@tonic-gate { 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate setname(name); 3960Sstevel@tonic-gate bferr("Undefined variable"); 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate 399*356Smuffin int 400*356Smuffin prefix(tchar *sub, tchar *str) 4010Sstevel@tonic-gate { 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate for (;;) { 4040Sstevel@tonic-gate if (*sub == 0) 4050Sstevel@tonic-gate return (1); 4060Sstevel@tonic-gate if (*str == 0) 4070Sstevel@tonic-gate return (0); 4080Sstevel@tonic-gate if (*sub++ != *str++) 4090Sstevel@tonic-gate return (0); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate 4130Sstevel@tonic-gate /* 4140Sstevel@tonic-gate * blk*_ routines 4150Sstevel@tonic-gate */ 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate char ** 418*356Smuffin blkend_(char **up) 4190Sstevel@tonic-gate { 4200Sstevel@tonic-gate 4210Sstevel@tonic-gate while (*up) 4220Sstevel@tonic-gate up++; 4230Sstevel@tonic-gate return (up); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate 426*356Smuffin int 427*356Smuffin blklen_(char **av) 4280Sstevel@tonic-gate { 429*356Smuffin int i = 0; 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate while (*av++) 4320Sstevel@tonic-gate i++; 4330Sstevel@tonic-gate return (i); 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate char ** 437*356Smuffin blkcpy_(char **oav, char **bv) 4380Sstevel@tonic-gate { 439*356Smuffin char **av = oav; 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate while (*av++ = *bv++) 4420Sstevel@tonic-gate continue; 4430Sstevel@tonic-gate return (oav); 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate char ** 447*356Smuffin blkcat_(char **up, char **vp) 4480Sstevel@tonic-gate { 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate (void) blkcpy_(blkend_(up), vp); 4510Sstevel@tonic-gate return (up); 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate char ** 455*356Smuffin blkspl_(char **up, char **vp) 4560Sstevel@tonic-gate { 457*356Smuffin char **wp = 4580Sstevel@tonic-gate (char **) calloc((unsigned) (blklen_(up) + blklen_(vp) + 1), 4590Sstevel@tonic-gate sizeof (char **)); 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate (void) blkcpy_(wp, up); 4620Sstevel@tonic-gate return (blkcat_(wp, vp)); 4630Sstevel@tonic-gate } 464