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