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 5*5976Snakanon * Common Development and Distribution License (the "License"). 6*5976Snakanon * 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 /* 23*5976Snakanon * 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 30527Schin #pragma ident "%Z%%M% %I% %E% SMI" 310Sstevel@tonic-gate /* 320Sstevel@tonic-gate * UNIX shell 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include "defs.h" 360Sstevel@tonic-gate #include "dup.h" 37527Schin #include <stdio.h> 380Sstevel@tonic-gate #include <fcntl.h> 390Sstevel@tonic-gate #include <sys/types.h> 400Sstevel@tonic-gate #include <sys/stat.h> 410Sstevel@tonic-gate #include <errno.h> 420Sstevel@tonic-gate 430Sstevel@tonic-gate short topfd; 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* ======== input output and file copying ======== */ 460Sstevel@tonic-gate 47527Schin void 48527Schin initf(int fd) 490Sstevel@tonic-gate { 50527Schin struct fileblk *f = standin; 510Sstevel@tonic-gate 520Sstevel@tonic-gate f->fdes = fd; 530Sstevel@tonic-gate f->fsiz = ((flags & oneflg) == 0 ? BUFFERSIZE : 1); 540Sstevel@tonic-gate f->fnxt = f->fend = f->fbuf; 550Sstevel@tonic-gate f->nxtoff = f->endoff = 0; 560Sstevel@tonic-gate f->feval = 0; 570Sstevel@tonic-gate f->flin = 1; 580Sstevel@tonic-gate f->feof = FALSE; 590Sstevel@tonic-gate } 600Sstevel@tonic-gate 61527Schin int 62527Schin estabf(unsigned char *s) 630Sstevel@tonic-gate { 64527Schin struct fileblk *f; 650Sstevel@tonic-gate 660Sstevel@tonic-gate (f = standin)->fdes = -1; 670Sstevel@tonic-gate f->fend = length(s) + (f->fnxt = s); 680Sstevel@tonic-gate f->nxtoff = 0; 690Sstevel@tonic-gate f->endoff = length(s); 700Sstevel@tonic-gate f->flin = 1; 710Sstevel@tonic-gate return (f->feof = (s == 0)); 720Sstevel@tonic-gate } 730Sstevel@tonic-gate 74527Schin void 75527Schin push(struct fileblk *af) 760Sstevel@tonic-gate { 77527Schin struct fileblk *f; 780Sstevel@tonic-gate 790Sstevel@tonic-gate (f = af)->fstak = standin; 800Sstevel@tonic-gate f->feof = 0; 810Sstevel@tonic-gate f->feval = 0; 820Sstevel@tonic-gate standin = f; 830Sstevel@tonic-gate } 840Sstevel@tonic-gate 85527Schin int 86527Schin pop(void) 870Sstevel@tonic-gate { 88527Schin struct fileblk *f; 890Sstevel@tonic-gate 900Sstevel@tonic-gate if ((f = standin)->fstak) 910Sstevel@tonic-gate { 920Sstevel@tonic-gate if (f->fdes >= 0) 930Sstevel@tonic-gate close(f->fdes); 940Sstevel@tonic-gate standin = f->fstak; 950Sstevel@tonic-gate return (TRUE); 960Sstevel@tonic-gate }else 970Sstevel@tonic-gate return (FALSE); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate 1000Sstevel@tonic-gate struct tempblk *tmpfptr; 1010Sstevel@tonic-gate 102527Schin void 103527Schin pushtemp(int fd, struct tempblk *tb) 1040Sstevel@tonic-gate { 1050Sstevel@tonic-gate tb->fdes = fd; 1060Sstevel@tonic-gate tb->fstak = tmpfptr; 1070Sstevel@tonic-gate tmpfptr = tb; 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate 110527Schin int 111527Schin poptemp(void) 1120Sstevel@tonic-gate { 1130Sstevel@tonic-gate if (tmpfptr){ 1140Sstevel@tonic-gate close(tmpfptr->fdes); 1150Sstevel@tonic-gate tmpfptr = tmpfptr->fstak; 1160Sstevel@tonic-gate return (TRUE); 1170Sstevel@tonic-gate }else 1180Sstevel@tonic-gate return (FALSE); 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate 121527Schin void 122527Schin chkpipe(int *pv) 1230Sstevel@tonic-gate { 1240Sstevel@tonic-gate if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0) 1250Sstevel@tonic-gate error(piperr); 1260Sstevel@tonic-gate } 1270Sstevel@tonic-gate 128527Schin int 129527Schin chkopen(unsigned char *idf, int mode) 1300Sstevel@tonic-gate { 131527Schin int rc; 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate if ((rc = open((char *)idf, mode, 0666)) < 0) 1340Sstevel@tonic-gate failed(idf, badopen); 1350Sstevel@tonic-gate else 1360Sstevel@tonic-gate return (rc); 1370Sstevel@tonic-gate } 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate /* 1400Sstevel@tonic-gate * Make f2 be a synonym (including the close-on-exec flag) for f1, which is 1410Sstevel@tonic-gate * then closed. If f2 is descriptor 0, modify the global ioset variable 1420Sstevel@tonic-gate * accordingly. 1430Sstevel@tonic-gate */ 144527Schin void 145527Schin renamef(int f1, int f2) 1460Sstevel@tonic-gate { 1470Sstevel@tonic-gate #ifdef RES 1480Sstevel@tonic-gate if (f1 != f2) 1490Sstevel@tonic-gate { 1500Sstevel@tonic-gate dup(f1 | DUPFLG, f2); 1510Sstevel@tonic-gate close(f1); 1520Sstevel@tonic-gate if (f2 == 0) 1530Sstevel@tonic-gate ioset |= 1; 1540Sstevel@tonic-gate } 1550Sstevel@tonic-gate #else 1560Sstevel@tonic-gate int fs; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate if (f1 != f2) 1590Sstevel@tonic-gate { 1600Sstevel@tonic-gate fs = fcntl(f2, 1, 0); 1610Sstevel@tonic-gate close(f2); 1620Sstevel@tonic-gate fcntl(f1, 0, f2); 1630Sstevel@tonic-gate close(f1); 1640Sstevel@tonic-gate if (fs == 1) 1650Sstevel@tonic-gate fcntl(f2, 2, 1); 1660Sstevel@tonic-gate if (f2 == 0) 1670Sstevel@tonic-gate ioset |= 1; 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate #endif 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate 172527Schin int 173527Schin create(unsigned char *s) 1740Sstevel@tonic-gate { 175527Schin int rc; 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate if ((rc = creat((char *)s, 0666)) < 0) 1780Sstevel@tonic-gate failed(s, badcreate); 1790Sstevel@tonic-gate else 1800Sstevel@tonic-gate return (rc); 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate 184527Schin int 185527Schin tmpfil(struct tempblk *tb) 1860Sstevel@tonic-gate { 1870Sstevel@tonic-gate int fd; 188527Schin int len; 189527Schin size_t size_left = TMPOUTSZ - tmpout_offset; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate /* make sure tmp file does not already exist. */ 1920Sstevel@tonic-gate do { 193527Schin len = snprintf((char *)&tmpout[tmpout_offset], size_left, 194527Schin "%u", serial); 195527Schin fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0600); 196527Schin serial++; 197527Schin if ((serial >= UINT_MAX) || (len >= size_left)) { 198527Schin /* 199527Schin * We've already cycled through all the possible 200527Schin * numbers or the tmp file name is being 201527Schin * truncated anyway (although TMPOUTSZ should be 202527Schin * big enough), so start over. 203527Schin */ 204527Schin serial = 0; 205527Schin break; 206527Schin } 2070Sstevel@tonic-gate } while ((fd == -1) && (errno == EEXIST)); 2080Sstevel@tonic-gate if (fd != -1) { 2090Sstevel@tonic-gate pushtemp(fd, tb); 2100Sstevel@tonic-gate return (fd); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate else 2130Sstevel@tonic-gate failed(tmpout, badcreate); 2140Sstevel@tonic-gate } 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate /* 2170Sstevel@tonic-gate * set by trim 2180Sstevel@tonic-gate */ 2190Sstevel@tonic-gate extern BOOL nosubst; 2200Sstevel@tonic-gate #define CPYSIZ 512 2210Sstevel@tonic-gate 222527Schin void 223527Schin copy(struct ionod *ioparg) 2240Sstevel@tonic-gate { 225527Schin unsigned char *cline; 226527Schin unsigned char *clinep; 227527Schin struct ionod *iop; 2280Sstevel@tonic-gate unsigned int c; 2290Sstevel@tonic-gate unsigned char *ends; 2300Sstevel@tonic-gate unsigned char *start; 2310Sstevel@tonic-gate int fd; 2320Sstevel@tonic-gate int i; 2330Sstevel@tonic-gate int stripflg; 2340Sstevel@tonic-gate unsigned char *pc; 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate if (iop = ioparg) 2380Sstevel@tonic-gate { 2390Sstevel@tonic-gate struct tempblk tb; 2400Sstevel@tonic-gate copy(iop->iolst); 2410Sstevel@tonic-gate ends = mactrim(iop->ioname); 2420Sstevel@tonic-gate stripflg = iop->iofile & IOSTRIP; 2430Sstevel@tonic-gate if (nosubst) 244*5976Snakanon iop->iofile &= ~IODOC_SUBST; 2450Sstevel@tonic-gate fd = tmpfil(&tb); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate if (fndef) 2480Sstevel@tonic-gate iop->ioname = (char *) make(tmpout); 2490Sstevel@tonic-gate else 2500Sstevel@tonic-gate iop->ioname = (char *) cpystak(tmpout); 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate iop->iolst = iotemp; 2530Sstevel@tonic-gate iotemp = iop; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate cline = clinep = start = locstak(); 2560Sstevel@tonic-gate if (stripflg) 2570Sstevel@tonic-gate { 2580Sstevel@tonic-gate iop->iofile &= ~IOSTRIP; 2590Sstevel@tonic-gate while (*ends == '\t') 2600Sstevel@tonic-gate ends++; 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate for (;;) 2630Sstevel@tonic-gate { 2640Sstevel@tonic-gate chkpr(); 2650Sstevel@tonic-gate if (nosubst) 2660Sstevel@tonic-gate { 2670Sstevel@tonic-gate c = readwc(); 2680Sstevel@tonic-gate if (stripflg) 2690Sstevel@tonic-gate while (c == '\t') 2700Sstevel@tonic-gate c = readwc(); 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate while (!eolchar(c)) 2730Sstevel@tonic-gate { 2740Sstevel@tonic-gate pc = readw(c); 2750Sstevel@tonic-gate while (*pc) { 2760Sstevel@tonic-gate if (clinep >= brkend) 2770Sstevel@tonic-gate growstak(clinep); 2780Sstevel@tonic-gate *clinep++ = *pc++; 2790Sstevel@tonic-gate } 2800Sstevel@tonic-gate c = readwc(); 2810Sstevel@tonic-gate } 2820Sstevel@tonic-gate }else{ 2830Sstevel@tonic-gate c = nextwc(); 2840Sstevel@tonic-gate if (stripflg) 2850Sstevel@tonic-gate while (c == '\t') 2860Sstevel@tonic-gate c = nextwc(); 2870Sstevel@tonic-gate 2880Sstevel@tonic-gate while (!eolchar(c)) 2890Sstevel@tonic-gate { 2900Sstevel@tonic-gate pc = readw(c); 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 if (c == '\\') 2970Sstevel@tonic-gate { 2980Sstevel@tonic-gate pc = readw(readwc()); 2990Sstevel@tonic-gate /* *pc might be NULL */ 3000Sstevel@tonic-gate if (*pc) { 3010Sstevel@tonic-gate while (*pc) { 3020Sstevel@tonic-gate if (clinep >= brkend) 3030Sstevel@tonic-gate growstak(clinep); 3040Sstevel@tonic-gate *clinep++ = *pc++; 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate } else { 3070Sstevel@tonic-gate if (clinep >= brkend) 3080Sstevel@tonic-gate growstak(clinep); 3090Sstevel@tonic-gate *clinep++ = *pc; 3100Sstevel@tonic-gate } 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate c = nextwc(); 3130Sstevel@tonic-gate } 3140Sstevel@tonic-gate } 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate if (clinep >= brkend) 3170Sstevel@tonic-gate growstak(clinep); 3180Sstevel@tonic-gate *clinep = 0; 3190Sstevel@tonic-gate if (eof || eq(cline, ends)) 3200Sstevel@tonic-gate { 3210Sstevel@tonic-gate if ((i = cline - start) > 0) 3220Sstevel@tonic-gate write(fd, start, i); 3230Sstevel@tonic-gate break; 3240Sstevel@tonic-gate }else{ 3250Sstevel@tonic-gate if (clinep >= brkend) 3260Sstevel@tonic-gate growstak(clinep); 3270Sstevel@tonic-gate *clinep++ = NL; 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate if ((i = clinep - start) < CPYSIZ) 3310Sstevel@tonic-gate cline = clinep; 3320Sstevel@tonic-gate else 3330Sstevel@tonic-gate { 3340Sstevel@tonic-gate write(fd, start, i); 3350Sstevel@tonic-gate cline = clinep = start; 3360Sstevel@tonic-gate } 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate poptemp(); /* 3400Sstevel@tonic-gate * pushed in tmpfil -- bug fix for problem 3410Sstevel@tonic-gate * deleting in-line scripts 3420Sstevel@tonic-gate */ 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 346527Schin void 347527Schin link_iodocs(struct ionod *i) 3480Sstevel@tonic-gate { 3490Sstevel@tonic-gate int r; 350527Schin int len; 351527Schin size_t size_left = TMPOUTSZ - tmpout_offset; 3520Sstevel@tonic-gate 353527Schin while (i) { 3540Sstevel@tonic-gate free(i->iolink); 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate /* make sure tmp file does not already exist. */ 3570Sstevel@tonic-gate do { 358527Schin len = snprintf((char *)&tmpout[tmpout_offset], 359527Schin size_left, "%u", serial); 360527Schin serial++; 3610Sstevel@tonic-gate r = link(i->ioname, (char *)tmpout); 362527Schin if ((serial >= UINT_MAX) || (len >= size_left)) { 363527Schin /* 364527Schin * We've already cycled through all the possible 365527Schin * numbers or the tmp file name is being 366527Schin * truncated anyway, so start over. 367527Schin */ 368527Schin serial = 0; 369527Schin break; 370527Schin } 3710Sstevel@tonic-gate } while (r == -1 && errno == EEXIST); 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate if (r != -1) { 3740Sstevel@tonic-gate i->iolink = (char *)make(tmpout); 3750Sstevel@tonic-gate i = i->iolst; 3760Sstevel@tonic-gate } else 3770Sstevel@tonic-gate failed(tmpout, badcreate); 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate } 3810Sstevel@tonic-gate 382527Schin void 383527Schin swap_iodoc_nm(struct ionod *i) 3840Sstevel@tonic-gate { 3850Sstevel@tonic-gate while (i) 3860Sstevel@tonic-gate { 3870Sstevel@tonic-gate free(i->ioname); 3880Sstevel@tonic-gate i->ioname = i->iolink; 3890Sstevel@tonic-gate i->iolink = 0; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate i = i->iolst; 3920Sstevel@tonic-gate } 3930Sstevel@tonic-gate } 3940Sstevel@tonic-gate 395527Schin int 396527Schin savefd(int fd) 3970Sstevel@tonic-gate { 398527Schin int f; 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate f = fcntl(fd, F_DUPFD, 10); 4010Sstevel@tonic-gate return (f); 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate 404527Schin void 405527Schin restore(int last) 4060Sstevel@tonic-gate { 407527Schin int i; 408527Schin int dupfd; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate for (i = topfd - 1; i >= last; i--) 4110Sstevel@tonic-gate { 4120Sstevel@tonic-gate if ((dupfd = fdmap[i].dup_fd) > 0) 4130Sstevel@tonic-gate renamef(dupfd, fdmap[i].org_fd); 4140Sstevel@tonic-gate else 4150Sstevel@tonic-gate close(fdmap[i].org_fd); 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate topfd = last; 4180Sstevel@tonic-gate } 419