10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55976Snakanon * Common Development and Distribution License (the "License"). 65976Snakanon * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 21527Schin 22527Schin /* 235976Snakanon * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24527Schin * Use is subject to license terms. 25527Schin */ 26527Schin 270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate /* 310Sstevel@tonic-gate * UNIX shell 320Sstevel@tonic-gate */ 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include "defs.h" 350Sstevel@tonic-gate #include "dup.h" 36527Schin #include <stdio.h> 370Sstevel@tonic-gate #include <fcntl.h> 380Sstevel@tonic-gate #include <sys/types.h> 390Sstevel@tonic-gate #include <sys/stat.h> 400Sstevel@tonic-gate #include <errno.h> 410Sstevel@tonic-gate 420Sstevel@tonic-gate short topfd; 430Sstevel@tonic-gate 440Sstevel@tonic-gate /* ======== input output and file copying ======== */ 450Sstevel@tonic-gate 46527Schin void 47527Schin initf(int fd) 480Sstevel@tonic-gate { 49527Schin struct fileblk *f = standin; 500Sstevel@tonic-gate 510Sstevel@tonic-gate f->fdes = fd; 520Sstevel@tonic-gate f->fsiz = ((flags & oneflg) == 0 ? BUFFERSIZE : 1); 530Sstevel@tonic-gate f->fnxt = f->fend = f->fbuf; 540Sstevel@tonic-gate f->nxtoff = f->endoff = 0; 550Sstevel@tonic-gate f->feval = 0; 560Sstevel@tonic-gate f->flin = 1; 570Sstevel@tonic-gate f->feof = FALSE; 580Sstevel@tonic-gate } 590Sstevel@tonic-gate 60527Schin int 61527Schin estabf(unsigned char *s) 620Sstevel@tonic-gate { 63527Schin struct fileblk *f; 640Sstevel@tonic-gate 650Sstevel@tonic-gate (f = standin)->fdes = -1; 660Sstevel@tonic-gate f->fend = length(s) + (f->fnxt = s); 670Sstevel@tonic-gate f->nxtoff = 0; 680Sstevel@tonic-gate f->endoff = length(s); 690Sstevel@tonic-gate f->flin = 1; 700Sstevel@tonic-gate return (f->feof = (s == 0)); 710Sstevel@tonic-gate } 720Sstevel@tonic-gate 73527Schin void 74527Schin push(struct fileblk *af) 750Sstevel@tonic-gate { 76527Schin struct fileblk *f; 770Sstevel@tonic-gate 780Sstevel@tonic-gate (f = af)->fstak = standin; 790Sstevel@tonic-gate f->feof = 0; 800Sstevel@tonic-gate f->feval = 0; 810Sstevel@tonic-gate standin = f; 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 84527Schin int 85527Schin pop(void) 860Sstevel@tonic-gate { 87527Schin struct fileblk *f; 880Sstevel@tonic-gate 89*7641SWilliam.Roche@Sun.COM if ((f = standin)->fstak) { 900Sstevel@tonic-gate if (f->fdes >= 0) 910Sstevel@tonic-gate close(f->fdes); 920Sstevel@tonic-gate standin = f->fstak; 930Sstevel@tonic-gate return (TRUE); 94*7641SWilliam.Roche@Sun.COM } else 950Sstevel@tonic-gate return (FALSE); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate struct tempblk *tmpfptr; 990Sstevel@tonic-gate 100527Schin void 101527Schin pushtemp(int fd, struct tempblk *tb) 1020Sstevel@tonic-gate { 1030Sstevel@tonic-gate tb->fdes = fd; 1040Sstevel@tonic-gate tb->fstak = tmpfptr; 1050Sstevel@tonic-gate tmpfptr = tb; 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 108527Schin int 109527Schin poptemp(void) 1100Sstevel@tonic-gate { 111*7641SWilliam.Roche@Sun.COM if (tmpfptr) { 1120Sstevel@tonic-gate close(tmpfptr->fdes); 1130Sstevel@tonic-gate tmpfptr = tmpfptr->fstak; 1140Sstevel@tonic-gate return (TRUE); 115*7641SWilliam.Roche@Sun.COM } else 1160Sstevel@tonic-gate return (FALSE); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 119527Schin void 120527Schin chkpipe(int *pv) 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0) 1230Sstevel@tonic-gate error(piperr); 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 126527Schin int 127527Schin chkopen(unsigned char *idf, int mode) 1280Sstevel@tonic-gate { 129527Schin int rc; 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate if ((rc = open((char *)idf, mode, 0666)) < 0) 1320Sstevel@tonic-gate failed(idf, badopen); 1330Sstevel@tonic-gate else 1340Sstevel@tonic-gate return (rc); 1350Sstevel@tonic-gate } 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate /* 1380Sstevel@tonic-gate * Make f2 be a synonym (including the close-on-exec flag) for f1, which is 1390Sstevel@tonic-gate * then closed. If f2 is descriptor 0, modify the global ioset variable 1400Sstevel@tonic-gate * accordingly. 1410Sstevel@tonic-gate */ 142527Schin void 143527Schin renamef(int f1, int f2) 1440Sstevel@tonic-gate { 1450Sstevel@tonic-gate #ifdef RES 146*7641SWilliam.Roche@Sun.COM if (f1 != f2) { 1470Sstevel@tonic-gate dup(f1 | DUPFLG, f2); 1480Sstevel@tonic-gate close(f1); 1490Sstevel@tonic-gate if (f2 == 0) 1500Sstevel@tonic-gate ioset |= 1; 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate #else 1530Sstevel@tonic-gate int fs; 1540Sstevel@tonic-gate 155*7641SWilliam.Roche@Sun.COM if (f1 != f2) { 1560Sstevel@tonic-gate fs = fcntl(f2, 1, 0); 1570Sstevel@tonic-gate close(f2); 1580Sstevel@tonic-gate fcntl(f1, 0, f2); 1590Sstevel@tonic-gate close(f1); 1600Sstevel@tonic-gate if (fs == 1) 1610Sstevel@tonic-gate fcntl(f2, 2, 1); 1620Sstevel@tonic-gate if (f2 == 0) 1630Sstevel@tonic-gate ioset |= 1; 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate #endif 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 168527Schin int 169527Schin create(unsigned char *s) 1700Sstevel@tonic-gate { 171527Schin int rc; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate if ((rc = creat((char *)s, 0666)) < 0) 1740Sstevel@tonic-gate failed(s, badcreate); 1750Sstevel@tonic-gate else 1760Sstevel@tonic-gate return (rc); 1770Sstevel@tonic-gate } 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate 180527Schin int 181527Schin tmpfil(struct tempblk *tb) 1820Sstevel@tonic-gate { 1830Sstevel@tonic-gate int fd; 184527Schin int len; 185527Schin size_t size_left = TMPOUTSZ - tmpout_offset; 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* make sure tmp file does not already exist. */ 1880Sstevel@tonic-gate do { 189527Schin len = snprintf((char *)&tmpout[tmpout_offset], size_left, 190527Schin "%u", serial); 191527Schin fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0600); 192527Schin serial++; 193527Schin if ((serial >= UINT_MAX) || (len >= size_left)) { 194527Schin /* 195527Schin * We've already cycled through all the possible 196527Schin * numbers or the tmp file name is being 197527Schin * truncated anyway (although TMPOUTSZ should be 198527Schin * big enough), so start over. 199527Schin */ 200527Schin serial = 0; 201527Schin break; 202527Schin } 2030Sstevel@tonic-gate } while ((fd == -1) && (errno == EEXIST)); 2040Sstevel@tonic-gate if (fd != -1) { 2050Sstevel@tonic-gate pushtemp(fd, tb); 2060Sstevel@tonic-gate return (fd); 2070Sstevel@tonic-gate } 2080Sstevel@tonic-gate else 2090Sstevel@tonic-gate failed(tmpout, badcreate); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* 2130Sstevel@tonic-gate * set by trim 2140Sstevel@tonic-gate */ 2150Sstevel@tonic-gate extern BOOL nosubst; 2160Sstevel@tonic-gate #define CPYSIZ 512 2170Sstevel@tonic-gate 218527Schin void 219527Schin copy(struct ionod *ioparg) 2200Sstevel@tonic-gate { 221527Schin unsigned char *cline; 222527Schin unsigned char *clinep; 223527Schin struct ionod *iop; 2240Sstevel@tonic-gate unsigned int c; 2250Sstevel@tonic-gate unsigned char *ends; 2260Sstevel@tonic-gate unsigned char *start; 2270Sstevel@tonic-gate int fd; 2280Sstevel@tonic-gate int i; 2290Sstevel@tonic-gate int stripflg; 2300Sstevel@tonic-gate unsigned char *pc; 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate 233*7641SWilliam.Roche@Sun.COM if (iop = ioparg) { 2340Sstevel@tonic-gate struct tempblk tb; 2350Sstevel@tonic-gate copy(iop->iolst); 2360Sstevel@tonic-gate ends = mactrim(iop->ioname); 2370Sstevel@tonic-gate stripflg = iop->iofile & IOSTRIP; 2380Sstevel@tonic-gate if (nosubst) 2395976Snakanon iop->iofile &= ~IODOC_SUBST; 2400Sstevel@tonic-gate fd = tmpfil(&tb); 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate if (fndef) 243*7641SWilliam.Roche@Sun.COM iop->ioname = (char *)make(tmpout); 2440Sstevel@tonic-gate else 245*7641SWilliam.Roche@Sun.COM iop->ioname = (char *)cpystak(tmpout); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate iop->iolst = iotemp; 2480Sstevel@tonic-gate iotemp = iop; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate cline = clinep = start = locstak(); 251*7641SWilliam.Roche@Sun.COM if (stripflg) { 2520Sstevel@tonic-gate iop->iofile &= ~IOSTRIP; 2530Sstevel@tonic-gate while (*ends == '\t') 2540Sstevel@tonic-gate ends++; 2550Sstevel@tonic-gate } 256*7641SWilliam.Roche@Sun.COM for (;;) { 2570Sstevel@tonic-gate chkpr(); 258*7641SWilliam.Roche@Sun.COM if (nosubst) { 2590Sstevel@tonic-gate c = readwc(); 2600Sstevel@tonic-gate if (stripflg) 2610Sstevel@tonic-gate while (c == '\t') 2620Sstevel@tonic-gate c = readwc(); 2630Sstevel@tonic-gate 264*7641SWilliam.Roche@Sun.COM while (!eolchar(c)) { 2650Sstevel@tonic-gate pc = readw(c); 2660Sstevel@tonic-gate while (*pc) { 2670Sstevel@tonic-gate if (clinep >= brkend) 2680Sstevel@tonic-gate growstak(clinep); 2690Sstevel@tonic-gate *clinep++ = *pc++; 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate c = readwc(); 2720Sstevel@tonic-gate } 273*7641SWilliam.Roche@Sun.COM } else { 2740Sstevel@tonic-gate c = nextwc(); 2750Sstevel@tonic-gate if (stripflg) 2760Sstevel@tonic-gate while (c == '\t') 2770Sstevel@tonic-gate c = nextwc(); 2780Sstevel@tonic-gate 279*7641SWilliam.Roche@Sun.COM while (!eolchar(c)) { 2800Sstevel@tonic-gate pc = readw(c); 2810Sstevel@tonic-gate while (*pc) { 2820Sstevel@tonic-gate if (clinep >= brkend) 2830Sstevel@tonic-gate growstak(clinep); 2840Sstevel@tonic-gate *clinep++ = *pc++; 2850Sstevel@tonic-gate } 286*7641SWilliam.Roche@Sun.COM if (c == '\\') { 2870Sstevel@tonic-gate pc = readw(readwc()); 2880Sstevel@tonic-gate /* *pc might be NULL */ 289*7641SWilliam.Roche@Sun.COM /* BEGIN CSTYLED */ 2900Sstevel@tonic-gate if (*pc) { 2910Sstevel@tonic-gate while (*pc) { 2920Sstevel@tonic-gate if (clinep >= brkend) 2930Sstevel@tonic-gate growstak(clinep); 2940Sstevel@tonic-gate *clinep++ = *pc++; 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate } else { 2970Sstevel@tonic-gate if (clinep >= brkend) 2980Sstevel@tonic-gate growstak(clinep); 2990Sstevel@tonic-gate *clinep++ = *pc; 3000Sstevel@tonic-gate } 301*7641SWilliam.Roche@Sun.COM /* END CSTYLED */ 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate c = nextwc(); 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate if (clinep >= brkend) 3080Sstevel@tonic-gate growstak(clinep); 3090Sstevel@tonic-gate *clinep = 0; 310*7641SWilliam.Roche@Sun.COM if (eof || eq(cline, ends)) { 3110Sstevel@tonic-gate if ((i = cline - start) > 0) 3120Sstevel@tonic-gate write(fd, start, i); 3130Sstevel@tonic-gate break; 314*7641SWilliam.Roche@Sun.COM } else { 3150Sstevel@tonic-gate if (clinep >= brkend) 3160Sstevel@tonic-gate growstak(clinep); 3170Sstevel@tonic-gate *clinep++ = NL; 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate if ((i = clinep - start) < CPYSIZ) 3210Sstevel@tonic-gate cline = clinep; 3220Sstevel@tonic-gate else 3230Sstevel@tonic-gate { 3240Sstevel@tonic-gate write(fd, start, i); 3250Sstevel@tonic-gate cline = clinep = start; 3260Sstevel@tonic-gate } 3270Sstevel@tonic-gate } 3280Sstevel@tonic-gate 329*7641SWilliam.Roche@Sun.COM /* 330*7641SWilliam.Roche@Sun.COM * Pushed in tmpfil -- bug fix for problem 331*7641SWilliam.Roche@Sun.COM * deleting in-line script. 332*7641SWilliam.Roche@Sun.COM */ 333*7641SWilliam.Roche@Sun.COM poptemp(); 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate 337527Schin void 338527Schin link_iodocs(struct ionod *i) 3390Sstevel@tonic-gate { 3400Sstevel@tonic-gate int r; 341527Schin int len; 342527Schin size_t size_left = TMPOUTSZ - tmpout_offset; 3430Sstevel@tonic-gate 344527Schin while (i) { 3450Sstevel@tonic-gate free(i->iolink); 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* make sure tmp file does not already exist. */ 3480Sstevel@tonic-gate do { 349527Schin len = snprintf((char *)&tmpout[tmpout_offset], 350527Schin size_left, "%u", serial); 351527Schin serial++; 3520Sstevel@tonic-gate r = link(i->ioname, (char *)tmpout); 353527Schin if ((serial >= UINT_MAX) || (len >= size_left)) { 354527Schin /* 355527Schin * We've already cycled through all the possible 356527Schin * numbers or the tmp file name is being 357*7641SWilliam.Roche@Sun.COM * truncated anyway, so start over. 358527Schin */ 359527Schin serial = 0; 360527Schin break; 361527Schin } 3620Sstevel@tonic-gate } while (r == -1 && errno == EEXIST); 3630Sstevel@tonic-gate 3640Sstevel@tonic-gate if (r != -1) { 3650Sstevel@tonic-gate i->iolink = (char *)make(tmpout); 3660Sstevel@tonic-gate i = i->iolst; 3670Sstevel@tonic-gate } else 3680Sstevel@tonic-gate failed(tmpout, badcreate); 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate 373527Schin void 374527Schin swap_iodoc_nm(struct ionod *i) 3750Sstevel@tonic-gate { 376*7641SWilliam.Roche@Sun.COM while (i) { 3770Sstevel@tonic-gate free(i->ioname); 3780Sstevel@tonic-gate i->ioname = i->iolink; 3790Sstevel@tonic-gate i->iolink = 0; 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate i = i->iolst; 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate 385527Schin int 386527Schin savefd(int fd) 3870Sstevel@tonic-gate { 388527Schin int f; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate f = fcntl(fd, F_DUPFD, 10); 391*7641SWilliam.Roche@Sun.COM /* this saved fd should not be found in an exec'ed cmd */ 392*7641SWilliam.Roche@Sun.COM (void) fcntl(f, F_SETFD, FD_CLOEXEC); 3930Sstevel@tonic-gate return (f); 3940Sstevel@tonic-gate } 3950Sstevel@tonic-gate 396527Schin void 397527Schin restore(int last) 3980Sstevel@tonic-gate { 399527Schin int i; 400527Schin int dupfd; 4010Sstevel@tonic-gate 402*7641SWilliam.Roche@Sun.COM for (i = topfd - 1; i >= last; i--) { 4030Sstevel@tonic-gate if ((dupfd = fdmap[i].dup_fd) > 0) 4040Sstevel@tonic-gate renamef(dupfd, fdmap[i].org_fd); 4050Sstevel@tonic-gate else 4060Sstevel@tonic-gate close(fdmap[i].org_fd); 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate topfd = last; 4090Sstevel@tonic-gate } 410