dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libshell / common / sh / io.c
blob6309c55815cc9a5cca0d10ddb535224222f64660
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1982-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * David Korn <dgk@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
23 * Input/output file processing
25 * David Korn
26 * AT&T Labs
30 #include "defs.h"
31 #include <fcin.h>
32 #include <ls.h>
33 #include <stdarg.h>
34 #include <regex.h>
35 #include "variables.h"
36 #include "path.h"
37 #include "io.h"
38 #include "jobs.h"
39 #include "shnodes.h"
40 #include "history.h"
41 #include "edit.h"
42 #include "timeout.h"
43 #include "FEATURE/externs"
44 #include "FEATURE/dynamic"
45 #include "FEATURE/poll"
47 #ifdef FNDELAY
48 # ifdef EAGAIN
49 # if EAGAIN!=EWOULDBLOCK
50 # undef EAGAIN
51 # define EAGAIN EWOULDBLOCK
52 # endif
53 # else
54 # define EAGAIN EWOULDBLOCK
55 # endif /* EAGAIN */
56 # ifndef O_NONBLOCK
57 # define O_NONBLOCK FNDELAY
58 # endif /* !O_NONBLOCK */
59 #endif /* FNDELAY */
61 #ifndef O_SERVICE
62 # define O_SERVICE O_NOCTTY
63 #endif
65 #define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
67 static void *timeout;
68 static int (*fdnotify)(int,int);
70 #if defined(_lib_socket) && defined(_sys_socket) && defined(_hdr_netinet_in)
71 # include <sys/socket.h>
72 # include <netdb.h>
73 # include <netinet/in.h>
74 # if !defined(htons) && !_lib_htons
75 # define htons(x) (x)
76 # endif
77 # if !defined(htonl) && !_lib_htonl
78 # define htonl(x) (x)
79 # endif
80 # if _pipe_socketpair
81 # ifndef SHUT_RD
82 # define SHUT_RD 0
83 # endif
84 # ifndef SHUT_WR
85 # define SHUT_WR 1
86 # endif
87 # if _socketpair_shutdown_mode
88 # 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)
89 # else
90 # 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)
91 # endif
92 # endif
94 #if !_lib_getaddrinfo
96 #undef EAI_SYSTEM
98 #define EAI_SYSTEM 1
100 #undef addrinfo
101 #undef getaddrinfo
102 #undef freeaddrinfo
104 #define addrinfo local_addrinfo
105 #define getaddrinfo local_getaddrinfo
106 #define freeaddrinfo local_freeaddrinfo
108 struct addrinfo
110 int ai_flags;
111 int ai_family;
112 int ai_socktype;
113 int ai_protocol;
114 socklen_t ai_addrlen;
115 struct sockaddr* ai_addr;
116 struct addrinfo* ai_next;
119 static int
120 getaddrinfo(const char* node, const char* service, const struct addrinfo* hint, struct addrinfo **addr)
122 unsigned long ip_addr = 0;
123 unsigned short ip_port = 0;
124 struct addrinfo* ap;
125 struct hostent* hp;
126 struct sockaddr_in* ip;
127 char* prot;
128 long n;
130 if (!(hp = gethostbyname(node)) || hp->h_addrtype!=AF_INET || hp->h_length>sizeof(struct in_addr))
132 errno = EADDRNOTAVAIL;
133 return EAI_SYSTEM;
135 ip_addr = (unsigned long)((struct in_addr*)hp->h_addr)->s_addr;
136 if ((n = strtol(service, &prot, 10)) > 0 && n <= USHRT_MAX && !*prot)
137 ip_port = htons((unsigned short)n);
138 else
140 struct servent* sp;
141 const char* protocol = 0;
143 if (hint)
144 switch (hint->ai_socktype)
146 case SOCK_STREAM:
147 switch (hint->ai_protocol)
149 case 0:
150 protocol = "tcp";
151 break;
152 #ifdef IPPROTO_SCTP
153 case IPPROTO_SCTP:
154 protocol = "sctp";
155 break;
156 #endif
158 break;
159 case SOCK_DGRAM:
160 protocol = "udp";
161 break;
163 if (!protocol)
165 errno = EPROTONOSUPPORT;
166 return 1;
168 if (sp = getservbyname(service, protocol))
169 ip_port = sp->s_port;
171 if (!ip_port)
173 errno = EADDRNOTAVAIL;
174 return EAI_SYSTEM;
176 if (!(ap = newof(0, struct addrinfo, 1, sizeof(struct sockaddr_in))))
177 return EAI_SYSTEM;
178 if (hint)
179 *ap = *hint;
180 ap->ai_family = hp->h_addrtype;
181 ap->ai_addrlen = sizeof(struct sockaddr_in);
182 ap->ai_addr = (struct sockaddr *)(ap+1);
183 ip = (struct sockaddr_in *)ap->ai_addr;
184 ip->sin_family = AF_INET;
185 ip->sin_port = ip_port;
186 ip->sin_addr.s_addr = ip_addr;
187 *addr = ap;
188 return 0;
191 static void
192 freeaddrinfo(struct addrinfo* ap)
194 free(ap);
197 #endif
200 * return <protocol>/<host>/<service> fd
203 typedef int (*Inetintr_f)(struct addrinfo*, void*);
205 static int
206 inetopen(const char* path, int server, Inetintr_f onintr, void* handle)
208 register char* s;
209 register char* t;
210 int fd;
211 int oerrno;
212 struct addrinfo hint;
213 struct addrinfo* addr;
214 struct addrinfo* p;
216 memset(&hint, 0, sizeof(hint));
217 hint.ai_family = PF_UNSPEC;
218 switch (path[0])
220 #ifdef IPPROTO_SCTP
221 case 's':
222 if (path[1]!='c' || path[2]!='t' || path[3]!='p' || path[4]!='/')
224 errno = ENOTDIR;
225 return -1;
227 hint.ai_socktype = SOCK_STREAM;
228 hint.ai_protocol = IPPROTO_SCTP;
229 path += 5;
230 break;
231 #endif
232 case 't':
233 if (path[1]!='c' || path[2]!='p' || path[3]!='/')
235 errno = ENOTDIR;
236 return -1;
238 hint.ai_socktype = SOCK_STREAM;
239 path += 4;
240 break;
241 case 'u':
242 if (path[1]!='d' || path[2]!='p' || path[3]!='/')
244 errno = ENOTDIR;
245 return -1;
247 hint.ai_socktype = SOCK_DGRAM;
248 path += 4;
249 break;
250 default:
251 errno = ENOTDIR;
252 return -1;
254 if (!(s = strdup(path)))
255 return -1;
256 if (t = strchr(s, '/'))
258 *t++ = 0;
259 if (streq(s, "local"))
260 s = "localhost";
261 fd = getaddrinfo(s, t, &hint, &addr);
263 else
264 fd = -1;
265 free(s);
266 if (fd)
268 if (fd != EAI_SYSTEM)
269 errno = ENOTDIR;
270 return -1;
272 oerrno = errno;
273 errno = 0;
274 fd = -1;
275 for (p = addr; p; p = p->ai_next)
278 * some api's don't take the hint
281 if (!p->ai_protocol)
282 p->ai_protocol = hint.ai_protocol;
283 if (!p->ai_socktype)
284 p->ai_socktype = hint.ai_socktype;
285 while ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) >= 0)
287 if (server && !bind(fd, p->ai_addr, p->ai_addrlen) && !listen(fd, 5) || !server && !connect(fd, p->ai_addr, p->ai_addrlen))
288 goto done;
289 close(fd);
290 fd = -1;
291 if (errno != EINTR || !onintr)
292 break;
293 if ((*onintr)(addr, handle))
294 return -1;
297 done:
298 freeaddrinfo(addr);
299 if (fd >= 0)
300 errno = oerrno;
301 return fd;
304 #else
306 #undef O_SERVICE
308 #endif
310 struct fdsave
312 int orig_fd; /* original file descriptor */
313 int save_fd; /* saved file descriptor */
314 int subshell; /* saved for subshell */
315 char *tname; /* name used with >; */
318 static int subexcept(Sfio_t*, int, void*, Sfdisc_t*);
319 static int eval_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
320 static int slowexcept(Sfio_t*, int, void*, Sfdisc_t*);
321 static int pipeexcept(Sfio_t*, int, void*, Sfdisc_t*);
322 static ssize_t piperead(Sfio_t*, void*, size_t, Sfdisc_t*);
323 static ssize_t slowread(Sfio_t*, void*, size_t, Sfdisc_t*);
324 static ssize_t subread(Sfio_t*, void*, size_t, Sfdisc_t*);
325 static ssize_t tee_write(Sfio_t*,const void*,size_t,Sfdisc_t*);
326 static int io_prompt(Sfio_t*,int);
327 static int io_heredoc(Shell_t*,register struct ionod*, const char*, int);
328 static void sftrack(Sfio_t*,int,void*);
329 static const Sfdisc_t eval_disc = { NULL, NULL, NULL, eval_exceptf, NULL};
330 static Sfdisc_t tee_disc = {NULL,tee_write,NULL,NULL,NULL};
331 static Sfio_t *subopen(Shell_t *,Sfio_t*, off_t, long);
332 static const Sfdisc_t sub_disc = { subread, 0, 0, subexcept, 0 };
334 struct subfile
336 Sfdisc_t disc;
337 Sfio_t *oldsp;
338 off_t offset;
339 long size;
340 long left;
343 struct Eof
345 Namfun_t hdr;
346 int fd;
349 static Sfdouble_t nget_cur_eof(register Namval_t* np, Namfun_t *fp)
351 struct Eof *ep = (struct Eof*)fp;
352 Sfoff_t end, cur =lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
353 if(*np->nvname=='C')
354 return((Sfdouble_t)cur);
355 if(cur<0)
356 return((Sfdouble_t)-1);
357 end =lseek(ep->fd, (Sfoff_t)0, SEEK_END);
358 lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
359 return((Sfdouble_t)end);
362 static const Namdisc_t EOF_disc = { sizeof(struct Eof), 0, 0, nget_cur_eof};
364 #define MATCH_BUFF (64*1024)
365 struct Match
367 Sfoff_t offset;
368 char *base;
371 static int matchf(void *handle, char *ptr, size_t size)
373 struct Match *mp = (struct Match*)handle;
374 mp->offset += (ptr-mp->base);
375 return(1);
379 static struct fdsave *filemap;
380 static short filemapsize;
382 /* ======== input output and file copying ======== */
384 void sh_ioinit(Shell_t *shp)
386 register int n;
387 filemapsize = 8;
388 filemap = (struct fdsave*)malloc(filemapsize*sizeof(struct fdsave));
389 #if SHOPT_FASTPIPE
390 n = shp->lim.open_max+2;
391 #else
392 n = shp->lim.open_max;
393 #endif /* SHOPT_FASTPIPE */
394 shp->fdstatus = (unsigned char*)malloc((unsigned)n);
395 memset((char*)shp->fdstatus,0,n);
396 shp->fdptrs = (int**)malloc(n*sizeof(int*));
397 memset((char*)shp->fdptrs,0,n*sizeof(int*));
398 shp->sftable = (Sfio_t**)malloc(n*sizeof(Sfio_t*));
399 memset((char*)shp->sftable,0,n*sizeof(Sfio_t*));
400 shp->sftable[0] = sfstdin;
401 shp->sftable[1] = sfstdout;
402 shp->sftable[2] = sfstderr;
403 sfnotify(sftrack);
404 sh_iostream(shp,0);
405 /* all write steams are in the same pool and share outbuff */
406 shp->outpool = sfopen(NIL(Sfio_t*),NIL(char*),"sw"); /* pool identifier */
407 shp->outbuff = (char*)malloc(IOBSIZE+4);
408 shp->errbuff = (char*)malloc(IOBSIZE/4);
409 sfsetbuf(sfstderr,shp->errbuff,IOBSIZE/4);
410 sfsetbuf(sfstdout,shp->outbuff,IOBSIZE);
411 sfpool(sfstdout,shp->outpool,SF_WRITE);
412 sfpool(sfstderr,shp->outpool,SF_WRITE);
413 sfset(sfstdout,SF_LINE,0);
414 sfset(sfstderr,SF_LINE,0);
415 sfset(sfstdin,SF_SHARE|SF_PUBLIC,1);
419 * Handle output stream exceptions
421 static int outexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
423 static int active = 0;
425 NOT_USED(handle);
426 if(type==SF_DPOP || type==SF_FINAL)
427 free((void*)handle);
428 else if(type==SF_WRITE && (*(ssize_t*)data)<0 && sffileno(iop)!=2)
429 switch (errno)
431 case EINTR:
432 case EPIPE:
433 #ifdef ECONNRESET
434 case ECONNRESET:
435 #endif
436 #ifdef ESHUTDOWN
437 case ESHUTDOWN:
438 #endif
439 break;
440 default:
441 if(!active)
443 int mode = ((struct checkpt*)sh.jmplist)->mode;
444 int save = errno;
445 active = 1;
446 ((struct checkpt*)sh.jmplist)->mode = 0;
447 sfpurge(iop);
448 sfpool(iop,NIL(Sfio_t*),SF_WRITE);
449 errno = save;
450 errormsg(SH_DICT,ERROR_system(1),e_badwrite,sffileno(iop));
451 active = 0;
452 ((struct checkpt*)sh.jmplist)->mode = mode;
453 sh_exit(1);
455 return(-1);
457 return(0);
461 * create or initialize a stream corresponding to descriptor <fd>
462 * a buffer with room for a sentinal is allocated for a read stream.
463 * A discipline is inserted when read stream is a tty or a pipe
464 * For output streams, the buffer is set to sh.output and put into
465 * the sh.outpool synchronization pool
467 Sfio_t *sh_iostream(Shell_t *shp, register int fd)
469 register Sfio_t *iop;
470 register int status = sh_iocheckfd(shp,fd);
471 register int flags = SF_WRITE;
472 char *bp;
473 Sfdisc_t *dp;
474 #if SHOPT_FASTPIPE
475 if(fd>=shp->lim.open_max)
476 return(shp->sftable[fd]);
477 #endif /* SHOPT_FASTPIPE */
478 if(status==IOCLOSE)
480 switch(fd)
482 case 0:
483 return(sfstdin);
484 case 1:
485 return(sfstdout);
486 case 2:
487 return(sfstderr);
489 return(NIL(Sfio_t*));
491 if(status&IOREAD)
493 if(!(bp = (char *)malloc(IOBSIZE+1)))
494 return(NIL(Sfio_t*));
495 flags |= SF_READ;
496 if(!(status&IOWRITE))
497 flags &= ~SF_WRITE;
499 else
500 bp = shp->outbuff;
501 if(status&IODUP)
502 flags |= SF_SHARE|SF_PUBLIC;
503 if((iop = shp->sftable[fd]) && sffileno(iop)>=0)
504 sfsetbuf(iop, bp, IOBSIZE);
505 else if(!(iop=sfnew((fd<=2?iop:0),bp,IOBSIZE,fd,flags)))
506 return(NIL(Sfio_t*));
507 dp = newof(0,Sfdisc_t,1,0);
508 if(status&IOREAD)
510 sfset(iop,SF_MALLOC,1);
511 if(!(status&IOWRITE))
512 sfset(iop,SF_IOCHECK,1);
513 dp->exceptf = slowexcept;
514 if(status&IOTTY)
515 dp->readf = slowread;
516 else if(status&IONOSEEK)
518 dp->readf = piperead;
519 sfset(iop, SF_IOINTR,1);
521 else
522 dp->readf = 0;
523 dp->seekf = 0;
524 dp->writef = 0;
526 else
528 dp->exceptf = outexcept;
529 sfpool(iop,shp->outpool,SF_WRITE);
531 sfdisc(iop,dp);
532 shp->sftable[fd] = iop;
533 return(iop);
537 * preserve the file descriptor or stream by moving it
539 static void io_preserve(Shell_t* shp, register Sfio_t *sp, register int f2)
541 register int fd;
542 if(sp)
543 fd = sfsetfd(sp,10);
544 else
545 fd = sh_fcntl(f2,F_DUPFD,10);
546 if(f2==shp->infd)
547 shp->infd = fd;
548 if(fd<0)
550 shp->toomany = 1;
551 ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
552 errormsg(SH_DICT,ERROR_system(1),e_toomany);
554 if(shp->fdptrs[fd]=shp->fdptrs[f2])
556 if(f2==job.fd)
557 job.fd=fd;
558 *shp->fdptrs[fd] = fd;
559 shp->fdptrs[f2] = 0;
561 shp->sftable[fd] = sp;
562 shp->fdstatus[fd] = shp->fdstatus[f2];
563 if(fcntl(f2,F_GETFD,0)&1)
565 fcntl(fd,F_SETFD,FD_CLOEXEC);
566 shp->fdstatus[fd] |= IOCLEX;
568 shp->sftable[f2] = 0;
572 * Given a file descriptor <f1>, move it to a file descriptor number <f2>
573 * If <f2> is needed move it, otherwise it is closed first.
574 * The original stream <f1> is closed.
575 * The new file descriptor <f2> is returned;
577 int sh_iorenumber(Shell_t *shp, register int f1,register int f2)
579 register Sfio_t *sp = shp->sftable[f2];
580 if(f1!=f2)
582 /* see whether file descriptor is in use */
583 if(sh_inuse(f2) || (f2>2 && sp))
585 if(!(shp->inuse_bits&(1<<f2)))
586 io_preserve(shp,sp,f2);
587 sp = 0;
589 else if(f2==0)
590 shp->st.ioset = 1;
591 sh_close(f2);
592 if(f2<=2 && sp)
594 register Sfio_t *spnew = sh_iostream(shp,f1);
595 shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
596 sfsetfd(spnew,f2);
597 sfswap(spnew,sp);
598 sfset(sp,SF_SHARE|SF_PUBLIC,1);
600 else
602 shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
603 if((f2 = sh_fcntl(f1,F_DUPFD, f2)) < 0)
604 errormsg(SH_DICT,ERROR_system(1),e_file+4);
605 else if(f2 <= 2)
606 sh_iostream(shp,f2);
608 if(sp)
609 shp->sftable[f1] = 0;
610 sh_close(f1);
612 return(f2);
616 * close a file descriptor and update stream table and attributes
618 int sh_close(register int fd)
620 register Sfio_t *sp;
621 register int r = 0;
622 if(fd<0)
623 return(-1);
624 if(!(sp=sh.sftable[fd]) || sfclose(sp) < 0)
626 if(fdnotify)
627 (*fdnotify)(fd,SH_FDCLOSE);
628 r=close(fd);
630 if(fd>2)
631 sh.sftable[fd] = 0;
632 sh.fdstatus[fd] = IOCLOSE;
633 if(sh.fdptrs[fd])
634 *sh.fdptrs[fd] = -1;
635 sh.fdptrs[fd] = 0;
636 if(fd < 10)
637 sh.inuse_bits &= ~(1<<fd);
638 return(r);
641 #ifdef O_SERVICE
643 static int
644 onintr(struct addrinfo* addr, void* handle)
646 Shell_t* sh = (Shell_t*)handle;
648 if (sh->trapnote&SH_SIGSET)
650 freeaddrinfo(addr);
651 sh_exit(SH_EXITSIG);
652 return -1;
654 if (sh->trapnote)
655 sh_chktrap();
656 return 0;
659 #endif
662 * Mimic open(2) with checks for pseudo /dev/ files.
664 int sh_open(register const char *path, int flags, ...)
666 Shell_t *shp = &sh;
667 register int fd = -1;
668 mode_t mode;
669 char *e;
670 va_list ap;
671 va_start(ap, flags);
672 mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
673 va_end(ap);
674 errno = 0;
675 if(*path==0)
677 errno = ENOENT;
678 return(-1);
680 if (path[0]=='/' && path[1]=='d' && path[2]=='e' && path[3]=='v' && path[4]=='/')
682 switch (path[5])
684 case 'f':
685 if (path[6]=='d' && path[7]=='/')
687 fd = (int)strtol(path+8, &e, 10);
688 if (*e)
689 fd = -1;
691 break;
692 case 's':
693 if (path[6]=='t' && path[7]=='d')
694 switch (path[8])
696 case 'e':
697 if (path[9]=='r' && path[10]=='r' && !path[11])
698 fd = 2;
699 break;
700 case 'i':
701 if (path[9]=='n' && !path[10])
702 fd = 0;
703 break;
704 case 'o':
705 if (path[9]=='u' && path[10]=='t' && !path[11])
706 fd = 1;
707 break;
710 #ifdef O_SERVICE
711 if (fd < 0)
713 if ((fd = inetopen(path+5, !!(flags & O_SERVICE), onintr, &sh)) < 0 && errno != ENOTDIR)
714 return -1;
715 if (fd >= 0)
716 goto ok;
718 #endif
720 if (fd >= 0)
722 int nfd= -1;
723 if (flags & O_CREAT)
725 struct stat st;
726 if (stat(path,&st) >=0)
727 nfd = open(path,flags,st.st_mode);
729 else
730 nfd = open(path,flags);
731 if(nfd>=0)
733 fd = nfd;
734 goto ok;
736 if((mode=sh_iocheckfd(shp,fd))==IOCLOSE)
737 return(-1);
738 flags &= O_ACCMODE;
739 if(!(mode&IOWRITE) && ((flags==O_WRONLY) || (flags==O_RDWR)))
740 return(-1);
741 if(!(mode&IOREAD) && ((flags==O_RDONLY) || (flags==O_RDWR)))
742 return(-1);
743 if((fd=dup(fd))<0)
744 return(-1);
746 else
748 #if SHOPT_REGRESS
749 char buf[PATH_MAX];
750 if(strncmp(path,"/etc/",5)==0)
752 sfsprintf(buf, sizeof(buf), "%s%s", sh_regress_etc(path, __LINE__, __FILE__), path+4);
753 path = buf;
755 #endif
756 while((fd = open(path, flags, mode)) < 0)
757 if(errno!=EINTR || sh.trapnote)
758 return(-1);
761 flags &= O_ACCMODE;
762 if(flags==O_WRONLY)
763 mode = IOWRITE;
764 else if(flags==O_RDWR)
765 mode = (IOREAD|IOWRITE);
766 else
767 mode = IOREAD;
768 sh.fdstatus[fd] = mode;
769 return(fd);
773 * Open a file for reading
774 * On failure, print message.
776 int sh_chkopen(register const char *name)
778 register int fd = sh_open(name,O_RDONLY,0);
779 if(fd < 0)
780 errormsg(SH_DICT,ERROR_system(1),e_open,name);
781 return(fd);
785 * move open file descriptor to a number > 2
787 int sh_iomovefd(register int fdold)
789 register int fdnew;
790 if(fdold<0 || fdold>2)
791 return(fdold);
792 fdnew = sh_iomovefd(dup(fdold));
793 sh.fdstatus[fdnew] = (sh.fdstatus[fdold]&~IOCLEX);
794 close(fdold);
795 sh.fdstatus[fdold] = IOCLOSE;
796 return(fdnew);
800 * create a pipe and print message on failure
802 int sh_pipe(register int pv[])
804 int fd[2];
805 if(pipe(fd)<0 || (pv[0]=fd[0])<0 || (pv[1]=fd[1])<0)
806 errormsg(SH_DICT,ERROR_system(1),e_pipe);
807 pv[0] = sh_iomovefd(pv[0]);
808 pv[1] = sh_iomovefd(pv[1]);
809 sh.fdstatus[pv[0]] = IONOSEEK|IOREAD;
810 sh.fdstatus[pv[1]] = IONOSEEK|IOWRITE;
811 sh_subsavefd(pv[0]);
812 sh_subsavefd(pv[1]);
813 return(0);
816 static int pat_seek(void *handle, const char *str, size_t sz)
818 char **bp = (char**)handle;
819 *bp = (char*)str;
820 return(-1);
823 static int pat_line(const regex_t* rp, const char *buff, register size_t n)
825 register const char *cp=buff, *sp;
826 while(n>0)
828 for(sp=cp; n-->0 && *cp++ != '\n';);
829 if(regnexec(rp,sp,cp-sp, 0, (regmatch_t*)0, 0)==0)
830 return(sp-buff);
832 return(cp-buff);
835 static int io_patseek(Shell_t *shp, regex_t *rp, Sfio_t* sp, int flags)
837 char *cp, *match;
838 int r, fd=sffileno(sp), close_exec = shp->fdstatus[fd]&IOCLEX;
839 int was_share,s=(PIPE_BUF>SF_BUFSIZE?SF_BUFSIZE:PIPE_BUF);
840 size_t n,m;
841 shp->fdstatus[sffileno(sp)] |= IOCLEX;
842 if(fd==0)
843 was_share = sfset(sp,SF_SHARE,1);
844 while((cp=sfreserve(sp, -s, SF_LOCKR)) || (cp=sfreserve(sp,SF_UNBOUND, SF_LOCKR)))
846 m = n = sfvalue(sp);
847 while(n>0 && cp[n-1]!='\n')
848 n--;
849 if(n)
850 m = n;
851 r = regrexec(rp,cp,m,0,(regmatch_t*)0, 0, '\n', (void*)&match, pat_seek);
852 if(r<0)
853 m = match-cp;
854 else if(r==2)
856 if((m = pat_line(rp,cp,m)) < n)
857 r = -1;
859 if(m && (flags&IOCOPY))
860 sfwrite(sfstdout,cp,m);
861 sfread(sp,cp,m);
862 if(r<0)
863 break;
865 if(!close_exec)
866 shp->fdstatus[sffileno(sp)] &= ~IOCLEX;
867 if(fd==0 && !(was_share&SF_SHARE))
868 sfset(sp, SF_SHARE,0);
869 return(0);
872 static Sfoff_t file_offset(Shell_t *shp, int fn, char *fname)
874 Sfio_t *sp = shp->sftable[fn];
875 char *cp;
876 Sfoff_t off;
877 struct Eof endf;
878 Namval_t *mp = nv_open("EOF",shp->var_tree,0);
879 Namval_t *pp = nv_open("CUR",shp->var_tree,0);
880 memset(&endf,0,sizeof(struct Eof));
881 endf.fd = fn;
882 endf.hdr.disc = &EOF_disc;
883 endf.hdr.nofree = 1;
884 if(mp)
885 nv_stack(mp, &endf.hdr);
886 if(pp)
887 nv_stack(pp, &endf.hdr);
888 if(sp)
889 sfsync(sp);
890 off = sh_strnum(fname, &cp, 0);
891 if(mp)
892 nv_stack(mp, NiL);
893 if(pp)
894 nv_stack(pp, NiL);
895 return(*cp?(Sfoff_t)-1:off);
899 * close a pipe
901 void sh_pclose(register int pv[])
903 if(pv[0]>=2)
904 sh_close(pv[0]);
905 if(pv[1]>=2)
906 sh_close(pv[1]);
907 pv[0] = pv[1] = -1;
910 static char *io_usename(char *name, int *perm, int mode)
912 struct stat statb;
913 char *tname, *sp, *ep;
914 int fd,len,n=0;
915 if(mode==0)
917 if((fd = sh_open(name,O_RDONLY,0)) > 0)
919 if(fstat(fd,&statb) < 0)
920 return(0);
921 if(!S_ISREG(statb.st_mode))
922 return(0);
923 *perm = statb.st_mode&(RW_ALL|(S_IXUSR|S_IXGRP|S_IXOTH));
925 else if(fd < 0 && errno!=ENOENT)
926 return(0);
928 tname = sp = (char*)stakalloc((len=strlen(name)) + 5);
929 if(ep = strrchr(name,'/'))
931 memcpy(sp,name,n=++ep-name);
932 len -=n;
933 sp += n;
935 else
936 ep = name;
937 *sp++ = '.';
938 memcpy(sp,ep,len);
939 strcpy(sp+len,".tmp");
940 switch(mode)
942 case 1:
943 rename(tname,name);
944 break;
945 case 2:
946 unlink(tname);
947 break;
949 return(tname);
953 * I/O redirection
954 * flag = 0 if files are to be restored
955 * flag = 2 if files are to be closed on exec
956 * flag = 3 when called from $( < ...), just open file and return
957 * flag = SH_SHOWME for trace only
959 int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
961 Sfoff_t off;
962 register char *fname;
963 register int fd, iof;
964 const char *message = e_open;
965 int o_mode; /* mode flag for open */
966 static char io_op[7]; /* used for -x trace info */
967 int trunc=0, clexec=0, fn, traceon;
968 int r, indx = shp->topfd, perm= -1;
969 char *tname=0, *after="", *trace = shp->st.trap[SH_DEBUGTRAP];
970 Namval_t *np=0;
971 int isstring = shp->subshell?(sfset(sfstdout,0,0)&SF_STRING):0;
972 if(flag==2)
973 clexec = 1;
974 if(iop)
975 traceon = sh_trace(NIL(char**),0);
976 for(;iop;iop=iop->ionxt)
978 iof=iop->iofile;
979 fn = (iof&IOUFD);
980 if(fn==1 && shp->subshell && !shp->subshare && (flag==2 || isstring))
981 sh_subfork();
982 io_op[0] = '0'+(iof&IOUFD);
983 if(iof&IOPUT)
985 io_op[1] = '>';
986 o_mode = O_WRONLY|O_CREAT;
988 else
990 io_op[1] = '<';
991 o_mode = O_RDONLY|O_NONBLOCK;
993 io_op[2] = 0;
994 io_op[3] = 0;
995 io_op[4] = 0;
996 fname = iop->ioname;
997 if(!(iof&IORAW))
999 if(iof&IOLSEEK)
1001 struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
1002 memset(ap, 0, ARGVAL);
1003 ap->argflag = ARG_MAC;
1004 strcpy(ap->argval,iop->ioname);
1005 fname=sh_macpat(shp,ap,(iof&IOARITH)?ARG_ARITH:ARG_EXP);
1007 else if(iof&IOPROCSUB)
1009 struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
1010 memset(ap, 0, ARGVAL);
1011 if(iof&IOPUT)
1012 ap->argflag = ARG_RAW;
1013 ap->argchn.ap = (struct argnod*)fname;
1014 ap = sh_argprocsub(shp,ap);
1015 fname = ap->argval;
1017 else
1018 fname=sh_mactrim(shp,fname,(!sh_isoption(SH_NOGLOB)&&sh_isoption(SH_INTERACTIVE))?2:0);
1020 errno=0;
1021 np = 0;
1022 if(iop->iovname)
1024 np = nv_open(iop->iovname,shp->var_tree,NV_NOASSIGN|NV_VARNAME);
1025 if(nv_isattr(np,NV_RDONLY))
1026 errormsg(SH_DICT,ERROR_exit(1),e_readonly, nv_name(np));
1027 io_op[0] = '}';
1028 if((iof&IOLSEEK) || ((iof&IOMOV) && *fname=='-'))
1029 fn = nv_getnum(np);
1031 if(iof&IOLSEEK)
1033 io_op[2] = '#';
1034 if(iof&IOARITH)
1036 strcpy(&io_op[3]," ((");
1037 after = "))";
1039 else if(iof&IOCOPY)
1040 io_op[3] = '#';
1041 goto traceit;
1043 if(*fname)
1045 if(iof&IODOC)
1047 if(traceon)
1048 sfputr(sfstderr,io_op,'<');
1049 fd = io_heredoc(shp,iop,fname,traceon);
1050 if(traceon && (flag==SH_SHOWME))
1051 sh_close(fd);
1052 fname = 0;
1054 else if(iof&IOMOV)
1056 int dupfd,toclose= -1;
1057 io_op[2] = '&';
1058 if((fd=fname[0])>='0' && fd<='9')
1060 char *number = fname;
1061 dupfd = strtol(fname,&number,10);
1062 if(*number=='-')
1064 toclose = dupfd;
1065 number++;
1067 if(*number || dupfd > IOUFD)
1069 message = e_file;
1070 goto fail;
1072 if(shp->subshell && dupfd==1 && (sfset(sfstdout,0,0)&SF_STRING))
1074 sh_subtmpfile(0);
1075 dupfd = sffileno(sfstdout);
1077 else if(shp->sftable[dupfd])
1078 sfsync(shp->sftable[dupfd]);
1080 else if(fd=='-' && fname[1]==0)
1082 fd= -1;
1083 goto traceit;
1085 else if(fd=='p' && fname[1]==0)
1087 if(iof&IOPUT)
1088 dupfd = shp->coutpipe;
1089 else
1090 dupfd = shp->cpipe[0];
1091 if(flag)
1092 toclose = dupfd;
1094 else
1096 message = e_file;
1097 goto fail;
1099 if(flag==SH_SHOWME)
1100 goto traceit;
1101 if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
1102 goto fail;
1103 sh_iocheckfd(shp,dupfd);
1104 shp->fdstatus[fd] = (shp->fdstatus[dupfd]&~IOCLEX);
1105 if(toclose<0 && shp->fdstatus[fd]&IOREAD)
1106 shp->fdstatus[fd] |= IODUP;
1107 else if(dupfd==shp->cpipe[0])
1108 sh_pclose(shp->cpipe);
1109 else if(toclose>=0)
1111 if(flag==0)
1112 sh_iosave(shp,toclose,indx,(char*)0); /* save file descriptor */
1113 sh_close(toclose);
1116 else if(iof&IORDW)
1118 if(sh_isoption(SH_RESTRICTED))
1119 errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1120 io_op[2] = '>';
1121 o_mode = O_RDWR|O_CREAT;
1122 if(iof&IOREWRITE)
1123 trunc = io_op[2] = ';';
1124 goto openit;
1126 else if(!(iof&IOPUT))
1128 if(flag==SH_SHOWME)
1129 goto traceit;
1130 fd=sh_chkopen(fname);
1132 else if(sh_isoption(SH_RESTRICTED))
1133 errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1134 else
1136 if(iof&IOAPP)
1138 io_op[2] = '>';
1139 o_mode |= O_APPEND;
1141 else if((iof&IOREWRITE) && (flag==0 || flag==1 || sh_subsavefd(fn)))
1143 io_op[2] = ';';
1144 o_mode |= O_TRUNC;
1145 tname = io_usename(fname,&perm,0);
1147 else
1149 o_mode |= O_TRUNC;
1150 if(iof&IOCLOB)
1151 io_op[2] = '|';
1152 else if(sh_isoption(SH_NOCLOBBER))
1154 struct stat sb;
1155 if(stat(fname,&sb)>=0)
1157 #if SHOPT_FS_3D
1158 if(S_ISREG(sb.st_mode)&&
1159 (!shp->lim.fs3d || iview(&sb)==0))
1160 #else
1161 if(S_ISREG(sb.st_mode))
1162 #endif /* SHOPT_FS_3D */
1164 errno = EEXIST;
1165 errormsg(SH_DICT,ERROR_system(1),e_exists,fname);
1168 else
1169 o_mode |= O_EXCL;
1172 openit:
1173 if(flag!=SH_SHOWME)
1175 if((fd=sh_open(tname?tname:fname,o_mode,RW_ALL)) <0)
1176 errormsg(SH_DICT,ERROR_system(1),((o_mode&O_CREAT)?e_create:e_open),fname);
1177 if(perm>0)
1178 #if _lib_fchmod
1179 fchmod(fd,perm);
1180 #else
1181 chmod(tname,perm);
1182 #endif
1185 traceit:
1186 if(traceon && fname)
1188 if(np)
1189 sfprintf(sfstderr,"{%s",nv_name(np));
1190 sfprintf(sfstderr,"%s %s%s%c",io_op,fname,after,iop->ionxt?' ':'\n');
1192 if(flag==SH_SHOWME)
1193 return(indx);
1194 if(trace && fname)
1196 char *argv[7], **av=argv;
1197 av[3] = io_op;
1198 av[4] = fname;
1199 av[5] = 0;
1200 av[6] = 0;
1201 if(iof&IOARITH)
1202 av[5] = after;
1203 if(np)
1205 av[0] = "{";
1206 av[1] = nv_name(np);
1207 av[2] = "}";
1209 else
1210 av +=3;
1211 sh_debug(shp,trace,(char*)0,(char*)0,av,ARG_NOGLOB);
1213 if(iof&IOLSEEK)
1215 Sfio_t *sp = shp->sftable[fn];
1216 r = shp->fdstatus[fn];
1217 if(!(r&(IOSEEK|IONOSEEK)))
1218 r = sh_iocheckfd(shp,fn);
1219 sfsprintf(io_op,sizeof(io_op),"%d\0",fn);
1220 if(r==IOCLOSE)
1222 fname = io_op;
1223 message = e_file;
1224 goto fail;
1226 if(iof&IOARITH)
1228 if(r&IONOSEEK)
1230 fname = io_op;
1231 message = e_notseek;
1232 goto fail;
1234 message = e_badseek;
1235 if((off = file_offset(shp,fn,fname))<0)
1236 goto fail;
1237 if(sp)
1239 off=sfseek(sp, off, SEEK_SET);
1240 sfsync(sp);
1242 else
1243 off=lseek(fn, off, SEEK_SET);
1244 if(off<0)
1245 r = -1;
1247 else
1249 regex_t *rp;
1250 extern const char e_notimp[];
1251 if(!(r&IOREAD))
1253 message = e_noread;
1254 goto fail;
1256 if(!(rp = regcache(fname, REG_SHELL|REG_NOSUB|REG_NEWLINE|REG_AUGMENTED|REG_FIRST|REG_LEFT|REG_RIGHT, &r)))
1258 message = e_badpattern;
1259 goto fail;
1261 if(!sp)
1262 sp = sh_iostream(shp,fn);
1263 r=io_patseek(shp,rp,sp,iof);
1264 if(sp && flag==3)
1266 /* close stream but not fn */
1267 sfsetfd(sp,-1);
1268 sfclose(sp);
1271 if(r<0)
1272 goto fail;
1273 if(flag==3)
1274 return(fn);
1275 continue;
1277 if(!np)
1279 if(flag==0 || tname)
1281 if(fd==fn)
1283 if((r=sh_fcntl(fd,F_DUPFD,10)) > 0)
1285 fd = r;
1286 sh_close(fn);
1289 sh_iosave(shp,fn,indx,tname?fname:(trunc?Empty:0));
1291 else if(sh_subsavefd(fn))
1292 sh_iosave(shp,fn,indx|IOSUBSHELL,tname?fname:0);
1294 if(fd<0)
1296 if(sh_inuse(fn) || (fn && fn==shp->infd))
1298 if(fn>9 || !(shp->inuse_bits&(1<<fn)))
1299 io_preserve(shp,shp->sftable[fn],fn);
1301 sh_close(fn);
1303 if(flag==3)
1304 return(fd);
1305 if(fd>=0)
1307 if(np)
1309 int32_t v;
1310 fn = fd;
1311 if(fd<10)
1313 if((fn=fcntl(fd,F_DUPFD,10)) < 0)
1314 goto fail;
1315 shp->fdstatus[fn] = shp->fdstatus[fd];
1316 sh_close(fd);
1317 fd = fn;
1319 nv_unset(np);
1320 nv_onattr(np,NV_INT32);
1321 v = fn;
1322 nv_putval(np,(char*)&v, NV_INT32);
1323 sh_iocheckfd(shp,fd);
1325 else
1327 fd = sh_iorenumber(shp,sh_iomovefd(fd),fn);
1328 if(fn>2 && fn<10)
1329 shp->inuse_bits |= (1<<fn);
1332 if(fd >2 && clexec)
1334 fcntl(fd,F_SETFD,FD_CLOEXEC);
1335 shp->fdstatus[fd] |= IOCLEX;
1338 else
1339 goto fail;
1341 return(indx);
1342 fail:
1343 errormsg(SH_DICT,ERROR_system(1),message,fname);
1344 /* NOTREACHED */
1345 return(0);
1348 * Create a tmp file for the here-document
1350 static int io_heredoc(Shell_t *shp,register struct ionod *iop, const char *name, int traceon)
1352 register Sfio_t *infile = 0, *outfile;
1353 register int fd;
1354 if(!(iop->iofile&IOSTRG) && (!shp->heredocs || iop->iosize==0))
1355 return(sh_open(e_devnull,O_RDONLY));
1356 /* create an unnamed temporary file */
1357 if(!(outfile=sftmp(0)))
1358 errormsg(SH_DICT,ERROR_system(1),e_tmpcreate);
1359 if(iop->iofile&IOSTRG)
1361 if(traceon)
1362 sfprintf(sfstderr,"< %s\n",name);
1363 sfputr(outfile,name,'\n');
1365 else
1367 infile = subopen(shp,shp->heredocs,iop->iooffset,iop->iosize);
1368 if(traceon)
1370 char *cp = sh_fmtq(iop->iodelim);
1371 fd = (*cp=='$' || *cp=='\'')?' ':'\\';
1372 sfprintf(sfstderr," %c%s\n",fd,cp);
1373 sfdisc(outfile,&tee_disc);
1375 if(iop->iofile&IOQUOTE)
1377 /* This is a quoted here-document, not expansion */
1378 sfmove(infile,outfile,SF_UNBOUND,-1);
1379 sfclose(infile);
1381 else
1383 char *lastpath = shp->lastpath;
1384 sh_machere(shp,infile,outfile,iop->ioname);
1385 shp->lastpath = lastpath;
1386 if(infile)
1387 sfclose(infile);
1390 /* close stream outfile, but save file descriptor */
1391 fd = sffileno(outfile);
1392 sfsetfd(outfile,-1);
1393 sfclose(outfile);
1394 if(traceon && !(iop->iofile&IOSTRG))
1395 sfputr(sfstderr,iop->ioname,'\n');
1396 lseek(fd,(off_t)0,SEEK_SET);
1397 shp->fdstatus[fd] = IOREAD;
1398 return(fd);
1402 * This write discipline also writes the output on standard error
1403 * This is used when tracing here-documents
1405 static ssize_t tee_write(Sfio_t *iop,const void *buff,size_t n,Sfdisc_t *unused)
1407 NOT_USED(unused);
1408 sfwrite(sfstderr,buff,n);
1409 return(write(sffileno(iop),buff,n));
1413 * copy file <origfd> into a save place
1414 * The saved file is set close-on-exec
1415 * if <origfd> < 0, then -origfd is saved, but not duped so that it
1416 * will be closed with sh_iorestore.
1418 void sh_iosave(Shell_t *shp, register int origfd, int oldtop, char *name)
1421 assume oldtop>=0 && oldtop<shp->lim.open_max;
1424 register int savefd;
1425 int flag = (oldtop&IOSUBSHELL);
1426 oldtop &= ~IOSUBSHELL;
1427 /* see if already saved, only save once */
1428 for(savefd=shp->topfd; --savefd>=oldtop; )
1430 if(filemap[savefd].orig_fd == origfd)
1431 return;
1433 /* make sure table is large enough */
1434 if(shp->topfd >= filemapsize)
1436 char *cp, *oldptr = (char*)filemap;
1437 char *oldend = (char*)&filemap[filemapsize];
1438 long moved;
1439 filemapsize += 8;
1440 if(!(filemap = (struct fdsave*)realloc(filemap,filemapsize*sizeof(struct fdsave))))
1441 errormsg(SH_DICT,ERROR_exit(4),e_nospace);
1442 if(moved = (char*)filemap - oldptr)
1444 #if SHOPT_FASTPIPE
1445 for(savefd=shp->lim.open_max+2; --savefd>=0; )
1446 #else
1447 for(savefd=shp->lim.open_max; --savefd>=0; )
1448 #endif /* SHOPT_FASTPIPE */
1450 cp = (char*)shp->fdptrs[savefd];
1451 if(cp >= oldptr && cp < oldend)
1452 shp->fdptrs[savefd] = (int*)(oldptr+moved);
1456 #if SHOPT_DEVFD
1457 if(origfd <0)
1459 savefd = origfd;
1460 origfd = -origfd;
1462 else
1463 #endif /* SHOPT_DEVFD */
1465 if((savefd = sh_fcntl(origfd, F_DUPFD, 10)) < 0 && errno!=EBADF)
1467 shp->toomany=1;
1468 ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
1469 errormsg(SH_DICT,ERROR_system(1),e_toomany);
1472 filemap[shp->topfd].tname = name;
1473 filemap[shp->topfd].subshell = flag;
1474 filemap[shp->topfd].orig_fd = origfd;
1475 filemap[shp->topfd++].save_fd = savefd;
1476 if(savefd >=0)
1478 register Sfio_t* sp = shp->sftable[origfd];
1479 /* make saved file close-on-exec */
1480 sh_fcntl(savefd,F_SETFD,FD_CLOEXEC);
1481 if(origfd==job.fd)
1482 job.fd = savefd;
1483 shp->fdstatus[savefd] = shp->fdstatus[origfd];
1484 shp->fdptrs[savefd] = &filemap[shp->topfd-1].save_fd;
1485 if(!(shp->sftable[savefd]=sp))
1486 return;
1487 sfsync(sp);
1488 if(origfd <=2)
1490 /* copy standard stream to new stream */
1491 sp = sfswap(sp,NIL(Sfio_t*));
1492 shp->sftable[savefd] = sp;
1494 else
1495 shp->sftable[origfd] = 0;
1500 * close all saved file descriptors
1502 void sh_iounsave(Shell_t* shp)
1504 register int fd, savefd, newfd;
1505 for(newfd=fd=0; fd < shp->topfd; fd++)
1507 if((savefd = filemap[fd].save_fd)< 0)
1508 filemap[newfd++] = filemap[fd];
1509 else
1511 shp->sftable[savefd] = 0;
1512 sh_close(savefd);
1515 shp->topfd = newfd;
1519 * restore saved file descriptors from <last> on
1521 void sh_iorestore(Shell_t *shp, int last, int jmpval)
1523 register int origfd, savefd, fd;
1524 int flag = (last&IOSUBSHELL);
1525 last &= ~IOSUBSHELL;
1526 for (fd = shp->topfd - 1; fd >= last; fd--)
1528 if(!flag && filemap[fd].subshell)
1529 continue;
1530 if(jmpval==SH_JMPSCRIPT)
1532 if ((savefd = filemap[fd].save_fd) >= 0)
1534 shp->sftable[savefd] = 0;
1535 sh_close(savefd);
1537 continue;
1539 origfd = filemap[fd].orig_fd;
1540 if(filemap[fd].tname == Empty && shp->exitval==0)
1541 ftruncate(origfd,lseek(origfd,0,SEEK_CUR));
1542 else if(filemap[fd].tname)
1543 io_usename(filemap[fd].tname,(int*)0,shp->exitval?2:1);
1544 sh_close(origfd);
1545 if ((savefd = filemap[fd].save_fd) >= 0)
1547 sh_fcntl(savefd, F_DUPFD, origfd);
1548 if(savefd==job.fd)
1549 job.fd=origfd;
1550 shp->fdstatus[origfd] = shp->fdstatus[savefd];
1551 /* turn off close-on-exec if flag if necessary */
1552 if(shp->fdstatus[origfd]&IOCLEX)
1553 fcntl(origfd,F_SETFD,FD_CLOEXEC);
1554 if(origfd<=2)
1556 sfswap(shp->sftable[savefd],shp->sftable[origfd]);
1557 if(origfd==0)
1558 shp->st.ioset = 0;
1560 else
1561 shp->sftable[origfd] = shp->sftable[savefd];
1562 shp->sftable[savefd] = 0;
1563 sh_close(savefd);
1565 else
1566 shp->fdstatus[origfd] = IOCLOSE;
1568 if(!flag)
1570 /* keep file descriptors for subshell restore */
1571 for (fd = last ; fd < shp->topfd; fd++)
1573 if(filemap[fd].subshell)
1574 filemap[last++] = filemap[fd];
1577 if(last < shp->topfd)
1578 shp->topfd = last;
1582 * returns access information on open file <fd>
1583 * returns -1 for failure, 0 for success
1584 * <mode> is the same as for access()
1586 int sh_ioaccess(int fd,register int mode)
1588 Shell_t *shp = &sh;
1589 register int flags;
1590 if(mode==X_OK)
1591 return(-1);
1592 if((flags=sh_iocheckfd(shp,fd))!=IOCLOSE)
1594 if(mode==F_OK)
1595 return(0);
1596 if(mode==R_OK && (flags&IOREAD))
1597 return(0);
1598 if(mode==W_OK && (flags&IOWRITE))
1599 return(0);
1601 return(-1);
1605 * Handle interrupts for slow streams
1607 static int slowexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
1609 register int n,fno;
1610 NOT_USED(handle);
1611 if(type==SF_DPOP || type==SF_FINAL)
1612 free((void*)handle);
1613 if(type!=SF_READ)
1614 return(0);
1615 if((sh.trapnote&(SH_SIGSET|SH_SIGTRAP)) && errno!=EIO && errno!=ENXIO)
1616 errno = EINTR;
1617 fno = sffileno(iop);
1618 if((n=sfvalue(iop))<=0)
1620 #ifndef FNDELAY
1621 # ifdef O_NDELAY
1622 if(errno==0 && (n=fcntl(fno,F_GETFL,0))&O_NDELAY)
1624 n &= ~O_NDELAY;
1625 fcntl(fno, F_SETFL, n);
1626 return(1);
1628 # endif /* O_NDELAY */
1629 #endif /* !FNDELAY */
1630 #ifdef O_NONBLOCK
1631 if(errno==EAGAIN)
1633 n = fcntl(fno,F_GETFL,0);
1634 n &= ~O_NONBLOCK;
1635 fcntl(fno, F_SETFL, n);
1636 return(1);
1638 #endif /* O_NONBLOCK */
1639 if(errno!=EINTR)
1640 return(0);
1641 n=1;
1642 sh_onstate(SH_TTYWAIT);
1644 else
1645 n = 0;
1646 if(sh.bltinfun && sh.bltindata.sigset)
1647 return(-1);
1648 errno = 0;
1649 if(sh.trapnote&SH_SIGSET)
1651 if(isatty(fno))
1652 sfputc(sfstderr,'\n');
1653 sh_exit(SH_EXITSIG);
1655 if(sh.trapnote&SH_SIGTRAP)
1656 sh_chktrap();
1657 return(n);
1661 * called when slowread times out
1663 static void time_grace(void *handle)
1665 NOT_USED(handle);
1666 timeout = 0;
1667 if(sh_isstate(SH_GRACE))
1669 sh_offstate(SH_GRACE);
1670 if(!sh_isstate(SH_INTERACTIVE))
1671 return;
1672 ((struct checkpt*)sh.jmplist)->mode = SH_JMPEXIT;
1673 errormsg(SH_DICT,2,e_timeout);
1674 sh.trapnote |= SH_SIGSET;
1675 return;
1677 errormsg(SH_DICT,0,e_timewarn);
1678 sh_onstate(SH_GRACE);
1679 sigrelease(SIGALRM);
1680 sh.trapnote |= SH_SIGTRAP;
1683 static ssize_t piperead(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1685 int fd = sffileno(iop);
1686 NOT_USED(handle);
1687 if(job.waitsafe && job.savesig)
1689 job_lock();
1690 job_unlock();
1692 if(sh.trapnote)
1694 errno = EINTR;
1695 return(-1);
1697 if(sh_isstate(SH_INTERACTIVE) && io_prompt(iop,sh.nextprompt)<0 && errno==EIO)
1698 return(0);
1699 sh_onstate(SH_TTYWAIT);
1700 if(!(sh.fdstatus[sffileno(iop)]&IOCLEX) && (sfset(iop,0,0)&SF_SHARE))
1701 size = ed_read(sh.ed_context, fd, (char*)buff, size,0);
1702 else
1703 size = sfrd(iop,buff,size,handle);
1704 sh_offstate(SH_TTYWAIT);
1705 return(size);
1708 * This is the read discipline that is applied to slow devices
1709 * This routine takes care of prompting for input
1711 static ssize_t slowread(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1713 int (*readf)(void*, int, char*, int, int);
1714 int reedit=0, rsize;
1715 #if SHOPT_HISTEXPAND
1716 char *xp=0;
1717 #endif
1718 NOT_USED(handle);
1719 # if SHOPT_ESH
1720 if(sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS))
1721 readf = ed_emacsread;
1722 else
1723 # endif /* SHOPT_ESH */
1724 # if SHOPT_VSH
1725 # if SHOPT_RAWONLY
1726 if(sh_isoption(SH_VI) || ((SHOPT_RAWONLY-0) && mbwide()))
1727 # else
1728 if(sh_isoption(SH_VI))
1729 # endif
1730 readf = ed_viread;
1731 else
1732 # endif /* SHOPT_VSH */
1733 readf = ed_read;
1734 if(sh.trapnote)
1736 errno = EINTR;
1737 return(-1);
1739 while(1)
1741 if(io_prompt(iop,sh.nextprompt)<0 && errno==EIO)
1742 return(0);
1743 if(sh.timeout)
1744 timeout = (void*)sh_timeradd(sh_isstate(SH_GRACE)?1000L*TGRACE:1000L*sh.timeout,0,time_grace,NIL(void*));
1745 rsize = (*readf)(sh.ed_context, sffileno(iop), (char*)buff, size, reedit);
1746 if(timeout)
1747 timerdel(timeout);
1748 timeout=0;
1749 #if SHOPT_HISTEXPAND
1750 if(rsize && *(char*)buff != '\n' && sh.nextprompt==1 && sh_isoption(SH_HISTEXPAND))
1752 int r;
1753 ((char*)buff)[rsize] = '\0';
1754 if(xp)
1756 free(xp);
1757 xp = 0;
1759 r = hist_expand(buff, &xp);
1760 if((r & (HIST_EVENT|HIST_PRINT)) && !(r & HIST_ERROR) && xp)
1762 strlcpy(buff, xp, size);
1763 rsize = strlen(buff);
1764 if(!sh_isoption(SH_HISTVERIFY) || readf==ed_read)
1766 sfputr(sfstderr, xp, -1);
1767 break;
1769 reedit = rsize - 1;
1770 continue;
1772 if((r & HIST_ERROR) && sh_isoption(SH_HISTREEDIT))
1774 reedit = rsize - 1;
1775 continue;
1777 if(r & (HIST_ERROR|HIST_PRINT))
1779 *(char*)buff = '\n';
1780 rsize = 1;
1783 #endif
1784 break;
1786 return(rsize);
1790 * check and return the attributes for a file descriptor
1793 int sh_iocheckfd(Shell_t *shp, register int fd)
1795 register int flags, n;
1796 if((n=sh.fdstatus[fd])&IOCLOSE)
1797 return(n);
1798 if(!(n&(IOREAD|IOWRITE)))
1800 #ifdef F_GETFL
1801 if((flags=fcntl(fd,F_GETFL,0)) < 0)
1802 return(sh.fdstatus[fd]=IOCLOSE);
1803 if((flags&O_ACCMODE)!=O_WRONLY)
1804 n |= IOREAD;
1805 if((flags&O_ACCMODE)!=O_RDONLY)
1806 n |= IOWRITE;
1807 #else
1808 struct stat statb;
1809 if((flags = fstat(fd,&statb))< 0)
1810 return(sh.fdstatus[fd]=IOCLOSE);
1811 n |= (IOREAD|IOWRITE);
1812 if(read(fd,"",0) < 0)
1813 n &= ~IOREAD;
1814 #endif /* F_GETFL */
1816 if(!(n&(IOSEEK|IONOSEEK)))
1818 struct stat statb;
1819 /* /dev/null check is a workaround for select bug */
1820 static ino_t null_ino;
1821 static dev_t null_dev;
1822 if(null_ino==0 && stat(e_devnull,&statb) >=0)
1824 null_ino = statb.st_ino;
1825 null_dev = statb.st_dev;
1827 if(tty_check(fd))
1828 n |= IOTTY;
1829 if(lseek(fd,NIL(off_t),SEEK_CUR)<0)
1831 n |= IONOSEEK;
1832 #ifdef S_ISSOCK
1833 if((fstat(fd,&statb)>=0) && S_ISSOCK(statb.st_mode))
1834 n |= IOREAD|IOWRITE;
1835 #endif /* S_ISSOCK */
1837 else if((fstat(fd,&statb)>=0) && (
1838 S_ISFIFO(statb.st_mode) ||
1839 #ifdef S_ISSOCK
1840 S_ISSOCK(statb.st_mode) ||
1841 #endif /* S_ISSOCK */
1842 /* The following is for sockets on the sgi */
1843 (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) ||
1844 (S_ISCHR(statb.st_mode) && (statb.st_ino!=null_ino || statb.st_dev!=null_dev))
1846 n |= IONOSEEK;
1847 else
1848 n |= IOSEEK;
1850 sh.fdstatus[fd] = n;
1851 return(n);
1855 * Display prompt PS<flag> on standard error
1858 static int io_prompt(Sfio_t *iop,register int flag)
1860 Shell_t *shp = &sh;
1861 register char *cp;
1862 char buff[1];
1863 char *endprompt;
1864 static short cmdno;
1865 int sfflags;
1866 if(flag<3 && !sh_isstate(SH_INTERACTIVE))
1867 flag = 0;
1868 if(flag==2 && sfpkrd(sffileno(iop),buff,1,'\n',0,1) >= 0)
1869 flag = 0;
1870 if(flag==0)
1871 return(sfsync(sfstderr));
1872 sfflags = sfset(sfstderr,SF_SHARE|SF_PUBLIC|SF_READ,0);
1873 if(!(sh.prompt=(char*)sfreserve(sfstderr,0,0)))
1874 sh.prompt = "";
1875 switch(flag)
1877 case 1:
1879 register int c;
1880 #if defined(TIOCLBIC) && defined(LFLUSHO)
1881 if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
1884 * re-enable output in case the user has
1885 * disabled it. Not needed with edit mode
1887 int mode = LFLUSHO;
1888 ioctl(sffileno(sfstderr),TIOCLBIC,&mode);
1890 #endif /* TIOCLBIC */
1891 cp = sh_mactry(shp,nv_getval(sh_scoped(shp,PS1NOD)));
1892 for(;c= *cp;cp++)
1894 if(c==HIST_CHAR)
1896 /* look at next character */
1897 c = *++cp;
1898 /* print out line number if not !! */
1899 if(c!= HIST_CHAR)
1901 sfprintf(sfstderr,"%d", sh.hist_ptr?(int)sh.hist_ptr->histind:++cmdno);
1903 if(c==0)
1904 goto done;
1906 sfputc(sfstderr,c);
1908 goto done;
1910 case 2:
1911 cp = nv_getval(sh_scoped(shp,PS2NOD));
1912 break;
1913 case 3:
1914 cp = nv_getval(sh_scoped(shp,PS3NOD));
1915 break;
1916 default:
1917 goto done;
1919 if(cp)
1920 sfputr(sfstderr,cp,-1);
1921 done:
1922 if(*sh.prompt && (endprompt=(char*)sfreserve(sfstderr,0,0)))
1923 *endprompt = 0;
1924 sfset(sfstderr,sfflags&SF_READ|SF_SHARE|SF_PUBLIC,1);
1925 return(sfsync(sfstderr));
1929 * This discipline is inserted on write pipes to prevent SIGPIPE
1930 * from causing an infinite loop
1932 static int pipeexcept(Sfio_t* iop, int mode, void *data, Sfdisc_t* handle)
1934 NOT_USED(iop);
1935 if(mode==SF_DPOP || mode==SF_FINAL)
1936 free((void*)handle);
1937 else if(mode==SF_WRITE && errno==EINTR && sh.lastsig==SIGPIPE)
1938 return(-1);
1939 return(0);
1943 * keep track of each stream that is opened and closed
1945 static void sftrack(Sfio_t* sp, int flag, void* data)
1947 Shell_t *shp = &sh;
1948 register int fd = sffileno(sp);
1949 register struct checkpt *pp;
1950 register int mode;
1951 int newfd = integralof(data);
1952 if(flag==SF_SETFD || flag==SF_CLOSING)
1954 if(newfd<0)
1955 flag = SF_CLOSING;
1956 if(fdnotify)
1957 (*fdnotify)(sffileno(sp),flag==SF_CLOSING?-1:newfd);
1959 #ifdef DEBUG
1960 if(flag==SF_READ || flag==SF_WRITE)
1962 char *z = fmtbase((long)getpid(),0,0);
1963 write(ERRIO,z,strlen(z));
1964 write(ERRIO,": ",2);
1965 write(ERRIO,"attempt to ",11);
1966 if(flag==SF_READ)
1967 write(ERRIO,"read from",9);
1968 else
1969 write(ERRIO,"write to",8);
1970 write(ERRIO," locked stream\n",15);
1971 return;
1973 #endif
1974 if((unsigned)fd >= shp->lim.open_max)
1975 return;
1976 if(sh_isstate(SH_NOTRACK))
1977 return;
1978 mode = sfset(sp,0,0);
1979 if(sp==shp->heredocs && fd < 10 && flag==SF_NEW)
1981 fd = sfsetfd(sp,10);
1982 fcntl(fd,F_SETFD,FD_CLOEXEC);
1984 if(fd < 3)
1985 return;
1986 if(flag==SF_NEW)
1988 if(!shp->sftable[fd] && shp->fdstatus[fd]==IOCLOSE)
1990 shp->sftable[fd] = sp;
1991 flag = (mode&SF_WRITE)?IOWRITE:0;
1992 if(mode&SF_READ)
1993 flag |= IOREAD;
1994 shp->fdstatus[fd] = flag;
1995 sh_iostream(shp,fd);
1997 if((pp=(struct checkpt*)shp->jmplist) && pp->mode==SH_JMPCMD)
1999 struct openlist *item;
2001 * record open file descriptors so they can
2002 * be closed in case a longjmp prevents
2003 * built-ins from cleanup
2005 item = new_of(struct openlist, 0);
2006 item->strm = sp;
2007 item->next = pp->olist;
2008 pp->olist = item;
2010 if(fdnotify)
2011 (*fdnotify)(-1,sffileno(sp));
2013 else if(flag==SF_CLOSING || (flag==SF_SETFD && newfd<=2))
2015 shp->sftable[fd] = 0;
2016 shp->fdstatus[fd]=IOCLOSE;
2017 if(pp=(struct checkpt*)shp->jmplist)
2019 struct openlist *item;
2020 for(item=pp->olist; item; item=item->next)
2022 if(item->strm == sp)
2024 item->strm = 0;
2025 break;
2032 struct eval
2034 Sfdisc_t disc;
2035 char **argv;
2036 short slen;
2037 char addspace;
2041 * Create a stream consisting of a space separated argv[] list
2044 Sfio_t *sh_sfeval(register char *argv[])
2046 register Sfio_t *iop;
2047 register char *cp;
2048 if(argv[1])
2049 cp = "";
2050 else
2051 cp = argv[0];
2052 iop = sfopen(NIL(Sfio_t*),(char*)cp,"s");
2053 if(argv[1])
2055 register struct eval *ep;
2056 if(!(ep = new_of(struct eval,0)))
2057 return(NIL(Sfio_t*));
2058 ep->disc = eval_disc;
2059 ep->argv = argv;
2060 ep->slen = -1;
2061 ep->addspace = 0;
2062 sfdisc(iop,&ep->disc);
2064 return(iop);
2068 * This code gets called whenever an end of string is found with eval
2071 static int eval_exceptf(Sfio_t *iop,int type, void *data, Sfdisc_t *handle)
2073 register struct eval *ep = (struct eval*)handle;
2074 register char *cp;
2075 register int len;
2077 /* no more to do */
2078 if(type!=SF_READ || !(cp = ep->argv[0]))
2080 if(type==SF_CLOSING)
2081 sfdisc(iop,SF_POPDISC);
2082 else if(ep && (type==SF_DPOP || type==SF_FINAL))
2083 free((void*)ep);
2084 return(0);
2087 if(!ep->addspace)
2089 /* get the length of this string */
2090 ep->slen = len = strlen(cp);
2091 /* move to next string */
2092 ep->argv++;
2094 else /* insert space between arguments */
2096 len = 1;
2097 cp = " ";
2099 /* insert the new string */
2100 sfsetbuf(iop,cp,len);
2101 ep->addspace = !ep->addspace;
2102 return(1);
2106 * This routine returns a stream pointer to a segment of length <size> from
2107 * the stream <sp> starting at offset <offset>
2108 * The stream can be read with the normal stream operations
2111 static Sfio_t *subopen(Shell_t *shp,Sfio_t* sp, off_t offset, long size)
2113 register struct subfile *disp;
2114 if(sfseek(sp,offset,SEEK_SET) <0)
2115 return(NIL(Sfio_t*));
2116 if(!(disp = (struct subfile*)malloc(sizeof(struct subfile)+IOBSIZE+1)))
2117 return(NIL(Sfio_t*));
2118 disp->disc = sub_disc;
2119 disp->oldsp = sp;
2120 disp->offset = offset;
2121 disp->size = disp->left = size;
2122 sp = sfnew(NIL(Sfio_t*),(char*)(disp+1),IOBSIZE,shp->lim.open_max,SF_READ);
2123 sfdisc(sp,&disp->disc);
2124 return(sp);
2128 * read function for subfile discipline
2130 static ssize_t subread(Sfio_t* sp,void* buff,register size_t size,Sfdisc_t* handle)
2132 register struct subfile *disp = (struct subfile*)handle;
2133 NOT_USED(sp);
2134 if(disp->left == 0)
2135 return(0);
2136 if(size > disp->left)
2137 size = disp->left;
2138 disp->left -= size;
2139 return(sfread(disp->oldsp,buff,size));
2143 * exception handler for subfile discipline
2145 static int subexcept(Sfio_t* sp,register int mode, void *data, Sfdisc_t* handle)
2147 register struct subfile *disp = (struct subfile*)handle;
2148 if(mode==SF_CLOSING)
2150 sfdisc(sp,SF_POPDISC);
2151 return(0);
2153 else if(disp && (mode==SF_DPOP || mode==SF_FINAL))
2155 free((void*)disp);
2156 return(0);
2158 #ifdef SF_ATEXIT
2159 else if (mode==SF_ATEXIT)
2161 sfdisc(sp, SF_POPDISC);
2162 return(0);
2164 #endif
2165 else if(mode==SF_READ)
2166 return(0);
2167 return(-1);
2170 #define NROW 15 /* number of rows before going to multi-columns */
2171 #define LBLSIZ 3 /* size of label field and interfield spacing */
2173 * print a list of arguments in columns
2175 void sh_menu(Sfio_t *outfile,int argn,char *argv[])
2177 Shell_t *shp = &sh;
2178 register int i,j;
2179 register char **arg;
2180 int nrow, ncol=1, ndigits=1;
2181 int fldsize, wsize = ed_window();
2182 char *cp = nv_getval(sh_scoped(shp,LINES));
2183 nrow = (cp?1+2*((int)strtol(cp, (char**)0, 10)/3):NROW);
2184 for(i=argn;i >= 10;i /= 10)
2185 ndigits++;
2186 if(argn < nrow)
2188 nrow = argn;
2189 goto skip;
2191 i = 0;
2192 for(arg=argv; *arg;arg++)
2194 if((j=strlen(*arg)) > i)
2195 i = j;
2197 i += (ndigits+LBLSIZ);
2198 if(i < wsize)
2199 ncol = wsize/i;
2200 if(argn > nrow*ncol)
2202 nrow = 1 + (argn-1)/ncol;
2204 else
2206 ncol = 1 + (argn-1)/nrow;
2207 nrow = 1 + (argn-1)/ncol;
2209 skip:
2210 fldsize = (wsize/ncol)-(ndigits+LBLSIZ);
2211 for(i=0;i<nrow;i++)
2213 if(sh.trapnote&SH_SIGSET)
2214 return;
2215 j = i;
2216 while(1)
2218 arg = argv+j;
2219 sfprintf(outfile,"%*d) %s",ndigits,j+1,*arg);
2220 j += nrow;
2221 if(j >= argn)
2222 break;
2223 sfnputc(outfile,' ',fldsize-strlen(*arg));
2225 sfputc(outfile,'\n');
2229 #undef read
2231 * shell version of read() for user added builtins
2233 ssize_t sh_read(register int fd, void* buff, size_t n)
2235 register Sfio_t *sp;
2236 if(sp=sh.sftable[fd])
2237 return(sfread(sp,buff,n));
2238 else
2239 return(read(fd,buff,n));
2242 #undef write
2244 * shell version of write() for user added builtins
2246 ssize_t sh_write(register int fd, const void* buff, size_t n)
2248 register Sfio_t *sp;
2249 if(sp=sh.sftable[fd])
2250 return(sfwrite(sp,buff,n));
2251 else
2252 return(write(fd,buff,n));
2255 #undef lseek
2257 * shell version of lseek() for user added builtins
2259 off_t sh_seek(register int fd, off_t offset, int whence)
2261 register Sfio_t *sp;
2262 if((sp=sh.sftable[fd]) && (sfset(sp,0,0)&(SF_READ|SF_WRITE)))
2263 return(sfseek(sp,offset,whence));
2264 else
2265 return(lseek(fd,offset,whence));
2268 #undef dup
2269 int sh_dup(register int old)
2271 register int fd = dup(old);
2272 if(fd>=0)
2274 if(sh.fdstatus[old] == IOCLOSE)
2275 sh.fdstatus[old] = 0;
2276 sh.fdstatus[fd] = (sh.fdstatus[old]&~IOCLEX);
2277 if(fdnotify)
2278 (*fdnotify)(old,fd);
2280 return(fd);
2283 #undef fcntl
2284 int sh_fcntl(register int fd, int op, ...)
2286 int newfd, arg;
2287 va_list ap;
2288 va_start(ap, op);
2289 arg = va_arg(ap, int) ;
2290 va_end(ap);
2291 newfd = fcntl(fd,op,arg);
2292 if(newfd>=0) switch(op)
2294 case F_DUPFD:
2295 if(sh.fdstatus[fd] == IOCLOSE)
2296 sh.fdstatus[fd] = 0;
2297 sh.fdstatus[newfd] = (sh.fdstatus[fd]&~IOCLEX);
2298 if(fdnotify)
2299 (*fdnotify)(fd,newfd);
2300 break;
2301 case F_SETFD:
2302 if(sh.fdstatus[fd] == IOCLOSE)
2303 sh.fdstatus[fd] = 0;
2304 if(arg&FD_CLOEXEC)
2305 sh.fdstatus[fd] |= IOCLEX;
2306 else
2307 sh.fdstatus[fd] &= ~IOCLEX;
2309 return(newfd);
2312 #undef umask
2313 mode_t sh_umask(mode_t m)
2315 sh.mask = m;
2316 return(umask(m));
2320 * give file descriptor <fd> and <mode>, return an iostream pointer
2321 * <mode> must be SF_READ or SF_WRITE
2322 * <fd> must be a non-negative number ofr SH_IOCOPROCESS or SH_IOHISTFILE.
2323 * returns NULL on failure and may set errno.
2326 Sfio_t *sh_iogetiop(int fd, int mode)
2328 Shell_t *shp = &sh;
2329 int n;
2330 Sfio_t *iop=0;
2331 if(mode!=SF_READ && mode!=SF_WRITE)
2333 errno = EINVAL;
2334 return(iop);
2336 switch(fd)
2338 case SH_IOHISTFILE:
2339 if(!sh_histinit((void*)shp))
2340 return(iop);
2341 fd = sffileno(shp->hist_ptr->histfp);
2342 break;
2343 case SH_IOCOPROCESS:
2344 if(mode==SF_WRITE)
2345 fd = shp->coutpipe;
2346 else
2347 fd = shp->cpipe[0];
2348 break;
2349 default:
2350 if(fd<0 || fd >= shp->lim.open_max)
2351 fd = -1;
2353 if(fd<0)
2355 errno = EBADF;
2356 return(iop);
2358 if(!(n=shp->fdstatus[fd]))
2359 n = sh_iocheckfd(shp,fd);
2360 if(mode==SF_WRITE && !(n&IOWRITE))
2361 return(iop);
2362 if(mode==SF_READ && !(n&IOREAD))
2363 return(iop);
2364 if(!(iop = shp->sftable[fd]))
2365 iop=sh_iostream(shp,fd);
2366 return(iop);
2369 typedef int (*Notify_f)(int,int);
2371 Notify_f sh_fdnotify(Notify_f notify)
2373 Notify_f old;
2374 old = fdnotify;
2375 fdnotify = notify;
2376 return(old);
2379 Sfio_t *sh_fd2sfio(int fd)
2381 Shell_t *shp = &sh;
2382 register int status;
2383 Sfio_t *sp = sh.sftable[fd];
2384 if(!sp && (status = sh_iocheckfd(shp,fd))!=IOCLOSE)
2386 register int flags=0;
2387 if(status&IOREAD)
2388 flags |= SF_READ;
2389 if(status&IOWRITE)
2390 flags |= SF_WRITE;
2391 sp = sfnew(NULL, NULL, -1, fd,flags);
2392 sh.sftable[fd] = sp;
2394 return(sp);
2397 Sfio_t *sh_pathopen(const char *cp)
2399 Shell_t *shp = &sh;
2400 int n;
2401 #ifdef PATH_BFPATH
2402 if((n=path_open(cp,path_get(cp))) < 0)
2403 n = path_open(cp,(Pathcomp_t*)0);
2404 #else
2405 if((n=path_open(cp,path_get(cp))) < 0)
2406 n = path_open(cp,"");
2407 #endif
2408 if(n < 0)
2409 errormsg(SH_DICT,ERROR_system(1),e_open,cp);
2410 return(sh_iostream(shp,n));