OpenSolaris_b135/cmd/sh/io.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
/*	  All Rights Reserved  	*/

/*
 * UNIX shell
 */

#include	"defs.h"
#include	"dup.h"
#include	<stdio.h>
#include	<fcntl.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<errno.h>

short topfd;

/* ========	input output and file copying ======== */

void
initf(int fd)
{
	struct fileblk *f = standin;

	f->fdes = fd;
	f->fsiz = ((flags & oneflg) == 0 ? BUFFERSIZE : 1);
	f->fnxt = f->fend = f->fbuf;
	f->nxtoff = f->endoff = 0;
	f->feval = 0;
	f->flin = 1;
	f->feof = FALSE;
}

int
estabf(unsigned char *s)
{
	struct fileblk *f;

	(f = standin)->fdes = -1;
	f->fend = length(s) + (f->fnxt = s);
	f->nxtoff = 0;
	f->endoff = length(s);
	f->flin = 1;
	return (f->feof = (s == 0));
}

void
push(struct fileblk *af)
{
	struct fileblk *f;

	(f = af)->fstak = standin;
	f->feof = 0;
	f->feval = 0;
	standin = f;
}

int
pop(void)
{
	struct fileblk *f;

	if ((f = standin)->fstak) {
		if (f->fdes >= 0)
			close(f->fdes);
		standin = f->fstak;
		return (TRUE);
	} else
		return (FALSE);
}

struct tempblk *tmpfptr;

void
pushtemp(int fd, struct tempblk *tb)
{
	tb->fdes = fd;
	tb->fstak = tmpfptr;
	tmpfptr = tb;
}

int
poptemp(void)
{
	if (tmpfptr) {
		close(tmpfptr->fdes);
		tmpfptr = tmpfptr->fstak;
		return (TRUE);
	} else
		return (FALSE);
}

void
chkpipe(int *pv)
{
	if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0)
		error(piperr);
}

int
chkopen(unsigned char *idf, int mode)
{
	int	rc;

	if ((rc = open((char *)idf, mode, 0666)) < 0)
		failed(idf, badopen);
	else
		return (rc);
}

/*
 * Make f2 be a synonym (including the close-on-exec flag) for f1, which is
 * then closed.  If f2 is descriptor 0, modify the global ioset variable
 * accordingly.
 */
void
renamef(int f1, int f2)
{
#ifdef RES
	if (f1 != f2) {
		dup(f1 | DUPFLG, f2);
		close(f1);
		if (f2 == 0)
			ioset |= 1;
	}
#else
	int	fs;

	if (f1 != f2) {
		fs = fcntl(f2, 1, 0);
		close(f2);
		fcntl(f1, 0, f2);
		close(f1);
		if (fs == 1)
			fcntl(f2, 2, 1);
		if (f2 == 0)
			ioset |= 1;
	}
#endif
}

int
create(unsigned char *s)
{
	int	rc;

	if ((rc = creat((char *)s, 0666)) < 0)
		failed(s, badcreate);
	else
		return (rc);
}


int
tmpfil(struct tempblk *tb)
{
	int fd;
	int len;
	size_t size_left = TMPOUTSZ - tmpout_offset;

	/* make sure tmp file does not already exist. */
	do {
		len = snprintf((char *)&tmpout[tmpout_offset], size_left,
		    "%u", serial);
		fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0600);
		serial++;
		if ((serial >= UINT_MAX) || (len >= size_left)) {
			/*
			 * We've already cycled through all the possible
			 * numbers or the tmp file name is being
			 * truncated anyway (although TMPOUTSZ should be
			 * big enough), so start over.
			 */
			serial = 0;
			break;
		}
	} while ((fd == -1) && (errno == EEXIST));
	if (fd != -1) {
		pushtemp(fd, tb);
		return (fd);
	}
	else
		failed(tmpout, badcreate);
}

/*
 * set by trim
 */
extern BOOL		nosubst;
#define			CPYSIZ		512

void
copy(struct ionod	*ioparg)
{
	unsigned char	*cline;
	unsigned char	*clinep;
	struct ionod	*iop;
	unsigned int	c;
	unsigned char	*ends;
	unsigned char	*start;
	int		fd;
	int		i;
	int		stripflg;
	unsigned char	*pc;


	if (iop = ioparg) {
		struct tempblk tb;
		copy(iop->iolst);
		ends = mactrim(iop->ioname);
		stripflg = iop->iofile & IOSTRIP;
		if (nosubst)
			iop->iofile &= ~IODOC_SUBST;
		fd = tmpfil(&tb);

		if (fndef)
			iop->ioname = (char *)make(tmpout);
		else
			iop->ioname = (char *)cpystak(tmpout);

		iop->iolst = iotemp;
		iotemp = iop;

		cline = clinep = start = locstak();
		if (stripflg) {
			iop->iofile &= ~IOSTRIP;
			while (*ends == '\t')
				ends++;
		}
		for (;;) {
			chkpr();
			if (nosubst) {
				c = readwc();
				if (stripflg)
					while (c == '\t')
						c = readwc();

				while (!eolchar(c)) {
					pc = readw(c);
					while (*pc) {
						if (clinep >= brkend)
							growstak(clinep);
						*clinep++ = *pc++;
					}
					c = readwc();
				}
			} else {
				c = nextwc();
				if (stripflg)
					while (c == '\t')
						c = nextwc();

				while (!eolchar(c)) {
					pc = readw(c);
					while (*pc) {
						if (clinep >= brkend)
							growstak(clinep);
						*clinep++ = *pc++;
					}
					if (c == '\\') {
						pc = readw(readwc());
						/* *pc might be NULL */
						/* BEGIN CSTYLED */
						if (*pc) {
							while (*pc) {
								if (clinep >= brkend)
									growstak(clinep);
								*clinep++ = *pc++;
							}
						} else {
							if (clinep >= brkend)
								growstak(clinep);
							*clinep++ = *pc;
						}
						/* END CSTYLED */
					}
					c = nextwc();
				}
			}

			if (clinep >= brkend)
				growstak(clinep);
			*clinep = 0;
			if (eof || eq(cline, ends)) {
				if ((i = cline - start) > 0)
					write(fd, start, i);
				break;
			} else {
				if (clinep >= brkend)
					growstak(clinep);
				*clinep++ = NL;
			}

			if ((i = clinep - start) < CPYSIZ)
				cline = clinep;
			else
			{
				write(fd, start, i);
				cline = clinep = start;
			}
		}

		/*
		 * Pushed in tmpfil -- bug fix for problem
		 * deleting in-line script.
		 */
		poptemp();
	}
}

void
link_iodocs(struct ionod *i)
{
	int r;
	int len;
	size_t size_left = TMPOUTSZ - tmpout_offset;

	while (i) {
		free(i->iolink);

		/* make sure tmp file does not already exist. */
		do {
			len = snprintf((char *)&tmpout[tmpout_offset],
			    size_left, "%u", serial);
			serial++;
			r = link(i->ioname, (char *)tmpout);
			if ((serial >= UINT_MAX) || (len >= size_left)) {
			/*
			 * We've already cycled through all the possible
			 * numbers or the tmp file name is being
			 * truncated anyway, so start over.
			 */
				serial = 0;
				break;
			}
		} while (r == -1 && errno == EEXIST);

		if (r != -1) {
			i->iolink = (char *)make(tmpout);
			i = i->iolst;
		} else
			failed(tmpout, badcreate);

	}
}

void
swap_iodoc_nm(struct ionod *i)
{
	while (i) {
		free(i->ioname);
		i->ioname = i->iolink;
		i->iolink = 0;

		i = i->iolst;
	}
}

int
savefd(int fd)
{
	int	f;

	f = fcntl(fd, F_DUPFD, 10);
	/* this saved fd should not be found in an exec'ed cmd */
	(void) fcntl(f, F_SETFD, FD_CLOEXEC);
	return (f);
}

void
restore(int last)
{
	int 	i;
	int	dupfd;

	for (i = topfd - 1; i >= last; i--) {
		if ((dupfd = fdmap[i].dup_fd) > 0)
			renamef(dupfd, fdmap[i].org_fd);
		else
			close(fdmap[i].org_fd);
	}
	topfd = last;
}