xref: /illumos-gate/usr/src/cmd/sh/io.c (revision 7c478bd9)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright (c) 1996, 2001 by Sun Microsystems, Inc.
28  * All rights reserved.
29  */
30 
31 #ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.10.2.1	*/
32 /*
33  * UNIX shell
34  */
35 
36 #include	"defs.h"
37 #include	"dup.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 initf(fd)
48 int	fd;
49 {
50 	register 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 estabf(s)
62 register unsigned char *s;
63 {
64 	register 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 push(af)
75 struct fileblk *af;
76 {
77 	register struct fileblk *f;
78 
79 	(f = af)->fstak = standin;
80 	f->feof = 0;
81 	f->feval = 0;
82 	standin = f;
83 }
84 
85 pop()
86 {
87 	register struct fileblk *f;
88 
89 	if ((f = standin)->fstak)
90 	{
91 		if (f->fdes >= 0)
92 			close(f->fdes);
93 		standin = f->fstak;
94 		return (TRUE);
95 	}else
96 		return (FALSE);
97 }
98 
99 struct tempblk *tmpfptr;
100 
101 pushtemp(fd, tb)
102 	int fd;
103 	struct tempblk *tb;
104 {
105 	tb->fdes = fd;
106 	tb->fstak = tmpfptr;
107 	tmpfptr = tb;
108 }
109 
110 poptemp()
111 {
112 	if (tmpfptr){
113 		close(tmpfptr->fdes);
114 		tmpfptr = tmpfptr->fstak;
115 		return (TRUE);
116 	}else
117 		return (FALSE);
118 }
119 
120 chkpipe(pv)
121 int	*pv;
122 {
123 	if (pipe(pv) < 0 || pv[INPIPE] < 0 || pv[OTPIPE] < 0)
124 		error(piperr);
125 }
126 
127 chkopen(idf, mode)
128 unsigned char *idf;
129 int mode;
130 {
131 	register 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 renamef(f1, f2)
145 register int	f1, 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 create(s)
173 unsigned char *s;
174 {
175 	register int	rc;
176 
177 	if ((rc = creat((char *)s, 0666)) < 0)
178 		failed(s, badcreate);
179 	else
180 		return (rc);
181 }
182 
183 
184 tmpfil(tb)
185 	struct tempblk *tb;
186 {
187 	int fd;
188 
189 	/* make sure tmp file does not already exist. */
190 	do {
191 		itos(serial++);
192 		movstr(numbuf, tmpname);
193 		fd = open((char *)tmpout, O_RDWR|O_CREAT|O_EXCL, 0666);
194 	} while ((fd == -1) && (errno == EEXIST));
195 	if (fd != -1) {
196 		pushtemp(fd, tb);
197 		return (fd);
198 	}
199 	else
200 		failed(tmpout, badcreate);
201 
202 }
203 
204 /*
205  * set by trim
206  */
207 extern BOOL		nosubst;
208 #define			CPYSIZ		512
209 
210 copy(ioparg)
211 struct ionod	*ioparg;
212 {
213 	register unsigned char	*cline;
214 	register unsigned char	*clinep;
215 	register struct ionod	*iop;
216 	unsigned int	c;
217 	unsigned char	*ends;
218 	unsigned char	*start;
219 	int		fd;
220 	int		i;
221 	int		stripflg;
222 	unsigned char	*pc;
223 
224 
225 	if (iop = ioparg)
226 	{
227 		struct tempblk tb;
228 		copy(iop->iolst);
229 		ends = mactrim(iop->ioname);
230 		stripflg = iop->iofile & IOSTRIP;
231 		if (nosubst)
232 			iop->iofile &= ~IODOC;
233 		fd = tmpfil(&tb);
234 
235 		if (fndef)
236 			iop->ioname = (char *) make(tmpout);
237 		else
238 			iop->ioname = (char *) cpystak(tmpout);
239 
240 		iop->iolst = iotemp;
241 		iotemp = iop;
242 
243 		cline = clinep = start = locstak();
244 		if (stripflg)
245 		{
246 			iop->iofile &= ~IOSTRIP;
247 			while (*ends == '\t')
248 				ends++;
249 		}
250 		for (;;)
251 		{
252 			chkpr();
253 			if (nosubst)
254 			{
255 				c = readwc();
256 				if (stripflg)
257 					while (c == '\t')
258 						c = readwc();
259 
260 				while (!eolchar(c))
261 				{
262 					pc = readw(c);
263 					while (*pc) {
264 						if (clinep >= brkend)
265 							growstak(clinep);
266 						*clinep++ = *pc++;
267 					}
268 					c = readwc();
269 				}
270 			}else{
271 				c = nextwc();
272 				if (stripflg)
273 					while (c == '\t')
274 						c = nextwc();
275 
276 				while (!eolchar(c))
277 				{
278 					pc = readw(c);
279 					while (*pc) {
280 						if (clinep >= brkend)
281 							growstak(clinep);
282 						*clinep++ = *pc++;
283 					}
284 					if (c == '\\')
285 					{
286 						pc = readw(readwc());
287 						/* *pc might be NULL */
288 						if (*pc) {
289 							while (*pc) {
290 								if (clinep >= brkend)
291 									growstak(clinep);
292 								*clinep++ = *pc++;
293 							}
294 						} else {
295 							if (clinep >= brkend)
296 								growstak(clinep);
297 							*clinep++ = *pc;
298 						}
299 					}
300 					c = nextwc();
301 				}
302 			}
303 
304 			if (clinep >= brkend)
305 				growstak(clinep);
306 			*clinep = 0;
307 			if (eof || eq(cline, ends))
308 			{
309 				if ((i = cline - start) > 0)
310 					write(fd, start, i);
311 				break;
312 			}else{
313 				if (clinep >= brkend)
314 					growstak(clinep);
315 				*clinep++ = NL;
316 			}
317 
318 			if ((i = clinep - start) < CPYSIZ)
319 				cline = clinep;
320 			else
321 			{
322 				write(fd, start, i);
323 				cline = clinep = start;
324 			}
325 		}
326 
327 		poptemp();	/*
328 				 * pushed in tmpfil -- bug fix for problem
329 				 * deleting in-line scripts
330 				 */
331 	}
332 }
333 
334 
335 link_iodocs(i)
336 	struct ionod	*i;
337 {
338 	int r;
339 
340 	while (i)
341 	{
342 		free(i->iolink);
343 
344 		/* make sure tmp file does not already exist. */
345 		do {
346 			itos(serial++);
347 			movstr(numbuf, tmpname);
348 			r = link(i->ioname, (char *)tmpout);
349 		} while (r == -1 && errno == EEXIST);
350 
351 		if (r != -1) {
352 			i->iolink = (char *)make(tmpout);
353 			i = i->iolst;
354 		} else
355 			failed(tmpout, badcreate);
356 
357 	}
358 }
359 
360 
361 swap_iodoc_nm(i)
362 	struct ionod	*i;
363 {
364 	while (i)
365 	{
366 		free(i->ioname);
367 		i->ioname = i->iolink;
368 		i->iolink = 0;
369 
370 		i = i->iolst;
371 	}
372 }
373 
374 
375 savefd(fd)
376 	int fd;
377 {
378 	register int	f;
379 
380 	f = fcntl(fd, F_DUPFD, 10);
381 	return (f);
382 }
383 
384 
385 restore(last)
386 	register int	last;
387 {
388 	register int 	i;
389 	register int	dupfd;
390 
391 	for (i = topfd - 1; i >= last; i--)
392 	{
393 		if ((dupfd = fdmap[i].dup_fd) > 0)
394 			renamef(dupfd, fdmap[i].org_fd);
395 		else
396 			close(fdmap[i].org_fd);
397 	}
398 	topfd = last;
399 }
400