xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/sh/io.c (revision b30d193948be5a7794d7ae3ba0ed9c2f72c88e0f)
1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman 
22*b30d1939SAndy Fiddaman /*
23*b30d1939SAndy Fiddaman  * Input/output file processing
24*b30d1939SAndy Fiddaman  *
25*b30d1939SAndy Fiddaman  *   David Korn
26*b30d1939SAndy Fiddaman  *   AT&T Labs
27*b30d1939SAndy Fiddaman  *
28*b30d1939SAndy Fiddaman  */
29*b30d1939SAndy Fiddaman 
30*b30d1939SAndy Fiddaman #include	"defs.h"
31*b30d1939SAndy Fiddaman #include	<fcin.h>
32*b30d1939SAndy Fiddaman #include	<ls.h>
33*b30d1939SAndy Fiddaman #include	<stdarg.h>
34*b30d1939SAndy Fiddaman #include	<regex.h>
35*b30d1939SAndy Fiddaman #include	"variables.h"
36*b30d1939SAndy Fiddaman #include	"path.h"
37*b30d1939SAndy Fiddaman #include	"io.h"
38*b30d1939SAndy Fiddaman #include	"jobs.h"
39*b30d1939SAndy Fiddaman #include	"shnodes.h"
40*b30d1939SAndy Fiddaman #include	"history.h"
41*b30d1939SAndy Fiddaman #include	"edit.h"
42*b30d1939SAndy Fiddaman #include	"timeout.h"
43*b30d1939SAndy Fiddaman #include	"FEATURE/externs"
44*b30d1939SAndy Fiddaman #include	"FEATURE/dynamic"
45*b30d1939SAndy Fiddaman #include	"FEATURE/poll"
46*b30d1939SAndy Fiddaman 
47*b30d1939SAndy Fiddaman #ifdef	FNDELAY
48*b30d1939SAndy Fiddaman #   ifdef EAGAIN
49*b30d1939SAndy Fiddaman #	if EAGAIN!=EWOULDBLOCK
50*b30d1939SAndy Fiddaman #	    undef EAGAIN
51*b30d1939SAndy Fiddaman #	    define EAGAIN       EWOULDBLOCK
52*b30d1939SAndy Fiddaman #	endif
53*b30d1939SAndy Fiddaman #   else
54*b30d1939SAndy Fiddaman #	define EAGAIN   EWOULDBLOCK
55*b30d1939SAndy Fiddaman #   endif /* EAGAIN */
56*b30d1939SAndy Fiddaman #   ifndef O_NONBLOCK
57*b30d1939SAndy Fiddaman #	define O_NONBLOCK	FNDELAY
58*b30d1939SAndy Fiddaman #   endif /* !O_NONBLOCK */
59*b30d1939SAndy Fiddaman #endif	/* FNDELAY */
60*b30d1939SAndy Fiddaman 
61*b30d1939SAndy Fiddaman #ifndef O_SERVICE
62*b30d1939SAndy Fiddaman #   define O_SERVICE	O_NOCTTY
63*b30d1939SAndy Fiddaman #endif
64*b30d1939SAndy Fiddaman 
65*b30d1939SAndy Fiddaman #ifndef ERROR_PIPE
66*b30d1939SAndy Fiddaman #ifdef ECONNRESET
67*b30d1939SAndy Fiddaman #define ERROR_PIPE(e)	((e)==EPIPE||(e)==ECONNRESET||(e)==EIO)
68*b30d1939SAndy Fiddaman #else
69*b30d1939SAndy Fiddaman #define ERROR_PIPE(e)	((e)==EPIPE||(e)==EIO)
70*b30d1939SAndy Fiddaman #endif
71*b30d1939SAndy Fiddaman #endif
72*b30d1939SAndy Fiddaman 
73*b30d1939SAndy Fiddaman #define RW_ALL	(S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
74*b30d1939SAndy Fiddaman 
75*b30d1939SAndy Fiddaman static void	*timeout;
76*b30d1939SAndy Fiddaman static int	(*fdnotify)(int,int);
77*b30d1939SAndy Fiddaman 
78*b30d1939SAndy Fiddaman #if defined(_lib_socket) && defined(_sys_socket) && defined(_hdr_netinet_in)
79*b30d1939SAndy Fiddaman #   include <sys/socket.h>
80*b30d1939SAndy Fiddaman #   include <netdb.h>
81*b30d1939SAndy Fiddaman #   include <netinet/in.h>
82*b30d1939SAndy Fiddaman #   if !defined(htons) && !_lib_htons
83*b30d1939SAndy Fiddaman #      define htons(x)	(x)
84*b30d1939SAndy Fiddaman #   endif
85*b30d1939SAndy Fiddaman #   if !defined(htonl) && !_lib_htonl
86*b30d1939SAndy Fiddaman #      define htonl(x)	(x)
87*b30d1939SAndy Fiddaman #   endif
88*b30d1939SAndy Fiddaman #   if _pipe_socketpair && !_stream_peek
89*b30d1939SAndy Fiddaman #      ifndef SHUT_RD
90*b30d1939SAndy Fiddaman #         define SHUT_RD         0
91*b30d1939SAndy Fiddaman #      endif
92*b30d1939SAndy Fiddaman #      ifndef SHUT_WR
93*b30d1939SAndy Fiddaman #         define SHUT_WR         1
94*b30d1939SAndy Fiddaman #      endif
95*b30d1939SAndy Fiddaman #      if _socketpair_shutdown_mode
96*b30d1939SAndy Fiddaman #         define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||fchmod((v)[1],S_IWUSR)<0||shutdown((v)[0],SHUT_WR)<0||fchmod((v)[0],S_IRUSR)<0)?(-1):0)
97*b30d1939SAndy Fiddaman #      else
98*b30d1939SAndy Fiddaman #         define pipe(v) ((socketpair(AF_UNIX,SOCK_STREAM,0,v)<0||shutdown((v)[1],SHUT_RD)<0||shutdown((v)[0],SHUT_WR)<0)?(-1):0)
99*b30d1939SAndy Fiddaman #      endif
100*b30d1939SAndy Fiddaman #   endif
101*b30d1939SAndy Fiddaman 
102*b30d1939SAndy Fiddaman #if !_lib_getaddrinfo
103*b30d1939SAndy Fiddaman 
104*b30d1939SAndy Fiddaman #undef	EAI_SYSTEM
105*b30d1939SAndy Fiddaman 
106*b30d1939SAndy Fiddaman #define EAI_SYSTEM		1
107*b30d1939SAndy Fiddaman 
108*b30d1939SAndy Fiddaman #undef	addrinfo
109*b30d1939SAndy Fiddaman #undef	getaddrinfo
110*b30d1939SAndy Fiddaman #undef	freeaddrinfo
111*b30d1939SAndy Fiddaman 
112*b30d1939SAndy Fiddaman #define addrinfo		local_addrinfo
113*b30d1939SAndy Fiddaman #define getaddrinfo		local_getaddrinfo
114*b30d1939SAndy Fiddaman #define freeaddrinfo		local_freeaddrinfo
115*b30d1939SAndy Fiddaman 
116*b30d1939SAndy Fiddaman struct addrinfo
117*b30d1939SAndy Fiddaman {
118*b30d1939SAndy Fiddaman         int			ai_flags;
119*b30d1939SAndy Fiddaman         int			ai_family;
120*b30d1939SAndy Fiddaman         int			ai_socktype;
121*b30d1939SAndy Fiddaman         int			ai_protocol;
122*b30d1939SAndy Fiddaman         socklen_t		ai_addrlen;
123*b30d1939SAndy Fiddaman         struct sockaddr*	ai_addr;
124*b30d1939SAndy Fiddaman         struct addrinfo*	ai_next;
125*b30d1939SAndy Fiddaman };
126*b30d1939SAndy Fiddaman 
127*b30d1939SAndy Fiddaman static int
getaddrinfo(const char * node,const char * service,const struct addrinfo * hint,struct addrinfo ** addr)128*b30d1939SAndy Fiddaman getaddrinfo(const char* node, const char* service, const struct addrinfo* hint, struct addrinfo **addr)
129*b30d1939SAndy Fiddaman {
130*b30d1939SAndy Fiddaman 	unsigned long	    	ip_addr = 0;
131*b30d1939SAndy Fiddaman 	unsigned short	    	ip_port = 0;
132*b30d1939SAndy Fiddaman 	struct addrinfo*	ap;
133*b30d1939SAndy Fiddaman 	struct hostent*		hp;
134*b30d1939SAndy Fiddaman 	struct sockaddr_in*	ip;
135*b30d1939SAndy Fiddaman 	char*			prot;
136*b30d1939SAndy Fiddaman 	long			n;
137*b30d1939SAndy Fiddaman 
138*b30d1939SAndy Fiddaman 	if (!(hp = gethostbyname(node)) || hp->h_addrtype!=AF_INET || hp->h_length>sizeof(struct in_addr))
139*b30d1939SAndy Fiddaman 	{
140*b30d1939SAndy Fiddaman 		errno = EADDRNOTAVAIL;
141*b30d1939SAndy Fiddaman 		return EAI_SYSTEM;
142*b30d1939SAndy Fiddaman 	}
143*b30d1939SAndy Fiddaman 	ip_addr = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr;
144*b30d1939SAndy Fiddaman 	if ((n = strtol(service, &prot, 10)) > 0 && n <= USHRT_MAX && !*prot)
145*b30d1939SAndy Fiddaman 		ip_port = htons((unsigned short)n);
146*b30d1939SAndy Fiddaman 	else
147*b30d1939SAndy Fiddaman 	{
148*b30d1939SAndy Fiddaman 		struct servent*	sp;
149*b30d1939SAndy Fiddaman 		const char*	protocol = 0;
150*b30d1939SAndy Fiddaman 
151*b30d1939SAndy Fiddaman 		if (hint)
152*b30d1939SAndy Fiddaman 			switch (hint->ai_socktype)
153*b30d1939SAndy Fiddaman 			{
154*b30d1939SAndy Fiddaman 			case SOCK_STREAM:
155*b30d1939SAndy Fiddaman 				switch (hint->ai_protocol)
156*b30d1939SAndy Fiddaman 				{
157*b30d1939SAndy Fiddaman 				case 0:
158*b30d1939SAndy Fiddaman 					protocol = "tcp";
159*b30d1939SAndy Fiddaman 					break;
160*b30d1939SAndy Fiddaman #ifdef IPPROTO_SCTP
161*b30d1939SAndy Fiddaman 				case IPPROTO_SCTP:
162*b30d1939SAndy Fiddaman 					protocol = "sctp";
163*b30d1939SAndy Fiddaman 					break;
164*b30d1939SAndy Fiddaman #endif
165*b30d1939SAndy Fiddaman 				}
166*b30d1939SAndy Fiddaman 				break;
167*b30d1939SAndy Fiddaman 			case SOCK_DGRAM:
168*b30d1939SAndy Fiddaman 				protocol = "udp";
169*b30d1939SAndy Fiddaman 				break;
170*b30d1939SAndy Fiddaman 			}
171*b30d1939SAndy Fiddaman 		if (!protocol)
172*b30d1939SAndy Fiddaman 		{
173*b30d1939SAndy Fiddaman 			errno =  EPROTONOSUPPORT;
174*b30d1939SAndy Fiddaman 			return 1;
175*b30d1939SAndy Fiddaman 		}
176*b30d1939SAndy Fiddaman 		if (sp = getservbyname(service, protocol))
177*b30d1939SAndy Fiddaman 			ip_port = sp->s_port;
178*b30d1939SAndy Fiddaman 	}
179*b30d1939SAndy Fiddaman 	if (!ip_port)
180*b30d1939SAndy Fiddaman 	{
181*b30d1939SAndy Fiddaman 		errno = EADDRNOTAVAIL;
182*b30d1939SAndy Fiddaman 		return EAI_SYSTEM;
183*b30d1939SAndy Fiddaman 	}
184*b30d1939SAndy Fiddaman 	if (!(ap = newof(0, struct addrinfo, 1, sizeof(struct sockaddr_in))))
185*b30d1939SAndy Fiddaman 		return EAI_SYSTEM;
186*b30d1939SAndy Fiddaman 	if (hint)
187*b30d1939SAndy Fiddaman 		*ap = *hint;
188*b30d1939SAndy Fiddaman 	ap->ai_family = hp->h_addrtype;
189*b30d1939SAndy Fiddaman 	ap->ai_addrlen 	= sizeof(struct sockaddr_in);
190*b30d1939SAndy Fiddaman 	ap->ai_addr = (struct sockaddr *)(ap+1);
191*b30d1939SAndy Fiddaman 	ip = (struct sockaddr_in *)ap->ai_addr;
192*b30d1939SAndy Fiddaman 	ip->sin_family = AF_INET;
193*b30d1939SAndy Fiddaman 	ip->sin_port = ip_port;
194*b30d1939SAndy Fiddaman 	ip->sin_addr.s_addr = ip_addr;
195*b30d1939SAndy Fiddaman 	*addr = ap;
196*b30d1939SAndy Fiddaman 	return 0;
197*b30d1939SAndy Fiddaman }
198*b30d1939SAndy Fiddaman 
199*b30d1939SAndy Fiddaman static void
freeaddrinfo(struct addrinfo * ap)200*b30d1939SAndy Fiddaman freeaddrinfo(struct addrinfo* ap)
201*b30d1939SAndy Fiddaman {
202*b30d1939SAndy Fiddaman 	if (ap)
203*b30d1939SAndy Fiddaman 		free(ap);
204*b30d1939SAndy Fiddaman }
205*b30d1939SAndy Fiddaman 
206*b30d1939SAndy Fiddaman #endif
207*b30d1939SAndy Fiddaman 
208*b30d1939SAndy Fiddaman /*
209*b30d1939SAndy Fiddaman  * return <protocol>/<host>/<service> fd
210*b30d1939SAndy Fiddaman  * If called with flags==O_NONBLOCK return 1 if protocol is supported
211*b30d1939SAndy Fiddaman  */
212*b30d1939SAndy Fiddaman 
213*b30d1939SAndy Fiddaman typedef int (*Inetintr_f)(struct addrinfo*, void*);
214*b30d1939SAndy Fiddaman 
215*b30d1939SAndy Fiddaman static int
inetopen(const char * path,int flags,Inetintr_f onintr,void * handle)216*b30d1939SAndy Fiddaman inetopen(const char* path, int flags, Inetintr_f onintr, void* handle)
217*b30d1939SAndy Fiddaman {
218*b30d1939SAndy Fiddaman 	register char*		s;
219*b30d1939SAndy Fiddaman 	register char*		t;
220*b30d1939SAndy Fiddaman 	int			fd;
221*b30d1939SAndy Fiddaman 	int			oerrno;
222*b30d1939SAndy Fiddaman 	struct addrinfo		hint;
223*b30d1939SAndy Fiddaman 	struct addrinfo*	addr;
224*b30d1939SAndy Fiddaman 	struct addrinfo*	p;
225*b30d1939SAndy Fiddaman 	int			server = !!(flags&O_SERVICE);
226*b30d1939SAndy Fiddaman 
227*b30d1939SAndy Fiddaman 	memset(&hint, 0, sizeof(hint));
228*b30d1939SAndy Fiddaman 	hint.ai_family = PF_UNSPEC;
229*b30d1939SAndy Fiddaman 	switch (path[0])
230*b30d1939SAndy Fiddaman 	{
231*b30d1939SAndy Fiddaman #ifdef IPPROTO_SCTP
232*b30d1939SAndy Fiddaman 	case 's':
233*b30d1939SAndy Fiddaman 		if (path[1]!='c' || path[2]!='t' || path[3]!='p' || path[4]!='/')
234*b30d1939SAndy Fiddaman 		{
235*b30d1939SAndy Fiddaman 			errno = ENOTDIR;
236*b30d1939SAndy Fiddaman 			return -1;
237*b30d1939SAndy Fiddaman 		}
238*b30d1939SAndy Fiddaman 		hint.ai_socktype = SOCK_STREAM;
239*b30d1939SAndy Fiddaman 		hint.ai_protocol = IPPROTO_SCTP;
240*b30d1939SAndy Fiddaman 		path += 5;
241*b30d1939SAndy Fiddaman 		break;
242*b30d1939SAndy Fiddaman #endif
243*b30d1939SAndy Fiddaman 	case 't':
244*b30d1939SAndy Fiddaman 		if (path[1]!='c' || path[2]!='p' || path[3]!='/')
245*b30d1939SAndy Fiddaman 		{
246*b30d1939SAndy Fiddaman 			errno = ENOTDIR;
247*b30d1939SAndy Fiddaman 			return -1;
248*b30d1939SAndy Fiddaman 		}
249*b30d1939SAndy Fiddaman 		hint.ai_socktype = SOCK_STREAM;
250*b30d1939SAndy Fiddaman 		path += 4;
251*b30d1939SAndy Fiddaman 		break;
252*b30d1939SAndy Fiddaman 	case 'u':
253*b30d1939SAndy Fiddaman 		if (path[1]!='d' || path[2]!='p' || path[3]!='/')
254*b30d1939SAndy Fiddaman 		{
255*b30d1939SAndy Fiddaman 			errno = ENOTDIR;
256*b30d1939SAndy Fiddaman 			return -1;
257*b30d1939SAndy Fiddaman 		}
258*b30d1939SAndy Fiddaman 		hint.ai_socktype = SOCK_DGRAM;
259*b30d1939SAndy Fiddaman 		path += 4;
260*b30d1939SAndy Fiddaman 		break;
261*b30d1939SAndy Fiddaman 	default:
262*b30d1939SAndy Fiddaman 		errno = ENOTDIR;
263*b30d1939SAndy Fiddaman 		return -1;
264*b30d1939SAndy Fiddaman 	}
265*b30d1939SAndy Fiddaman 	if(flags==O_NONBLOCK)
266*b30d1939SAndy Fiddaman 		return 1;
267*b30d1939SAndy Fiddaman 	if (!(s = strdup(path)))
268*b30d1939SAndy Fiddaman 		return -1;
269*b30d1939SAndy Fiddaman 	if (t = strchr(s, '/'))
270*b30d1939SAndy Fiddaman 	{
271*b30d1939SAndy Fiddaman 		*t++ = 0;
272*b30d1939SAndy Fiddaman 		if (streq(s, "local"))
273*b30d1939SAndy Fiddaman 			s = strdup("localhost");
274*b30d1939SAndy Fiddaman 		fd = getaddrinfo(s, t, &hint, &addr);
275*b30d1939SAndy Fiddaman 	}
276*b30d1939SAndy Fiddaman 	else
277*b30d1939SAndy Fiddaman 		fd = -1;
278*b30d1939SAndy Fiddaman 	free(s);
279*b30d1939SAndy Fiddaman 	if (fd)
280*b30d1939SAndy Fiddaman 	{
281*b30d1939SAndy Fiddaman 		if (fd != EAI_SYSTEM)
282*b30d1939SAndy Fiddaman 			errno = ENOTDIR;
283*b30d1939SAndy Fiddaman 		return -1;
284*b30d1939SAndy Fiddaman 	}
285*b30d1939SAndy Fiddaman 	oerrno = errno;
286*b30d1939SAndy Fiddaman 	errno = 0;
287*b30d1939SAndy Fiddaman 	fd = -1;
288*b30d1939SAndy Fiddaman 	for (p = addr; p; p = p->ai_next)
289*b30d1939SAndy Fiddaman 	{
290*b30d1939SAndy Fiddaman 		/*
291*b30d1939SAndy Fiddaman 		 * some api's don't take the hint
292*b30d1939SAndy Fiddaman 		 */
293*b30d1939SAndy Fiddaman 
294*b30d1939SAndy Fiddaman 		if (!p->ai_protocol)
295*b30d1939SAndy Fiddaman 			p->ai_protocol = hint.ai_protocol;
296*b30d1939SAndy Fiddaman 		if (!p->ai_socktype)
297*b30d1939SAndy Fiddaman 			p->ai_socktype = hint.ai_socktype;
298*b30d1939SAndy Fiddaman 		while ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) >= 0)
299*b30d1939SAndy Fiddaman 		{
300*b30d1939SAndy Fiddaman 			if (server && !bind(fd, p->ai_addr, p->ai_addrlen) && !listen(fd, 5) || !server && !connect(fd, p->ai_addr, p->ai_addrlen))
301*b30d1939SAndy Fiddaman 				goto done;
302*b30d1939SAndy Fiddaman 			close(fd);
303*b30d1939SAndy Fiddaman 			fd = -1;
304*b30d1939SAndy Fiddaman 			if (errno != EINTR || !onintr)
305*b30d1939SAndy Fiddaman 				break;
306*b30d1939SAndy Fiddaman 			if ((*onintr)(addr, handle))
307*b30d1939SAndy Fiddaman 				goto done;
308*b30d1939SAndy Fiddaman 		}
309*b30d1939SAndy Fiddaman 	}
310*b30d1939SAndy Fiddaman  done:
311*b30d1939SAndy Fiddaman 	freeaddrinfo(addr);
312*b30d1939SAndy Fiddaman 	if (fd >= 0)
313*b30d1939SAndy Fiddaman 		errno = oerrno;
314*b30d1939SAndy Fiddaman 	return fd;
315*b30d1939SAndy Fiddaman }
316*b30d1939SAndy Fiddaman 
317*b30d1939SAndy Fiddaman #else
318*b30d1939SAndy Fiddaman 
319*b30d1939SAndy Fiddaman #undef	O_SERVICE
320*b30d1939SAndy Fiddaman #undef	SHOPT_COSHELL
321*b30d1939SAndy Fiddaman 
322*b30d1939SAndy Fiddaman #endif
323*b30d1939SAndy Fiddaman 
324*b30d1939SAndy Fiddaman struct fdsave
325*b30d1939SAndy Fiddaman {
326*b30d1939SAndy Fiddaman 	int	orig_fd;	/* original file descriptor */
327*b30d1939SAndy Fiddaman 	int	save_fd;	/* saved file descriptor */
328*b30d1939SAndy Fiddaman 	int	subshell;	/* saved for subshell */
329*b30d1939SAndy Fiddaman 	char	*tname;		/* name used with >; */
330*b30d1939SAndy Fiddaman };
331*b30d1939SAndy Fiddaman 
332*b30d1939SAndy Fiddaman struct Iodisc
333*b30d1939SAndy Fiddaman {
334*b30d1939SAndy Fiddaman 	Sfdisc_t	disc;
335*b30d1939SAndy Fiddaman 	Shell_t		*sh;
336*b30d1939SAndy Fiddaman };
337*b30d1939SAndy Fiddaman 
338*b30d1939SAndy Fiddaman static int  	subexcept(Sfio_t*, int, void*, Sfdisc_t*);
339*b30d1939SAndy Fiddaman static int  	eval_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
340*b30d1939SAndy Fiddaman static int  	slowexcept(Sfio_t*, int, void*, Sfdisc_t*);
341*b30d1939SAndy Fiddaman static int	pipeexcept(Sfio_t*, int, void*, Sfdisc_t*);
342*b30d1939SAndy Fiddaman static ssize_t	piperead(Sfio_t*, void*, size_t, Sfdisc_t*);
343*b30d1939SAndy Fiddaman static ssize_t	slowread(Sfio_t*, void*, size_t, Sfdisc_t*);
344*b30d1939SAndy Fiddaman static ssize_t	subread(Sfio_t*, void*, size_t, Sfdisc_t*);
345*b30d1939SAndy Fiddaman static ssize_t	tee_write(Sfio_t*,const void*,size_t,Sfdisc_t*);
346*b30d1939SAndy Fiddaman static int	io_prompt(Shell_t*,Sfio_t*,int);
347*b30d1939SAndy Fiddaman static int	io_heredoc(Shell_t*,register struct ionod*, const char*, int);
348*b30d1939SAndy Fiddaman static void	sftrack(Sfio_t*,int,void*);
349*b30d1939SAndy Fiddaman static const Sfdisc_t eval_disc = { NULL, NULL, NULL, eval_exceptf, NULL};
350*b30d1939SAndy Fiddaman static Sfdisc_t tee_disc = {NULL,tee_write,NULL,NULL,NULL};
351*b30d1939SAndy Fiddaman static Sfio_t *subopen(Shell_t *,Sfio_t*, off_t, long);
352*b30d1939SAndy Fiddaman static const Sfdisc_t sub_disc = { subread, 0, 0, subexcept, 0 };
353*b30d1939SAndy Fiddaman 
354*b30d1939SAndy Fiddaman struct subfile
355*b30d1939SAndy Fiddaman {
356*b30d1939SAndy Fiddaman 	Sfdisc_t	disc;
357*b30d1939SAndy Fiddaman 	Sfio_t		*oldsp;
358*b30d1939SAndy Fiddaman 	off_t		offset;
359*b30d1939SAndy Fiddaman 	long		size;
360*b30d1939SAndy Fiddaman 	long		left;
361*b30d1939SAndy Fiddaman };
362*b30d1939SAndy Fiddaman 
363*b30d1939SAndy Fiddaman struct Eof
364*b30d1939SAndy Fiddaman {
365*b30d1939SAndy Fiddaman 	Namfun_t	hdr;
366*b30d1939SAndy Fiddaman 	int		fd;
367*b30d1939SAndy Fiddaman };
368*b30d1939SAndy Fiddaman 
nget_cur_eof(register Namval_t * np,Namfun_t * fp)369*b30d1939SAndy Fiddaman static Sfdouble_t nget_cur_eof(register Namval_t* np, Namfun_t *fp)
370*b30d1939SAndy Fiddaman {
371*b30d1939SAndy Fiddaman 	struct Eof *ep = (struct Eof*)fp;
372*b30d1939SAndy Fiddaman 	Sfoff_t end, cur =lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
373*b30d1939SAndy Fiddaman 	if(*np->nvname=='C')
374*b30d1939SAndy Fiddaman 	        return((Sfdouble_t)cur);
375*b30d1939SAndy Fiddaman 	if(cur<0)
376*b30d1939SAndy Fiddaman 		return((Sfdouble_t)-1);
377*b30d1939SAndy Fiddaman 	end =lseek(ep->fd, (Sfoff_t)0, SEEK_END);
378*b30d1939SAndy Fiddaman 	lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
379*b30d1939SAndy Fiddaman         return((Sfdouble_t)end);
380*b30d1939SAndy Fiddaman }
381*b30d1939SAndy Fiddaman 
382*b30d1939SAndy Fiddaman static const Namdisc_t EOF_disc	= { sizeof(struct Eof), 0, 0, nget_cur_eof};
383*b30d1939SAndy Fiddaman 
384*b30d1939SAndy Fiddaman #define	MATCH_BUFF	(64*1024)
385*b30d1939SAndy Fiddaman struct Match
386*b30d1939SAndy Fiddaman {
387*b30d1939SAndy Fiddaman 	Sfoff_t	offset;
388*b30d1939SAndy Fiddaman 	char	*base;
389*b30d1939SAndy Fiddaman };
390*b30d1939SAndy Fiddaman 
matchf(void * handle,char * ptr,size_t size)391*b30d1939SAndy Fiddaman static int matchf(void *handle, char *ptr, size_t size)
392*b30d1939SAndy Fiddaman {
393*b30d1939SAndy Fiddaman 	struct Match *mp = (struct Match*)handle;
394*b30d1939SAndy Fiddaman 	mp->offset += (ptr-mp->base);
395*b30d1939SAndy Fiddaman 	return(1);
396*b30d1939SAndy Fiddaman }
397*b30d1939SAndy Fiddaman 
398*b30d1939SAndy Fiddaman 
399*b30d1939SAndy Fiddaman static struct fdsave	*filemap;
400*b30d1939SAndy Fiddaman static short		filemapsize;
401*b30d1939SAndy Fiddaman 
402*b30d1939SAndy Fiddaman #define PSEUDOFD	(SHRT_MAX)
403*b30d1939SAndy Fiddaman 
404*b30d1939SAndy Fiddaman /* ======== input output and file copying ======== */
405*b30d1939SAndy Fiddaman 
sh_iovalidfd(Shell_t * shp,int fd)406*b30d1939SAndy Fiddaman int  sh_iovalidfd(Shell_t *shp, int fd)
407*b30d1939SAndy Fiddaman {
408*b30d1939SAndy Fiddaman 	Sfio_t		**sftable = shp->sftable;
409*b30d1939SAndy Fiddaman 	int		max,n, **fdptrs = shp->fdptrs;
410*b30d1939SAndy Fiddaman 	unsigned char	*fdstatus = shp->fdstatus;
411*b30d1939SAndy Fiddaman 	if(fd<0)
412*b30d1939SAndy Fiddaman 		return(0);
413*b30d1939SAndy Fiddaman 	if(fd < shp->gd->lim.open_max)
414*b30d1939SAndy Fiddaman 		return(1);
415*b30d1939SAndy Fiddaman 	max = strtol(astconf("OPEN_MAX",NiL,NiL),NiL,0);
416*b30d1939SAndy Fiddaman 	if(fd >= max)
417*b30d1939SAndy Fiddaman 	{
418*b30d1939SAndy Fiddaman 		errno = EBADF;
419*b30d1939SAndy Fiddaman 		return(0);
420*b30d1939SAndy Fiddaman 	}
421*b30d1939SAndy Fiddaman 	n = (fd+16)&~0xf;
422*b30d1939SAndy Fiddaman 	if(n > max)
423*b30d1939SAndy Fiddaman 		n = max;
424*b30d1939SAndy Fiddaman 	max = shp->gd->lim.open_max;
425*b30d1939SAndy Fiddaman 	shp->sftable = (Sfio_t**)calloc((n+1)*(sizeof(int*)+sizeof(Sfio_t*)+1),1);
426*b30d1939SAndy Fiddaman 	if(max)
427*b30d1939SAndy Fiddaman 		memcpy(shp->sftable,sftable,max*sizeof(Sfio_t*));
428*b30d1939SAndy Fiddaman 	shp->fdptrs = (int**)(&shp->sftable[n]);
429*b30d1939SAndy Fiddaman 	if(max)
430*b30d1939SAndy Fiddaman 		memcpy(shp->fdptrs,fdptrs,max*sizeof(int*));
431*b30d1939SAndy Fiddaman 	shp->fdstatus = (unsigned char*)(&shp->fdptrs[n]);
432*b30d1939SAndy Fiddaman 	if(max)
433*b30d1939SAndy Fiddaman 		memcpy(shp->fdstatus,fdstatus,max);
434*b30d1939SAndy Fiddaman 	if(sftable)
435*b30d1939SAndy Fiddaman 		free((void*)sftable);
436*b30d1939SAndy Fiddaman 	shp->gd->lim.open_max = n;
437*b30d1939SAndy Fiddaman 	return(1);
438*b30d1939SAndy Fiddaman }
439*b30d1939SAndy Fiddaman 
sh_inuse(Shell_t * shp,int fd)440*b30d1939SAndy Fiddaman int  sh_inuse(Shell_t *shp, int fd)
441*b30d1939SAndy Fiddaman {
442*b30d1939SAndy Fiddaman 	return(fd < shp->gd->lim.open_max && shp->fdptrs[fd]);
443*b30d1939SAndy Fiddaman }
444*b30d1939SAndy Fiddaman 
sh_ioinit(Shell_t * shp)445*b30d1939SAndy Fiddaman void sh_ioinit(Shell_t *shp)
446*b30d1939SAndy Fiddaman {
447*b30d1939SAndy Fiddaman 	filemapsize = 8;
448*b30d1939SAndy Fiddaman 	filemap = (struct fdsave*)malloc(filemapsize*sizeof(struct fdsave));
449*b30d1939SAndy Fiddaman 	sh_iovalidfd(shp,16);
450*b30d1939SAndy Fiddaman 	shp->sftable[0] = sfstdin;
451*b30d1939SAndy Fiddaman 	shp->sftable[1] = sfstdout;
452*b30d1939SAndy Fiddaman 	shp->sftable[2] = sfstderr;
453*b30d1939SAndy Fiddaman 	sfnotify(sftrack);
454*b30d1939SAndy Fiddaman 	sh_iostream(shp,0);
455*b30d1939SAndy Fiddaman 	sh_iostream(shp,1);
456*b30d1939SAndy Fiddaman 	/* all write steams are in the same pool and share outbuff */
457*b30d1939SAndy Fiddaman 	shp->outpool = sfopen(NIL(Sfio_t*),NIL(char*),"sw");  /* pool identifier */
458*b30d1939SAndy Fiddaman 	shp->outbuff = (char*)malloc(IOBSIZE+4);
459*b30d1939SAndy Fiddaman 	shp->errbuff = (char*)malloc(IOBSIZE/4);
460*b30d1939SAndy Fiddaman 	sfsetbuf(sfstderr,shp->errbuff,IOBSIZE/4);
461*b30d1939SAndy Fiddaman 	sfsetbuf(sfstdout,shp->outbuff,IOBSIZE);
462*b30d1939SAndy Fiddaman 	sfpool(sfstdout,shp->outpool,SF_WRITE);
463*b30d1939SAndy Fiddaman 	sfpool(sfstderr,shp->outpool,SF_WRITE);
464*b30d1939SAndy Fiddaman 	sfset(sfstdout,SF_LINE,0);
465*b30d1939SAndy Fiddaman 	sfset(sfstderr,SF_LINE,0);
466*b30d1939SAndy Fiddaman 	sfset(sfstdin,SF_SHARE|SF_PUBLIC,1);
467*b30d1939SAndy Fiddaman }
468*b30d1939SAndy Fiddaman 
469*b30d1939SAndy Fiddaman /*
470*b30d1939SAndy Fiddaman  *  Handle output stream exceptions
471*b30d1939SAndy Fiddaman  */
outexcept(register Sfio_t * iop,int type,void * data,Sfdisc_t * handle)472*b30d1939SAndy Fiddaman static int outexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
473*b30d1939SAndy Fiddaman {
474*b30d1939SAndy Fiddaman 	Shell_t *shp = ((struct Iodisc*)handle)->sh;
475*b30d1939SAndy Fiddaman 	static int	active = 0;
476*b30d1939SAndy Fiddaman 	if(type==SF_DPOP || type==SF_FINAL)
477*b30d1939SAndy Fiddaman 		free((void*)handle);
478*b30d1939SAndy Fiddaman 	else if(type==SF_WRITE && (*(ssize_t*)data)<0 && sffileno(iop)!=2)
479*b30d1939SAndy Fiddaman 		switch (errno)
480*b30d1939SAndy Fiddaman 		{
481*b30d1939SAndy Fiddaman 		case EINTR:
482*b30d1939SAndy Fiddaman 		case EPIPE:
483*b30d1939SAndy Fiddaman #ifdef ECONNRESET
484*b30d1939SAndy Fiddaman 		case ECONNRESET:
485*b30d1939SAndy Fiddaman #endif
486*b30d1939SAndy Fiddaman #ifdef ESHUTDOWN
487*b30d1939SAndy Fiddaman 		case ESHUTDOWN:
488*b30d1939SAndy Fiddaman #endif
489*b30d1939SAndy Fiddaman 			break;
490*b30d1939SAndy Fiddaman 		default:
491*b30d1939SAndy Fiddaman 			if(!active)
492*b30d1939SAndy Fiddaman 			{
493*b30d1939SAndy Fiddaman 				int mode = ((struct checkpt*)shp->jmplist)->mode;
494*b30d1939SAndy Fiddaman 				int save = errno;
495*b30d1939SAndy Fiddaman 				active = 1;
496*b30d1939SAndy Fiddaman 				((struct checkpt*)shp->jmplist)->mode = 0;
497*b30d1939SAndy Fiddaman 				sfpurge(iop);
498*b30d1939SAndy Fiddaman 				sfpool(iop,NIL(Sfio_t*),SF_WRITE);
499*b30d1939SAndy Fiddaman 				errno = save;
500*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_system(1),e_badwrite,sffileno(iop));
501*b30d1939SAndy Fiddaman 				active = 0;
502*b30d1939SAndy Fiddaman 				((struct checkpt*)shp->jmplist)->mode = mode;
503*b30d1939SAndy Fiddaman 				sh_exit(1);
504*b30d1939SAndy Fiddaman 			}
505*b30d1939SAndy Fiddaman 			return(-1);
506*b30d1939SAndy Fiddaman 		}
507*b30d1939SAndy Fiddaman 	return(0);
508*b30d1939SAndy Fiddaman }
509*b30d1939SAndy Fiddaman 
510*b30d1939SAndy Fiddaman /*
511*b30d1939SAndy Fiddaman  * create or initialize a stream corresponding to descriptor <fd>
512*b30d1939SAndy Fiddaman  * a buffer with room for a sentinal is allocated for a read stream.
513*b30d1939SAndy Fiddaman  * A discipline is inserted when read stream is a tty or a pipe
514*b30d1939SAndy Fiddaman  * For output streams, the buffer is set to sh.output and put into
515*b30d1939SAndy Fiddaman  * the sh.outpool synchronization pool
516*b30d1939SAndy Fiddaman  */
sh_iostream(Shell_t * shp,register int fd)517*b30d1939SAndy Fiddaman Sfio_t *sh_iostream(Shell_t *shp, register int fd)
518*b30d1939SAndy Fiddaman {
519*b30d1939SAndy Fiddaman 	register Sfio_t *iop;
520*b30d1939SAndy Fiddaman 	register int status = sh_iocheckfd(shp,fd);
521*b30d1939SAndy Fiddaman 	register int flags = SF_WRITE;
522*b30d1939SAndy Fiddaman 	char *bp;
523*b30d1939SAndy Fiddaman 	struct Iodisc *dp;
524*b30d1939SAndy Fiddaman 	if(status==IOCLOSE)
525*b30d1939SAndy Fiddaman 	{
526*b30d1939SAndy Fiddaman 		switch(fd)
527*b30d1939SAndy Fiddaman 		{
528*b30d1939SAndy Fiddaman 		    case 0:
529*b30d1939SAndy Fiddaman 			return(sfstdin);
530*b30d1939SAndy Fiddaman 		    case 1:
531*b30d1939SAndy Fiddaman 			return(sfstdout);
532*b30d1939SAndy Fiddaman 		    case 2:
533*b30d1939SAndy Fiddaman 			return(sfstderr);
534*b30d1939SAndy Fiddaman 		}
535*b30d1939SAndy Fiddaman 		return(NIL(Sfio_t*));
536*b30d1939SAndy Fiddaman 	}
537*b30d1939SAndy Fiddaman 	if(status&IOREAD)
538*b30d1939SAndy Fiddaman 	{
539*b30d1939SAndy Fiddaman 		if(!(bp = (char *)malloc(IOBSIZE+1)))
540*b30d1939SAndy Fiddaman 			return(NIL(Sfio_t*));
541*b30d1939SAndy Fiddaman 		flags |= SF_READ;
542*b30d1939SAndy Fiddaman 		if(!(status&IOWRITE))
543*b30d1939SAndy Fiddaman 			flags &= ~SF_WRITE;
544*b30d1939SAndy Fiddaman 	}
545*b30d1939SAndy Fiddaman 	else
546*b30d1939SAndy Fiddaman 		bp = shp->outbuff;
547*b30d1939SAndy Fiddaman 	if(status&IODUP)
548*b30d1939SAndy Fiddaman 		flags |= SF_SHARE|SF_PUBLIC;
549*b30d1939SAndy Fiddaman 	if((iop = shp->sftable[fd]) && sffileno(iop)>=0)
550*b30d1939SAndy Fiddaman 	{
551*b30d1939SAndy Fiddaman 		if(status&IOTTY)
552*b30d1939SAndy Fiddaman 			sfset(iop,SF_LINE|SF_WCWIDTH,1);
553*b30d1939SAndy Fiddaman 		sfsetbuf(iop, bp, IOBSIZE);
554*b30d1939SAndy Fiddaman 	}
555*b30d1939SAndy Fiddaman 	else if(!(iop=sfnew((fd<=2?iop:0),bp,IOBSIZE,fd,flags)))
556*b30d1939SAndy Fiddaman 		return(NIL(Sfio_t*));
557*b30d1939SAndy Fiddaman 	dp = newof(0,struct Iodisc,1,0);
558*b30d1939SAndy Fiddaman 	dp->sh = shp;
559*b30d1939SAndy Fiddaman 	if(status&IOREAD)
560*b30d1939SAndy Fiddaman 	{
561*b30d1939SAndy Fiddaman 		sfset(iop,SF_MALLOC,1);
562*b30d1939SAndy Fiddaman 		if(!(status&IOWRITE))
563*b30d1939SAndy Fiddaman 			sfset(iop,SF_IOCHECK,1);
564*b30d1939SAndy Fiddaman 		dp->disc.exceptf = slowexcept;
565*b30d1939SAndy Fiddaman 		if(status&IOTTY)
566*b30d1939SAndy Fiddaman 			dp->disc.readf = slowread;
567*b30d1939SAndy Fiddaman 		else if(status&IONOSEEK)
568*b30d1939SAndy Fiddaman 		{
569*b30d1939SAndy Fiddaman 			dp->disc.readf = piperead;
570*b30d1939SAndy Fiddaman 			sfset(iop, SF_IOINTR,1);
571*b30d1939SAndy Fiddaman 		}
572*b30d1939SAndy Fiddaman 		else
573*b30d1939SAndy Fiddaman 			dp->disc.readf = 0;
574*b30d1939SAndy Fiddaman 		dp->disc.seekf = 0;
575*b30d1939SAndy Fiddaman 		dp->disc.writef = 0;
576*b30d1939SAndy Fiddaman 	}
577*b30d1939SAndy Fiddaman 	else
578*b30d1939SAndy Fiddaman 	{
579*b30d1939SAndy Fiddaman 		if((status&(IONOSEEK|IOTTY)) == IONOSEEK)
580*b30d1939SAndy Fiddaman 			dp->disc.exceptf = pipeexcept;
581*b30d1939SAndy Fiddaman 		else
582*b30d1939SAndy Fiddaman 			dp->disc.exceptf = outexcept;
583*b30d1939SAndy Fiddaman 		sfpool(iop,shp->outpool,SF_WRITE);
584*b30d1939SAndy Fiddaman 	}
585*b30d1939SAndy Fiddaman 	sfdisc(iop,&dp->disc);
586*b30d1939SAndy Fiddaman 	shp->sftable[fd] = iop;
587*b30d1939SAndy Fiddaman 	return(iop);
588*b30d1939SAndy Fiddaman }
589*b30d1939SAndy Fiddaman 
590*b30d1939SAndy Fiddaman /*
591*b30d1939SAndy Fiddaman  * preserve the file descriptor or stream by moving it
592*b30d1939SAndy Fiddaman  */
io_preserve(Shell_t * shp,register Sfio_t * sp,register int f2)593*b30d1939SAndy Fiddaman static void io_preserve(Shell_t* shp, register Sfio_t *sp, register int f2)
594*b30d1939SAndy Fiddaman {
595*b30d1939SAndy Fiddaman 	register int fd;
596*b30d1939SAndy Fiddaman 	if(sp)
597*b30d1939SAndy Fiddaman 		fd = sfsetfd(sp,10);
598*b30d1939SAndy Fiddaman 	else
599*b30d1939SAndy Fiddaman 		fd = sh_fcntl(f2,F_DUPFD,10);
600*b30d1939SAndy Fiddaman 	if(f2==shp->infd)
601*b30d1939SAndy Fiddaman 		shp->infd = fd;
602*b30d1939SAndy Fiddaman 	if(fd<0)
603*b30d1939SAndy Fiddaman 	{
604*b30d1939SAndy Fiddaman 		shp->toomany = 1;
605*b30d1939SAndy Fiddaman 		((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
606*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_toomany);
607*b30d1939SAndy Fiddaman 	}
608*b30d1939SAndy Fiddaman 
609*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
610*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, f2);
611*b30d1939SAndy Fiddaman 
612*b30d1939SAndy Fiddaman 	if(shp->fdptrs[fd]=shp->fdptrs[f2])
613*b30d1939SAndy Fiddaman 	{
614*b30d1939SAndy Fiddaman 		if(f2==job.fd)
615*b30d1939SAndy Fiddaman 			job.fd=fd;
616*b30d1939SAndy Fiddaman 		*shp->fdptrs[fd] = fd;
617*b30d1939SAndy Fiddaman 		shp->fdptrs[f2] = 0;
618*b30d1939SAndy Fiddaman 	}
619*b30d1939SAndy Fiddaman 	shp->sftable[fd] = sp;
620*b30d1939SAndy Fiddaman 	shp->fdstatus[fd] = shp->fdstatus[f2];
621*b30d1939SAndy Fiddaman 	if(fcntl(f2,F_GETFD,0)&1)
622*b30d1939SAndy Fiddaman 	{
623*b30d1939SAndy Fiddaman 		fcntl(fd,F_SETFD,FD_CLOEXEC);
624*b30d1939SAndy Fiddaman 		shp->fdstatus[fd] |= IOCLEX;
625*b30d1939SAndy Fiddaman 	}
626*b30d1939SAndy Fiddaman 	shp->sftable[f2] = 0;
627*b30d1939SAndy Fiddaman }
628*b30d1939SAndy Fiddaman 
629*b30d1939SAndy Fiddaman /*
630*b30d1939SAndy Fiddaman  * Given a file descriptor <f1>, move it to a file descriptor number <f2>
631*b30d1939SAndy Fiddaman  * If <f2> is needed move it, otherwise it is closed first.
632*b30d1939SAndy Fiddaman  * The original stream <f1> is closed.
633*b30d1939SAndy Fiddaman  *  The new file descriptor <f2> is returned;
634*b30d1939SAndy Fiddaman  */
sh_iorenumber(Shell_t * shp,register int f1,register int f2)635*b30d1939SAndy Fiddaman int sh_iorenumber(Shell_t *shp, register int f1,register int f2)
636*b30d1939SAndy Fiddaman {
637*b30d1939SAndy Fiddaman 	register Sfio_t *sp;
638*b30d1939SAndy Fiddaman 
639*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, f1);
640*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, f2);
641*b30d1939SAndy Fiddaman 
642*b30d1939SAndy Fiddaman 	sp = shp->sftable[f2];
643*b30d1939SAndy Fiddaman 	if(f1!=f2)
644*b30d1939SAndy Fiddaman 	{
645*b30d1939SAndy Fiddaman 		/* see whether file descriptor is in use */
646*b30d1939SAndy Fiddaman 		if(sh_inuse(shp,f2) || (f2>2 && sp))
647*b30d1939SAndy Fiddaman 		{
648*b30d1939SAndy Fiddaman 			if(!(shp->inuse_bits&(1<<f2)))
649*b30d1939SAndy Fiddaman 				io_preserve(shp,sp,f2);
650*b30d1939SAndy Fiddaman 			sp = 0;
651*b30d1939SAndy Fiddaman 		}
652*b30d1939SAndy Fiddaman 		else if(f2==0)
653*b30d1939SAndy Fiddaman 			shp->st.ioset = 1;
654*b30d1939SAndy Fiddaman 		sh_close(f2);
655*b30d1939SAndy Fiddaman 		if(f2<=2 && sp)
656*b30d1939SAndy Fiddaman 		{
657*b30d1939SAndy Fiddaman 			register Sfio_t *spnew = sh_iostream(shp,f1);
658*b30d1939SAndy Fiddaman 			shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
659*b30d1939SAndy Fiddaman 			sfsetfd(spnew,f2);
660*b30d1939SAndy Fiddaman 			sfswap(spnew,sp);
661*b30d1939SAndy Fiddaman 			sfset(sp,SF_SHARE|SF_PUBLIC,1);
662*b30d1939SAndy Fiddaman 		}
663*b30d1939SAndy Fiddaman 		else
664*b30d1939SAndy Fiddaman 		{
665*b30d1939SAndy Fiddaman 			shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
666*b30d1939SAndy Fiddaman 			if((f2 = sh_fcntl(f1,F_DUPFD, f2)) < 0)
667*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_system(1),e_file+4);
668*b30d1939SAndy Fiddaman 			else if(f2 <= 2)
669*b30d1939SAndy Fiddaman 				sh_iostream(shp,f2);
670*b30d1939SAndy Fiddaman 		}
671*b30d1939SAndy Fiddaman 		if(sp)
672*b30d1939SAndy Fiddaman 			shp->sftable[f1] = 0;
673*b30d1939SAndy Fiddaman 		if(shp->fdstatus[f1]!=IOCLOSE)
674*b30d1939SAndy Fiddaman 			sh_close(f1);
675*b30d1939SAndy Fiddaman 	}
676*b30d1939SAndy Fiddaman 	else if(sp)
677*b30d1939SAndy Fiddaman 	{
678*b30d1939SAndy Fiddaman 		sfsetfd(sp,f2);
679*b30d1939SAndy Fiddaman 		if(f2<=2)
680*b30d1939SAndy Fiddaman 			sfset(sp,SF_SHARE|SF_PUBLIC,1);
681*b30d1939SAndy Fiddaman 	}
682*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, f2);
683*b30d1939SAndy Fiddaman 	return(f2);
684*b30d1939SAndy Fiddaman }
685*b30d1939SAndy Fiddaman 
686*b30d1939SAndy Fiddaman /*
687*b30d1939SAndy Fiddaman  * close a file descriptor and update stream table and attributes
688*b30d1939SAndy Fiddaman  */
sh_close(register int fd)689*b30d1939SAndy Fiddaman int sh_close(register int fd)
690*b30d1939SAndy Fiddaman {
691*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
692*b30d1939SAndy Fiddaman 	register Sfio_t *sp;
693*b30d1939SAndy Fiddaman 	register int r = 0;
694*b30d1939SAndy Fiddaman 	if(fd<0)
695*b30d1939SAndy Fiddaman 		return(-1);
696*b30d1939SAndy Fiddaman 
697*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
698*b30d1939SAndy Fiddaman 
699*b30d1939SAndy Fiddaman 	if(!(sp=shp->sftable[fd]) || sfclose(sp) < 0)
700*b30d1939SAndy Fiddaman 	{
701*b30d1939SAndy Fiddaman 		int err=errno;
702*b30d1939SAndy Fiddaman 		if(fdnotify)
703*b30d1939SAndy Fiddaman 			(*fdnotify)(fd,SH_FDCLOSE);
704*b30d1939SAndy Fiddaman 		while((r=close(fd)) < 0 && errno==EINTR)
705*b30d1939SAndy Fiddaman 			errno = err;
706*b30d1939SAndy Fiddaman 	}
707*b30d1939SAndy Fiddaman 	if(fd>2)
708*b30d1939SAndy Fiddaman 		shp->sftable[fd] = 0;
709*b30d1939SAndy Fiddaman 	shp->fdstatus[fd] = IOCLOSE;
710*b30d1939SAndy Fiddaman 	if(shp->fdptrs[fd])
711*b30d1939SAndy Fiddaman 		*shp->fdptrs[fd] = -1;
712*b30d1939SAndy Fiddaman 	shp->fdptrs[fd] = 0;
713*b30d1939SAndy Fiddaman 	if(fd < 10)
714*b30d1939SAndy Fiddaman 		shp->inuse_bits &= ~(1<<fd);
715*b30d1939SAndy Fiddaman 	return(r);
716*b30d1939SAndy Fiddaman }
717*b30d1939SAndy Fiddaman 
718*b30d1939SAndy Fiddaman #ifdef O_SERVICE
719*b30d1939SAndy Fiddaman 
720*b30d1939SAndy Fiddaman static int
onintr(struct addrinfo * addr,void * handle)721*b30d1939SAndy Fiddaman onintr(struct addrinfo* addr, void* handle)
722*b30d1939SAndy Fiddaman {
723*b30d1939SAndy Fiddaman 	Shell_t*	sh = (Shell_t*)handle;
724*b30d1939SAndy Fiddaman 
725*b30d1939SAndy Fiddaman 	if (sh->trapnote&SH_SIGSET)
726*b30d1939SAndy Fiddaman 	{
727*b30d1939SAndy Fiddaman 		freeaddrinfo(addr);
728*b30d1939SAndy Fiddaman 		sh_exit(SH_EXITSIG);
729*b30d1939SAndy Fiddaman 		return -1;
730*b30d1939SAndy Fiddaman 	}
731*b30d1939SAndy Fiddaman 	if (sh->trapnote)
732*b30d1939SAndy Fiddaman 		sh_chktrap(sh);
733*b30d1939SAndy Fiddaman 	return 0;
734*b30d1939SAndy Fiddaman }
735*b30d1939SAndy Fiddaman 
736*b30d1939SAndy Fiddaman #endif
737*b30d1939SAndy Fiddaman 
738*b30d1939SAndy Fiddaman /*
739*b30d1939SAndy Fiddaman  * Mimic open(2) with checks for pseudo /dev/ files.
740*b30d1939SAndy Fiddaman  */
sh_open(register const char * path,int flags,...)741*b30d1939SAndy Fiddaman int sh_open(register const char *path, int flags, ...)
742*b30d1939SAndy Fiddaman {
743*b30d1939SAndy Fiddaman 	Shell_t			*shp = sh_getinterp();
744*b30d1939SAndy Fiddaman 	register int		fd = -1;
745*b30d1939SAndy Fiddaman 	mode_t			mode;
746*b30d1939SAndy Fiddaman 	char			*e;
747*b30d1939SAndy Fiddaman 	va_list			ap;
748*b30d1939SAndy Fiddaman 	va_start(ap, flags);
749*b30d1939SAndy Fiddaman 	mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
750*b30d1939SAndy Fiddaman 	va_end(ap);
751*b30d1939SAndy Fiddaman 	errno = 0;
752*b30d1939SAndy Fiddaman 	if(path==0)
753*b30d1939SAndy Fiddaman 	{
754*b30d1939SAndy Fiddaman 		errno = EFAULT;
755*b30d1939SAndy Fiddaman 		return(-1);
756*b30d1939SAndy Fiddaman 	}
757*b30d1939SAndy Fiddaman 	if(*path==0)
758*b30d1939SAndy Fiddaman 	{
759*b30d1939SAndy Fiddaman 		errno = ENOENT;
760*b30d1939SAndy Fiddaman 		return(-1);
761*b30d1939SAndy Fiddaman 	}
762*b30d1939SAndy Fiddaman 	if (path[0]=='/' && path[1]=='d' && path[2]=='e' && path[3]=='v' && path[4]=='/')
763*b30d1939SAndy Fiddaman 	{
764*b30d1939SAndy Fiddaman 		switch (path[5])
765*b30d1939SAndy Fiddaman 		{
766*b30d1939SAndy Fiddaman 		case 'f':
767*b30d1939SAndy Fiddaman 			if (path[6]=='d' && path[7]=='/')
768*b30d1939SAndy Fiddaman 			{
769*b30d1939SAndy Fiddaman 				if(flags==O_NONBLOCK)
770*b30d1939SAndy Fiddaman 					return(1);
771*b30d1939SAndy Fiddaman 				fd = (int)strtol(path+8, &e, 10);
772*b30d1939SAndy Fiddaman 				if (*e)
773*b30d1939SAndy Fiddaman 					fd = -1;
774*b30d1939SAndy Fiddaman 			}
775*b30d1939SAndy Fiddaman 			break;
776*b30d1939SAndy Fiddaman 		case 's':
777*b30d1939SAndy Fiddaman 			if (path[6]=='t' && path[7]=='d')
778*b30d1939SAndy Fiddaman 				switch (path[8])
779*b30d1939SAndy Fiddaman 				{
780*b30d1939SAndy Fiddaman 				case 'e':
781*b30d1939SAndy Fiddaman 					if (path[9]=='r' && path[10]=='r' && !path[11])
782*b30d1939SAndy Fiddaman 						fd = 2;
783*b30d1939SAndy Fiddaman 					break;
784*b30d1939SAndy Fiddaman 				case 'i':
785*b30d1939SAndy Fiddaman 					if (path[9]=='n' && !path[10])
786*b30d1939SAndy Fiddaman 						fd = 0;
787*b30d1939SAndy Fiddaman 					break;
788*b30d1939SAndy Fiddaman 				case 'o':
789*b30d1939SAndy Fiddaman 					if (path[9]=='u' && path[10]=='t' && !path[11])
790*b30d1939SAndy Fiddaman 						fd = 1;
791*b30d1939SAndy Fiddaman 					break;
792*b30d1939SAndy Fiddaman 				}
793*b30d1939SAndy Fiddaman 		}
794*b30d1939SAndy Fiddaman #ifdef O_SERVICE
795*b30d1939SAndy Fiddaman 		if (fd < 0)
796*b30d1939SAndy Fiddaman 		{
797*b30d1939SAndy Fiddaman 			if ((fd = inetopen(path+5, flags, onintr, shp)) < 0 && errno != ENOTDIR)
798*b30d1939SAndy Fiddaman 				return -1;
799*b30d1939SAndy Fiddaman 			if(flags==O_NONBLOCK)
800*b30d1939SAndy Fiddaman 				return(fd>=0);
801*b30d1939SAndy Fiddaman 			if (fd >= 0)
802*b30d1939SAndy Fiddaman 				goto ok;
803*b30d1939SAndy Fiddaman 		}
804*b30d1939SAndy Fiddaman 		if(flags==O_NONBLOCK)
805*b30d1939SAndy Fiddaman 			return(0);
806*b30d1939SAndy Fiddaman #endif
807*b30d1939SAndy Fiddaman 	}
808*b30d1939SAndy Fiddaman 	if (fd >= 0)
809*b30d1939SAndy Fiddaman 	{
810*b30d1939SAndy Fiddaman 		int nfd= -1;
811*b30d1939SAndy Fiddaman 		if (flags & O_CREAT)
812*b30d1939SAndy Fiddaman 		{
813*b30d1939SAndy Fiddaman 			struct stat st;
814*b30d1939SAndy Fiddaman 			if (stat(path,&st) >=0)
815*b30d1939SAndy Fiddaman 				nfd = open(path,flags,st.st_mode);
816*b30d1939SAndy Fiddaman 		}
817*b30d1939SAndy Fiddaman 		else
818*b30d1939SAndy Fiddaman 			nfd = open(path,flags);
819*b30d1939SAndy Fiddaman 		if(nfd>=0)
820*b30d1939SAndy Fiddaman 		{
821*b30d1939SAndy Fiddaman 			fd = nfd;
822*b30d1939SAndy Fiddaman 			goto ok;
823*b30d1939SAndy Fiddaman 		}
824*b30d1939SAndy Fiddaman 		if((mode=sh_iocheckfd(shp,fd))==IOCLOSE)
825*b30d1939SAndy Fiddaman 			return(-1);
826*b30d1939SAndy Fiddaman 		flags &= O_ACCMODE;
827*b30d1939SAndy Fiddaman 		if(!(mode&IOWRITE) && ((flags==O_WRONLY) || (flags==O_RDWR)))
828*b30d1939SAndy Fiddaman 			return(-1);
829*b30d1939SAndy Fiddaman 		if(!(mode&IOREAD) && ((flags==O_RDONLY) || (flags==O_RDWR)))
830*b30d1939SAndy Fiddaman 			return(-1);
831*b30d1939SAndy Fiddaman 		if((fd=dup(fd))<0)
832*b30d1939SAndy Fiddaman 			return(-1);
833*b30d1939SAndy Fiddaman 	}
834*b30d1939SAndy Fiddaman 	else
835*b30d1939SAndy Fiddaman 	{
836*b30d1939SAndy Fiddaman #if SHOPT_REGRESS
837*b30d1939SAndy Fiddaman 		char	buf[PATH_MAX];
838*b30d1939SAndy Fiddaman 		if(strncmp(path,"/etc/",5)==0)
839*b30d1939SAndy Fiddaman 		{
840*b30d1939SAndy Fiddaman 			sfsprintf(buf, sizeof(buf), "%s%s", sh_regress_etc(path, __LINE__, __FILE__), path+4);
841*b30d1939SAndy Fiddaman 			path = buf;
842*b30d1939SAndy Fiddaman 		}
843*b30d1939SAndy Fiddaman #endif
844*b30d1939SAndy Fiddaman 		while((fd = open(path, flags, mode)) < 0)
845*b30d1939SAndy Fiddaman 			if(errno!=EINTR || shp->trapnote)
846*b30d1939SAndy Fiddaman 				return(-1);
847*b30d1939SAndy Fiddaman  	}
848*b30d1939SAndy Fiddaman  ok:
849*b30d1939SAndy Fiddaman 	flags &= O_ACCMODE;
850*b30d1939SAndy Fiddaman 	if(flags==O_WRONLY)
851*b30d1939SAndy Fiddaman 		mode = IOWRITE;
852*b30d1939SAndy Fiddaman 	else if(flags==O_RDWR)
853*b30d1939SAndy Fiddaman 		mode = (IOREAD|IOWRITE);
854*b30d1939SAndy Fiddaman 	else
855*b30d1939SAndy Fiddaman 		mode = IOREAD;
856*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
857*b30d1939SAndy Fiddaman 	shp->fdstatus[fd] = mode;
858*b30d1939SAndy Fiddaman 	return(fd);
859*b30d1939SAndy Fiddaman }
860*b30d1939SAndy Fiddaman 
861*b30d1939SAndy Fiddaman /*
862*b30d1939SAndy Fiddaman  * Open a file for reading
863*b30d1939SAndy Fiddaman  * On failure, print message.
864*b30d1939SAndy Fiddaman  */
sh_chkopen(register const char * name)865*b30d1939SAndy Fiddaman int sh_chkopen(register const char *name)
866*b30d1939SAndy Fiddaman {
867*b30d1939SAndy Fiddaman 	register int fd = sh_open(name,O_RDONLY,0);
868*b30d1939SAndy Fiddaman 	if(fd < 0)
869*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_open,name);
870*b30d1939SAndy Fiddaman 	return(fd);
871*b30d1939SAndy Fiddaman }
872*b30d1939SAndy Fiddaman 
873*b30d1939SAndy Fiddaman /*
874*b30d1939SAndy Fiddaman  * move open file descriptor to a number > 2
875*b30d1939SAndy Fiddaman  */
sh_iomovefd(register int fdold)876*b30d1939SAndy Fiddaman int sh_iomovefd(register int fdold)
877*b30d1939SAndy Fiddaman {
878*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
879*b30d1939SAndy Fiddaman 	register int fdnew;
880*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fdold);
881*b30d1939SAndy Fiddaman 	if(fdold<0 || fdold>2)
882*b30d1939SAndy Fiddaman 		return(fdold);
883*b30d1939SAndy Fiddaman 	fdnew = sh_iomovefd(dup(fdold));
884*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fdold);
885*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fdnew);
886*b30d1939SAndy Fiddaman 	shp->fdstatus[fdnew] = (shp->fdstatus[fdold]&~IOCLEX);
887*b30d1939SAndy Fiddaman 	close(fdold);
888*b30d1939SAndy Fiddaman 	shp->fdstatus[fdold] = IOCLOSE;
889*b30d1939SAndy Fiddaman 	return(fdnew);
890*b30d1939SAndy Fiddaman }
891*b30d1939SAndy Fiddaman 
892*b30d1939SAndy Fiddaman /*
893*b30d1939SAndy Fiddaman  * create a pipe and print message on failure
894*b30d1939SAndy Fiddaman  */
sh_pipe(register int pv[])895*b30d1939SAndy Fiddaman int	sh_pipe(register int pv[])
896*b30d1939SAndy Fiddaman {
897*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
898*b30d1939SAndy Fiddaman 	int fd[2];
899*b30d1939SAndy Fiddaman 	if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
900*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_pipe);
901*b30d1939SAndy Fiddaman 	pv[0] = sh_iomovefd(pv[0]);
902*b30d1939SAndy Fiddaman 	pv[1] = sh_iomovefd(pv[1]);
903*b30d1939SAndy Fiddaman 	shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
904*b30d1939SAndy Fiddaman 	shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
905*b30d1939SAndy Fiddaman 	sh_subsavefd(pv[0]);
906*b30d1939SAndy Fiddaman 	sh_subsavefd(pv[1]);
907*b30d1939SAndy Fiddaman 	return(0);
908*b30d1939SAndy Fiddaman }
909*b30d1939SAndy Fiddaman 
910*b30d1939SAndy Fiddaman #ifndef pipe
sh_rpipe(register int pv[])911*b30d1939SAndy Fiddaman    int	sh_rpipe(register int pv[])
912*b30d1939SAndy Fiddaman    {
913*b30d1939SAndy Fiddaman    	return sh_pipe(pv);
914*b30d1939SAndy Fiddaman    }
915*b30d1939SAndy Fiddaman #else
916*b30d1939SAndy Fiddaman #  undef pipe
917*b30d1939SAndy Fiddaman    /* create a real pipe when pipe() is socketpair */
sh_rpipe(register int pv[])918*b30d1939SAndy Fiddaman    int	sh_rpipe(register int pv[])
919*b30d1939SAndy Fiddaman    {
920*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
921*b30d1939SAndy Fiddaman 	int fd[2];
922*b30d1939SAndy Fiddaman 	if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
923*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_pipe);
924*b30d1939SAndy Fiddaman 	pv[0] = sh_iomovefd(pv[0]);
925*b30d1939SAndy Fiddaman 	pv[1] = sh_iomovefd(pv[1]);
926*b30d1939SAndy Fiddaman 	shp->fdstatus[pv[0]] = IONOSEEK|IOREAD;
927*b30d1939SAndy Fiddaman 	shp->fdstatus[pv[1]] = IONOSEEK|IOWRITE;
928*b30d1939SAndy Fiddaman 	sh_subsavefd(pv[0]);
929*b30d1939SAndy Fiddaman 	sh_subsavefd(pv[1]);
930*b30d1939SAndy Fiddaman 	return(0);
931*b30d1939SAndy Fiddaman    }
932*b30d1939SAndy Fiddaman #endif
933*b30d1939SAndy Fiddaman 
934*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
sh_coaccept(Shell_t * shp,int * pv,int out)935*b30d1939SAndy Fiddaman     int sh_coaccept(Shell_t *shp,int *pv,int out)
936*b30d1939SAndy Fiddaman     {
937*b30d1939SAndy Fiddaman 	int fd = accept(pv[0],(struct sockaddr*)0,(socklen_t*)0);
938*b30d1939SAndy Fiddaman 	sh_close(pv[0]);
939*b30d1939SAndy Fiddaman 	pv[0] = -1;
940*b30d1939SAndy Fiddaman 	if(fd<0)
941*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_pipe);
942*b30d1939SAndy Fiddaman 	if((pv[out]=sh_fcntl(fd,F_DUPFD,10)) >=10)
943*b30d1939SAndy Fiddaman 		sh_close(fd);
944*b30d1939SAndy Fiddaman 	else
945*b30d1939SAndy Fiddaman 		pv[out] = sh_iomovefd(fd);
946*b30d1939SAndy Fiddaman 
947*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, pv[out]);
948*b30d1939SAndy Fiddaman 
949*b30d1939SAndy Fiddaman 	if(fcntl(pv[out],F_SETFD,FD_CLOEXEC) >=0)
950*b30d1939SAndy Fiddaman 		shp->fdstatus[pv[out]] |= IOCLEX;
951*b30d1939SAndy Fiddaman 	shp->fdstatus[pv[out]] = (out?IOWRITE:IOREAD);
952*b30d1939SAndy Fiddaman 	shp->fdstatus[pv[out]] |= IONOSEEK;
953*b30d1939SAndy Fiddaman 	sh_subsavefd(pv[out]);
954*b30d1939SAndy Fiddaman #if defined(SHUT_RD) && defined(SHUT_WR)
955*b30d1939SAndy Fiddaman 	shutdown(pv[out],out?SHUT_RD:SHUT_WR);
956*b30d1939SAndy Fiddaman #endif
957*b30d1939SAndy Fiddaman 	return(0);
958*b30d1939SAndy Fiddaman     }
959*b30d1939SAndy Fiddaman 
sh_copipe(Shell_t * shp,int * pv,int out)960*b30d1939SAndy Fiddaman     int sh_copipe(Shell_t *shp, int *pv, int out)
961*b30d1939SAndy Fiddaman     {
962*b30d1939SAndy Fiddaman 	int			r,port=20000;
963*b30d1939SAndy Fiddaman 	struct sockaddr_in	sin;
964*b30d1939SAndy Fiddaman 	socklen_t		slen;
965*b30d1939SAndy Fiddaman 	if ((pv[out] = socket (AF_INET, SOCK_STREAM, 0)) < 0)
966*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_pipe);
967*b30d1939SAndy Fiddaman 	do
968*b30d1939SAndy Fiddaman 	{
969*b30d1939SAndy Fiddaman 		sin.sin_family = AF_INET;
970*b30d1939SAndy Fiddaman 		sin.sin_port = htons(++port);
971*b30d1939SAndy Fiddaman 		sin.sin_addr.s_addr = INADDR_ANY;
972*b30d1939SAndy Fiddaman 		slen = sizeof (sin);
973*b30d1939SAndy Fiddaman 	}
974*b30d1939SAndy Fiddaman 	while ((r=bind (pv[out], (struct sockaddr *) &sin, slen)) == -1 && errno==EADDRINUSE);
975*b30d1939SAndy Fiddaman 	if(r<0 ||  listen(pv[out],5) <0)
976*b30d1939SAndy Fiddaman 	{
977*b30d1939SAndy Fiddaman 		close(pv[out]);
978*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_pipe);
979*b30d1939SAndy Fiddaman 	}
980*b30d1939SAndy Fiddaman 	fcntl(pv[out],F_SETFD,FD_CLOEXEC);
981*b30d1939SAndy Fiddaman 
982*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, pv[out]);
983*b30d1939SAndy Fiddaman 
984*b30d1939SAndy Fiddaman 	shp->fdstatus[pv[out]] |= IOCLEX;
985*b30d1939SAndy Fiddaman 	pv[1-out] = -1;
986*b30d1939SAndy Fiddaman 	pv[2] = port;
987*b30d1939SAndy Fiddaman 	return(0);
988*b30d1939SAndy Fiddaman     }
989*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
990*b30d1939SAndy Fiddaman 
pat_seek(void * handle,const char * str,size_t sz)991*b30d1939SAndy Fiddaman static int pat_seek(void *handle, const char *str, size_t sz)
992*b30d1939SAndy Fiddaman {
993*b30d1939SAndy Fiddaman 	char **bp = (char**)handle;
994*b30d1939SAndy Fiddaman 	*bp = (char*)str;
995*b30d1939SAndy Fiddaman 	return(-1);
996*b30d1939SAndy Fiddaman }
997*b30d1939SAndy Fiddaman 
pat_line(const regex_t * rp,const char * buff,register size_t n)998*b30d1939SAndy Fiddaman static int pat_line(const regex_t* rp, const char *buff, register size_t n)
999*b30d1939SAndy Fiddaman {
1000*b30d1939SAndy Fiddaman 	register const char *cp=buff, *sp;
1001*b30d1939SAndy Fiddaman 	while(n>0)
1002*b30d1939SAndy Fiddaman 	{
1003*b30d1939SAndy Fiddaman 		for(sp=cp; n-->0 && *cp++ != '\n';);
1004*b30d1939SAndy Fiddaman 		if(regnexec(rp,sp,cp-sp, 0, (regmatch_t*)0, 0)==0)
1005*b30d1939SAndy Fiddaman 			return(sp-buff);
1006*b30d1939SAndy Fiddaman 	}
1007*b30d1939SAndy Fiddaman 	return(cp-buff);
1008*b30d1939SAndy Fiddaman }
1009*b30d1939SAndy Fiddaman 
io_patseek(Shell_t * shp,regex_t * rp,Sfio_t * sp,int flags)1010*b30d1939SAndy Fiddaman static int io_patseek(Shell_t *shp, regex_t *rp, Sfio_t* sp, int flags)
1011*b30d1939SAndy Fiddaman {
1012*b30d1939SAndy Fiddaman 	char	*cp, *match;
1013*b30d1939SAndy Fiddaman 	int	r, fd, close_exec;
1014*b30d1939SAndy Fiddaman 	int	was_share,s=(PIPE_BUF>SF_BUFSIZE?SF_BUFSIZE:PIPE_BUF);
1015*b30d1939SAndy Fiddaman 	size_t	n,m;
1016*b30d1939SAndy Fiddaman 
1017*b30d1939SAndy Fiddaman 	fd = sffileno(sp);
1018*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
1019*b30d1939SAndy Fiddaman 	close_exec = shp->fdstatus[fd]&IOCLEX;
1020*b30d1939SAndy Fiddaman 	shp->fdstatus[sffileno(sp)] |= IOCLEX;
1021*b30d1939SAndy Fiddaman 	if(fd==0)
1022*b30d1939SAndy Fiddaman 		was_share = sfset(sp,SF_SHARE,1);
1023*b30d1939SAndy Fiddaman 	while((cp=sfreserve(sp, -s, SF_LOCKR)) || (cp=sfreserve(sp,SF_UNBOUND, SF_LOCKR)))
1024*b30d1939SAndy Fiddaman 	{
1025*b30d1939SAndy Fiddaman 		m = n = sfvalue(sp);
1026*b30d1939SAndy Fiddaman 		while(n>0 && cp[n-1]!='\n')
1027*b30d1939SAndy Fiddaman 			n--;
1028*b30d1939SAndy Fiddaman 		if(n)
1029*b30d1939SAndy Fiddaman 			m = n;
1030*b30d1939SAndy Fiddaman 		r = regrexec(rp,cp,m,0,(regmatch_t*)0, 0, '\n', (void*)&match, pat_seek);
1031*b30d1939SAndy Fiddaman 		if(r<0)
1032*b30d1939SAndy Fiddaman 			m = match-cp;
1033*b30d1939SAndy Fiddaman 		else if(r==2)
1034*b30d1939SAndy Fiddaman 		{
1035*b30d1939SAndy Fiddaman 			if((m = pat_line(rp,cp,m)) < n)
1036*b30d1939SAndy Fiddaman 				r = -1;
1037*b30d1939SAndy Fiddaman 		}
1038*b30d1939SAndy Fiddaman 		if(m && (flags&IOCOPY))
1039*b30d1939SAndy Fiddaman 			sfwrite(sfstdout,cp,m);
1040*b30d1939SAndy Fiddaman 		sfread(sp,cp,m);
1041*b30d1939SAndy Fiddaman 		if(r<0)
1042*b30d1939SAndy Fiddaman 			break;
1043*b30d1939SAndy Fiddaman 	}
1044*b30d1939SAndy Fiddaman 	if(!close_exec)
1045*b30d1939SAndy Fiddaman 		shp->fdstatus[sffileno(sp)] &= ~IOCLEX;
1046*b30d1939SAndy Fiddaman 	if(fd==0 && !(was_share&SF_SHARE))
1047*b30d1939SAndy Fiddaman 		sfset(sp, SF_SHARE,0);
1048*b30d1939SAndy Fiddaman 	return(0);
1049*b30d1939SAndy Fiddaman }
1050*b30d1939SAndy Fiddaman 
file_offset(Shell_t * shp,int fn,char * fname)1051*b30d1939SAndy Fiddaman static Sfoff_t	file_offset(Shell_t *shp, int fn, char *fname)
1052*b30d1939SAndy Fiddaman {
1053*b30d1939SAndy Fiddaman 	Sfio_t		*sp;
1054*b30d1939SAndy Fiddaman 	char		*cp;
1055*b30d1939SAndy Fiddaman 	Sfoff_t		off;
1056*b30d1939SAndy Fiddaman 	struct Eof	endf;
1057*b30d1939SAndy Fiddaman 	Namval_t	*mp = nv_open("EOF",shp->var_tree,0);
1058*b30d1939SAndy Fiddaman 	Namval_t	*pp = nv_open("CUR",shp->var_tree,0);
1059*b30d1939SAndy Fiddaman 
1060*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fn);
1061*b30d1939SAndy Fiddaman 
1062*b30d1939SAndy Fiddaman 	sp = shp->sftable[fn];
1063*b30d1939SAndy Fiddaman 
1064*b30d1939SAndy Fiddaman 	memset(&endf,0,sizeof(struct Eof));
1065*b30d1939SAndy Fiddaman 	endf.fd = fn;
1066*b30d1939SAndy Fiddaman 	endf.hdr.disc = &EOF_disc;
1067*b30d1939SAndy Fiddaman 	endf.hdr.nofree = 1;
1068*b30d1939SAndy Fiddaman 	if(mp)
1069*b30d1939SAndy Fiddaman 		nv_stack(mp, &endf.hdr);
1070*b30d1939SAndy Fiddaman 	if(pp)
1071*b30d1939SAndy Fiddaman 		nv_stack(pp, &endf.hdr);
1072*b30d1939SAndy Fiddaman 	if(sp)
1073*b30d1939SAndy Fiddaman 		sfsync(sp);
1074*b30d1939SAndy Fiddaman 	off = sh_strnum(fname, &cp, 0);
1075*b30d1939SAndy Fiddaman 	if(mp)
1076*b30d1939SAndy Fiddaman 		nv_stack(mp, NiL);
1077*b30d1939SAndy Fiddaman 	if(pp)
1078*b30d1939SAndy Fiddaman 		nv_stack(pp, NiL);
1079*b30d1939SAndy Fiddaman 	return(*cp?(Sfoff_t)-1:off);
1080*b30d1939SAndy Fiddaman }
1081*b30d1939SAndy Fiddaman 
1082*b30d1939SAndy Fiddaman /*
1083*b30d1939SAndy Fiddaman  * close a pipe
1084*b30d1939SAndy Fiddaman  */
sh_pclose(register int pv[])1085*b30d1939SAndy Fiddaman void sh_pclose(register int pv[])
1086*b30d1939SAndy Fiddaman {
1087*b30d1939SAndy Fiddaman 	if(pv[0]>=2)
1088*b30d1939SAndy Fiddaman 		sh_close(pv[0]);
1089*b30d1939SAndy Fiddaman 	if(pv[1]>=2)
1090*b30d1939SAndy Fiddaman 		sh_close(pv[1]);
1091*b30d1939SAndy Fiddaman 	pv[0] = pv[1] = -1;
1092*b30d1939SAndy Fiddaman }
1093*b30d1939SAndy Fiddaman 
io_usename(char * name,int * perm,int fno,int mode)1094*b30d1939SAndy Fiddaman static char *io_usename(char *name, int *perm, int fno, int mode)
1095*b30d1939SAndy Fiddaman {
1096*b30d1939SAndy Fiddaman 	struct stat	statb;
1097*b30d1939SAndy Fiddaman 	char		*tname, *sp, *ep, path[PATH_MAX+1];
1098*b30d1939SAndy Fiddaman 	int		fd,r;
1099*b30d1939SAndy Fiddaman 	if(mode==0)
1100*b30d1939SAndy Fiddaman 	{
1101*b30d1939SAndy Fiddaman 		if((fd = sh_open(name,O_RDONLY,0)) >= 0)
1102*b30d1939SAndy Fiddaman 		{
1103*b30d1939SAndy Fiddaman 			r = fstat(fd,&statb);
1104*b30d1939SAndy Fiddaman 			close(fd);
1105*b30d1939SAndy Fiddaman 			if(r)
1106*b30d1939SAndy Fiddaman 				return(0);
1107*b30d1939SAndy Fiddaman 			if(!S_ISREG(statb.st_mode))
1108*b30d1939SAndy Fiddaman 				return(0);
1109*b30d1939SAndy Fiddaman 		 	*perm = statb.st_mode&(RW_ALL|(S_IXUSR|S_IXGRP|S_IXOTH));
1110*b30d1939SAndy Fiddaman 		}
1111*b30d1939SAndy Fiddaman 		else if(fd < 0  && errno!=ENOENT)
1112*b30d1939SAndy Fiddaman 			return(0);
1113*b30d1939SAndy Fiddaman 	}
1114*b30d1939SAndy Fiddaman 	while((fd=readlink(name, path, PATH_MAX)) >0)
1115*b30d1939SAndy Fiddaman 	{
1116*b30d1939SAndy Fiddaman 		name=path;
1117*b30d1939SAndy Fiddaman 		name[fd] = 0;
1118*b30d1939SAndy Fiddaman 	}
1119*b30d1939SAndy Fiddaman 	stakseek(1);
1120*b30d1939SAndy Fiddaman 	stakputs(name);
1121*b30d1939SAndy Fiddaman 	stakputc(0);
1122*b30d1939SAndy Fiddaman 	pathcanon(stakptr(1),PATH_PHYSICAL);
1123*b30d1939SAndy Fiddaman 	sp = ep = stakptr(1);
1124*b30d1939SAndy Fiddaman 	if(ep = strrchr(sp,'/'))
1125*b30d1939SAndy Fiddaman 	{
1126*b30d1939SAndy Fiddaman 		memmove(stakptr(0),sp,++ep-sp);
1127*b30d1939SAndy Fiddaman 		stakseek(ep-sp);
1128*b30d1939SAndy Fiddaman 	}
1129*b30d1939SAndy Fiddaman 	else
1130*b30d1939SAndy Fiddaman 	{
1131*b30d1939SAndy Fiddaman 		ep = sp;
1132*b30d1939SAndy Fiddaman 		stakseek(0);
1133*b30d1939SAndy Fiddaman 	}
1134*b30d1939SAndy Fiddaman 	stakputc('.');
1135*b30d1939SAndy Fiddaman 	sfprintf(stkstd,"%<#d_%d{;.tmp",getpid(),fno);
1136*b30d1939SAndy Fiddaman 	tname = stakfreeze(1);
1137*b30d1939SAndy Fiddaman 	switch(mode)
1138*b30d1939SAndy Fiddaman 	{
1139*b30d1939SAndy Fiddaman 	    case 1:
1140*b30d1939SAndy Fiddaman 		rename(tname,name);
1141*b30d1939SAndy Fiddaman 		break;
1142*b30d1939SAndy Fiddaman 	    default:
1143*b30d1939SAndy Fiddaman 		unlink(tname);
1144*b30d1939SAndy Fiddaman 		break;
1145*b30d1939SAndy Fiddaman 	}
1146*b30d1939SAndy Fiddaman 	return(tname);
1147*b30d1939SAndy Fiddaman }
1148*b30d1939SAndy Fiddaman 
1149*b30d1939SAndy Fiddaman /*
1150*b30d1939SAndy Fiddaman  * I/O redirection
1151*b30d1939SAndy Fiddaman  * flag = 0 if files are to be restored
1152*b30d1939SAndy Fiddaman  * flag = 2 if files are to be closed on exec
1153*b30d1939SAndy Fiddaman  * flag = 3 when called from $( < ...), just open file and return
1154*b30d1939SAndy Fiddaman  * flag = SH_SHOWME for trace only
1155*b30d1939SAndy Fiddaman  */
sh_redirect(Shell_t * shp,struct ionod * iop,int flag)1156*b30d1939SAndy Fiddaman int	sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
1157*b30d1939SAndy Fiddaman {
1158*b30d1939SAndy Fiddaman 	Sfoff_t off;
1159*b30d1939SAndy Fiddaman 	register char *fname;
1160*b30d1939SAndy Fiddaman 	register int 	fd, iof;
1161*b30d1939SAndy Fiddaman 	const char *message = e_open;
1162*b30d1939SAndy Fiddaman 	int o_mode;		/* mode flag for open */
1163*b30d1939SAndy Fiddaman 	static char io_op[7];	/* used for -x trace info */
1164*b30d1939SAndy Fiddaman 	int trunc=0, clexec=0, fn, traceon;
1165*b30d1939SAndy Fiddaman 	int r, indx = shp->topfd, perm= -1;
1166*b30d1939SAndy Fiddaman 	char *tname=0, *after="", *trace = shp->st.trap[SH_DEBUGTRAP];
1167*b30d1939SAndy Fiddaman 	Namval_t *np=0;
1168*b30d1939SAndy Fiddaman 	int isstring = shp->subshell?(sfset(sfstdout,0,0)&SF_STRING):0;
1169*b30d1939SAndy Fiddaman 
1170*b30d1939SAndy Fiddaman 	if(flag==2)
1171*b30d1939SAndy Fiddaman 		clexec = 1;
1172*b30d1939SAndy Fiddaman 	if(iop)
1173*b30d1939SAndy Fiddaman 		traceon = sh_trace(shp,NIL(char**),0);
1174*b30d1939SAndy Fiddaman 	for(;iop;iop=iop->ionxt)
1175*b30d1939SAndy Fiddaman 	{
1176*b30d1939SAndy Fiddaman 		iof=iop->iofile;
1177*b30d1939SAndy Fiddaman 		fn = (iof&IOUFD);
1178*b30d1939SAndy Fiddaman 		if(fn==1 && shp->subshell && !shp->subshare && (flag==2 || isstring))
1179*b30d1939SAndy Fiddaman 			sh_subfork();
1180*b30d1939SAndy Fiddaman 		if(shp->redir0 && fn==0 && !(iof&IOMOV))
1181*b30d1939SAndy Fiddaman 			shp->redir0 = 2;
1182*b30d1939SAndy Fiddaman 		io_op[0] = '0'+(iof&IOUFD);
1183*b30d1939SAndy Fiddaman 		if(iof&IOPUT)
1184*b30d1939SAndy Fiddaman 		{
1185*b30d1939SAndy Fiddaman 			io_op[1] = '>';
1186*b30d1939SAndy Fiddaman 			o_mode = O_WRONLY|O_CREAT;
1187*b30d1939SAndy Fiddaman 		}
1188*b30d1939SAndy Fiddaman 		else
1189*b30d1939SAndy Fiddaman 		{
1190*b30d1939SAndy Fiddaman 			io_op[1] = '<';
1191*b30d1939SAndy Fiddaman 			o_mode = O_RDONLY|O_NONBLOCK;
1192*b30d1939SAndy Fiddaman 		}
1193*b30d1939SAndy Fiddaman 		io_op[2] = 0;
1194*b30d1939SAndy Fiddaman 		io_op[3] = 0;
1195*b30d1939SAndy Fiddaman 		io_op[4] = 0;
1196*b30d1939SAndy Fiddaman 		fname = iop->ioname;
1197*b30d1939SAndy Fiddaman 		if(!(iof&IORAW))
1198*b30d1939SAndy Fiddaman 		{
1199*b30d1939SAndy Fiddaman 			if(iof&IOLSEEK)
1200*b30d1939SAndy Fiddaman 			{
1201*b30d1939SAndy Fiddaman 				struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
1202*b30d1939SAndy Fiddaman 				memset(ap, 0, ARGVAL);
1203*b30d1939SAndy Fiddaman 				ap->argflag = ARG_MAC;
1204*b30d1939SAndy Fiddaman 				strcpy(ap->argval,iop->ioname);
1205*b30d1939SAndy Fiddaman 				fname=sh_macpat(shp,ap,(iof&IOARITH)?ARG_ARITH:ARG_EXP);
1206*b30d1939SAndy Fiddaman 			}
1207*b30d1939SAndy Fiddaman 			else if(iof&IOPROCSUB)
1208*b30d1939SAndy Fiddaman 			{
1209*b30d1939SAndy Fiddaman 				struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
1210*b30d1939SAndy Fiddaman 				memset(ap, 0, ARGVAL);
1211*b30d1939SAndy Fiddaman 				if(iof&IOPUT)
1212*b30d1939SAndy Fiddaman 					ap->argflag = ARG_RAW;
1213*b30d1939SAndy Fiddaman 				else if(shp->subshell)
1214*b30d1939SAndy Fiddaman 					sh_subtmpfile(shp);
1215*b30d1939SAndy Fiddaman 				ap->argchn.ap = (struct argnod*)fname;
1216*b30d1939SAndy Fiddaman 				ap = sh_argprocsub(shp,ap);
1217*b30d1939SAndy Fiddaman 				fname = ap->argval;
1218*b30d1939SAndy Fiddaman 			}
1219*b30d1939SAndy Fiddaman 			else
1220*b30d1939SAndy Fiddaman 				fname=sh_mactrim(shp,fname,(!sh_isoption(SH_NOGLOB)&&sh_isoption(SH_INTERACTIVE))?2:0);
1221*b30d1939SAndy Fiddaman 		}
1222*b30d1939SAndy Fiddaman 		errno=0;
1223*b30d1939SAndy Fiddaman 		np = 0;
1224*b30d1939SAndy Fiddaman #if SHOPT_COSHELL
1225*b30d1939SAndy Fiddaman 		if(shp->inpool)
1226*b30d1939SAndy Fiddaman 		{
1227*b30d1939SAndy Fiddaman 			if(!(iof&(IODOC|IOLSEEK|IOMOV)))
1228*b30d1939SAndy Fiddaman 				sh_coaddfile(shp,fname);
1229*b30d1939SAndy Fiddaman 			continue;
1230*b30d1939SAndy Fiddaman 		}
1231*b30d1939SAndy Fiddaman #endif /* SHOPT_COSHELL */
1232*b30d1939SAndy Fiddaman 		if(iop->iovname)
1233*b30d1939SAndy Fiddaman 		{
1234*b30d1939SAndy Fiddaman 			np = nv_open(iop->iovname,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
1235*b30d1939SAndy Fiddaman 			if(nv_isattr(np,NV_RDONLY))
1236*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
1237*b30d1939SAndy Fiddaman 			io_op[0] = '}';
1238*b30d1939SAndy Fiddaman 			if((iof&IOLSEEK) || ((iof&IOMOV) && *fname=='-'))
1239*b30d1939SAndy Fiddaman 				fn = nv_getnum(np);
1240*b30d1939SAndy Fiddaman 		}
1241*b30d1939SAndy Fiddaman 		if (!VALIDATE_FD(shp, fn))
1242*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_system(1),e_file+4);
1243*b30d1939SAndy Fiddaman 		if(iof&IOLSEEK)
1244*b30d1939SAndy Fiddaman 		{
1245*b30d1939SAndy Fiddaman 			io_op[2] = '#';
1246*b30d1939SAndy Fiddaman 			if(iof&IOARITH)
1247*b30d1939SAndy Fiddaman 			{
1248*b30d1939SAndy Fiddaman 				strcpy(&io_op[3]," ((");
1249*b30d1939SAndy Fiddaman 				after = "))";
1250*b30d1939SAndy Fiddaman 			}
1251*b30d1939SAndy Fiddaman 			else if(iof&IOCOPY)
1252*b30d1939SAndy Fiddaman 				io_op[3] = '#';
1253*b30d1939SAndy Fiddaman 			goto traceit;
1254*b30d1939SAndy Fiddaman 		}
1255*b30d1939SAndy Fiddaman 		if(*fname || (iof&(IODOC|IOSTRG))==(IODOC|IOSTRG))
1256*b30d1939SAndy Fiddaman 		{
1257*b30d1939SAndy Fiddaman 			if(iof&IODOC)
1258*b30d1939SAndy Fiddaman 			{
1259*b30d1939SAndy Fiddaman 				if(traceon)
1260*b30d1939SAndy Fiddaman 					sfputr(sfstderr,io_op,'<');
1261*b30d1939SAndy Fiddaman 				fd = io_heredoc(shp,iop,fname,traceon);
1262*b30d1939SAndy Fiddaman 				if(traceon && (flag==SH_SHOWME))
1263*b30d1939SAndy Fiddaman 					sh_close(fd);
1264*b30d1939SAndy Fiddaman 				fname = 0;
1265*b30d1939SAndy Fiddaman 			}
1266*b30d1939SAndy Fiddaman 			else if(iof&IOMOV)
1267*b30d1939SAndy Fiddaman 			{
1268*b30d1939SAndy Fiddaman 				int dupfd,toclose= -1;
1269*b30d1939SAndy Fiddaman 				io_op[2] = '&';
1270*b30d1939SAndy Fiddaman 				if((fd=fname[0])>='0' && fd<='9')
1271*b30d1939SAndy Fiddaman 				{
1272*b30d1939SAndy Fiddaman 					char *number = fname;
1273*b30d1939SAndy Fiddaman 					dupfd = strtol(fname,&number,10);
1274*b30d1939SAndy Fiddaman 					if(*number=='-')
1275*b30d1939SAndy Fiddaman 					{
1276*b30d1939SAndy Fiddaman 						toclose = dupfd;
1277*b30d1939SAndy Fiddaman 						number++;
1278*b30d1939SAndy Fiddaman 					}
1279*b30d1939SAndy Fiddaman 					if(*number || dupfd > IOUFD)
1280*b30d1939SAndy Fiddaman 					{
1281*b30d1939SAndy Fiddaman 						message = e_file;
1282*b30d1939SAndy Fiddaman 						goto fail;
1283*b30d1939SAndy Fiddaman 					}
1284*b30d1939SAndy Fiddaman 					VALIDATE_FD(shp, dupfd);
1285*b30d1939SAndy Fiddaman 					if(shp->subshell && dupfd==1)
1286*b30d1939SAndy Fiddaman 					{
1287*b30d1939SAndy Fiddaman 						if(sfset(sfstdout,0,0)&SF_STRING)
1288*b30d1939SAndy Fiddaman 							sh_subtmpfile(shp);
1289*b30d1939SAndy Fiddaman 						if(shp->comsub==1)
1290*b30d1939SAndy Fiddaman 							shp->subdup |= 1<<fn;
1291*b30d1939SAndy Fiddaman 						dupfd = sffileno(sfstdout);
1292*b30d1939SAndy Fiddaman 					}
1293*b30d1939SAndy Fiddaman 					else if(shp->sftable[dupfd])
1294*b30d1939SAndy Fiddaman 						sfsync(shp->sftable[dupfd]);
1295*b30d1939SAndy Fiddaman 					if(dupfd!=1 && fn < 10)
1296*b30d1939SAndy Fiddaman 						shp->subdup &= ~(1<<fn);
1297*b30d1939SAndy Fiddaman 				}
1298*b30d1939SAndy Fiddaman 				else if(fd=='-' && fname[1]==0)
1299*b30d1939SAndy Fiddaman 				{
1300*b30d1939SAndy Fiddaman 					fd= -1;
1301*b30d1939SAndy Fiddaman 					goto traceit;
1302*b30d1939SAndy Fiddaman 				}
1303*b30d1939SAndy Fiddaman 				else if(fd=='p' && fname[1]==0)
1304*b30d1939SAndy Fiddaman 				{
1305*b30d1939SAndy Fiddaman 					if(iof&IOPUT)
1306*b30d1939SAndy Fiddaman 						dupfd = shp->coutpipe;
1307*b30d1939SAndy Fiddaman 					else
1308*b30d1939SAndy Fiddaman 						dupfd = shp->cpipe[0];
1309*b30d1939SAndy Fiddaman 					if(flag)
1310*b30d1939SAndy Fiddaman 						toclose = dupfd;
1311*b30d1939SAndy Fiddaman 				}
1312*b30d1939SAndy Fiddaman 				else
1313*b30d1939SAndy Fiddaman 				{
1314*b30d1939SAndy Fiddaman 					message = e_file;
1315*b30d1939SAndy Fiddaman 					goto fail;
1316*b30d1939SAndy Fiddaman 				}
1317*b30d1939SAndy Fiddaman 				if(flag==SH_SHOWME)
1318*b30d1939SAndy Fiddaman 					goto traceit;
1319*b30d1939SAndy Fiddaman 				if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
1320*b30d1939SAndy Fiddaman 					goto fail;
1321*b30d1939SAndy Fiddaman 				VALIDATE_FD(shp, fd);
1322*b30d1939SAndy Fiddaman 				sh_iocheckfd(shp,dupfd);
1323*b30d1939SAndy Fiddaman 				shp->fdstatus[fd] = (shp->fdstatus[dupfd]&~IOCLEX);
1324*b30d1939SAndy Fiddaman 				if(toclose<0 && shp->fdstatus[fd]&IOREAD)
1325*b30d1939SAndy Fiddaman 					shp->fdstatus[fd] |= IODUP;
1326*b30d1939SAndy Fiddaman 				else if(dupfd==shp->cpipe[0])
1327*b30d1939SAndy Fiddaman 					sh_pclose(shp->cpipe);
1328*b30d1939SAndy Fiddaman 				else if(toclose>=0)
1329*b30d1939SAndy Fiddaman 				{
1330*b30d1939SAndy Fiddaman 					if(flag==0)
1331*b30d1939SAndy Fiddaman 						sh_iosave(shp,toclose,indx,(char*)0); /* save file descriptor */
1332*b30d1939SAndy Fiddaman 					sh_close(toclose);
1333*b30d1939SAndy Fiddaman 				}
1334*b30d1939SAndy Fiddaman 			}
1335*b30d1939SAndy Fiddaman 			else if(iof&IORDW)
1336*b30d1939SAndy Fiddaman 			{
1337*b30d1939SAndy Fiddaman 				if(sh_isoption(SH_RESTRICTED))
1338*b30d1939SAndy Fiddaman 					errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1339*b30d1939SAndy Fiddaman 				io_op[2] = '>';
1340*b30d1939SAndy Fiddaman 				o_mode = O_RDWR|O_CREAT;
1341*b30d1939SAndy Fiddaman 				if(iof&IOREWRITE)
1342*b30d1939SAndy Fiddaman 					trunc = io_op[2] = ';';
1343*b30d1939SAndy Fiddaman 				goto openit;
1344*b30d1939SAndy Fiddaman 			}
1345*b30d1939SAndy Fiddaman 			else if(!(iof&IOPUT))
1346*b30d1939SAndy Fiddaman 			{
1347*b30d1939SAndy Fiddaman 				if(flag==SH_SHOWME)
1348*b30d1939SAndy Fiddaman 					goto traceit;
1349*b30d1939SAndy Fiddaman 				fd=sh_chkopen(fname);
1350*b30d1939SAndy Fiddaman 			}
1351*b30d1939SAndy Fiddaman 			else if(sh_isoption(SH_RESTRICTED))
1352*b30d1939SAndy Fiddaman 				errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1353*b30d1939SAndy Fiddaman 			else
1354*b30d1939SAndy Fiddaman 			{
1355*b30d1939SAndy Fiddaman 				if(iof&IOAPP)
1356*b30d1939SAndy Fiddaman 				{
1357*b30d1939SAndy Fiddaman 					io_op[2] = '>';
1358*b30d1939SAndy Fiddaman 					o_mode |= O_APPEND;
1359*b30d1939SAndy Fiddaman 				}
1360*b30d1939SAndy Fiddaman 				else if((iof&IOREWRITE) && (flag==0 || flag==1 || sh_subsavefd(fn)))
1361*b30d1939SAndy Fiddaman 				{
1362*b30d1939SAndy Fiddaman 					io_op[2] = ';';
1363*b30d1939SAndy Fiddaman 					o_mode |= O_TRUNC;
1364*b30d1939SAndy Fiddaman 					if(tname = io_usename(fname,&perm,fn,0))
1365*b30d1939SAndy Fiddaman 						o_mode |= O_EXCL;
1366*b30d1939SAndy Fiddaman 				}
1367*b30d1939SAndy Fiddaman 				else
1368*b30d1939SAndy Fiddaman 				{
1369*b30d1939SAndy Fiddaman 					o_mode |= O_TRUNC;
1370*b30d1939SAndy Fiddaman 					if(iof&IOCLOB)
1371*b30d1939SAndy Fiddaman 						io_op[2] = '|';
1372*b30d1939SAndy Fiddaman 					else if(sh_isoption(SH_NOCLOBBER))
1373*b30d1939SAndy Fiddaman 					{
1374*b30d1939SAndy Fiddaman 						struct stat sb;
1375*b30d1939SAndy Fiddaman 						if(stat(fname,&sb)>=0)
1376*b30d1939SAndy Fiddaman 						{
1377*b30d1939SAndy Fiddaman #if SHOPT_FS_3D
1378*b30d1939SAndy Fiddaman 							if(S_ISREG(sb.st_mode)&&
1379*b30d1939SAndy Fiddaman 						                (!shp->gd->lim.fs3d || iview(&sb)==0))
1380*b30d1939SAndy Fiddaman #else
1381*b30d1939SAndy Fiddaman 							if(S_ISREG(sb.st_mode))
1382*b30d1939SAndy Fiddaman #endif /* SHOPT_FS_3D */
1383*b30d1939SAndy Fiddaman 							{
1384*b30d1939SAndy Fiddaman 								errno = EEXIST;
1385*b30d1939SAndy Fiddaman 								errormsg(SH_DICT,ERROR_system(1),e_exists,fname);
1386*b30d1939SAndy Fiddaman 							}
1387*b30d1939SAndy Fiddaman 						}
1388*b30d1939SAndy Fiddaman 						else
1389*b30d1939SAndy Fiddaman 							o_mode |= O_EXCL;
1390*b30d1939SAndy Fiddaman 					}
1391*b30d1939SAndy Fiddaman 				}
1392*b30d1939SAndy Fiddaman 			openit:
1393*b30d1939SAndy Fiddaman 				if(flag!=SH_SHOWME)
1394*b30d1939SAndy Fiddaman 				{
1395*b30d1939SAndy Fiddaman 					if((fd=sh_open(tname?tname:fname,o_mode,RW_ALL)) <0)
1396*b30d1939SAndy Fiddaman 						errormsg(SH_DICT,ERROR_system(1),((o_mode&O_CREAT)?e_create:e_open),fname);
1397*b30d1939SAndy Fiddaman 					if(perm>0)
1398*b30d1939SAndy Fiddaman #if _lib_fchmod
1399*b30d1939SAndy Fiddaman 						fchmod(fd,perm);
1400*b30d1939SAndy Fiddaman #else
1401*b30d1939SAndy Fiddaman 						chmod(tname,perm);
1402*b30d1939SAndy Fiddaman #endif
1403*b30d1939SAndy Fiddaman 				}
1404*b30d1939SAndy Fiddaman 			}
1405*b30d1939SAndy Fiddaman 		traceit:
1406*b30d1939SAndy Fiddaman 			if(traceon && fname)
1407*b30d1939SAndy Fiddaman 			{
1408*b30d1939SAndy Fiddaman 				if(np)
1409*b30d1939SAndy Fiddaman 					sfprintf(sfstderr,"{%s",nv_name(np));
1410*b30d1939SAndy Fiddaman 				sfprintf(sfstderr,"%s %s%s%c",io_op,fname,after,iop->ionxt?' ':'\n');
1411*b30d1939SAndy Fiddaman 			}
1412*b30d1939SAndy Fiddaman 			if(flag==SH_SHOWME)
1413*b30d1939SAndy Fiddaman 				return(indx);
1414*b30d1939SAndy Fiddaman 			if(trace && fname)
1415*b30d1939SAndy Fiddaman 			{
1416*b30d1939SAndy Fiddaman 				char *argv[7], **av=argv;
1417*b30d1939SAndy Fiddaman 				av[3] = io_op;
1418*b30d1939SAndy Fiddaman 				av[4] = fname;
1419*b30d1939SAndy Fiddaman 				av[5] = 0;
1420*b30d1939SAndy Fiddaman 				av[6] = 0;
1421*b30d1939SAndy Fiddaman 				if(iof&IOARITH)
1422*b30d1939SAndy Fiddaman 					av[5] = after;
1423*b30d1939SAndy Fiddaman 				if(np)
1424*b30d1939SAndy Fiddaman 				{
1425*b30d1939SAndy Fiddaman 					av[0] = "{";
1426*b30d1939SAndy Fiddaman 					av[1] = nv_name(np);
1427*b30d1939SAndy Fiddaman 					av[2] = "}";
1428*b30d1939SAndy Fiddaman 				}
1429*b30d1939SAndy Fiddaman 				else
1430*b30d1939SAndy Fiddaman 					av +=3;
1431*b30d1939SAndy Fiddaman 				sh_debug(shp,trace,(char*)0,(char*)0,av,ARG_NOGLOB);
1432*b30d1939SAndy Fiddaman 			}
1433*b30d1939SAndy Fiddaman 			if(iof&IOLSEEK)
1434*b30d1939SAndy Fiddaman 			{
1435*b30d1939SAndy Fiddaman 				Sfio_t *sp;
1436*b30d1939SAndy Fiddaman 
1437*b30d1939SAndy Fiddaman 				VALIDATE_FD(shp, fn);
1438*b30d1939SAndy Fiddaman 
1439*b30d1939SAndy Fiddaman 				sp = shp->sftable[fn];
1440*b30d1939SAndy Fiddaman 				r = shp->fdstatus[fn];
1441*b30d1939SAndy Fiddaman 				if(!(r&(IOSEEK|IONOSEEK)))
1442*b30d1939SAndy Fiddaman 					r = sh_iocheckfd(shp,fn);
1443*b30d1939SAndy Fiddaman 				sfsprintf(io_op,sizeof(io_op),"%d\0",fn);
1444*b30d1939SAndy Fiddaman 				if(r==IOCLOSE)
1445*b30d1939SAndy Fiddaman 				{
1446*b30d1939SAndy Fiddaman 					fname = io_op;
1447*b30d1939SAndy Fiddaman 					message = e_file;
1448*b30d1939SAndy Fiddaman 					goto fail;
1449*b30d1939SAndy Fiddaman 				}
1450*b30d1939SAndy Fiddaman 				if(iof&IOARITH)
1451*b30d1939SAndy Fiddaman 				{
1452*b30d1939SAndy Fiddaman 					if(r&IONOSEEK)
1453*b30d1939SAndy Fiddaman 					{
1454*b30d1939SAndy Fiddaman 						fname = io_op;
1455*b30d1939SAndy Fiddaman 						message = e_notseek;
1456*b30d1939SAndy Fiddaman 						goto fail;
1457*b30d1939SAndy Fiddaman 					}
1458*b30d1939SAndy Fiddaman 					message = e_badseek;
1459*b30d1939SAndy Fiddaman 					if((off = file_offset(shp,fn,fname))<0)
1460*b30d1939SAndy Fiddaman 						goto fail;
1461*b30d1939SAndy Fiddaman 					if(sp)
1462*b30d1939SAndy Fiddaman 					{
1463*b30d1939SAndy Fiddaman 						off=sfseek(sp, off, SEEK_SET);
1464*b30d1939SAndy Fiddaman 						sfsync(sp);
1465*b30d1939SAndy Fiddaman 					}
1466*b30d1939SAndy Fiddaman 					else
1467*b30d1939SAndy Fiddaman 						off=lseek(fn, off, SEEK_SET);
1468*b30d1939SAndy Fiddaman 					if(off<0)
1469*b30d1939SAndy Fiddaman 						r = -1;
1470*b30d1939SAndy Fiddaman 				}
1471*b30d1939SAndy Fiddaman 				else
1472*b30d1939SAndy Fiddaman 				{
1473*b30d1939SAndy Fiddaman 					regex_t *rp;
1474*b30d1939SAndy Fiddaman 					extern const char e_notimp[];
1475*b30d1939SAndy Fiddaman 					if(!(r&IOREAD))
1476*b30d1939SAndy Fiddaman 					{
1477*b30d1939SAndy Fiddaman 						message = e_noread;
1478*b30d1939SAndy Fiddaman 						goto fail;
1479*b30d1939SAndy Fiddaman 					}
1480*b30d1939SAndy Fiddaman 					if(!(rp = regcache(fname, REG_SHELL|REG_NOSUB|REG_NEWLINE|REG_AUGMENTED|REG_FIRST|REG_LEFT|REG_RIGHT, &r)))
1481*b30d1939SAndy Fiddaman 					{
1482*b30d1939SAndy Fiddaman 						message = e_badpattern;
1483*b30d1939SAndy Fiddaman 						goto fail;
1484*b30d1939SAndy Fiddaman 					}
1485*b30d1939SAndy Fiddaman 					if(!sp)
1486*b30d1939SAndy Fiddaman 						sp = sh_iostream(shp,fn);
1487*b30d1939SAndy Fiddaman 					r=io_patseek(shp,rp,sp,iof);
1488*b30d1939SAndy Fiddaman 					if(sp && flag==3)
1489*b30d1939SAndy Fiddaman 					{
1490*b30d1939SAndy Fiddaman 						/* close stream but not fn */
1491*b30d1939SAndy Fiddaman 						sfsetfd(sp,-1);
1492*b30d1939SAndy Fiddaman 						sfclose(sp);
1493*b30d1939SAndy Fiddaman 					}
1494*b30d1939SAndy Fiddaman 				}
1495*b30d1939SAndy Fiddaman 				if(r<0)
1496*b30d1939SAndy Fiddaman 					goto fail;
1497*b30d1939SAndy Fiddaman 				if(flag==3)
1498*b30d1939SAndy Fiddaman 					return(fn);
1499*b30d1939SAndy Fiddaman 				continue;
1500*b30d1939SAndy Fiddaman 			}
1501*b30d1939SAndy Fiddaman 			if(!np)
1502*b30d1939SAndy Fiddaman 			{
1503*b30d1939SAndy Fiddaman 				if(flag==0 || tname || (flag==1 && fn==1 && (shp->fdstatus[fn]&IONOSEEK) && shp->outpipepid && shp->outpipepid==getpid()))
1504*b30d1939SAndy Fiddaman 				{
1505*b30d1939SAndy Fiddaman 					if(fd==fn)
1506*b30d1939SAndy Fiddaman 					{
1507*b30d1939SAndy Fiddaman 						if((r=sh_fcntl(fd,F_DUPFD,10)) > 0)
1508*b30d1939SAndy Fiddaman 						{
1509*b30d1939SAndy Fiddaman 							fd = r;
1510*b30d1939SAndy Fiddaman 							sh_close(fn);
1511*b30d1939SAndy Fiddaman 						}
1512*b30d1939SAndy Fiddaman 					}
1513*b30d1939SAndy Fiddaman 					sh_iosave(shp,fn,indx,tname?fname:(trunc?Empty:0));
1514*b30d1939SAndy Fiddaman 				}
1515*b30d1939SAndy Fiddaman 				else if(sh_subsavefd(fn))
1516*b30d1939SAndy Fiddaman 					sh_iosave(shp,fn,indx|IOSUBSHELL,tname?fname:0);
1517*b30d1939SAndy Fiddaman 			}
1518*b30d1939SAndy Fiddaman 			if(fd<0)
1519*b30d1939SAndy Fiddaman 			{
1520*b30d1939SAndy Fiddaman 				VALIDATE_FD(shp, fn);
1521*b30d1939SAndy Fiddaman 				if(sh_inuse(shp,fn) || (fn && fn==shp->infd))
1522*b30d1939SAndy Fiddaman 				{
1523*b30d1939SAndy Fiddaman 					if(fn>9 || !(shp->inuse_bits&(1<<fn)))
1524*b30d1939SAndy Fiddaman 						io_preserve(shp,shp->sftable[fn],fn);
1525*b30d1939SAndy Fiddaman 				}
1526*b30d1939SAndy Fiddaman 				sh_close(fn);
1527*b30d1939SAndy Fiddaman 			}
1528*b30d1939SAndy Fiddaman 			if(flag==3)
1529*b30d1939SAndy Fiddaman 				return(fd);
1530*b30d1939SAndy Fiddaman 			if(fd>=0)
1531*b30d1939SAndy Fiddaman 			{
1532*b30d1939SAndy Fiddaman 				if(np)
1533*b30d1939SAndy Fiddaman 				{
1534*b30d1939SAndy Fiddaman 					int32_t v;
1535*b30d1939SAndy Fiddaman 					fn = fd;
1536*b30d1939SAndy Fiddaman 					if(fd<10)
1537*b30d1939SAndy Fiddaman 					{
1538*b30d1939SAndy Fiddaman 						if((fn=fcntl(fd,F_DUPFD,10)) < 0)
1539*b30d1939SAndy Fiddaman 							goto fail;
1540*b30d1939SAndy Fiddaman 						if (!VALIDATE_FD(shp, fn))
1541*b30d1939SAndy Fiddaman 							goto fail;
1542*b30d1939SAndy Fiddaman 						if(flag!=2 || shp->subshell)
1543*b30d1939SAndy Fiddaman 							sh_iosave(shp,fn,indx|0x10000,tname?fname:(trunc?Empty:0));
1544*b30d1939SAndy Fiddaman 						shp->fdstatus[fn] = shp->fdstatus[fd];
1545*b30d1939SAndy Fiddaman 						sh_close(fd);
1546*b30d1939SAndy Fiddaman 						fd = fn;
1547*b30d1939SAndy Fiddaman 					}
1548*b30d1939SAndy Fiddaman 					_nv_unset(np,0);
1549*b30d1939SAndy Fiddaman 					nv_onattr(np,NV_INT32);
1550*b30d1939SAndy Fiddaman 					v = fn;
1551*b30d1939SAndy Fiddaman 					nv_putval(np,(char*)&v, NV_INT32);
1552*b30d1939SAndy Fiddaman 					sh_iocheckfd(shp,fd);
1553*b30d1939SAndy Fiddaman 				}
1554*b30d1939SAndy Fiddaman 				else
1555*b30d1939SAndy Fiddaman 				{
1556*b30d1939SAndy Fiddaman 					fd = sh_iorenumber(shp,sh_iomovefd(fd),fn);
1557*b30d1939SAndy Fiddaman 					if(fn>2 && fn<10)
1558*b30d1939SAndy Fiddaman 						shp->inuse_bits |= (1<<fn);
1559*b30d1939SAndy Fiddaman 				}
1560*b30d1939SAndy Fiddaman 			}
1561*b30d1939SAndy Fiddaman 			if(fd >2 && clexec)
1562*b30d1939SAndy Fiddaman 			{
1563*b30d1939SAndy Fiddaman 				fcntl(fd,F_SETFD,FD_CLOEXEC);
1564*b30d1939SAndy Fiddaman 				shp->fdstatus[fd] |= IOCLEX;
1565*b30d1939SAndy Fiddaman 			}
1566*b30d1939SAndy Fiddaman 		}
1567*b30d1939SAndy Fiddaman 		else
1568*b30d1939SAndy Fiddaman 			goto fail;
1569*b30d1939SAndy Fiddaman 	}
1570*b30d1939SAndy Fiddaman 	return(indx);
1571*b30d1939SAndy Fiddaman fail:
1572*b30d1939SAndy Fiddaman 	errormsg(SH_DICT,ERROR_system(1),message,fname);
1573*b30d1939SAndy Fiddaman 	/* NOTREACHED */
1574*b30d1939SAndy Fiddaman 	return(0);
1575*b30d1939SAndy Fiddaman }
1576*b30d1939SAndy Fiddaman /*
1577*b30d1939SAndy Fiddaman  * Create a tmp file for the here-document
1578*b30d1939SAndy Fiddaman  */
io_heredoc(Shell_t * shp,register struct ionod * iop,const char * name,int traceon)1579*b30d1939SAndy Fiddaman static int io_heredoc(Shell_t *shp,register struct ionod *iop, const char *name, int traceon)
1580*b30d1939SAndy Fiddaman {
1581*b30d1939SAndy Fiddaman 	register Sfio_t	*infile = 0, *outfile, *tmp;
1582*b30d1939SAndy Fiddaman 	register int		fd;
1583*b30d1939SAndy Fiddaman 	Sfoff_t			off;
1584*b30d1939SAndy Fiddaman 	if(!(iop->iofile&IOSTRG) && (!shp->heredocs || iop->iosize==0))
1585*b30d1939SAndy Fiddaman 		return(sh_open(e_devnull,O_RDONLY));
1586*b30d1939SAndy Fiddaman 	/* create an unnamed temporary file */
1587*b30d1939SAndy Fiddaman 	if(!(outfile=sftmp(0)))
1588*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
1589*b30d1939SAndy Fiddaman 	if(iop->iofile&IOSTRG)
1590*b30d1939SAndy Fiddaman 	{
1591*b30d1939SAndy Fiddaman 		if(traceon)
1592*b30d1939SAndy Fiddaman 			sfprintf(sfstderr,"< %s\n",name);
1593*b30d1939SAndy Fiddaman 		sfputr(outfile,name,'\n');
1594*b30d1939SAndy Fiddaman 	}
1595*b30d1939SAndy Fiddaman 	else
1596*b30d1939SAndy Fiddaman 	{
1597*b30d1939SAndy Fiddaman 		/*
1598*b30d1939SAndy Fiddaman 		 * the locking is only needed in case & blocks process
1599*b30d1939SAndy Fiddaman 		 * here-docs so this can be eliminted in some cases
1600*b30d1939SAndy Fiddaman 		 */
1601*b30d1939SAndy Fiddaman 		struct flock	lock;
1602*b30d1939SAndy Fiddaman 		int	fno = sffileno(shp->heredocs);
1603*b30d1939SAndy Fiddaman 		if(fno>=0)
1604*b30d1939SAndy Fiddaman 		{
1605*b30d1939SAndy Fiddaman 			memset((void*)&lock,0,sizeof(lock));
1606*b30d1939SAndy Fiddaman 			lock.l_type = F_WRLCK;
1607*b30d1939SAndy Fiddaman 			lock.l_whence = SEEK_SET;
1608*b30d1939SAndy Fiddaman 			fcntl(fno,F_SETLKW,&lock);
1609*b30d1939SAndy Fiddaman 			lock.l_type = F_UNLCK;
1610*b30d1939SAndy Fiddaman 		}
1611*b30d1939SAndy Fiddaman 		off = sftell(shp->heredocs);
1612*b30d1939SAndy Fiddaman 		infile = subopen(shp,shp->heredocs,iop->iooffset,iop->iosize);
1613*b30d1939SAndy Fiddaman 		if(traceon)
1614*b30d1939SAndy Fiddaman 		{
1615*b30d1939SAndy Fiddaman 			char *cp = sh_fmtq(iop->iodelim);
1616*b30d1939SAndy Fiddaman 			fd = (*cp=='$' || *cp=='\'')?' ':'\\';
1617*b30d1939SAndy Fiddaman 			sfprintf(sfstderr," %c%s\n",fd,cp);
1618*b30d1939SAndy Fiddaman 			sfdisc(outfile,&tee_disc);
1619*b30d1939SAndy Fiddaman 		}
1620*b30d1939SAndy Fiddaman 		tmp = outfile;
1621*b30d1939SAndy Fiddaman 		if(fno>=0 && !(iop->iofile&IOQUOTE))
1622*b30d1939SAndy Fiddaman 			tmp = sftmp(iop->iosize<IOBSIZE?iop->iosize:0);
1623*b30d1939SAndy Fiddaman 		if(fno>=0 || (iop->iofile&IOQUOTE))
1624*b30d1939SAndy Fiddaman 		{
1625*b30d1939SAndy Fiddaman 			/* This is a quoted here-document, not expansion */
1626*b30d1939SAndy Fiddaman 			sfmove(infile,tmp,SF_UNBOUND,-1);
1627*b30d1939SAndy Fiddaman 			sfclose(infile);
1628*b30d1939SAndy Fiddaman 			if(sffileno(tmp)>0)
1629*b30d1939SAndy Fiddaman 			{
1630*b30d1939SAndy Fiddaman 				sfsetbuf(tmp,malloc(IOBSIZE+1),IOBSIZE);
1631*b30d1939SAndy Fiddaman 				sfset(tmp,SF_MALLOC,1);
1632*b30d1939SAndy Fiddaman 			}
1633*b30d1939SAndy Fiddaman 			sfseek(shp->heredocs,off,SEEK_SET);
1634*b30d1939SAndy Fiddaman 			if(fno>=0)
1635*b30d1939SAndy Fiddaman 				fcntl(fno,F_SETLK,&lock);
1636*b30d1939SAndy Fiddaman 			sfseek(tmp,(off_t)0,SEEK_SET);
1637*b30d1939SAndy Fiddaman 			infile = tmp;
1638*b30d1939SAndy Fiddaman 		}
1639*b30d1939SAndy Fiddaman 		if(!(iop->iofile&IOQUOTE))
1640*b30d1939SAndy Fiddaman 		{
1641*b30d1939SAndy Fiddaman 			char *lastpath = shp->lastpath;
1642*b30d1939SAndy Fiddaman 			sh_machere(shp,infile,outfile,iop->ioname);
1643*b30d1939SAndy Fiddaman 			shp->lastpath = lastpath;
1644*b30d1939SAndy Fiddaman 			if(infile)
1645*b30d1939SAndy Fiddaman 				sfclose(infile);
1646*b30d1939SAndy Fiddaman 		}
1647*b30d1939SAndy Fiddaman 	}
1648*b30d1939SAndy Fiddaman 	/* close stream outfile, but save file descriptor */
1649*b30d1939SAndy Fiddaman 	fd = sffileno(outfile);
1650*b30d1939SAndy Fiddaman 	sfsetfd(outfile,-1);
1651*b30d1939SAndy Fiddaman 	sfclose(outfile);
1652*b30d1939SAndy Fiddaman 	if(traceon && !(iop->iofile&IOSTRG))
1653*b30d1939SAndy Fiddaman 		sfputr(sfstderr,iop->ioname,'\n');
1654*b30d1939SAndy Fiddaman 	lseek(fd,(off_t)0,SEEK_SET);
1655*b30d1939SAndy Fiddaman 	shp->fdstatus[fd] = IOREAD;
1656*b30d1939SAndy Fiddaman 	return(fd);
1657*b30d1939SAndy Fiddaman }
1658*b30d1939SAndy Fiddaman 
1659*b30d1939SAndy Fiddaman /*
1660*b30d1939SAndy Fiddaman  * This write discipline also writes the output on standard error
1661*b30d1939SAndy Fiddaman  * This is used when tracing here-documents
1662*b30d1939SAndy Fiddaman  */
tee_write(Sfio_t * iop,const void * buff,size_t n,Sfdisc_t * unused)1663*b30d1939SAndy Fiddaman static ssize_t tee_write(Sfio_t *iop,const void *buff,size_t n,Sfdisc_t *unused)
1664*b30d1939SAndy Fiddaman {
1665*b30d1939SAndy Fiddaman 	NOT_USED(unused);
1666*b30d1939SAndy Fiddaman 	sfwrite(sfstderr,buff,n);
1667*b30d1939SAndy Fiddaman 	return(write(sffileno(iop),buff,n));
1668*b30d1939SAndy Fiddaman }
1669*b30d1939SAndy Fiddaman 
1670*b30d1939SAndy Fiddaman /*
1671*b30d1939SAndy Fiddaman  * copy file <origfd> into a save place
1672*b30d1939SAndy Fiddaman  * The saved file is set close-on-exec
1673*b30d1939SAndy Fiddaman  * if <origfd> < 0, then -origfd is saved, but not duped so that it
1674*b30d1939SAndy Fiddaman  *   will be closed with sh_iorestore.
1675*b30d1939SAndy Fiddaman  */
sh_iosave(Shell_t * shp,register int origfd,int oldtop,char * name)1676*b30d1939SAndy Fiddaman void sh_iosave(Shell_t *shp, register int origfd, int oldtop, char *name)
1677*b30d1939SAndy Fiddaman {
1678*b30d1939SAndy Fiddaman 	register int	savefd;
1679*b30d1939SAndy Fiddaman 	int flag = (oldtop&(IOSUBSHELL|IOPICKFD));
1680*b30d1939SAndy Fiddaman 	oldtop &= ~(IOSUBSHELL|IOPICKFD);
1681*b30d1939SAndy Fiddaman 	/* see if already saved, only save once */
1682*b30d1939SAndy Fiddaman 	for(savefd=shp->topfd; --savefd>=oldtop; )
1683*b30d1939SAndy Fiddaman 	{
1684*b30d1939SAndy Fiddaman 		if(filemap[savefd].orig_fd == origfd)
1685*b30d1939SAndy Fiddaman 			return;
1686*b30d1939SAndy Fiddaman 	}
1687*b30d1939SAndy Fiddaman 	/* make sure table is large enough */
1688*b30d1939SAndy Fiddaman 	if(shp->topfd >= filemapsize)
1689*b30d1939SAndy Fiddaman 	{
1690*b30d1939SAndy Fiddaman 		char 	*cp, *oldptr = (char*)filemap;
1691*b30d1939SAndy Fiddaman 		char 	*oldend = (char*)&filemap[filemapsize];
1692*b30d1939SAndy Fiddaman 		long	moved;
1693*b30d1939SAndy Fiddaman 		filemapsize += 8;
1694*b30d1939SAndy Fiddaman 		if(!(filemap = (struct fdsave*)realloc(filemap,filemapsize*sizeof(struct fdsave))))
1695*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_exit(4),e_nospace);
1696*b30d1939SAndy Fiddaman 		if(moved = (char*)filemap - oldptr)
1697*b30d1939SAndy Fiddaman 		{
1698*b30d1939SAndy Fiddaman 			for(savefd=shp->gd->lim.open_max; --savefd>=0; )
1699*b30d1939SAndy Fiddaman 			{
1700*b30d1939SAndy Fiddaman 				cp = (char*)shp->fdptrs[savefd];
1701*b30d1939SAndy Fiddaman 				if(cp >= oldptr && cp < oldend)
1702*b30d1939SAndy Fiddaman 					shp->fdptrs[savefd] = (int*)(cp+moved);
1703*b30d1939SAndy Fiddaman 			}
1704*b30d1939SAndy Fiddaman 		}
1705*b30d1939SAndy Fiddaman 	}
1706*b30d1939SAndy Fiddaman #if SHOPT_DEVFD
1707*b30d1939SAndy Fiddaman 	if(origfd <0)
1708*b30d1939SAndy Fiddaman 	{
1709*b30d1939SAndy Fiddaman 		savefd = origfd;
1710*b30d1939SAndy Fiddaman 		origfd = -origfd;
1711*b30d1939SAndy Fiddaman 	}
1712*b30d1939SAndy Fiddaman 	else
1713*b30d1939SAndy Fiddaman #endif /* SHOPT_DEVFD */
1714*b30d1939SAndy Fiddaman 	if(flag&IOPICKFD)
1715*b30d1939SAndy Fiddaman 		savefd = -1;
1716*b30d1939SAndy Fiddaman 	else
1717*b30d1939SAndy Fiddaman 	{
1718*b30d1939SAndy Fiddaman 		if((savefd = sh_fcntl(origfd, F_DUPFD, 10)) < 0 && errno!=EBADF)
1719*b30d1939SAndy Fiddaman 		{
1720*b30d1939SAndy Fiddaman 			shp->toomany=1;
1721*b30d1939SAndy Fiddaman 			((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
1722*b30d1939SAndy Fiddaman 			errormsg(SH_DICT,ERROR_system(1),e_toomany);
1723*b30d1939SAndy Fiddaman 		}
1724*b30d1939SAndy Fiddaman 	}
1725*b30d1939SAndy Fiddaman 	filemap[shp->topfd].tname = name;
1726*b30d1939SAndy Fiddaman 	filemap[shp->topfd].subshell = (flag&IOSUBSHELL);
1727*b30d1939SAndy Fiddaman 	filemap[shp->topfd].orig_fd = origfd;
1728*b30d1939SAndy Fiddaman 	filemap[shp->topfd++].save_fd = savefd;
1729*b30d1939SAndy Fiddaman 	if(savefd >=0)
1730*b30d1939SAndy Fiddaman 	{
1731*b30d1939SAndy Fiddaman 		register Sfio_t* sp;
1732*b30d1939SAndy Fiddaman 
1733*b30d1939SAndy Fiddaman 		VALIDATE_FD(shp, origfd);
1734*b30d1939SAndy Fiddaman 		VALIDATE_FD(shp, savefd);
1735*b30d1939SAndy Fiddaman 
1736*b30d1939SAndy Fiddaman 		sp = shp->sftable[origfd];
1737*b30d1939SAndy Fiddaman 		/* make saved file close-on-exec */
1738*b30d1939SAndy Fiddaman 		sh_fcntl(savefd,F_SETFD,FD_CLOEXEC);
1739*b30d1939SAndy Fiddaman 		if(origfd==job.fd)
1740*b30d1939SAndy Fiddaman 			job.fd = savefd;
1741*b30d1939SAndy Fiddaman 		shp->fdstatus[savefd] = shp->fdstatus[origfd];
1742*b30d1939SAndy Fiddaman 		shp->fdptrs[savefd] = &filemap[shp->topfd-1].save_fd;
1743*b30d1939SAndy Fiddaman 		if(!(shp->sftable[savefd]=sp))
1744*b30d1939SAndy Fiddaman 			return;
1745*b30d1939SAndy Fiddaman 		sfsync(sp);
1746*b30d1939SAndy Fiddaman 		if(origfd <=2)
1747*b30d1939SAndy Fiddaman 		{
1748*b30d1939SAndy Fiddaman 			/* copy standard stream to new stream */
1749*b30d1939SAndy Fiddaman 			sp = sfswap(sp,NIL(Sfio_t*));
1750*b30d1939SAndy Fiddaman 			shp->sftable[savefd] = sp;
1751*b30d1939SAndy Fiddaman 		}
1752*b30d1939SAndy Fiddaman 		else
1753*b30d1939SAndy Fiddaman 			shp->sftable[origfd] = 0;
1754*b30d1939SAndy Fiddaman 	}
1755*b30d1939SAndy Fiddaman }
1756*b30d1939SAndy Fiddaman 
1757*b30d1939SAndy Fiddaman /*
1758*b30d1939SAndy Fiddaman  *  close all saved file descriptors
1759*b30d1939SAndy Fiddaman  */
sh_iounsave(Shell_t * shp)1760*b30d1939SAndy Fiddaman void	sh_iounsave(Shell_t* shp)
1761*b30d1939SAndy Fiddaman {
1762*b30d1939SAndy Fiddaman 	register int fd, savefd, newfd;
1763*b30d1939SAndy Fiddaman 	for(newfd=fd=0; fd < shp->topfd; fd++)
1764*b30d1939SAndy Fiddaman 	{
1765*b30d1939SAndy Fiddaman 		if((savefd = filemap[fd].save_fd)< 0)
1766*b30d1939SAndy Fiddaman 			filemap[newfd++] = filemap[fd];
1767*b30d1939SAndy Fiddaman 		else
1768*b30d1939SAndy Fiddaman 		{
1769*b30d1939SAndy Fiddaman 			VALIDATE_FD(shp, savefd);
1770*b30d1939SAndy Fiddaman 			shp->sftable[savefd] = 0;
1771*b30d1939SAndy Fiddaman 			sh_close(savefd);
1772*b30d1939SAndy Fiddaman 		}
1773*b30d1939SAndy Fiddaman 	}
1774*b30d1939SAndy Fiddaman 	shp->topfd = newfd;
1775*b30d1939SAndy Fiddaman }
1776*b30d1939SAndy Fiddaman 
1777*b30d1939SAndy Fiddaman /*
1778*b30d1939SAndy Fiddaman  *  restore saved file descriptors from <last> on
1779*b30d1939SAndy Fiddaman  */
sh_iorestore(Shell_t * shp,int last,int jmpval)1780*b30d1939SAndy Fiddaman void	sh_iorestore(Shell_t *shp, int last, int jmpval)
1781*b30d1939SAndy Fiddaman {
1782*b30d1939SAndy Fiddaman 	register int 	origfd, savefd, fd;
1783*b30d1939SAndy Fiddaman 	int flag = (last&IOSUBSHELL);
1784*b30d1939SAndy Fiddaman 	last &= ~IOSUBSHELL;
1785*b30d1939SAndy Fiddaman 	for (fd = shp->topfd - 1; fd >= last; fd--)
1786*b30d1939SAndy Fiddaman 	{
1787*b30d1939SAndy Fiddaman 		if(!flag && filemap[fd].subshell)
1788*b30d1939SAndy Fiddaman 			continue;
1789*b30d1939SAndy Fiddaman 		if(jmpval==SH_JMPSCRIPT)
1790*b30d1939SAndy Fiddaman 		{
1791*b30d1939SAndy Fiddaman 			if ((savefd = filemap[fd].save_fd) >= 0)
1792*b30d1939SAndy Fiddaman 			{
1793*b30d1939SAndy Fiddaman 				VALIDATE_FD(shp, savefd);
1794*b30d1939SAndy Fiddaman 				shp->sftable[savefd] = 0;
1795*b30d1939SAndy Fiddaman 				sh_close(savefd);
1796*b30d1939SAndy Fiddaman 			}
1797*b30d1939SAndy Fiddaman 			continue;
1798*b30d1939SAndy Fiddaman 		}
1799*b30d1939SAndy Fiddaman 		origfd = filemap[fd].orig_fd;
1800*b30d1939SAndy Fiddaman 		VALIDATE_FD(shp, origfd);
1801*b30d1939SAndy Fiddaman 		if(origfd<0)
1802*b30d1939SAndy Fiddaman 		{
1803*b30d1939SAndy Fiddaman 			/* this should never happen */
1804*b30d1939SAndy Fiddaman 			savefd = filemap[fd].save_fd;
1805*b30d1939SAndy Fiddaman 			VALIDATE_FD(shp, savefd);
1806*b30d1939SAndy Fiddaman 			shp->sftable[savefd] = 0;
1807*b30d1939SAndy Fiddaman 			sh_close(savefd);
1808*b30d1939SAndy Fiddaman 			return;
1809*b30d1939SAndy Fiddaman 		}
1810*b30d1939SAndy Fiddaman 		if(filemap[fd].tname == Empty && shp->exitval==0)
1811*b30d1939SAndy Fiddaman 			ftruncate(origfd,lseek(origfd,0,SEEK_CUR));
1812*b30d1939SAndy Fiddaman 		else if(filemap[fd].tname)
1813*b30d1939SAndy Fiddaman 			io_usename(filemap[fd].tname,(int*)0,origfd,shp->exitval?2:1);
1814*b30d1939SAndy Fiddaman 		sh_close(origfd);
1815*b30d1939SAndy Fiddaman 		if ((savefd = filemap[fd].save_fd) >= 0)
1816*b30d1939SAndy Fiddaman 		{
1817*b30d1939SAndy Fiddaman 			VALIDATE_FD(shp, savefd);
1818*b30d1939SAndy Fiddaman 			sh_fcntl(savefd, F_DUPFD, origfd);
1819*b30d1939SAndy Fiddaman 			if(savefd==job.fd)
1820*b30d1939SAndy Fiddaman 				job.fd=origfd;
1821*b30d1939SAndy Fiddaman 			shp->fdstatus[origfd] = shp->fdstatus[savefd];
1822*b30d1939SAndy Fiddaman 			/* turn off close-on-exec if flag if necessary */
1823*b30d1939SAndy Fiddaman 			if(shp->fdstatus[origfd]&IOCLEX)
1824*b30d1939SAndy Fiddaman 				fcntl(origfd,F_SETFD,FD_CLOEXEC);
1825*b30d1939SAndy Fiddaman 			if(origfd<=2)
1826*b30d1939SAndy Fiddaman 			{
1827*b30d1939SAndy Fiddaman 				sfswap(shp->sftable[savefd],shp->sftable[origfd]);
1828*b30d1939SAndy Fiddaman 				if(origfd==0)
1829*b30d1939SAndy Fiddaman 					shp->st.ioset = 0;
1830*b30d1939SAndy Fiddaman 			}
1831*b30d1939SAndy Fiddaman 			else
1832*b30d1939SAndy Fiddaman 				shp->sftable[origfd] = shp->sftable[savefd];
1833*b30d1939SAndy Fiddaman 			shp->sftable[savefd] = 0;
1834*b30d1939SAndy Fiddaman 			sh_close(savefd);
1835*b30d1939SAndy Fiddaman 		}
1836*b30d1939SAndy Fiddaman 		else
1837*b30d1939SAndy Fiddaman 			shp->fdstatus[origfd] = IOCLOSE;
1838*b30d1939SAndy Fiddaman 	}
1839*b30d1939SAndy Fiddaman 	if(!flag)
1840*b30d1939SAndy Fiddaman 	{
1841*b30d1939SAndy Fiddaman 		/* keep file descriptors for subshell restore */
1842*b30d1939SAndy Fiddaman 		for (fd = last ; fd < shp->topfd; fd++)
1843*b30d1939SAndy Fiddaman 		{
1844*b30d1939SAndy Fiddaman 			if(filemap[fd].subshell)
1845*b30d1939SAndy Fiddaman 				filemap[last++] = filemap[fd];
1846*b30d1939SAndy Fiddaman 		}
1847*b30d1939SAndy Fiddaman 	}
1848*b30d1939SAndy Fiddaman 	if(last < shp->topfd)
1849*b30d1939SAndy Fiddaman 		shp->topfd = last;
1850*b30d1939SAndy Fiddaman }
1851*b30d1939SAndy Fiddaman 
1852*b30d1939SAndy Fiddaman /*
1853*b30d1939SAndy Fiddaman  * returns access information on open file <fd>
1854*b30d1939SAndy Fiddaman  * returns -1 for failure, 0 for success
1855*b30d1939SAndy Fiddaman  * <mode> is the same as for access()
1856*b30d1939SAndy Fiddaman  */
sh_ioaccess(int fd,register int mode)1857*b30d1939SAndy Fiddaman int sh_ioaccess(int fd,register int mode)
1858*b30d1939SAndy Fiddaman {
1859*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
1860*b30d1939SAndy Fiddaman 	register int flags;
1861*b30d1939SAndy Fiddaman 	if(mode==X_OK)
1862*b30d1939SAndy Fiddaman 		return(-1);
1863*b30d1939SAndy Fiddaman 	if((flags=sh_iocheckfd(shp,fd))!=IOCLOSE)
1864*b30d1939SAndy Fiddaman 	{
1865*b30d1939SAndy Fiddaman 		if(mode==F_OK)
1866*b30d1939SAndy Fiddaman 			return(0);
1867*b30d1939SAndy Fiddaman 		if(mode==R_OK && (flags&IOREAD))
1868*b30d1939SAndy Fiddaman 			return(0);
1869*b30d1939SAndy Fiddaman 		if(mode==W_OK && (flags&IOWRITE))
1870*b30d1939SAndy Fiddaman 			return(0);
1871*b30d1939SAndy Fiddaman 	}
1872*b30d1939SAndy Fiddaman 	return(-1);
1873*b30d1939SAndy Fiddaman }
1874*b30d1939SAndy Fiddaman 
1875*b30d1939SAndy Fiddaman /*
1876*b30d1939SAndy Fiddaman  *  Handle interrupts for slow streams
1877*b30d1939SAndy Fiddaman  */
slowexcept(register Sfio_t * iop,int type,void * data,Sfdisc_t * handle)1878*b30d1939SAndy Fiddaman static int slowexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
1879*b30d1939SAndy Fiddaman {
1880*b30d1939SAndy Fiddaman 	Shell_t *shp = ((struct Iodisc*)handle)->sh;
1881*b30d1939SAndy Fiddaman 	register int	n,fno;
1882*b30d1939SAndy Fiddaman 	NOT_USED(handle);
1883*b30d1939SAndy Fiddaman 	if(type==SF_DPOP || type==SF_FINAL)
1884*b30d1939SAndy Fiddaman 		free((void*)handle);
1885*b30d1939SAndy Fiddaman 	if(type==SF_WRITE && ERROR_PIPE(errno))
1886*b30d1939SAndy Fiddaman 	{
1887*b30d1939SAndy Fiddaman 		sfpurge(iop);
1888*b30d1939SAndy Fiddaman 		return(-1);
1889*b30d1939SAndy Fiddaman 	}
1890*b30d1939SAndy Fiddaman 	if(type!=SF_READ)
1891*b30d1939SAndy Fiddaman 		return(0);
1892*b30d1939SAndy Fiddaman 	if((shp->trapnote&(SH_SIGSET|SH_SIGTRAP)) && errno!=EIO && errno!=ENXIO)
1893*b30d1939SAndy Fiddaman 		errno = EINTR;
1894*b30d1939SAndy Fiddaman 	fno = sffileno(iop);
1895*b30d1939SAndy Fiddaman 	if((n=sfvalue(iop))<=0)
1896*b30d1939SAndy Fiddaman 	{
1897*b30d1939SAndy Fiddaman #ifndef FNDELAY
1898*b30d1939SAndy Fiddaman #   ifdef O_NDELAY
1899*b30d1939SAndy Fiddaman 		if(errno==0 && (n=fcntl(fno,F_GETFL,0))&O_NDELAY)
1900*b30d1939SAndy Fiddaman 		{
1901*b30d1939SAndy Fiddaman 			n &= ~O_NDELAY;
1902*b30d1939SAndy Fiddaman 			fcntl(fno, F_SETFL, n);
1903*b30d1939SAndy Fiddaman 			return(1);
1904*b30d1939SAndy Fiddaman 		}
1905*b30d1939SAndy Fiddaman #   endif /* O_NDELAY */
1906*b30d1939SAndy Fiddaman #endif /* !FNDELAY */
1907*b30d1939SAndy Fiddaman #ifdef O_NONBLOCK
1908*b30d1939SAndy Fiddaman 		if(errno==EAGAIN)
1909*b30d1939SAndy Fiddaman 		{
1910*b30d1939SAndy Fiddaman 			n = fcntl(fno,F_GETFL,0);
1911*b30d1939SAndy Fiddaman 			n &= ~O_NONBLOCK;
1912*b30d1939SAndy Fiddaman 			fcntl(fno, F_SETFL, n);
1913*b30d1939SAndy Fiddaman 			return(1);
1914*b30d1939SAndy Fiddaman 		}
1915*b30d1939SAndy Fiddaman #endif /* O_NONBLOCK */
1916*b30d1939SAndy Fiddaman 		if(errno!=EINTR)
1917*b30d1939SAndy Fiddaman 			return(0);
1918*b30d1939SAndy Fiddaman 		else if(shp->bltinfun && (shp->trapnote&SH_SIGTRAP) && shp->lastsig)
1919*b30d1939SAndy Fiddaman 			return(-1);
1920*b30d1939SAndy Fiddaman 		n=1;
1921*b30d1939SAndy Fiddaman 		sh_onstate(SH_TTYWAIT);
1922*b30d1939SAndy Fiddaman 	}
1923*b30d1939SAndy Fiddaman 	else
1924*b30d1939SAndy Fiddaman 		n = 0;
1925*b30d1939SAndy Fiddaman 	if(shp->bltinfun && shp->bltindata.sigset)
1926*b30d1939SAndy Fiddaman 		return(-1);
1927*b30d1939SAndy Fiddaman 	errno = 0;
1928*b30d1939SAndy Fiddaman 	if(shp->trapnote&SH_SIGSET)
1929*b30d1939SAndy Fiddaman 	{
1930*b30d1939SAndy Fiddaman 		if(isatty(fno))
1931*b30d1939SAndy Fiddaman 			sfputc(sfstderr,'\n');
1932*b30d1939SAndy Fiddaman 		sh_exit(SH_EXITSIG);
1933*b30d1939SAndy Fiddaman 	}
1934*b30d1939SAndy Fiddaman 	if(shp->trapnote&SH_SIGTRAP)
1935*b30d1939SAndy Fiddaman 		sh_chktrap(shp);
1936*b30d1939SAndy Fiddaman 	return(n);
1937*b30d1939SAndy Fiddaman }
1938*b30d1939SAndy Fiddaman 
1939*b30d1939SAndy Fiddaman /*
1940*b30d1939SAndy Fiddaman  * called when slowread times out
1941*b30d1939SAndy Fiddaman  */
time_grace(void * handle)1942*b30d1939SAndy Fiddaman static void time_grace(void *handle)
1943*b30d1939SAndy Fiddaman {
1944*b30d1939SAndy Fiddaman 	Shell_t *shp = (Shell_t*)handle;
1945*b30d1939SAndy Fiddaman 	timeout = 0;
1946*b30d1939SAndy Fiddaman 	if(sh_isstate(SH_GRACE))
1947*b30d1939SAndy Fiddaman 	{
1948*b30d1939SAndy Fiddaman 		sh_offstate(SH_GRACE);
1949*b30d1939SAndy Fiddaman 		if(!sh_isstate(SH_INTERACTIVE))
1950*b30d1939SAndy Fiddaman 			return;
1951*b30d1939SAndy Fiddaman 		((struct checkpt*)shp->jmplist)->mode = SH_JMPEXIT;
1952*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,2,e_timeout);
1953*b30d1939SAndy Fiddaman 		shp->trapnote |= SH_SIGSET;
1954*b30d1939SAndy Fiddaman 		return;
1955*b30d1939SAndy Fiddaman 	}
1956*b30d1939SAndy Fiddaman 	errormsg(SH_DICT,0,e_timewarn);
1957*b30d1939SAndy Fiddaman 	sh_onstate(SH_GRACE);
1958*b30d1939SAndy Fiddaman 	sigrelease(SIGALRM);
1959*b30d1939SAndy Fiddaman 	shp->trapnote |= SH_SIGTRAP;
1960*b30d1939SAndy Fiddaman }
1961*b30d1939SAndy Fiddaman 
piperead(Sfio_t * iop,void * buff,register size_t size,Sfdisc_t * handle)1962*b30d1939SAndy Fiddaman static ssize_t piperead(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1963*b30d1939SAndy Fiddaman {
1964*b30d1939SAndy Fiddaman 	Shell_t *shp = ((struct Iodisc*)handle)->sh;
1965*b30d1939SAndy Fiddaman 	int fd = sffileno(iop);
1966*b30d1939SAndy Fiddaman 	if(job.waitsafe && job.savesig)
1967*b30d1939SAndy Fiddaman 	{
1968*b30d1939SAndy Fiddaman 		job_lock();
1969*b30d1939SAndy Fiddaman 		job_unlock();
1970*b30d1939SAndy Fiddaman 	}
1971*b30d1939SAndy Fiddaman 	if(shp->trapnote)
1972*b30d1939SAndy Fiddaman 	{
1973*b30d1939SAndy Fiddaman 		errno = EINTR;
1974*b30d1939SAndy Fiddaman 		return(-1);
1975*b30d1939SAndy Fiddaman 	}
1976*b30d1939SAndy Fiddaman 	if(sh_isstate(SH_INTERACTIVE) && sffileno(iop)==0 && io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
1977*b30d1939SAndy Fiddaman 		return(0);
1978*b30d1939SAndy Fiddaman 	sh_onstate(SH_TTYWAIT);
1979*b30d1939SAndy Fiddaman 	if(!(shp->fdstatus[fd]&IOCLEX) && (sfset(iop,0,0)&SF_SHARE))
1980*b30d1939SAndy Fiddaman 		size = ed_read(shgd->ed_context, fd, (char*)buff, size,0);
1981*b30d1939SAndy Fiddaman 	else
1982*b30d1939SAndy Fiddaman 		size = sfrd(iop,buff,size,handle);
1983*b30d1939SAndy Fiddaman 	sh_offstate(SH_TTYWAIT);
1984*b30d1939SAndy Fiddaman 	return(size);
1985*b30d1939SAndy Fiddaman }
1986*b30d1939SAndy Fiddaman /*
1987*b30d1939SAndy Fiddaman  * This is the read discipline that is applied to slow devices
1988*b30d1939SAndy Fiddaman  * This routine takes care of prompting for input
1989*b30d1939SAndy Fiddaman  */
slowread(Sfio_t * iop,void * buff,register size_t size,Sfdisc_t * handle)1990*b30d1939SAndy Fiddaman static ssize_t slowread(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1991*b30d1939SAndy Fiddaman {
1992*b30d1939SAndy Fiddaman 	Shell_t *shp = ((struct Iodisc*)handle)->sh;
1993*b30d1939SAndy Fiddaman 	int	(*readf)(void*, int, char*, int, int);
1994*b30d1939SAndy Fiddaman 	int	reedit=0, rsize;
1995*b30d1939SAndy Fiddaman #if SHOPT_HISTEXPAND
1996*b30d1939SAndy Fiddaman 	char    *xp=0;
1997*b30d1939SAndy Fiddaman #endif
1998*b30d1939SAndy Fiddaman #   if SHOPT_ESH
1999*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS))
2000*b30d1939SAndy Fiddaman 		readf = ed_emacsread;
2001*b30d1939SAndy Fiddaman 	else
2002*b30d1939SAndy Fiddaman #   endif	/* SHOPT_ESH */
2003*b30d1939SAndy Fiddaman #   if SHOPT_VSH
2004*b30d1939SAndy Fiddaman #	if SHOPT_RAWONLY
2005*b30d1939SAndy Fiddaman 	    if(sh_isoption(SH_VI) || ((SHOPT_RAWONLY-0) && mbwide()))
2006*b30d1939SAndy Fiddaman #	else
2007*b30d1939SAndy Fiddaman 	    if(sh_isoption(SH_VI))
2008*b30d1939SAndy Fiddaman #	endif
2009*b30d1939SAndy Fiddaman 		readf = ed_viread;
2010*b30d1939SAndy Fiddaman 	else
2011*b30d1939SAndy Fiddaman #   endif	/* SHOPT_VSH */
2012*b30d1939SAndy Fiddaman 		readf = ed_read;
2013*b30d1939SAndy Fiddaman 	if(shp->trapnote)
2014*b30d1939SAndy Fiddaman 	{
2015*b30d1939SAndy Fiddaman 		errno = EINTR;
2016*b30d1939SAndy Fiddaman 		return(-1);
2017*b30d1939SAndy Fiddaman 	}
2018*b30d1939SAndy Fiddaman 	while(1)
2019*b30d1939SAndy Fiddaman 	{
2020*b30d1939SAndy Fiddaman 		if(io_prompt(shp,iop,shp->nextprompt)<0 && errno==EIO)
2021*b30d1939SAndy Fiddaman 			return(0);
2022*b30d1939SAndy Fiddaman 		if(shp->timeout)
2023*b30d1939SAndy Fiddaman 			timeout = (void*)sh_timeradd(sh_isstate(SH_GRACE)?1000L*TGRACE:1000L*shp->timeout,0,time_grace,shp);
2024*b30d1939SAndy Fiddaman 		rsize = (*readf)(shgd->ed_context, sffileno(iop), (char*)buff, size, reedit);
2025*b30d1939SAndy Fiddaman 		if(timeout)
2026*b30d1939SAndy Fiddaman 			timerdel(timeout);
2027*b30d1939SAndy Fiddaman 		timeout=0;
2028*b30d1939SAndy Fiddaman #if SHOPT_HISTEXPAND
2029*b30d1939SAndy Fiddaman 		if(rsize && *(char*)buff != '\n' && shp->nextprompt==1 && sh_isoption(SH_HISTEXPAND))
2030*b30d1939SAndy Fiddaman 		{
2031*b30d1939SAndy Fiddaman 			int r;
2032*b30d1939SAndy Fiddaman 			((char*)buff)[rsize] = '\0';
2033*b30d1939SAndy Fiddaman 			if(xp)
2034*b30d1939SAndy Fiddaman 			{
2035*b30d1939SAndy Fiddaman 				free(xp);
2036*b30d1939SAndy Fiddaman 				xp = 0;
2037*b30d1939SAndy Fiddaman 			}
2038*b30d1939SAndy Fiddaman 			r = hist_expand(buff, &xp);
2039*b30d1939SAndy Fiddaman 			if((r & (HIST_EVENT|HIST_PRINT)) && !(r & HIST_ERROR) && xp)
2040*b30d1939SAndy Fiddaman 			{
2041*b30d1939SAndy Fiddaman 				strlcpy(buff, xp, size);
2042*b30d1939SAndy Fiddaman 				rsize = strlen(buff);
2043*b30d1939SAndy Fiddaman 				if(!sh_isoption(SH_HISTVERIFY) || readf==ed_read)
2044*b30d1939SAndy Fiddaman 				{
2045*b30d1939SAndy Fiddaman 					sfputr(sfstderr, xp, -1);
2046*b30d1939SAndy Fiddaman 					break;
2047*b30d1939SAndy Fiddaman 				}
2048*b30d1939SAndy Fiddaman 				reedit = rsize - 1;
2049*b30d1939SAndy Fiddaman 				continue;
2050*b30d1939SAndy Fiddaman 			}
2051*b30d1939SAndy Fiddaman 			if((r & HIST_ERROR) && sh_isoption(SH_HISTREEDIT))
2052*b30d1939SAndy Fiddaman 			{
2053*b30d1939SAndy Fiddaman 				reedit  = rsize - 1;
2054*b30d1939SAndy Fiddaman 				continue;
2055*b30d1939SAndy Fiddaman 			}
2056*b30d1939SAndy Fiddaman 			if(r & (HIST_ERROR|HIST_PRINT))
2057*b30d1939SAndy Fiddaman 			{
2058*b30d1939SAndy Fiddaman 				*(char*)buff = '\n';
2059*b30d1939SAndy Fiddaman 				rsize = 1;
2060*b30d1939SAndy Fiddaman 			}
2061*b30d1939SAndy Fiddaman 		}
2062*b30d1939SAndy Fiddaman #endif
2063*b30d1939SAndy Fiddaman 		break;
2064*b30d1939SAndy Fiddaman 	}
2065*b30d1939SAndy Fiddaman 	return(rsize);
2066*b30d1939SAndy Fiddaman }
2067*b30d1939SAndy Fiddaman 
2068*b30d1939SAndy Fiddaman /*
2069*b30d1939SAndy Fiddaman  * check and return the attributes for a file descriptor
2070*b30d1939SAndy Fiddaman  */
2071*b30d1939SAndy Fiddaman 
sh_iocheckfd(Shell_t * shp,register int fd)2072*b30d1939SAndy Fiddaman int sh_iocheckfd(Shell_t *shp, register int fd)
2073*b30d1939SAndy Fiddaman {
2074*b30d1939SAndy Fiddaman 	register int flags, n;
2075*b30d1939SAndy Fiddaman 
2076*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2077*b30d1939SAndy Fiddaman 
2078*b30d1939SAndy Fiddaman 	if((n=shp->fdstatus[fd])&IOCLOSE)
2079*b30d1939SAndy Fiddaman 		return(n);
2080*b30d1939SAndy Fiddaman 	if(!(n&(IOREAD|IOWRITE)))
2081*b30d1939SAndy Fiddaman 	{
2082*b30d1939SAndy Fiddaman #ifdef F_GETFL
2083*b30d1939SAndy Fiddaman 		if((flags=fcntl(fd,F_GETFL,0)) < 0)
2084*b30d1939SAndy Fiddaman 			return(shp->fdstatus[fd]=IOCLOSE);
2085*b30d1939SAndy Fiddaman 		if((flags&O_ACCMODE)!=O_WRONLY)
2086*b30d1939SAndy Fiddaman 			n |= IOREAD;
2087*b30d1939SAndy Fiddaman 		if((flags&O_ACCMODE)!=O_RDONLY)
2088*b30d1939SAndy Fiddaman 			n |= IOWRITE;
2089*b30d1939SAndy Fiddaman #else
2090*b30d1939SAndy Fiddaman 		struct stat statb;
2091*b30d1939SAndy Fiddaman 		if((flags = fstat(fd,&statb))< 0)
2092*b30d1939SAndy Fiddaman 			return(shp->fdstatus[fd]=IOCLOSE);
2093*b30d1939SAndy Fiddaman 		n |= (IOREAD|IOWRITE);
2094*b30d1939SAndy Fiddaman 		if(read(fd,"",0) < 0)
2095*b30d1939SAndy Fiddaman 			n &= ~IOREAD;
2096*b30d1939SAndy Fiddaman #endif /* F_GETFL */
2097*b30d1939SAndy Fiddaman 	}
2098*b30d1939SAndy Fiddaman 	if(!(n&(IOSEEK|IONOSEEK)))
2099*b30d1939SAndy Fiddaman 	{
2100*b30d1939SAndy Fiddaman 		struct stat statb;
2101*b30d1939SAndy Fiddaman 		/* /dev/null check is a workaround for select bug */
2102*b30d1939SAndy Fiddaman 		static ino_t null_ino;
2103*b30d1939SAndy Fiddaman 		static dev_t null_dev;
2104*b30d1939SAndy Fiddaman 		if(null_ino==0 && stat(e_devnull,&statb) >=0)
2105*b30d1939SAndy Fiddaman 		{
2106*b30d1939SAndy Fiddaman 			null_ino = statb.st_ino;
2107*b30d1939SAndy Fiddaman 			null_dev = statb.st_dev;
2108*b30d1939SAndy Fiddaman 		}
2109*b30d1939SAndy Fiddaman 		if(tty_check(fd))
2110*b30d1939SAndy Fiddaman 			n |= IOTTY;
2111*b30d1939SAndy Fiddaman 		if(lseek(fd,NIL(off_t),SEEK_CUR)<0)
2112*b30d1939SAndy Fiddaman 		{
2113*b30d1939SAndy Fiddaman 			n |= IONOSEEK;
2114*b30d1939SAndy Fiddaman #ifdef S_ISSOCK
2115*b30d1939SAndy Fiddaman 			if((fstat(fd,&statb)>=0) && S_ISSOCK(statb.st_mode))
2116*b30d1939SAndy Fiddaman 			{
2117*b30d1939SAndy Fiddaman 				n |= IOREAD|IOWRITE;
2118*b30d1939SAndy Fiddaman #   if _socketpair_shutdown_mode
2119*b30d1939SAndy Fiddaman 				if(!(statb.st_mode&S_IRUSR))
2120*b30d1939SAndy Fiddaman 					n &= ~IOREAD;
2121*b30d1939SAndy Fiddaman 				else if(!(statb.st_mode&S_IWUSR))
2122*b30d1939SAndy Fiddaman 					n &= ~IOWRITE;
2123*b30d1939SAndy Fiddaman #   endif
2124*b30d1939SAndy Fiddaman 			}
2125*b30d1939SAndy Fiddaman #endif /* S_ISSOCK */
2126*b30d1939SAndy Fiddaman 		}
2127*b30d1939SAndy Fiddaman 		else if((fstat(fd,&statb)>=0) && (
2128*b30d1939SAndy Fiddaman 			S_ISFIFO(statb.st_mode) ||
2129*b30d1939SAndy Fiddaman #ifdef S_ISSOCK
2130*b30d1939SAndy Fiddaman 			S_ISSOCK(statb.st_mode) ||
2131*b30d1939SAndy Fiddaman #endif /* S_ISSOCK */
2132*b30d1939SAndy Fiddaman 			/* The following is for sockets on the sgi */
2133*b30d1939SAndy Fiddaman 			(statb.st_ino==0 && (statb.st_mode & ~(S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH|S_IXUSR|S_IXGRP|S_IXOTH|S_ISUID|S_ISGID))==0) ||
2134*b30d1939SAndy Fiddaman 			(S_ISCHR(statb.st_mode) && (statb.st_ino!=null_ino || statb.st_dev!=null_dev))
2135*b30d1939SAndy Fiddaman 		))
2136*b30d1939SAndy Fiddaman 			n |= IONOSEEK;
2137*b30d1939SAndy Fiddaman 		else
2138*b30d1939SAndy Fiddaman 			n |= IOSEEK;
2139*b30d1939SAndy Fiddaman 	}
2140*b30d1939SAndy Fiddaman 	if(fd==0)
2141*b30d1939SAndy Fiddaman 		n &= ~IOWRITE;
2142*b30d1939SAndy Fiddaman 	else if(fd==1)
2143*b30d1939SAndy Fiddaman 		n &= ~IOREAD;
2144*b30d1939SAndy Fiddaman 	shp->fdstatus[fd] = n;
2145*b30d1939SAndy Fiddaman 	return(n);
2146*b30d1939SAndy Fiddaman }
2147*b30d1939SAndy Fiddaman 
2148*b30d1939SAndy Fiddaman /*
2149*b30d1939SAndy Fiddaman  * Display prompt PS<flag> on standard error
2150*b30d1939SAndy Fiddaman  */
2151*b30d1939SAndy Fiddaman 
io_prompt(Shell_t * shp,Sfio_t * iop,register int flag)2152*b30d1939SAndy Fiddaman static int	io_prompt(Shell_t *shp,Sfio_t *iop,register int flag)
2153*b30d1939SAndy Fiddaman {
2154*b30d1939SAndy Fiddaman 	register char *cp;
2155*b30d1939SAndy Fiddaman 	char buff[1];
2156*b30d1939SAndy Fiddaman 	char *endprompt;
2157*b30d1939SAndy Fiddaman 	static short cmdno;
2158*b30d1939SAndy Fiddaman 	int sfflags;
2159*b30d1939SAndy Fiddaman 	if(flag<3 && !sh_isstate(SH_INTERACTIVE))
2160*b30d1939SAndy Fiddaman 		flag = 0;
2161*b30d1939SAndy Fiddaman 	if(flag==2 && sfpkrd(sffileno(iop),buff,1,'\n',0,1) >= 0)
2162*b30d1939SAndy Fiddaman 		flag = 0;
2163*b30d1939SAndy Fiddaman 	if(flag==0)
2164*b30d1939SAndy Fiddaman 		return(sfsync(sfstderr));
2165*b30d1939SAndy Fiddaman 	sfflags = sfset(sfstderr,SF_SHARE|SF_PUBLIC|SF_READ,0);
2166*b30d1939SAndy Fiddaman 	if(!(shp->prompt=(char*)sfreserve(sfstderr,0,0)))
2167*b30d1939SAndy Fiddaman 		shp->prompt = "";
2168*b30d1939SAndy Fiddaman 	switch(flag)
2169*b30d1939SAndy Fiddaman 	{
2170*b30d1939SAndy Fiddaman 		case 1:
2171*b30d1939SAndy Fiddaman 		{
2172*b30d1939SAndy Fiddaman 			register int c;
2173*b30d1939SAndy Fiddaman #if defined(TIOCLBIC) && defined(LFLUSHO)
2174*b30d1939SAndy Fiddaman 			if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
2175*b30d1939SAndy Fiddaman 			{
2176*b30d1939SAndy Fiddaman 				/*
2177*b30d1939SAndy Fiddaman 				 * re-enable output in case the user has
2178*b30d1939SAndy Fiddaman 				 * disabled it.  Not needed with edit mode
2179*b30d1939SAndy Fiddaman 				 */
2180*b30d1939SAndy Fiddaman 				int mode = LFLUSHO;
2181*b30d1939SAndy Fiddaman 				ioctl(sffileno(sfstderr),TIOCLBIC,&mode);
2182*b30d1939SAndy Fiddaman 			}
2183*b30d1939SAndy Fiddaman #endif	/* TIOCLBIC */
2184*b30d1939SAndy Fiddaman 			cp = sh_mactry(shp,nv_getval(sh_scoped(shp,PS1NOD)));
2185*b30d1939SAndy Fiddaman 			for(;c= *cp;cp++)
2186*b30d1939SAndy Fiddaman 			{
2187*b30d1939SAndy Fiddaman 				if(c==HIST_CHAR)
2188*b30d1939SAndy Fiddaman 				{
2189*b30d1939SAndy Fiddaman 					/* look at next character */
2190*b30d1939SAndy Fiddaman 					c = *++cp;
2191*b30d1939SAndy Fiddaman 					/* print out line number if not !! */
2192*b30d1939SAndy Fiddaman 					if(c!= HIST_CHAR)
2193*b30d1939SAndy Fiddaman 					{
2194*b30d1939SAndy Fiddaman 						sfprintf(sfstderr,"%d", shp->gd->hist_ptr?(int)shp->gd->hist_ptr->histind:++cmdno);
2195*b30d1939SAndy Fiddaman 					}
2196*b30d1939SAndy Fiddaman 					if(c==0)
2197*b30d1939SAndy Fiddaman 						goto done;
2198*b30d1939SAndy Fiddaman 				}
2199*b30d1939SAndy Fiddaman 				sfputc(sfstderr,c);
2200*b30d1939SAndy Fiddaman 			}
2201*b30d1939SAndy Fiddaman 			goto done;
2202*b30d1939SAndy Fiddaman 		}
2203*b30d1939SAndy Fiddaman 		case 2:
2204*b30d1939SAndy Fiddaman 			cp = nv_getval(sh_scoped(shp,PS2NOD));
2205*b30d1939SAndy Fiddaman 			break;
2206*b30d1939SAndy Fiddaman 		case 3:
2207*b30d1939SAndy Fiddaman 			cp = nv_getval(sh_scoped(shp,PS3NOD));
2208*b30d1939SAndy Fiddaman 			break;
2209*b30d1939SAndy Fiddaman 		default:
2210*b30d1939SAndy Fiddaman 			goto done;
2211*b30d1939SAndy Fiddaman 	}
2212*b30d1939SAndy Fiddaman 	if(cp)
2213*b30d1939SAndy Fiddaman 		sfputr(sfstderr,cp,-1);
2214*b30d1939SAndy Fiddaman done:
2215*b30d1939SAndy Fiddaman 	if(*shp->prompt && (endprompt=(char*)sfreserve(sfstderr,0,0)))
2216*b30d1939SAndy Fiddaman 		*endprompt = 0;
2217*b30d1939SAndy Fiddaman 	sfset(sfstderr,sfflags&SF_READ|SF_SHARE|SF_PUBLIC,1);
2218*b30d1939SAndy Fiddaman 	return(sfsync(sfstderr));
2219*b30d1939SAndy Fiddaman }
2220*b30d1939SAndy Fiddaman 
2221*b30d1939SAndy Fiddaman /*
2222*b30d1939SAndy Fiddaman  * This discipline is inserted on write pipes to prevent SIGPIPE
2223*b30d1939SAndy Fiddaman  * from causing an infinite loop
2224*b30d1939SAndy Fiddaman  */
pipeexcept(Sfio_t * iop,int mode,void * data,Sfdisc_t * handle)2225*b30d1939SAndy Fiddaman static int pipeexcept(Sfio_t* iop, int mode, void *data, Sfdisc_t* handle)
2226*b30d1939SAndy Fiddaman {
2227*b30d1939SAndy Fiddaman 	if(mode==SF_DPOP || mode==SF_FINAL)
2228*b30d1939SAndy Fiddaman 		free((void*)handle);
2229*b30d1939SAndy Fiddaman 	else if(mode==SF_WRITE && ERROR_PIPE(errno))
2230*b30d1939SAndy Fiddaman 	{
2231*b30d1939SAndy Fiddaman 		sfpurge(iop);
2232*b30d1939SAndy Fiddaman 		return(-1);
2233*b30d1939SAndy Fiddaman 	}
2234*b30d1939SAndy Fiddaman 	return(0);
2235*b30d1939SAndy Fiddaman }
2236*b30d1939SAndy Fiddaman 
2237*b30d1939SAndy Fiddaman /*
2238*b30d1939SAndy Fiddaman  * keep track of each stream that is opened and closed
2239*b30d1939SAndy Fiddaman  */
sftrack(Sfio_t * sp,int flag,void * data)2240*b30d1939SAndy Fiddaman static void	sftrack(Sfio_t* sp, int flag, void* data)
2241*b30d1939SAndy Fiddaman {
2242*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2243*b30d1939SAndy Fiddaman 	register int fd = sffileno(sp);
2244*b30d1939SAndy Fiddaman 	register struct checkpt *pp;
2245*b30d1939SAndy Fiddaman 	register int mode;
2246*b30d1939SAndy Fiddaman 	int newfd = integralof(data);
2247*b30d1939SAndy Fiddaman 	if(flag==SF_SETFD || flag==SF_CLOSING)
2248*b30d1939SAndy Fiddaman 	{
2249*b30d1939SAndy Fiddaman 		if(newfd<0)
2250*b30d1939SAndy Fiddaman 			flag = SF_CLOSING;
2251*b30d1939SAndy Fiddaman 		if(fdnotify)
2252*b30d1939SAndy Fiddaman 			(*fdnotify)(sffileno(sp),flag==SF_CLOSING?-1:newfd);
2253*b30d1939SAndy Fiddaman 	}
2254*b30d1939SAndy Fiddaman #ifdef DEBUG
2255*b30d1939SAndy Fiddaman 	if(flag==SF_READ || flag==SF_WRITE)
2256*b30d1939SAndy Fiddaman 	{
2257*b30d1939SAndy Fiddaman 		char *z = fmtbase((long)getpid(),0,0);
2258*b30d1939SAndy Fiddaman 		write(ERRIO,z,strlen(z));
2259*b30d1939SAndy Fiddaman 		write(ERRIO,": ",2);
2260*b30d1939SAndy Fiddaman 		write(ERRIO,"attempt to ",11);
2261*b30d1939SAndy Fiddaman 		if(flag==SF_READ)
2262*b30d1939SAndy Fiddaman 			write(ERRIO,"read from",9);
2263*b30d1939SAndy Fiddaman 		else
2264*b30d1939SAndy Fiddaman 			write(ERRIO,"write to",8);
2265*b30d1939SAndy Fiddaman 		write(ERRIO," locked stream\n",15);
2266*b30d1939SAndy Fiddaman 		return;
2267*b30d1939SAndy Fiddaman 	}
2268*b30d1939SAndy Fiddaman #endif
2269*b30d1939SAndy Fiddaman 	if(fd<0 || fd==PSEUDOFD || !VALIDATE_FD(shp, fd))
2270*b30d1939SAndy Fiddaman 		return;
2271*b30d1939SAndy Fiddaman 	if(sh_isstate(SH_NOTRACK))
2272*b30d1939SAndy Fiddaman 		return;
2273*b30d1939SAndy Fiddaman 	mode = sfset(sp,0,0);
2274*b30d1939SAndy Fiddaman 	if(sp==shp->heredocs && fd < 10 && flag==SF_SETFD)
2275*b30d1939SAndy Fiddaman 	{
2276*b30d1939SAndy Fiddaman 		fd = sfsetfd(sp,10);
2277*b30d1939SAndy Fiddaman 		fcntl(fd,F_SETFD,FD_CLOEXEC);
2278*b30d1939SAndy Fiddaman 	}
2279*b30d1939SAndy Fiddaman 	if(fd < 3)
2280*b30d1939SAndy Fiddaman 		return;
2281*b30d1939SAndy Fiddaman 	if(flag==SF_NEW)
2282*b30d1939SAndy Fiddaman 	{
2283*b30d1939SAndy Fiddaman 		if(!shp->sftable[fd] && shp->fdstatus[fd]==IOCLOSE)
2284*b30d1939SAndy Fiddaman 		{
2285*b30d1939SAndy Fiddaman 			shp->sftable[fd] = sp;
2286*b30d1939SAndy Fiddaman 			flag = (mode&SF_WRITE)?IOWRITE:0;
2287*b30d1939SAndy Fiddaman 			if(mode&SF_READ)
2288*b30d1939SAndy Fiddaman 				flag |= IOREAD;
2289*b30d1939SAndy Fiddaman 			shp->fdstatus[fd] = flag;
2290*b30d1939SAndy Fiddaman 			sh_iostream(shp,fd);
2291*b30d1939SAndy Fiddaman 		}
2292*b30d1939SAndy Fiddaman 		if((pp=(struct checkpt*)shp->jmplist) && pp->mode==SH_JMPCMD)
2293*b30d1939SAndy Fiddaman 		{
2294*b30d1939SAndy Fiddaman 			struct openlist *item;
2295*b30d1939SAndy Fiddaman 			/*
2296*b30d1939SAndy Fiddaman 			 * record open file descriptors so they can
2297*b30d1939SAndy Fiddaman 			 * be closed in case a longjmp prevents
2298*b30d1939SAndy Fiddaman 			 * built-ins from cleanup
2299*b30d1939SAndy Fiddaman 			 */
2300*b30d1939SAndy Fiddaman 			item = new_of(struct openlist, 0);
2301*b30d1939SAndy Fiddaman 			item->strm = sp;
2302*b30d1939SAndy Fiddaman 			item->next = pp->olist;
2303*b30d1939SAndy Fiddaman 			pp->olist = item;
2304*b30d1939SAndy Fiddaman 		}
2305*b30d1939SAndy Fiddaman 		if(fdnotify)
2306*b30d1939SAndy Fiddaman 			(*fdnotify)(-1,sffileno(sp));
2307*b30d1939SAndy Fiddaman 	}
2308*b30d1939SAndy Fiddaman 	else if(flag==SF_CLOSING || (flag==SF_SETFD  && newfd<=2))
2309*b30d1939SAndy Fiddaman 	{
2310*b30d1939SAndy Fiddaman 		shp->sftable[fd] = 0;
2311*b30d1939SAndy Fiddaman 		shp->fdstatus[fd]=IOCLOSE;
2312*b30d1939SAndy Fiddaman 		if(pp=(struct checkpt*)shp->jmplist)
2313*b30d1939SAndy Fiddaman 		{
2314*b30d1939SAndy Fiddaman 			struct openlist *item;
2315*b30d1939SAndy Fiddaman 			for(item=pp->olist; item; item=item->next)
2316*b30d1939SAndy Fiddaman 			{
2317*b30d1939SAndy Fiddaman 				if(item->strm == sp)
2318*b30d1939SAndy Fiddaman 				{
2319*b30d1939SAndy Fiddaman 					item->strm = 0;
2320*b30d1939SAndy Fiddaman 					break;
2321*b30d1939SAndy Fiddaman 				}
2322*b30d1939SAndy Fiddaman 			}
2323*b30d1939SAndy Fiddaman 		}
2324*b30d1939SAndy Fiddaman 	}
2325*b30d1939SAndy Fiddaman }
2326*b30d1939SAndy Fiddaman 
2327*b30d1939SAndy Fiddaman struct eval
2328*b30d1939SAndy Fiddaman {
2329*b30d1939SAndy Fiddaman 	Sfdisc_t	disc;
2330*b30d1939SAndy Fiddaman 	char		**argv;
2331*b30d1939SAndy Fiddaman 	short		slen;
2332*b30d1939SAndy Fiddaman 	char		addspace;
2333*b30d1939SAndy Fiddaman };
2334*b30d1939SAndy Fiddaman 
2335*b30d1939SAndy Fiddaman /*
2336*b30d1939SAndy Fiddaman  * Create a stream consisting of a space separated argv[] list
2337*b30d1939SAndy Fiddaman  */
2338*b30d1939SAndy Fiddaman 
sh_sfeval(register char * argv[])2339*b30d1939SAndy Fiddaman Sfio_t *sh_sfeval(register char *argv[])
2340*b30d1939SAndy Fiddaman {
2341*b30d1939SAndy Fiddaman 	register Sfio_t *iop;
2342*b30d1939SAndy Fiddaman 	register char *cp;
2343*b30d1939SAndy Fiddaman 	if(argv[1])
2344*b30d1939SAndy Fiddaman 		cp = "";
2345*b30d1939SAndy Fiddaman 	else
2346*b30d1939SAndy Fiddaman 		cp = argv[0];
2347*b30d1939SAndy Fiddaman 	iop = sfopen(NIL(Sfio_t*),(char*)cp,"s");
2348*b30d1939SAndy Fiddaman 	if(argv[1])
2349*b30d1939SAndy Fiddaman 	{
2350*b30d1939SAndy Fiddaman 		register struct eval *ep;
2351*b30d1939SAndy Fiddaman 		if(!(ep = new_of(struct eval,0)))
2352*b30d1939SAndy Fiddaman 			return(NIL(Sfio_t*));
2353*b30d1939SAndy Fiddaman 		ep->disc = eval_disc;
2354*b30d1939SAndy Fiddaman 		ep->argv = argv;
2355*b30d1939SAndy Fiddaman 		ep->slen  = -1;
2356*b30d1939SAndy Fiddaman 		ep->addspace  = 0;
2357*b30d1939SAndy Fiddaman 		sfdisc(iop,&ep->disc);
2358*b30d1939SAndy Fiddaman 	}
2359*b30d1939SAndy Fiddaman 	return(iop);
2360*b30d1939SAndy Fiddaman }
2361*b30d1939SAndy Fiddaman 
2362*b30d1939SAndy Fiddaman /*
2363*b30d1939SAndy Fiddaman  * This code gets called whenever an end of string is found with eval
2364*b30d1939SAndy Fiddaman  */
2365*b30d1939SAndy Fiddaman 
eval_exceptf(Sfio_t * iop,int type,void * data,Sfdisc_t * handle)2366*b30d1939SAndy Fiddaman static int eval_exceptf(Sfio_t *iop,int type, void *data, Sfdisc_t *handle)
2367*b30d1939SAndy Fiddaman {
2368*b30d1939SAndy Fiddaman 	register struct eval *ep = (struct eval*)handle;
2369*b30d1939SAndy Fiddaman 	register char	*cp;
2370*b30d1939SAndy Fiddaman 	register int	len;
2371*b30d1939SAndy Fiddaman 
2372*b30d1939SAndy Fiddaman 	/* no more to do */
2373*b30d1939SAndy Fiddaman 	if(type!=SF_READ || !(cp = ep->argv[0]))
2374*b30d1939SAndy Fiddaman 	{
2375*b30d1939SAndy Fiddaman 		if(type==SF_CLOSING)
2376*b30d1939SAndy Fiddaman 			sfdisc(iop,SF_POPDISC);
2377*b30d1939SAndy Fiddaman 		else if(ep && (type==SF_DPOP || type==SF_FINAL))
2378*b30d1939SAndy Fiddaman 			free((void*)ep);
2379*b30d1939SAndy Fiddaman 		return(0);
2380*b30d1939SAndy Fiddaman 	}
2381*b30d1939SAndy Fiddaman 
2382*b30d1939SAndy Fiddaman 	if(!ep->addspace)
2383*b30d1939SAndy Fiddaman 	{
2384*b30d1939SAndy Fiddaman 		/* get the length of this string */
2385*b30d1939SAndy Fiddaman 		ep->slen = len = strlen(cp);
2386*b30d1939SAndy Fiddaman 		/* move to next string */
2387*b30d1939SAndy Fiddaman 		ep->argv++;
2388*b30d1939SAndy Fiddaman 	}
2389*b30d1939SAndy Fiddaman 	else /* insert space between arguments */
2390*b30d1939SAndy Fiddaman 	{
2391*b30d1939SAndy Fiddaman 		len = 1;
2392*b30d1939SAndy Fiddaman 		cp = " ";
2393*b30d1939SAndy Fiddaman 	}
2394*b30d1939SAndy Fiddaman 	/* insert the new string */
2395*b30d1939SAndy Fiddaman 	sfsetbuf(iop,cp,len);
2396*b30d1939SAndy Fiddaman 	ep->addspace = !ep->addspace;
2397*b30d1939SAndy Fiddaman 	return(1);
2398*b30d1939SAndy Fiddaman }
2399*b30d1939SAndy Fiddaman 
2400*b30d1939SAndy Fiddaman /*
2401*b30d1939SAndy Fiddaman  * This routine returns a stream pointer to a segment of length <size> from
2402*b30d1939SAndy Fiddaman  * the stream <sp> starting at offset <offset>
2403*b30d1939SAndy Fiddaman  * The stream can be read with the normal stream operations
2404*b30d1939SAndy Fiddaman  */
2405*b30d1939SAndy Fiddaman 
subopen(Shell_t * shp,Sfio_t * sp,off_t offset,long size)2406*b30d1939SAndy Fiddaman static Sfio_t *subopen(Shell_t *shp,Sfio_t* sp, off_t offset, long size)
2407*b30d1939SAndy Fiddaman {
2408*b30d1939SAndy Fiddaman 	register struct subfile *disp;
2409*b30d1939SAndy Fiddaman 	if(sfseek(sp,offset,SEEK_SET) <0)
2410*b30d1939SAndy Fiddaman 		return(NIL(Sfio_t*));
2411*b30d1939SAndy Fiddaman 	if(!(disp = (struct subfile*)malloc(sizeof(struct subfile)+IOBSIZE+1)))
2412*b30d1939SAndy Fiddaman 		return(NIL(Sfio_t*));
2413*b30d1939SAndy Fiddaman 	disp->disc = sub_disc;
2414*b30d1939SAndy Fiddaman 	disp->oldsp = sp;
2415*b30d1939SAndy Fiddaman 	disp->offset = offset;
2416*b30d1939SAndy Fiddaman 	disp->size = disp->left = size;
2417*b30d1939SAndy Fiddaman 	sp = sfnew(NIL(Sfio_t*),(char*)(disp+1),IOBSIZE,PSEUDOFD,SF_READ);
2418*b30d1939SAndy Fiddaman 	sfdisc(sp,&disp->disc);
2419*b30d1939SAndy Fiddaman 	return(sp);
2420*b30d1939SAndy Fiddaman }
2421*b30d1939SAndy Fiddaman 
2422*b30d1939SAndy Fiddaman /*
2423*b30d1939SAndy Fiddaman  * read function for subfile discipline
2424*b30d1939SAndy Fiddaman  */
subread(Sfio_t * sp,void * buff,register size_t size,Sfdisc_t * handle)2425*b30d1939SAndy Fiddaman static ssize_t subread(Sfio_t* sp,void* buff,register size_t size,Sfdisc_t* handle)
2426*b30d1939SAndy Fiddaman {
2427*b30d1939SAndy Fiddaman 	register struct subfile *disp = (struct subfile*)handle;
2428*b30d1939SAndy Fiddaman 	ssize_t	n;
2429*b30d1939SAndy Fiddaman 	NOT_USED(sp);
2430*b30d1939SAndy Fiddaman 	sfseek(disp->oldsp,disp->offset,SEEK_SET);
2431*b30d1939SAndy Fiddaman 	if(disp->left == 0)
2432*b30d1939SAndy Fiddaman 		return(0);
2433*b30d1939SAndy Fiddaman 	if(size > disp->left)
2434*b30d1939SAndy Fiddaman 		size = disp->left;
2435*b30d1939SAndy Fiddaman 	disp->left -= size;
2436*b30d1939SAndy Fiddaman 	n = sfread(disp->oldsp,buff,size);
2437*b30d1939SAndy Fiddaman 	if(size>0)
2438*b30d1939SAndy Fiddaman 		disp->offset += size;
2439*b30d1939SAndy Fiddaman 	return(n);
2440*b30d1939SAndy Fiddaman }
2441*b30d1939SAndy Fiddaman 
2442*b30d1939SAndy Fiddaman /*
2443*b30d1939SAndy Fiddaman  * exception handler for subfile discipline
2444*b30d1939SAndy Fiddaman  */
subexcept(Sfio_t * sp,register int mode,void * data,Sfdisc_t * handle)2445*b30d1939SAndy Fiddaman static int subexcept(Sfio_t* sp,register int mode, void *data, Sfdisc_t* handle)
2446*b30d1939SAndy Fiddaman {
2447*b30d1939SAndy Fiddaman 	register struct subfile *disp = (struct subfile*)handle;
2448*b30d1939SAndy Fiddaman 	if(mode==SF_CLOSING)
2449*b30d1939SAndy Fiddaman 	{
2450*b30d1939SAndy Fiddaman 		sfdisc(sp,SF_POPDISC);
2451*b30d1939SAndy Fiddaman 		sfsetfd(sp,-1);
2452*b30d1939SAndy Fiddaman 		return(0);
2453*b30d1939SAndy Fiddaman 	}
2454*b30d1939SAndy Fiddaman 	else if(disp && (mode==SF_DPOP || mode==SF_FINAL))
2455*b30d1939SAndy Fiddaman 	{
2456*b30d1939SAndy Fiddaman 		free((void*)disp);
2457*b30d1939SAndy Fiddaman 		return(0);
2458*b30d1939SAndy Fiddaman 	}
2459*b30d1939SAndy Fiddaman #ifdef SF_ATEXIT
2460*b30d1939SAndy Fiddaman 	else if (mode==SF_ATEXIT)
2461*b30d1939SAndy Fiddaman 	{
2462*b30d1939SAndy Fiddaman 		sfdisc(sp, SF_POPDISC);
2463*b30d1939SAndy Fiddaman 		return(0);
2464*b30d1939SAndy Fiddaman 	}
2465*b30d1939SAndy Fiddaman #endif
2466*b30d1939SAndy Fiddaman 	else if(mode==SF_READ)
2467*b30d1939SAndy Fiddaman 		return(0);
2468*b30d1939SAndy Fiddaman 	return(-1);
2469*b30d1939SAndy Fiddaman }
2470*b30d1939SAndy Fiddaman 
2471*b30d1939SAndy Fiddaman #define NROW    15      /* number of rows before going to multi-columns */
2472*b30d1939SAndy Fiddaman #define LBLSIZ	3	/* size of label field and interfield spacing */
2473*b30d1939SAndy Fiddaman /*
2474*b30d1939SAndy Fiddaman  * print a list of arguments in columns
2475*b30d1939SAndy Fiddaman  */
sh_menu(Sfio_t * outfile,int argn,char * argv[])2476*b30d1939SAndy Fiddaman void	sh_menu(Sfio_t *outfile,int argn,char *argv[])
2477*b30d1939SAndy Fiddaman {
2478*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2479*b30d1939SAndy Fiddaman 	register int i,j;
2480*b30d1939SAndy Fiddaman 	register char **arg;
2481*b30d1939SAndy Fiddaman 	int nrow, ncol=1, ndigits=1;
2482*b30d1939SAndy Fiddaman 	int fldsize, wsize = ed_window();
2483*b30d1939SAndy Fiddaman 	char *cp = nv_getval(sh_scoped(shp,LINES));
2484*b30d1939SAndy Fiddaman 	nrow = (cp?1+2*((int)strtol(cp, (char**)0, 10)/3):NROW);
2485*b30d1939SAndy Fiddaman 	for(i=argn;i >= 10;i /= 10)
2486*b30d1939SAndy Fiddaman 		ndigits++;
2487*b30d1939SAndy Fiddaman 	if(argn < nrow)
2488*b30d1939SAndy Fiddaman 	{
2489*b30d1939SAndy Fiddaman 		nrow = argn;
2490*b30d1939SAndy Fiddaman 		goto skip;
2491*b30d1939SAndy Fiddaman 	}
2492*b30d1939SAndy Fiddaman 	i = 0;
2493*b30d1939SAndy Fiddaman 	for(arg=argv; *arg;arg++)
2494*b30d1939SAndy Fiddaman 	{
2495*b30d1939SAndy Fiddaman 		if((j=strlen(*arg)) > i)
2496*b30d1939SAndy Fiddaman 			i = j;
2497*b30d1939SAndy Fiddaman 	}
2498*b30d1939SAndy Fiddaman 	i += (ndigits+LBLSIZ);
2499*b30d1939SAndy Fiddaman 	if(i < wsize)
2500*b30d1939SAndy Fiddaman 		ncol = wsize/i;
2501*b30d1939SAndy Fiddaman 	if(argn > nrow*ncol)
2502*b30d1939SAndy Fiddaman 	{
2503*b30d1939SAndy Fiddaman 		nrow = 1 + (argn-1)/ncol;
2504*b30d1939SAndy Fiddaman 	}
2505*b30d1939SAndy Fiddaman 	else
2506*b30d1939SAndy Fiddaman 	{
2507*b30d1939SAndy Fiddaman 		ncol = 1 + (argn-1)/nrow;
2508*b30d1939SAndy Fiddaman 		nrow = 1 + (argn-1)/ncol;
2509*b30d1939SAndy Fiddaman 	}
2510*b30d1939SAndy Fiddaman skip:
2511*b30d1939SAndy Fiddaman 	fldsize = (wsize/ncol)-(ndigits+LBLSIZ);
2512*b30d1939SAndy Fiddaman 	for(i=0;i<nrow;i++)
2513*b30d1939SAndy Fiddaman 	{
2514*b30d1939SAndy Fiddaman 		if(shp->trapnote&SH_SIGSET)
2515*b30d1939SAndy Fiddaman 			return;
2516*b30d1939SAndy Fiddaman 		j = i;
2517*b30d1939SAndy Fiddaman 		while(1)
2518*b30d1939SAndy Fiddaman 		{
2519*b30d1939SAndy Fiddaman 			arg = argv+j;
2520*b30d1939SAndy Fiddaman 			sfprintf(outfile,"%*d) %s",ndigits,j+1,*arg);
2521*b30d1939SAndy Fiddaman 			j += nrow;
2522*b30d1939SAndy Fiddaman 			if(j >= argn)
2523*b30d1939SAndy Fiddaman 				break;
2524*b30d1939SAndy Fiddaman 			sfnputc(outfile,' ',fldsize-strlen(*arg));
2525*b30d1939SAndy Fiddaman 		}
2526*b30d1939SAndy Fiddaman 		sfputc(outfile,'\n');
2527*b30d1939SAndy Fiddaman 	}
2528*b30d1939SAndy Fiddaman }
2529*b30d1939SAndy Fiddaman 
2530*b30d1939SAndy Fiddaman #undef read
2531*b30d1939SAndy Fiddaman /*
2532*b30d1939SAndy Fiddaman  * shell version of read() for user added builtins
2533*b30d1939SAndy Fiddaman  */
sh_read(register int fd,void * buff,size_t n)2534*b30d1939SAndy Fiddaman ssize_t sh_read(register int fd, void* buff, size_t n)
2535*b30d1939SAndy Fiddaman {
2536*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2537*b30d1939SAndy Fiddaman 	register Sfio_t *sp;
2538*b30d1939SAndy Fiddaman 
2539*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2540*b30d1939SAndy Fiddaman 	if(sp=shp->sftable[fd])
2541*b30d1939SAndy Fiddaman 		return(sfread(sp,buff,n));
2542*b30d1939SAndy Fiddaman 	else
2543*b30d1939SAndy Fiddaman 		return(read(fd,buff,n));
2544*b30d1939SAndy Fiddaman }
2545*b30d1939SAndy Fiddaman 
2546*b30d1939SAndy Fiddaman #undef write
2547*b30d1939SAndy Fiddaman /*
2548*b30d1939SAndy Fiddaman  * shell version of write() for user added builtins
2549*b30d1939SAndy Fiddaman  */
sh_write(register int fd,const void * buff,size_t n)2550*b30d1939SAndy Fiddaman ssize_t sh_write(register int fd, const void* buff, size_t n)
2551*b30d1939SAndy Fiddaman {
2552*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2553*b30d1939SAndy Fiddaman 	register Sfio_t *sp;
2554*b30d1939SAndy Fiddaman 
2555*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2556*b30d1939SAndy Fiddaman 	if(sp=shp->sftable[fd])
2557*b30d1939SAndy Fiddaman 		return(sfwrite(sp,buff,n));
2558*b30d1939SAndy Fiddaman 	else
2559*b30d1939SAndy Fiddaman 		return(write(fd,buff,n));
2560*b30d1939SAndy Fiddaman }
2561*b30d1939SAndy Fiddaman 
2562*b30d1939SAndy Fiddaman #undef lseek
2563*b30d1939SAndy Fiddaman /*
2564*b30d1939SAndy Fiddaman  * shell version of lseek() for user added builtins
2565*b30d1939SAndy Fiddaman  */
sh_seek(register int fd,off_t offset,int whence)2566*b30d1939SAndy Fiddaman off_t sh_seek(register int fd, off_t offset, int whence)
2567*b30d1939SAndy Fiddaman {
2568*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2569*b30d1939SAndy Fiddaman 	register Sfio_t *sp;
2570*b30d1939SAndy Fiddaman 
2571*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2572*b30d1939SAndy Fiddaman 	if((sp=shp->sftable[fd]) && (sfset(sp,0,0)&(SF_READ|SF_WRITE)))
2573*b30d1939SAndy Fiddaman 		return(sfseek(sp,offset,whence));
2574*b30d1939SAndy Fiddaman 	else
2575*b30d1939SAndy Fiddaman 		return(lseek(fd,offset,whence));
2576*b30d1939SAndy Fiddaman }
2577*b30d1939SAndy Fiddaman 
2578*b30d1939SAndy Fiddaman #undef dup
sh_dup(register int old)2579*b30d1939SAndy Fiddaman int sh_dup(register int old)
2580*b30d1939SAndy Fiddaman {
2581*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2582*b30d1939SAndy Fiddaman 	register int fd = dup(old);
2583*b30d1939SAndy Fiddaman 
2584*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, old);
2585*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2586*b30d1939SAndy Fiddaman 	if(fd>=0)
2587*b30d1939SAndy Fiddaman 	{
2588*b30d1939SAndy Fiddaman 		if(shp->fdstatus[old] == IOCLOSE)
2589*b30d1939SAndy Fiddaman 			shp->fdstatus[old] = 0;
2590*b30d1939SAndy Fiddaman 		shp->fdstatus[fd] = (shp->fdstatus[old]&~IOCLEX);
2591*b30d1939SAndy Fiddaman 		if(fdnotify)
2592*b30d1939SAndy Fiddaman 			(*fdnotify)(old,fd);
2593*b30d1939SAndy Fiddaman 	}
2594*b30d1939SAndy Fiddaman 	return(fd);
2595*b30d1939SAndy Fiddaman }
2596*b30d1939SAndy Fiddaman 
2597*b30d1939SAndy Fiddaman #undef fcntl
sh_fcntl(register int fd,int op,...)2598*b30d1939SAndy Fiddaman int sh_fcntl(register int fd, int op, ...)
2599*b30d1939SAndy Fiddaman {
2600*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2601*b30d1939SAndy Fiddaman 	int newfd, arg;
2602*b30d1939SAndy Fiddaman 	va_list		ap;
2603*b30d1939SAndy Fiddaman 	va_start(ap, op);
2604*b30d1939SAndy Fiddaman 	arg =  va_arg(ap, int) ;
2605*b30d1939SAndy Fiddaman 	va_end(ap);
2606*b30d1939SAndy Fiddaman 	newfd = fcntl(fd,op,arg);
2607*b30d1939SAndy Fiddaman 
2608*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2609*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, newfd);
2610*b30d1939SAndy Fiddaman 
2611*b30d1939SAndy Fiddaman 	if(newfd>=0) switch(op)
2612*b30d1939SAndy Fiddaman 	{
2613*b30d1939SAndy Fiddaman 	    case F_DUPFD:
2614*b30d1939SAndy Fiddaman 		if(shp->fdstatus[fd] == IOCLOSE)
2615*b30d1939SAndy Fiddaman 			shp->fdstatus[fd] = 0;
2616*b30d1939SAndy Fiddaman 		shp->fdstatus[newfd] = (shp->fdstatus[fd]&~IOCLEX);
2617*b30d1939SAndy Fiddaman 		if(fdnotify)
2618*b30d1939SAndy Fiddaman 			(*fdnotify)(fd,newfd);
2619*b30d1939SAndy Fiddaman 		break;
2620*b30d1939SAndy Fiddaman 	    case F_SETFD:
2621*b30d1939SAndy Fiddaman 		if(shp->fdstatus[fd] == IOCLOSE)
2622*b30d1939SAndy Fiddaman 			shp->fdstatus[fd] = 0;
2623*b30d1939SAndy Fiddaman 		if(arg&FD_CLOEXEC)
2624*b30d1939SAndy Fiddaman 			shp->fdstatus[fd] |= IOCLEX;
2625*b30d1939SAndy Fiddaman 		else
2626*b30d1939SAndy Fiddaman 			shp->fdstatus[fd] &= ~IOCLEX;
2627*b30d1939SAndy Fiddaman 	}
2628*b30d1939SAndy Fiddaman 	return(newfd);
2629*b30d1939SAndy Fiddaman }
2630*b30d1939SAndy Fiddaman 
2631*b30d1939SAndy Fiddaman #undef umask
sh_umask(mode_t m)2632*b30d1939SAndy Fiddaman mode_t	sh_umask(mode_t m)
2633*b30d1939SAndy Fiddaman {
2634*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2635*b30d1939SAndy Fiddaman 	shp->mask = m;
2636*b30d1939SAndy Fiddaman 	return(umask(m));
2637*b30d1939SAndy Fiddaman }
2638*b30d1939SAndy Fiddaman 
2639*b30d1939SAndy Fiddaman /*
2640*b30d1939SAndy Fiddaman  * give file descriptor <fd> and <mode>, return an iostream pointer
2641*b30d1939SAndy Fiddaman  * <mode> must be SF_READ or SF_WRITE
2642*b30d1939SAndy Fiddaman  * <fd> must be a non-negative number ofr SH_IOCOPROCESS or SH_IOHISTFILE.
2643*b30d1939SAndy Fiddaman  * returns NULL on failure and may set errno.
2644*b30d1939SAndy Fiddaman  */
2645*b30d1939SAndy Fiddaman 
sh_iogetiop(int fd,int mode)2646*b30d1939SAndy Fiddaman Sfio_t *sh_iogetiop(int fd, int mode)
2647*b30d1939SAndy Fiddaman {
2648*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
2649*b30d1939SAndy Fiddaman 	int n;
2650*b30d1939SAndy Fiddaman 	Sfio_t *iop=0;
2651*b30d1939SAndy Fiddaman 	if(mode!=SF_READ && mode!=SF_WRITE)
2652*b30d1939SAndy Fiddaman 	{
2653*b30d1939SAndy Fiddaman 		errno = EINVAL;
2654*b30d1939SAndy Fiddaman 		return(iop);
2655*b30d1939SAndy Fiddaman 	}
2656*b30d1939SAndy Fiddaman 	switch(fd)
2657*b30d1939SAndy Fiddaman 	{
2658*b30d1939SAndy Fiddaman 	    case SH_IOHISTFILE:
2659*b30d1939SAndy Fiddaman 		if(!sh_histinit((void*)shp))
2660*b30d1939SAndy Fiddaman 			return(iop);
2661*b30d1939SAndy Fiddaman 		fd = sffileno(shp->gd->hist_ptr->histfp);
2662*b30d1939SAndy Fiddaman 		break;
2663*b30d1939SAndy Fiddaman 	    case SH_IOCOPROCESS:
2664*b30d1939SAndy Fiddaman 		if(mode==SF_WRITE)
2665*b30d1939SAndy Fiddaman 			fd = shp->coutpipe;
2666*b30d1939SAndy Fiddaman 		else
2667*b30d1939SAndy Fiddaman 			fd = shp->cpipe[0];
2668*b30d1939SAndy Fiddaman 		break;
2669*b30d1939SAndy Fiddaman 	    default:
2670*b30d1939SAndy Fiddaman 		if(fd<0 || !sh_iovalidfd(shp,fd))
2671*b30d1939SAndy Fiddaman 			fd = -1;
2672*b30d1939SAndy Fiddaman 	}
2673*b30d1939SAndy Fiddaman 	if(fd<0)
2674*b30d1939SAndy Fiddaman 	{
2675*b30d1939SAndy Fiddaman 		errno = EBADF;
2676*b30d1939SAndy Fiddaman 		return(iop);
2677*b30d1939SAndy Fiddaman 	}
2678*b30d1939SAndy Fiddaman 	if(!(n=shp->fdstatus[fd]))
2679*b30d1939SAndy Fiddaman 		n = sh_iocheckfd(shp,fd);
2680*b30d1939SAndy Fiddaman 	if(mode==SF_WRITE && !(n&IOWRITE))
2681*b30d1939SAndy Fiddaman 		return(iop);
2682*b30d1939SAndy Fiddaman 	if(mode==SF_READ && !(n&IOREAD))
2683*b30d1939SAndy Fiddaman 		return(iop);
2684*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2685*b30d1939SAndy Fiddaman 	if(!(iop = shp->sftable[fd]))
2686*b30d1939SAndy Fiddaman 		iop=sh_iostream(shp,fd);
2687*b30d1939SAndy Fiddaman 	return(iop);
2688*b30d1939SAndy Fiddaman }
2689*b30d1939SAndy Fiddaman 
2690*b30d1939SAndy Fiddaman typedef int (*Notify_f)(int,int);
2691*b30d1939SAndy Fiddaman 
sh_fdnotify(Notify_f notify)2692*b30d1939SAndy Fiddaman Notify_f    sh_fdnotify(Notify_f notify)
2693*b30d1939SAndy Fiddaman {
2694*b30d1939SAndy Fiddaman 	Notify_f old;
2695*b30d1939SAndy Fiddaman         old = fdnotify;
2696*b30d1939SAndy Fiddaman         fdnotify = notify;
2697*b30d1939SAndy Fiddaman         return(old);
2698*b30d1939SAndy Fiddaman }
2699*b30d1939SAndy Fiddaman 
sh_fd2sfio(int fd)2700*b30d1939SAndy Fiddaman Sfio_t	*sh_fd2sfio(int fd)
2701*b30d1939SAndy Fiddaman {
2702*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
2703*b30d1939SAndy Fiddaman 	register int status;
2704*b30d1939SAndy Fiddaman 	Sfio_t *sp;
2705*b30d1939SAndy Fiddaman 
2706*b30d1939SAndy Fiddaman 	VALIDATE_FD(shp, fd);
2707*b30d1939SAndy Fiddaman 	sp = shp->sftable[fd];
2708*b30d1939SAndy Fiddaman 	if(!sp  && (status = sh_iocheckfd(shp,fd))!=IOCLOSE)
2709*b30d1939SAndy Fiddaman 	{
2710*b30d1939SAndy Fiddaman 		register int flags=0;
2711*b30d1939SAndy Fiddaman 		if(status&IOREAD)
2712*b30d1939SAndy Fiddaman 			flags |= SF_READ;
2713*b30d1939SAndy Fiddaman 		if(status&IOWRITE)
2714*b30d1939SAndy Fiddaman 			flags |= SF_WRITE;
2715*b30d1939SAndy Fiddaman 		sp = sfnew(NULL, NULL, -1, fd,flags);
2716*b30d1939SAndy Fiddaman 		shp->sftable[fd] = sp;
2717*b30d1939SAndy Fiddaman 	}
2718*b30d1939SAndy Fiddaman 	return(sp);
2719*b30d1939SAndy Fiddaman }
2720*b30d1939SAndy Fiddaman 
sh_pathopen(const char * cp)2721*b30d1939SAndy Fiddaman Sfio_t *sh_pathopen(const char *cp)
2722*b30d1939SAndy Fiddaman {
2723*b30d1939SAndy Fiddaman 	Shell_t *shp = sh_getinterp();
2724*b30d1939SAndy Fiddaman 	int n;
2725*b30d1939SAndy Fiddaman #ifdef PATH_BFPATH
2726*b30d1939SAndy Fiddaman 	if((n=path_open(shp,cp,path_get(shp,cp))) < 0)
2727*b30d1939SAndy Fiddaman 		n = path_open(shp,cp,(Pathcomp_t*)0);
2728*b30d1939SAndy Fiddaman #else
2729*b30d1939SAndy Fiddaman 	if((n=path_open(shp,cp,path_get(cp))) < 0)
2730*b30d1939SAndy Fiddaman 		n = path_open(shp,cp,"");
2731*b30d1939SAndy Fiddaman #endif
2732*b30d1939SAndy Fiddaman 	if(n < 0)
2733*b30d1939SAndy Fiddaman 		errormsg(SH_DICT,ERROR_system(1),e_open,cp);
2734*b30d1939SAndy Fiddaman 	return(sh_iostream(shp,n));
2735*b30d1939SAndy Fiddaman }
2736*b30d1939SAndy Fiddaman 
sh_isdevfd(register const char * fd)2737*b30d1939SAndy Fiddaman int sh_isdevfd(register const char *fd)
2738*b30d1939SAndy Fiddaman {
2739*b30d1939SAndy Fiddaman 	if(!fd || memcmp(fd,"/dev/fd/",8) || fd[8]==0)
2740*b30d1939SAndy Fiddaman 		return(0);
2741*b30d1939SAndy Fiddaman 	for ( fd=&fd[8] ; *fd != '\0' ; fd++ )
2742*b30d1939SAndy Fiddaman 	{
2743*b30d1939SAndy Fiddaman 		if (*fd < '0' || *fd > '9')
2744*b30d1939SAndy Fiddaman 			return(0);
2745*b30d1939SAndy Fiddaman 	}
2746*b30d1939SAndy Fiddaman 	return(1);
2747*b30d1939SAndy Fiddaman }
2748*b30d1939SAndy Fiddaman 
2749*b30d1939SAndy Fiddaman #undef fchdir
sh_fchdir(int fd)2750*b30d1939SAndy Fiddaman int sh_fchdir(int fd)
2751*b30d1939SAndy Fiddaman {
2752*b30d1939SAndy Fiddaman 	int r,err=errno;
2753*b30d1939SAndy Fiddaman 	while((r=fchdir(fd))<0 && errno==EINTR)
2754*b30d1939SAndy Fiddaman 		errno = err;
2755*b30d1939SAndy Fiddaman 	return(r);
2756*b30d1939SAndy Fiddaman }
2757*b30d1939SAndy Fiddaman 
2758*b30d1939SAndy Fiddaman #undef chdir
sh_chdir(const char * dir)2759*b30d1939SAndy Fiddaman int sh_chdir(const char* dir)
2760*b30d1939SAndy Fiddaman {
2761*b30d1939SAndy Fiddaman 	int r,err=errno;
2762*b30d1939SAndy Fiddaman 	while((r=chdir(dir))<0 && errno==EINTR)
2763*b30d1939SAndy Fiddaman 		errno = err;
2764*b30d1939SAndy Fiddaman 	return(r);
2765*b30d1939SAndy Fiddaman }
2766*b30d1939SAndy Fiddaman 
2767*b30d1939SAndy Fiddaman // Return the lowest numbered fd that is equal to or greater than the requested
2768*b30d1939SAndy Fiddaman // `min_fd` and which is not currently in use.
sh_get_unused_fd(Shell_t * shp,int min_fd)2769*b30d1939SAndy Fiddaman int sh_get_unused_fd(Shell_t* shp, int min_fd) {
2770*b30d1939SAndy Fiddaman 	int fd;
2771*b30d1939SAndy Fiddaman 
2772*b30d1939SAndy Fiddaman  	while (1) {
2773*b30d1939SAndy Fiddaman  	if (fcntl(min_fd, F_GETFD) == -1) {
2774*b30d1939SAndy Fiddaman  		for(fd = 0; fd < shp->topfd; fd++) {
2775*b30d1939SAndy Fiddaman  			if (filemap[fd].save_fd == min_fd || filemap[fd].orig_fd == min_fd) break;
2776*b30d1939SAndy Fiddaman  		}
2777*b30d1939SAndy Fiddaman  		if (fd == shp->topfd) break;
2778*b30d1939SAndy Fiddaman  		}
2779*b30d1939SAndy Fiddaman  	min_fd++;
2780*b30d1939SAndy Fiddaman  	}
2781*b30d1939SAndy Fiddaman 
2782*b30d1939SAndy Fiddaman  	return min_fd;
2783*b30d1939SAndy Fiddaman }
2784*b30d1939SAndy Fiddaman 
2785