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