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
initf(int fd)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
estabf(unsigned char * s)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
push(struct fileblk * af)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
pop(void)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
pushtemp(int fd,struct tempblk * tb)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
poptemp(void)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
chkpipe(int * pv)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
chkopen(unsigned char * idf,int mode)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
renamef(int f1,int f2)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
create(unsigned char * s)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
tmpfil(struct tempblk * tb)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
copy(struct ionod * ioparg)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
link_iodocs(struct ionod * i)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
swap_iodoc_nm(struct ionod * i)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
savefd(int fd)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
restore(int last)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