xref: /onnv-gate/usr/src/cmd/sh/io.c (revision 527)
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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*527Schin 
23*527Schin /*
24*527Schin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25*527Schin  * Use is subject to license terms.
26*527Schin  */
27*527Schin 
280Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
290Sstevel@tonic-gate /*	  All Rights Reserved  	*/
300Sstevel@tonic-gate 
31*527Schin #pragma ident	"%Z%%M%	%I%	%E% SMI"
320Sstevel@tonic-gate /*
330Sstevel@tonic-gate  * UNIX shell
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include	"defs.h"
370Sstevel@tonic-gate #include	"dup.h"
38*527Schin #include	<stdio.h>
390Sstevel@tonic-gate #include	<fcntl.h>
400Sstevel@tonic-gate #include	<sys/types.h>
410Sstevel@tonic-gate #include	<sys/stat.h>
420Sstevel@tonic-gate #include	<errno.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate short topfd;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /* ========	input output and file copying ======== */
470Sstevel@tonic-gate 
48*527Schin void
49*527Schin initf(int fd)
500Sstevel@tonic-gate {
51*527Schin 	struct fileblk *f = standin;
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	f->fdes = fd;
540Sstevel@tonic-gate 	f->fsiz = ((flags & oneflg) == 0 ? BUFFERSIZE : 1);
550Sstevel@tonic-gate 	f->fnxt = f->fend = f->fbuf;
560Sstevel@tonic-gate 	f->nxtoff = f->endoff = 0;
570Sstevel@tonic-gate 	f->feval = 0;
580Sstevel@tonic-gate 	f->flin = 1;
590Sstevel@tonic-gate 	f->feof = FALSE;
600Sstevel@tonic-gate }
610Sstevel@tonic-gate 
62*527Schin int
63*527Schin estabf(unsigned char *s)
640Sstevel@tonic-gate {
65*527Schin 	struct fileblk *f;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	(f = standin)->fdes = -1;
680Sstevel@tonic-gate 	f->fend = length(s) + (f->fnxt = s);
690Sstevel@tonic-gate 	f->nxtoff = 0;
700Sstevel@tonic-gate 	f->endoff = length(s);
710Sstevel@tonic-gate 	f->flin = 1;
720Sstevel@tonic-gate 	return (f->feof = (s == 0));
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
75*527Schin void
76*527Schin push(struct fileblk *af)
770Sstevel@tonic-gate {
78*527Schin 	struct fileblk *f;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	(f = af)->fstak = standin;
810Sstevel@tonic-gate 	f->feof = 0;
820Sstevel@tonic-gate 	f->feval = 0;
830Sstevel@tonic-gate 	standin = f;
840Sstevel@tonic-gate }
850Sstevel@tonic-gate 
86*527Schin int
87*527Schin pop(void)
880Sstevel@tonic-gate {
89*527Schin 	struct fileblk *f;
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	if ((f = standin)->fstak)
920Sstevel@tonic-gate 	{
930Sstevel@tonic-gate 		if (f->fdes >= 0)
940Sstevel@tonic-gate 			close(f->fdes);
950Sstevel@tonic-gate 		standin = f->fstak;
960Sstevel@tonic-gate 		return (TRUE);
970Sstevel@tonic-gate 	}else
980Sstevel@tonic-gate 		return (FALSE);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate struct tempblk *tmpfptr;
1020Sstevel@tonic-gate 
103*527Schin void
104*527Schin pushtemp(int fd, struct tempblk *tb)
1050Sstevel@tonic-gate {
1060Sstevel@tonic-gate 	tb->fdes = fd;
1070Sstevel@tonic-gate 	tb->fstak = tmpfptr;
1080Sstevel@tonic-gate 	tmpfptr = tb;
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate 
111*527Schin int
112*527Schin poptemp(void)
1130Sstevel@tonic-gate {
1140Sstevel@tonic-gate 	if (tmpfptr){
1150Sstevel@tonic-gate 		close(tmpfptr->fdes);
1160Sstevel@tonic-gate 		tmpfptr = tmpfptr->fstak;
1170Sstevel@tonic-gate 		return (TRUE);
1180Sstevel@tonic-gate 	}else
1190Sstevel@tonic-gate 		return (FALSE);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
122*527Schin void
123*527Schin chkpipe(int *pv)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate 	if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0)
1260Sstevel@tonic-gate 		error(piperr);
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate 
129*527Schin int
130*527Schin chkopen(unsigned char *idf, int mode)
1310Sstevel@tonic-gate {
132*527Schin 	int	rc;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	if ((rc = open((char *)idf, mode, 0666)) < 0)
1350Sstevel@tonic-gate 		failed(idf, badopen);
1360Sstevel@tonic-gate 	else
1370Sstevel@tonic-gate 		return (rc);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate /*
1410Sstevel@tonic-gate  * Make f2 be a synonym (including the close-on-exec flag) for f1, which is
1420Sstevel@tonic-gate  * then closed.  If f2 is descriptor 0, modify the global ioset variable
1430Sstevel@tonic-gate  * accordingly.
1440Sstevel@tonic-gate  */
145*527Schin void
146*527Schin renamef(int f1, int f2)
1470Sstevel@tonic-gate {
1480Sstevel@tonic-gate #ifdef RES
1490Sstevel@tonic-gate 	if (f1 != f2)
1500Sstevel@tonic-gate 	{
1510Sstevel@tonic-gate 		dup(f1 | DUPFLG, f2);
1520Sstevel@tonic-gate 		close(f1);
1530Sstevel@tonic-gate 		if (f2 == 0)
1540Sstevel@tonic-gate 			ioset |= 1;
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate #else
1570Sstevel@tonic-gate 	int	fs;
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	if (f1 != f2)
1600Sstevel@tonic-gate 	{
1610Sstevel@tonic-gate 		fs = fcntl(f2, 1, 0);
1620Sstevel@tonic-gate 		close(f2);
1630Sstevel@tonic-gate 		fcntl(f1, 0, f2);
1640Sstevel@tonic-gate 		close(f1);
1650Sstevel@tonic-gate 		if (fs == 1)
1660Sstevel@tonic-gate 			fcntl(f2, 2, 1);
1670Sstevel@tonic-gate 		if (f2 == 0)
1680Sstevel@tonic-gate 			ioset |= 1;
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate #endif
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate 
173*527Schin int
174*527Schin create(unsigned char *s)
1750Sstevel@tonic-gate {
176*527Schin 	int	rc;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 	if ((rc = creat((char *)s, 0666)) < 0)
1790Sstevel@tonic-gate 		failed(s, badcreate);
1800Sstevel@tonic-gate 	else
1810Sstevel@tonic-gate 		return (rc);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 
185*527Schin int
186*527Schin tmpfil(struct tempblk *tb)
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate 	int fd;
189*527Schin 	int len;
190*527Schin 	size_t size_left = TMPOUTSZ - tmpout_offset;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	/* make sure tmp file does not already exist. */
1930Sstevel@tonic-gate 	do {
194*527Schin 		len = snprintf((char *)&tmpout[tmpout_offset], size_left,
195*527Schin 		    "%u", serial);
196*527Schin 		fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0600);
197*527Schin 		serial++;
198*527Schin 		if ((serial >= UINT_MAX) || (len >= size_left)) {
199*527Schin 			/*
200*527Schin 			 * We've already cycled through all the possible
201*527Schin 			 * numbers or the tmp file name is being
202*527Schin 			 * truncated anyway (although TMPOUTSZ should be
203*527Schin 			 * big enough), so start over.
204*527Schin 			 */
205*527Schin 			serial = 0;
206*527Schin 			break;
207*527Schin 		}
2080Sstevel@tonic-gate 	} while ((fd == -1) && (errno == EEXIST));
2090Sstevel@tonic-gate 	if (fd != -1) {
2100Sstevel@tonic-gate 		pushtemp(fd, tb);
2110Sstevel@tonic-gate 		return (fd);
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate 	else
2140Sstevel@tonic-gate 		failed(tmpout, badcreate);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate /*
2180Sstevel@tonic-gate  * set by trim
2190Sstevel@tonic-gate  */
2200Sstevel@tonic-gate extern BOOL		nosubst;
2210Sstevel@tonic-gate #define			CPYSIZ		512
2220Sstevel@tonic-gate 
223*527Schin void
224*527Schin copy(struct ionod	*ioparg)
2250Sstevel@tonic-gate {
226*527Schin 	unsigned char	*cline;
227*527Schin 	unsigned char	*clinep;
228*527Schin 	struct ionod	*iop;
2290Sstevel@tonic-gate 	unsigned int	c;
2300Sstevel@tonic-gate 	unsigned char	*ends;
2310Sstevel@tonic-gate 	unsigned char	*start;
2320Sstevel@tonic-gate 	int		fd;
2330Sstevel@tonic-gate 	int		i;
2340Sstevel@tonic-gate 	int		stripflg;
2350Sstevel@tonic-gate 	unsigned char	*pc;
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	if (iop = ioparg)
2390Sstevel@tonic-gate 	{
2400Sstevel@tonic-gate 		struct tempblk tb;
2410Sstevel@tonic-gate 		copy(iop->iolst);
2420Sstevel@tonic-gate 		ends = mactrim(iop->ioname);
2430Sstevel@tonic-gate 		stripflg = iop->iofile & IOSTRIP;
2440Sstevel@tonic-gate 		if (nosubst)
2450Sstevel@tonic-gate 			iop->iofile &= ~IODOC;
2460Sstevel@tonic-gate 		fd = tmpfil(&tb);
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 		if (fndef)
2490Sstevel@tonic-gate 			iop->ioname = (char *) make(tmpout);
2500Sstevel@tonic-gate 		else
2510Sstevel@tonic-gate 			iop->ioname = (char *) cpystak(tmpout);
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 		iop->iolst = iotemp;
2540Sstevel@tonic-gate 		iotemp = iop;
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 		cline = clinep = start = locstak();
2570Sstevel@tonic-gate 		if (stripflg)
2580Sstevel@tonic-gate 		{
2590Sstevel@tonic-gate 			iop->iofile &= ~IOSTRIP;
2600Sstevel@tonic-gate 			while (*ends == '\t')
2610Sstevel@tonic-gate 				ends++;
2620Sstevel@tonic-gate 		}
2630Sstevel@tonic-gate 		for (;;)
2640Sstevel@tonic-gate 		{
2650Sstevel@tonic-gate 			chkpr();
2660Sstevel@tonic-gate 			if (nosubst)
2670Sstevel@tonic-gate 			{
2680Sstevel@tonic-gate 				c = readwc();
2690Sstevel@tonic-gate 				if (stripflg)
2700Sstevel@tonic-gate 					while (c == '\t')
2710Sstevel@tonic-gate 						c = readwc();
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 				while (!eolchar(c))
2740Sstevel@tonic-gate 				{
2750Sstevel@tonic-gate 					pc = readw(c);
2760Sstevel@tonic-gate 					while (*pc) {
2770Sstevel@tonic-gate 						if (clinep >= brkend)
2780Sstevel@tonic-gate 							growstak(clinep);
2790Sstevel@tonic-gate 						*clinep++ = *pc++;
2800Sstevel@tonic-gate 					}
2810Sstevel@tonic-gate 					c = readwc();
2820Sstevel@tonic-gate 				}
2830Sstevel@tonic-gate 			}else{
2840Sstevel@tonic-gate 				c = nextwc();
2850Sstevel@tonic-gate 				if (stripflg)
2860Sstevel@tonic-gate 					while (c == '\t')
2870Sstevel@tonic-gate 						c = nextwc();
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 				while (!eolchar(c))
2900Sstevel@tonic-gate 				{
2910Sstevel@tonic-gate 					pc = readw(c);
2920Sstevel@tonic-gate 					while (*pc) {
2930Sstevel@tonic-gate 						if (clinep >= brkend)
2940Sstevel@tonic-gate 							growstak(clinep);
2950Sstevel@tonic-gate 						*clinep++ = *pc++;
2960Sstevel@tonic-gate 					}
2970Sstevel@tonic-gate 					if (c == '\\')
2980Sstevel@tonic-gate 					{
2990Sstevel@tonic-gate 						pc = readw(readwc());
3000Sstevel@tonic-gate 						/* *pc might be NULL */
3010Sstevel@tonic-gate 						if (*pc) {
3020Sstevel@tonic-gate 							while (*pc) {
3030Sstevel@tonic-gate 								if (clinep >= brkend)
3040Sstevel@tonic-gate 									growstak(clinep);
3050Sstevel@tonic-gate 								*clinep++ = *pc++;
3060Sstevel@tonic-gate 							}
3070Sstevel@tonic-gate 						} else {
3080Sstevel@tonic-gate 							if (clinep >= brkend)
3090Sstevel@tonic-gate 								growstak(clinep);
3100Sstevel@tonic-gate 							*clinep++ = *pc;
3110Sstevel@tonic-gate 						}
3120Sstevel@tonic-gate 					}
3130Sstevel@tonic-gate 					c = nextwc();
3140Sstevel@tonic-gate 				}
3150Sstevel@tonic-gate 			}
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 			if (clinep >= brkend)
3180Sstevel@tonic-gate 				growstak(clinep);
3190Sstevel@tonic-gate 			*clinep = 0;
3200Sstevel@tonic-gate 			if (eof || eq(cline, ends))
3210Sstevel@tonic-gate 			{
3220Sstevel@tonic-gate 				if ((i = cline - start) > 0)
3230Sstevel@tonic-gate 					write(fd, start, i);
3240Sstevel@tonic-gate 				break;
3250Sstevel@tonic-gate 			}else{
3260Sstevel@tonic-gate 				if (clinep >= brkend)
3270Sstevel@tonic-gate 					growstak(clinep);
3280Sstevel@tonic-gate 				*clinep++ = NL;
3290Sstevel@tonic-gate 			}
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 			if ((i = clinep - start) < CPYSIZ)
3320Sstevel@tonic-gate 				cline = clinep;
3330Sstevel@tonic-gate 			else
3340Sstevel@tonic-gate 			{
3350Sstevel@tonic-gate 				write(fd, start, i);
3360Sstevel@tonic-gate 				cline = clinep = start;
3370Sstevel@tonic-gate 			}
3380Sstevel@tonic-gate 		}
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 		poptemp();	/*
3410Sstevel@tonic-gate 				 * pushed in tmpfil -- bug fix for problem
3420Sstevel@tonic-gate 				 * deleting in-line scripts
3430Sstevel@tonic-gate 				 */
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate 
347*527Schin void
348*527Schin link_iodocs(struct ionod *i)
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate 	int r;
351*527Schin 	int len;
352*527Schin 	size_t size_left = TMPOUTSZ - tmpout_offset;
3530Sstevel@tonic-gate 
354*527Schin 	while (i) {
3550Sstevel@tonic-gate 		free(i->iolink);
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 		/* make sure tmp file does not already exist. */
3580Sstevel@tonic-gate 		do {
359*527Schin 			len = snprintf((char *)&tmpout[tmpout_offset],
360*527Schin 			    size_left, "%u", serial);
361*527Schin 			serial++;
3620Sstevel@tonic-gate 			r = link(i->ioname, (char *)tmpout);
363*527Schin 			if ((serial >= UINT_MAX) || (len >= size_left)) {
364*527Schin 			/*
365*527Schin 			 * We've already cycled through all the possible
366*527Schin 			 * numbers or the tmp file name is being
367*527Schin 			 * truncated anyway, so start over.
368*527Schin 			 */
369*527Schin 				serial = 0;
370*527Schin 				break;
371*527Schin 			}
3720Sstevel@tonic-gate 		} while (r == -1 && errno == EEXIST);
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 		if (r != -1) {
3750Sstevel@tonic-gate 			i->iolink = (char *)make(tmpout);
3760Sstevel@tonic-gate 			i = i->iolst;
3770Sstevel@tonic-gate 		} else
3780Sstevel@tonic-gate 			failed(tmpout, badcreate);
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	}
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate 
383*527Schin void
384*527Schin swap_iodoc_nm(struct ionod *i)
3850Sstevel@tonic-gate {
3860Sstevel@tonic-gate 	while (i)
3870Sstevel@tonic-gate 	{
3880Sstevel@tonic-gate 		free(i->ioname);
3890Sstevel@tonic-gate 		i->ioname = i->iolink;
3900Sstevel@tonic-gate 		i->iolink = 0;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 		i = i->iolst;
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate 
396*527Schin int
397*527Schin savefd(int fd)
3980Sstevel@tonic-gate {
399*527Schin 	int	f;
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	f = fcntl(fd, F_DUPFD, 10);
4020Sstevel@tonic-gate 	return (f);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate 
405*527Schin void
406*527Schin restore(int last)
4070Sstevel@tonic-gate {
408*527Schin 	int 	i;
409*527Schin 	int	dupfd;
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	for (i = topfd - 1; i >= last; i--)
4120Sstevel@tonic-gate 	{
4130Sstevel@tonic-gate 		if ((dupfd = fdmap[i].dup_fd) > 0)
4140Sstevel@tonic-gate 			renamef(dupfd, fdmap[i].org_fd);
4150Sstevel@tonic-gate 		else
4160Sstevel@tonic-gate 			close(fdmap[i].org_fd);
4170Sstevel@tonic-gate 	}
4180Sstevel@tonic-gate 	topfd = last;
4190Sstevel@tonic-gate }
420