Home | History | Annotate | Download | only in sh
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 /*
     31  * UNIX shell
     32  */
     33 
     34 #include	"defs.h"
     35 #include	"dup.h"
     36 #include	<stdio.h>
     37 #include	<fcntl.h>
     38 #include	<sys/types.h>
     39 #include	<sys/stat.h>
     40 #include	<errno.h>
     41 
     42 short topfd;
     43 
     44 /* ========	input output and file copying ======== */
     45 
     46 void
     47 initf(int fd)
     48 {
     49 	struct fileblk *f = standin;
     50 
     51 	f->fdes = fd;
     52 	f->fsiz = ((flags & oneflg) == 0 ? BUFFERSIZE : 1);
     53 	f->fnxt = f->fend = f->fbuf;
     54 	f->nxtoff = f->endoff = 0;
     55 	f->feval = 0;
     56 	f->flin = 1;
     57 	f->feof = FALSE;
     58 }
     59 
     60 int
     61 estabf(unsigned char *s)
     62 {
     63 	struct fileblk *f;
     64 
     65 	(f = standin)->fdes = -1;
     66 	f->fend = length(s) + (f->fnxt = s);
     67 	f->nxtoff = 0;
     68 	f->endoff = length(s);
     69 	f->flin = 1;
     70 	return (f->feof = (s == 0));
     71 }
     72 
     73 void
     74 push(struct fileblk *af)
     75 {
     76 	struct fileblk *f;
     77 
     78 	(f = af)->fstak = standin;
     79 	f->feof = 0;
     80 	f->feval = 0;
     81 	standin = f;
     82 }
     83 
     84 int
     85 pop(void)
     86 {
     87 	struct fileblk *f;
     88 
     89 	if ((f = standin)->fstak) {
     90 		if (f->fdes >= 0)
     91 			close(f->fdes);
     92 		standin = f->fstak;
     93 		return (TRUE);
     94 	} else
     95 		return (FALSE);
     96 }
     97 
     98 struct tempblk *tmpfptr;
     99 
    100 void
    101 pushtemp(int fd, struct tempblk *tb)
    102 {
    103 	tb->fdes = fd;
    104 	tb->fstak = tmpfptr;
    105 	tmpfptr = tb;
    106 }
    107 
    108 int
    109 poptemp(void)
    110 {
    111 	if (tmpfptr) {
    112 		close(tmpfptr->fdes);
    113 		tmpfptr = tmpfptr->fstak;
    114 		return (TRUE);
    115 	} else
    116 		return (FALSE);
    117 }
    118 
    119 void
    120 chkpipe(int *pv)
    121 {
    122 	if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0)
    123 		error(piperr);
    124 }
    125 
    126 int
    127 chkopen(unsigned char *idf, int mode)
    128 {
    129 	int	rc;
    130 
    131 	if ((rc = open((char *)idf, mode, 0666)) < 0)
    132 		failed(idf, badopen);
    133 	else
    134 		return (rc);
    135 }
    136 
    137 /*
    138  * Make f2 be a synonym (including the close-on-exec flag) for f1, which is
    139  * then closed.  If f2 is descriptor 0, modify the global ioset variable
    140  * accordingly.
    141  */
    142 void
    143 renamef(int f1, int f2)
    144 {
    145 #ifdef RES
    146 	if (f1 != f2) {
    147 		dup(f1 | DUPFLG, f2);
    148 		close(f1);
    149 		if (f2 == 0)
    150 			ioset |= 1;
    151 	}
    152 #else
    153 	int	fs;
    154 
    155 	if (f1 != f2) {
    156 		fs = fcntl(f2, 1, 0);
    157 		close(f2);
    158 		fcntl(f1, 0, f2);
    159 		close(f1);
    160 		if (fs == 1)
    161 			fcntl(f2, 2, 1);
    162 		if (f2 == 0)
    163 			ioset |= 1;
    164 	}
    165 #endif
    166 }
    167 
    168 int
    169 create(unsigned char *s)
    170 {
    171 	int	rc;
    172 
    173 	if ((rc = creat((char *)s, 0666)) < 0)
    174 		failed(s, badcreate);
    175 	else
    176 		return (rc);
    177 }
    178 
    179 
    180 int
    181 tmpfil(struct tempblk *tb)
    182 {
    183 	int fd;
    184 	int len;
    185 	size_t size_left = TMPOUTSZ - tmpout_offset;
    186 
    187 	/* make sure tmp file does not already exist. */
    188 	do {
    189 		len = snprintf((char *)&tmpout[tmpout_offset], size_left,
    190 		    "%u", serial);
    191 		fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0600);
    192 		serial++;
    193 		if ((serial >= UINT_MAX) || (len >= size_left)) {
    194 			/*
    195 			 * We've already cycled through all the possible
    196 			 * numbers or the tmp file name is being
    197 			 * truncated anyway (although TMPOUTSZ should be
    198 			 * big enough), so start over.
    199 			 */
    200 			serial = 0;
    201 			break;
    202 		}
    203 	} while ((fd == -1) && (errno == EEXIST));
    204 	if (fd != -1) {
    205 		pushtemp(fd, tb);
    206 		return (fd);
    207 	}
    208 	else
    209 		failed(tmpout, badcreate);
    210 }
    211 
    212 /*
    213  * set by trim
    214  */
    215 extern BOOL		nosubst;
    216 #define			CPYSIZ		512
    217 
    218 void
    219 copy(struct ionod	*ioparg)
    220 {
    221 	unsigned char	*cline;
    222 	unsigned char	*clinep;
    223 	struct ionod	*iop;
    224 	unsigned int	c;
    225 	unsigned char	*ends;
    226 	unsigned char	*start;
    227 	int		fd;
    228 	int		i;
    229 	int		stripflg;
    230 	unsigned char	*pc;
    231 
    232 
    233 	if (iop = ioparg) {
    234 		struct tempblk tb;
    235 		copy(iop->iolst);
    236 		ends = mactrim(iop->ioname);
    237 		stripflg = iop->iofile & IOSTRIP;
    238 		if (nosubst)
    239 			iop->iofile &= ~IODOC_SUBST;
    240 		fd = tmpfil(&tb);
    241 
    242 		if (fndef)
    243 			iop->ioname = (char *)make(tmpout);
    244 		else
    245 			iop->ioname = (char *)cpystak(tmpout);
    246 
    247 		iop->iolst = iotemp;
    248 		iotemp = iop;
    249 
    250 		cline = clinep = start = locstak();
    251 		if (stripflg) {
    252 			iop->iofile &= ~IOSTRIP;
    253 			while (*ends == '\t')
    254 				ends++;
    255 		}
    256 		for (;;) {
    257 			chkpr();
    258 			if (nosubst) {
    259 				c = readwc();
    260 				if (stripflg)
    261 					while (c == '\t')
    262 						c = readwc();
    263 
    264 				while (!eolchar(c)) {
    265 					pc = readw(c);
    266 					while (*pc) {
    267 						if (clinep >= brkend)
    268 							growstak(clinep);
    269 						*clinep++ = *pc++;
    270 					}
    271 					c = readwc();
    272 				}
    273 			} else {
    274 				c = nextwc();
    275 				if (stripflg)
    276 					while (c == '\t')
    277 						c = nextwc();
    278 
    279 				while (!eolchar(c)) {
    280 					pc = readw(c);
    281 					while (*pc) {
    282 						if (clinep >= brkend)
    283 							growstak(clinep);
    284 						*clinep++ = *pc++;
    285 					}
    286 					if (c == '\\') {
    287 						pc = readw(readwc());
    288 						/* *pc might be NULL */
    289 						/* BEGIN CSTYLED */
    290 						if (*pc) {
    291 							while (*pc) {
    292 								if (clinep >= brkend)
    293 									growstak(clinep);
    294 								*clinep++ = *pc++;
    295 							}
    296 						} else {
    297 							if (clinep >= brkend)
    298 								growstak(clinep);
    299 							*clinep++ = *pc;
    300 						}
    301 						/* END CSTYLED */
    302 					}
    303 					c = nextwc();
    304 				}
    305 			}
    306 
    307 			if (clinep >= brkend)
    308 				growstak(clinep);
    309 			*clinep = 0;
    310 			if (eof || eq(cline, ends)) {
    311 				if ((i = cline - start) > 0)
    312 					write(fd, start, i);
    313 				break;
    314 			} else {
    315 				if (clinep >= brkend)
    316 					growstak(clinep);
    317 				*clinep++ = NL;
    318 			}
    319 
    320 			if ((i = clinep - start) < CPYSIZ)
    321 				cline = clinep;
    322 			else
    323 			{
    324 				write(fd, start, i);
    325 				cline = clinep = start;
    326 			}
    327 		}
    328 
    329 		/*
    330 		 * Pushed in tmpfil -- bug fix for problem
    331 		 * deleting in-line script.
    332 		 */
    333 		poptemp();
    334 	}
    335 }
    336 
    337 void
    338 link_iodocs(struct ionod *i)
    339 {
    340 	int r;
    341 	int len;
    342 	size_t size_left = TMPOUTSZ - tmpout_offset;
    343 
    344 	while (i) {
    345 		free(i->iolink);
    346 
    347 		/* make sure tmp file does not already exist. */
    348 		do {
    349 			len = snprintf((char *)&tmpout[tmpout_offset],
    350 			    size_left, "%u", serial);
    351 			serial++;
    352 			r = link(i->ioname, (char *)tmpout);
    353 			if ((serial >= UINT_MAX) || (len >= size_left)) {
    354 			/*
    355 			 * We've already cycled through all the possible
    356 			 * numbers or the tmp file name is being
    357 			 * truncated anyway, so start over.
    358 			 */
    359 				serial = 0;
    360 				break;
    361 			}
    362 		} while (r == -1 && errno == EEXIST);
    363 
    364 		if (r != -1) {
    365 			i->iolink = (char *)make(tmpout);
    366 			i = i->iolst;
    367 		} else
    368 			failed(tmpout, badcreate);
    369 
    370 	}
    371 }
    372 
    373 void
    374 swap_iodoc_nm(struct ionod *i)
    375 {
    376 	while (i) {
    377 		free(i->ioname);
    378 		i->ioname = i->iolink;
    379 		i->iolink = 0;
    380 
    381 		i = i->iolst;
    382 	}
    383 }
    384 
    385 int
    386 savefd(int fd)
    387 {
    388 	int	f;
    389 
    390 	f = fcntl(fd, F_DUPFD, 10);
    391 	/* this saved fd should not be found in an exec'ed cmd */
    392 	(void) fcntl(f, F_SETFD, FD_CLOEXEC);
    393 	return (f);
    394 }
    395 
    396 void
    397 restore(int last)
    398 {
    399 	int 	i;
    400 	int	dupfd;
    401 
    402 	for (i = topfd - 1; i >= last; i--) {
    403 		if ((dupfd = fdmap[i].dup_fd) > 0)
    404 			renamef(dupfd, fdmap[i].org_fd);
    405 		else
    406 			close(fdmap[i].org_fd);
    407 	}
    408 	topfd = last;
    409 }
    410