xref: /onnv-gate/usr/src/cmd/sh/io.c (revision 7641:a12d809425f1)
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