1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * David Korn <dgk@research.att.com> *
19 ***********************************************************************/
23 * Input/output file processing
35 #include "variables.h"
43 #include "FEATURE/externs"
44 #include "FEATURE/dynamic"
45 #include "FEATURE/poll"
49 # if EAGAIN!=EWOULDBLOCK
51 # define EAGAIN EWOULDBLOCK
54 # define EAGAIN EWOULDBLOCK
57 # define O_NONBLOCK FNDELAY
58 # endif /* !O_NONBLOCK */
62 # define O_SERVICE O_NOCTTY
65 #define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
68 static int (*fdnotify
)(int,int);
70 #if defined(_lib_socket) && defined(_sys_socket) && defined(_hdr_netinet_in)
71 # include <sys/socket.h>
73 # include <netinet/in.h>
74 # if !defined(htons) && !_lib_htons
77 # if !defined(htonl) && !_lib_htonl
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)
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)
104 #define addrinfo local_addrinfo
105 #define getaddrinfo local_getaddrinfo
106 #define freeaddrinfo local_freeaddrinfo
114 socklen_t ai_addrlen
;
115 struct sockaddr
* ai_addr
;
116 struct addrinfo
* ai_next
;
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;
126 struct sockaddr_in
* ip
;
130 if (!(hp
= gethostbyname(node
)) || hp
->h_addrtype
!=AF_INET
|| hp
->h_length
>sizeof(struct in_addr
))
132 errno
= EADDRNOTAVAIL
;
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
);
141 const char* protocol
= 0;
144 switch (hint
->ai_socktype
)
147 switch (hint
->ai_protocol
)
165 errno
= EPROTONOSUPPORT
;
168 if (sp
= getservbyname(service
, protocol
))
169 ip_port
= sp
->s_port
;
173 errno
= EADDRNOTAVAIL
;
176 if (!(ap
= newof(0, struct addrinfo
, 1, sizeof(struct sockaddr_in
))))
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
;
192 freeaddrinfo(struct addrinfo
* ap
)
201 * return <protocol>/<host>/<service> fd
204 typedef int (*Inetintr_f
)(struct addrinfo
*, void*);
207 inetopen(const char* path
, int server
, Inetintr_f onintr
, void* handle
)
213 struct addrinfo hint
;
214 struct addrinfo
* addr
;
217 memset(&hint
, 0, sizeof(hint
));
218 hint
.ai_family
= PF_UNSPEC
;
223 if (path
[1]!='c' || path
[2]!='t' || path
[3]!='p' || path
[4]!='/')
228 hint
.ai_socktype
= SOCK_STREAM
;
229 hint
.ai_protocol
= IPPROTO_SCTP
;
234 if (path
[1]!='c' || path
[2]!='p' || path
[3]!='/')
239 hint
.ai_socktype
= SOCK_STREAM
;
243 if (path
[1]!='d' || path
[2]!='p' || path
[3]!='/')
248 hint
.ai_socktype
= SOCK_DGRAM
;
255 if (!(s
= strdup(path
)))
257 if (t
= strchr(s
, '/'))
260 if (streq(s
, "local"))
262 fd
= getaddrinfo(s
, t
, &hint
, &addr
);
269 if (fd
!= EAI_SYSTEM
)
276 for (p
= addr
; p
; p
= p
->ai_next
)
279 * some api's don't take the hint
283 p
->ai_protocol
= hint
.ai_protocol
;
285 p
->ai_socktype
= hint
.ai_socktype
;
286 while ((fd
= socket(p
->ai_family
, p
->ai_socktype
, p
->ai_protocol
)) >= 0)
288 if (server
&& !bind(fd
, p
->ai_addr
, p
->ai_addrlen
) && !listen(fd
, 5) || !server
&& !connect(fd
, p
->ai_addr
, p
->ai_addrlen
))
292 if (errno
!= EINTR
|| !onintr
)
294 if ((*onintr
)(addr
, handle
))
313 int orig_fd
; /* original file descriptor */
314 int save_fd
; /* saved file descriptor */
315 int subshell
; /* saved for subshell */
316 char *tname
; /* name used with >; */
319 static int subexcept(Sfio_t
*, int, void*, Sfdisc_t
*);
320 static int eval_exceptf(Sfio_t
*, int, void*, Sfdisc_t
*);
321 static int slowexcept(Sfio_t
*, int, void*, Sfdisc_t
*);
322 static int pipeexcept(Sfio_t
*, int, void*, Sfdisc_t
*);
323 static ssize_t
piperead(Sfio_t
*, void*, size_t, Sfdisc_t
*);
324 static ssize_t
slowread(Sfio_t
*, void*, size_t, Sfdisc_t
*);
325 static ssize_t
subread(Sfio_t
*, void*, size_t, Sfdisc_t
*);
326 static ssize_t
tee_write(Sfio_t
*,const void*,size_t,Sfdisc_t
*);
327 static int io_prompt(Sfio_t
*,int);
328 static int io_heredoc(Shell_t
*,register struct ionod
*, const char*, int);
329 static void sftrack(Sfio_t
*,int,void*);
330 static const Sfdisc_t eval_disc
= { NULL
, NULL
, NULL
, eval_exceptf
, NULL
};
331 static Sfdisc_t tee_disc
= {NULL
,tee_write
,NULL
,NULL
,NULL
};
332 static Sfio_t
*subopen(Shell_t
*,Sfio_t
*, off_t
, long);
333 static const Sfdisc_t sub_disc
= { subread
, 0, 0, subexcept
, 0 };
350 static Sfdouble_t
nget_cur_eof(register Namval_t
* np
, Namfun_t
*fp
)
352 struct Eof
*ep
= (struct Eof
*)fp
;
353 Sfoff_t end
, cur
=lseek(ep
->fd
, (Sfoff_t
)0, SEEK_CUR
);
355 return((Sfdouble_t
)cur
);
357 return((Sfdouble_t
)-1);
358 end
=lseek(ep
->fd
, (Sfoff_t
)0, SEEK_END
);
359 lseek(ep
->fd
, (Sfoff_t
)0, SEEK_CUR
);
360 return((Sfdouble_t
)end
);
363 static const Namdisc_t EOF_disc
= { sizeof(struct Eof
), 0, 0, nget_cur_eof
};
365 #define MATCH_BUFF (64*1024)
372 static int matchf(void *handle
, char *ptr
, size_t size
)
374 struct Match
*mp
= (struct Match
*)handle
;
375 mp
->offset
+= (ptr
-mp
->base
);
380 static struct fdsave
*filemap
;
381 static short filemapsize
;
383 /* ======== input output and file copying ======== */
385 void sh_ioinit(Shell_t
*shp
)
389 filemap
= (struct fdsave
*)malloc(filemapsize
*sizeof(struct fdsave
));
391 n
= shp
->lim
.open_max
+2;
393 n
= shp
->lim
.open_max
;
394 #endif /* SHOPT_FASTPIPE */
395 shp
->fdstatus
= (unsigned char*)malloc((unsigned)n
);
396 memset((char*)shp
->fdstatus
,0,n
);
397 shp
->fdptrs
= (int**)malloc(n
*sizeof(int*));
398 memset((char*)shp
->fdptrs
,0,n
*sizeof(int*));
399 shp
->sftable
= (Sfio_t
**)malloc(n
*sizeof(Sfio_t
*));
400 memset((char*)shp
->sftable
,0,n
*sizeof(Sfio_t
*));
401 shp
->sftable
[0] = sfstdin
;
402 shp
->sftable
[1] = sfstdout
;
403 shp
->sftable
[2] = sfstderr
;
406 /* all write steams are in the same pool and share outbuff */
407 shp
->outpool
= sfopen(NIL(Sfio_t
*),NIL(char*),"sw"); /* pool identifier */
408 shp
->outbuff
= (char*)malloc(IOBSIZE
+4);
409 shp
->errbuff
= (char*)malloc(IOBSIZE
/4);
410 sfsetbuf(sfstderr
,shp
->errbuff
,IOBSIZE
/4);
411 sfsetbuf(sfstdout
,shp
->outbuff
,IOBSIZE
);
412 sfpool(sfstdout
,shp
->outpool
,SF_WRITE
);
413 sfpool(sfstderr
,shp
->outpool
,SF_WRITE
);
414 sfset(sfstdout
,SF_LINE
,0);
415 sfset(sfstderr
,SF_LINE
,0);
416 sfset(sfstdin
,SF_SHARE
|SF_PUBLIC
,1);
420 * Handle output stream exceptions
422 static int outexcept(register Sfio_t
*iop
,int type
,void *data
,Sfdisc_t
*handle
)
424 static int active
= 0;
427 if(type
==SF_DPOP
|| type
==SF_FINAL
)
429 else if(type
==SF_WRITE
&& (*(ssize_t
*)data
)<0 && sffileno(iop
)!=2)
444 int mode
= ((struct checkpt
*)sh
.jmplist
)->mode
;
447 ((struct checkpt
*)sh
.jmplist
)->mode
= 0;
449 sfpool(iop
,NIL(Sfio_t
*),SF_WRITE
);
451 errormsg(SH_DICT
,ERROR_system(1),e_badwrite
,sffileno(iop
));
453 ((struct checkpt
*)sh
.jmplist
)->mode
= mode
;
462 * create or initialize a stream corresponding to descriptor <fd>
463 * a buffer with room for a sentinal is allocated for a read stream.
464 * A discipline is inserted when read stream is a tty or a pipe
465 * For output streams, the buffer is set to sh.output and put into
466 * the sh.outpool synchronization pool
468 Sfio_t
*sh_iostream(Shell_t
*shp
, register int fd
)
470 register Sfio_t
*iop
;
471 register int status
= sh_iocheckfd(shp
,fd
);
472 register int flags
= SF_WRITE
;
476 if(fd
>=shp
->lim
.open_max
)
477 return(shp
->sftable
[fd
]);
478 #endif /* SHOPT_FASTPIPE */
490 return(NIL(Sfio_t
*));
494 if(!(bp
= (char *)malloc(IOBSIZE
+1)))
495 return(NIL(Sfio_t
*));
497 if(!(status
&IOWRITE
))
503 flags
|= SF_SHARE
|SF_PUBLIC
;
504 if((iop
= shp
->sftable
[fd
]) && sffileno(iop
)>=0)
505 sfsetbuf(iop
, bp
, IOBSIZE
);
506 else if(!(iop
=sfnew((fd
<=2?iop
:0),bp
,IOBSIZE
,fd
,flags
)))
507 return(NIL(Sfio_t
*));
508 dp
= newof(0,Sfdisc_t
,1,0);
511 sfset(iop
,SF_MALLOC
,1);
512 if(!(status
&IOWRITE
))
513 sfset(iop
,SF_IOCHECK
,1);
514 dp
->exceptf
= slowexcept
;
516 dp
->readf
= slowread
;
517 else if(status
&IONOSEEK
)
519 dp
->readf
= piperead
;
520 sfset(iop
, SF_IOINTR
,1);
529 dp
->exceptf
= outexcept
;
530 sfpool(iop
,shp
->outpool
,SF_WRITE
);
533 shp
->sftable
[fd
] = iop
;
538 * preserve the file descriptor or stream by moving it
540 static void io_preserve(Shell_t
* shp
, register Sfio_t
*sp
, register int f2
)
546 fd
= sh_fcntl(f2
,F_DUPFD
,10);
552 ((struct checkpt
*)shp
->jmplist
)->mode
= SH_JMPERREXIT
;
553 errormsg(SH_DICT
,ERROR_system(1),e_toomany
);
555 if(shp
->fdptrs
[fd
]=shp
->fdptrs
[f2
])
559 *shp
->fdptrs
[fd
] = fd
;
562 shp
->sftable
[fd
] = sp
;
563 shp
->fdstatus
[fd
] = shp
->fdstatus
[f2
];
564 if(fcntl(f2
,F_GETFD
,0)&1)
566 fcntl(fd
,F_SETFD
,FD_CLOEXEC
);
567 shp
->fdstatus
[fd
] |= IOCLEX
;
569 shp
->sftable
[f2
] = 0;
573 * Given a file descriptor <f1>, move it to a file descriptor number <f2>
574 * If <f2> is needed move it, otherwise it is closed first.
575 * The original stream <f1> is closed.
576 * The new file descriptor <f2> is returned;
578 int sh_iorenumber(Shell_t
*shp
, register int f1
,register int f2
)
580 register Sfio_t
*sp
= shp
->sftable
[f2
];
583 /* see whether file descriptor is in use */
584 if(sh_inuse(f2
) || (f2
>2 && sp
))
586 if(!(shp
->inuse_bits
&(1<<f2
)))
587 io_preserve(shp
,sp
,f2
);
595 register Sfio_t
*spnew
= sh_iostream(shp
,f1
);
596 shp
->fdstatus
[f2
] = (shp
->fdstatus
[f1
]&~IOCLEX
);
599 sfset(sp
,SF_SHARE
|SF_PUBLIC
,1);
603 shp
->fdstatus
[f2
] = (shp
->fdstatus
[f1
]&~IOCLEX
);
604 if((f2
= sh_fcntl(f1
,F_DUPFD
, f2
)) < 0)
605 errormsg(SH_DICT
,ERROR_system(1),e_file
+4);
610 shp
->sftable
[f1
] = 0;
617 * close a file descriptor and update stream table and attributes
619 int sh_close(register int fd
)
625 if(!(sp
=sh
.sftable
[fd
]) || sfclose(sp
) < 0)
628 (*fdnotify
)(fd
,SH_FDCLOSE
);
633 sh
.fdstatus
[fd
] = IOCLOSE
;
638 sh
.inuse_bits
&= ~(1<<fd
);
645 onintr(struct addrinfo
* addr
, void* handle
)
647 Shell_t
* sh
= (Shell_t
*)handle
;
649 if (sh
->trapnote
&SH_SIGSET
)
663 * Mimic open(2) with checks for pseudo /dev/ files.
665 int sh_open(register const char *path
, int flags
, ...)
668 register int fd
= -1;
673 mode
= (flags
& O_CREAT
) ? va_arg(ap
, int) : 0;
681 if (path
[0]=='/' && path
[1]=='d' && path
[2]=='e' && path
[3]=='v' && path
[4]=='/')
686 if (path
[6]=='d' && path
[7]=='/')
688 fd
= (int)strtol(path
+8, &e
, 10);
694 if (path
[6]=='t' && path
[7]=='d')
698 if (path
[9]=='r' && path
[10]=='r' && !path
[11])
702 if (path
[9]=='n' && !path
[10])
706 if (path
[9]=='u' && path
[10]=='t' && !path
[11])
714 if ((fd
= inetopen(path
+5, !!(flags
& O_SERVICE
), onintr
, &sh
)) < 0 && errno
!= ENOTDIR
)
727 if (stat(path
,&st
) >=0)
728 nfd
= open(path
,flags
,st
.st_mode
);
731 nfd
= open(path
,flags
);
737 if((mode
=sh_iocheckfd(shp
,fd
))==IOCLOSE
)
740 if(!(mode
&IOWRITE
) && ((flags
==O_WRONLY
) || (flags
==O_RDWR
)))
742 if(!(mode
&IOREAD
) && ((flags
==O_RDONLY
) || (flags
==O_RDWR
)))
751 if(strncmp(path
,"/etc/",5)==0)
753 sfsprintf(buf
, sizeof(buf
), "%s%s", sh_regress_etc(path
, __LINE__
, __FILE__
), path
+4);
757 while((fd
= open(path
, flags
, mode
)) < 0)
758 if(errno
!=EINTR
|| sh
.trapnote
)
765 else if(flags
==O_RDWR
)
766 mode
= (IOREAD
|IOWRITE
);
769 sh
.fdstatus
[fd
] = mode
;
774 * Open a file for reading
775 * On failure, print message.
777 int sh_chkopen(register const char *name
)
779 register int fd
= sh_open(name
,O_RDONLY
,0);
781 errormsg(SH_DICT
,ERROR_system(1),e_open
,name
);
786 * move open file descriptor to a number > 2
788 int sh_iomovefd(register int fdold
)
791 if(fdold
<0 || fdold
>2)
793 fdnew
= sh_iomovefd(dup(fdold
));
794 sh
.fdstatus
[fdnew
] = (sh
.fdstatus
[fdold
]&~IOCLEX
);
796 sh
.fdstatus
[fdold
] = IOCLOSE
;
801 * create a pipe and print message on failure
803 int sh_pipe(register int pv
[])
806 if(pipe(fd
)<0 || (pv
[0]=fd
[0])<0 || (pv
[1]=fd
[1])<0)
807 errormsg(SH_DICT
,ERROR_system(1),e_pipe
);
808 pv
[0] = sh_iomovefd(pv
[0]);
809 pv
[1] = sh_iomovefd(pv
[1]);
810 sh
.fdstatus
[pv
[0]] = IONOSEEK
|IOREAD
;
811 sh
.fdstatus
[pv
[1]] = IONOSEEK
|IOWRITE
;
817 static int pat_seek(void *handle
, const char *str
, size_t sz
)
819 char **bp
= (char**)handle
;
824 static int pat_line(const regex_t
* rp
, const char *buff
, register size_t n
)
826 register const char *cp
=buff
, *sp
;
829 for(sp
=cp
; n
-->0 && *cp
++ != '\n';);
830 if(regnexec(rp
,sp
,cp
-sp
, 0, (regmatch_t
*)0, 0)==0)
836 static int io_patseek(Shell_t
*shp
, regex_t
*rp
, Sfio_t
* sp
, int flags
)
839 int r
, fd
=sffileno(sp
), close_exec
= shp
->fdstatus
[fd
]&IOCLEX
;
840 int was_share
,s
=(PIPE_BUF
>SF_BUFSIZE
?SF_BUFSIZE
:PIPE_BUF
);
842 shp
->fdstatus
[sffileno(sp
)] |= IOCLEX
;
844 was_share
= sfset(sp
,SF_SHARE
,1);
845 while((cp
=sfreserve(sp
, -s
, SF_LOCKR
)) || (cp
=sfreserve(sp
,SF_UNBOUND
, SF_LOCKR
)))
848 while(n
>0 && cp
[n
-1]!='\n')
852 r
= regrexec(rp
,cp
,m
,0,(regmatch_t
*)0, 0, '\n', (void*)&match
, pat_seek
);
857 if((m
= pat_line(rp
,cp
,m
)) < n
)
860 if(m
&& (flags
&IOCOPY
))
861 sfwrite(sfstdout
,cp
,m
);
867 shp
->fdstatus
[sffileno(sp
)] &= ~IOCLEX
;
868 if(fd
==0 && !(was_share
&SF_SHARE
))
869 sfset(sp
, SF_SHARE
,0);
873 static Sfoff_t
file_offset(Shell_t
*shp
, int fn
, char *fname
)
875 Sfio_t
*sp
= shp
->sftable
[fn
];
879 Namval_t
*mp
= nv_open("EOF",shp
->var_tree
,0);
880 Namval_t
*pp
= nv_open("CUR",shp
->var_tree
,0);
881 memset(&endf
,0,sizeof(struct Eof
));
883 endf
.hdr
.disc
= &EOF_disc
;
886 nv_stack(mp
, &endf
.hdr
);
888 nv_stack(pp
, &endf
.hdr
);
891 off
= sh_strnum(fname
, &cp
, 0);
896 return(*cp
?(Sfoff_t
)-1:off
);
902 void sh_pclose(register int pv
[])
911 static char *io_usename(char *name
, int *perm
, int mode
)
914 char *tname
, *sp
, *ep
;
918 if((fd
= sh_open(name
,O_RDONLY
,0)) > 0)
920 if(fstat(fd
,&statb
) < 0)
922 if(!S_ISREG(statb
.st_mode
))
924 *perm
= statb
.st_mode
&(RW_ALL
|(S_IXUSR
|S_IXGRP
|S_IXOTH
));
926 else if(fd
< 0 && errno
!=ENOENT
)
929 tname
= sp
= (char*)stakalloc((len
=strlen(name
)) + 5);
930 if(ep
= strrchr(name
,'/'))
932 memcpy(sp
,name
,n
=++ep
-name
);
940 strcpy(sp
+len
,".tmp");
955 * flag = 0 if files are to be restored
956 * flag = 2 if files are to be closed on exec
957 * flag = 3 when called from $( < ...), just open file and return
958 * flag = SH_SHOWME for trace only
960 int sh_redirect(Shell_t
*shp
,struct ionod
*iop
, int flag
)
963 register char *fname
;
964 register int fd
, iof
;
965 const char *message
= e_open
;
966 int o_mode
; /* mode flag for open */
967 static char io_op
[7]; /* used for -x trace info */
968 int trunc
=0, clexec
=0, fn
, traceon
;
969 int r
, indx
= shp
->topfd
, perm
= -1;
970 char *tname
=0, *after
="", *trace
= shp
->st
.trap
[SH_DEBUGTRAP
];
972 int isstring
= shp
->subshell
?(sfset(sfstdout
,0,0)&SF_STRING
):0;
976 traceon
= sh_trace(NIL(char**),0);
977 for(;iop
;iop
=iop
->ionxt
)
981 if(fn
==1 && shp
->subshell
&& !shp
->subshare
&& (flag
==2 || isstring
))
983 io_op
[0] = '0'+(iof
&IOUFD
);
987 o_mode
= O_WRONLY
|O_CREAT
;
992 o_mode
= O_RDONLY
|O_NONBLOCK
;
1002 struct argnod
*ap
= (struct argnod
*)stakalloc(ARGVAL
+strlen(iop
->ioname
));
1003 memset(ap
, 0, ARGVAL
);
1004 ap
->argflag
= ARG_MAC
;
1005 strcpy(ap
->argval
,iop
->ioname
);
1006 fname
=sh_macpat(shp
,ap
,(iof
&IOARITH
)?ARG_ARITH
:ARG_EXP
);
1008 else if(iof
&IOPROCSUB
)
1010 struct argnod
*ap
= (struct argnod
*)stakalloc(ARGVAL
+strlen(iop
->ioname
));
1011 memset(ap
, 0, ARGVAL
);
1013 ap
->argflag
= ARG_RAW
;
1014 ap
->argchn
.ap
= (struct argnod
*)fname
;
1015 ap
= sh_argprocsub(shp
,ap
);
1019 fname
=sh_mactrim(shp
,fname
,(!sh_isoption(SH_NOGLOB
)&&sh_isoption(SH_INTERACTIVE
))?2:0);
1025 np
= nv_open(iop
->iovname
,shp
->var_tree
,NV_NOASSIGN
|NV_VARNAME
);
1026 if(nv_isattr(np
,NV_RDONLY
))
1027 errormsg(SH_DICT
,ERROR_exit(1),e_readonly
, nv_name(np
));
1029 if((iof
&IOLSEEK
) || ((iof
&IOMOV
) && *fname
=='-'))
1037 strcpy(&io_op
[3]," ((");
1049 sfputr(sfstderr
,io_op
,'<');
1050 fd
= io_heredoc(shp
,iop
,fname
,traceon
);
1051 if(traceon
&& (flag
==SH_SHOWME
))
1057 int dupfd
,toclose
= -1;
1059 if((fd
=fname
[0])>='0' && fd
<='9')
1061 char *number
= fname
;
1062 dupfd
= strtol(fname
,&number
,10);
1068 if(*number
|| dupfd
> IOUFD
)
1073 if(shp
->subshell
&& dupfd
==1 && (sfset(sfstdout
,0,0)&SF_STRING
))
1076 dupfd
= sffileno(sfstdout
);
1078 else if(shp
->sftable
[dupfd
])
1079 sfsync(shp
->sftable
[dupfd
]);
1081 else if(fd
=='-' && fname
[1]==0)
1086 else if(fd
=='p' && fname
[1]==0)
1089 dupfd
= shp
->coutpipe
;
1091 dupfd
= shp
->cpipe
[0];
1102 if((fd
=sh_fcntl(dupfd
,F_DUPFD
,3))<0)
1104 sh_iocheckfd(shp
,dupfd
);
1105 shp
->fdstatus
[fd
] = (shp
->fdstatus
[dupfd
]&~IOCLEX
);
1106 if(toclose
<0 && shp
->fdstatus
[fd
]&IOREAD
)
1107 shp
->fdstatus
[fd
] |= IODUP
;
1108 else if(dupfd
==shp
->cpipe
[0])
1109 sh_pclose(shp
->cpipe
);
1113 sh_iosave(shp
,toclose
,indx
,(char*)0); /* save file descriptor */
1119 if(sh_isoption(SH_RESTRICTED
))
1120 errormsg(SH_DICT
,ERROR_exit(1),e_restricted
,fname
);
1122 o_mode
= O_RDWR
|O_CREAT
;
1124 trunc
= io_op
[2] = ';';
1127 else if(!(iof
&IOPUT
))
1131 fd
=sh_chkopen(fname
);
1133 else if(sh_isoption(SH_RESTRICTED
))
1134 errormsg(SH_DICT
,ERROR_exit(1),e_restricted
,fname
);
1142 else if((iof
&IOREWRITE
) && (flag
==0 || flag
==1 || sh_subsavefd(fn
)))
1146 tname
= io_usename(fname
,&perm
,0);
1153 else if(sh_isoption(SH_NOCLOBBER
))
1156 if(stat(fname
,&sb
)>=0)
1159 if(S_ISREG(sb
.st_mode
)&&
1160 (!shp
->lim
.fs3d
|| iview(&sb
)==0))
1162 if(S_ISREG(sb
.st_mode
))
1163 #endif /* SHOPT_FS_3D */
1166 errormsg(SH_DICT
,ERROR_system(1),e_exists
,fname
);
1176 if((fd
=sh_open(tname
?tname
:fname
,o_mode
,RW_ALL
)) <0)
1177 errormsg(SH_DICT
,ERROR_system(1),((o_mode
&O_CREAT
)?e_create
:e_open
),fname
);
1187 if(traceon
&& fname
)
1190 sfprintf(sfstderr
,"{%s",nv_name(np
));
1191 sfprintf(sfstderr
,"%s %s%s%c",io_op
,fname
,after
,iop
->ionxt
?' ':'\n');
1197 char *argv
[7], **av
=argv
;
1207 av
[1] = nv_name(np
);
1212 sh_debug(shp
,trace
,(char*)0,(char*)0,av
,ARG_NOGLOB
);
1216 Sfio_t
*sp
= shp
->sftable
[fn
];
1217 r
= shp
->fdstatus
[fn
];
1218 if(!(r
&(IOSEEK
|IONOSEEK
)))
1219 r
= sh_iocheckfd(shp
,fn
);
1220 sfsprintf(io_op
,sizeof(io_op
),"%d\0",fn
);
1232 message
= e_notseek
;
1235 message
= e_badseek
;
1236 if((off
= file_offset(shp
,fn
,fname
))<0)
1240 off
=sfseek(sp
, off
, SEEK_SET
);
1244 off
=lseek(fn
, off
, SEEK_SET
);
1251 extern const char e_notimp
[];
1257 if(!(rp
= regcache(fname
, REG_SHELL
|REG_NOSUB
|REG_NEWLINE
|REG_AUGMENTED
|REG_FIRST
|REG_LEFT
|REG_RIGHT
, &r
)))
1259 message
= e_badpattern
;
1263 sp
= sh_iostream(shp
,fn
);
1264 r
=io_patseek(shp
,rp
,sp
,iof
);
1267 /* close stream but not fn */
1280 if(flag
==0 || tname
)
1284 if((r
=sh_fcntl(fd
,F_DUPFD
,10)) > 0)
1290 sh_iosave(shp
,fn
,indx
,tname
?fname
:(trunc
?Empty
:0));
1292 else if(sh_subsavefd(fn
))
1293 sh_iosave(shp
,fn
,indx
|IOSUBSHELL
,tname
?fname
:0);
1297 if(sh_inuse(fn
) || (fn
&& fn
==shp
->infd
))
1299 if(fn
>9 || !(shp
->inuse_bits
&(1<<fn
)))
1300 io_preserve(shp
,shp
->sftable
[fn
],fn
);
1314 if((fn
=fcntl(fd
,F_DUPFD
,10)) < 0)
1316 shp
->fdstatus
[fn
] = shp
->fdstatus
[fd
];
1321 nv_onattr(np
,NV_INT32
);
1323 nv_putval(np
,(char*)&v
, NV_INT32
);
1324 sh_iocheckfd(shp
,fd
);
1328 fd
= sh_iorenumber(shp
,sh_iomovefd(fd
),fn
);
1330 shp
->inuse_bits
|= (1<<fn
);
1335 fcntl(fd
,F_SETFD
,FD_CLOEXEC
);
1336 shp
->fdstatus
[fd
] |= IOCLEX
;
1344 errormsg(SH_DICT
,ERROR_system(1),message
,fname
);
1349 * Create a tmp file for the here-document
1351 static int io_heredoc(Shell_t
*shp
,register struct ionod
*iop
, const char *name
, int traceon
)
1353 register Sfio_t
*infile
= 0, *outfile
;
1355 if(!(iop
->iofile
&IOSTRG
) && (!shp
->heredocs
|| iop
->iosize
==0))
1356 return(sh_open(e_devnull
,O_RDONLY
));
1357 /* create an unnamed temporary file */
1358 if(!(outfile
=sftmp(0)))
1359 errormsg(SH_DICT
,ERROR_system(1),e_tmpcreate
);
1360 if(iop
->iofile
&IOSTRG
)
1363 sfprintf(sfstderr
,"< %s\n",name
);
1364 sfputr(outfile
,name
,'\n');
1368 infile
= subopen(shp
,shp
->heredocs
,iop
->iooffset
,iop
->iosize
);
1371 char *cp
= sh_fmtq(iop
->iodelim
);
1372 fd
= (*cp
=='$' || *cp
=='\'')?' ':'\\';
1373 sfprintf(sfstderr
," %c%s\n",fd
,cp
);
1374 sfdisc(outfile
,&tee_disc
);
1376 if(iop
->iofile
&IOQUOTE
)
1378 /* This is a quoted here-document, not expansion */
1379 sfmove(infile
,outfile
,SF_UNBOUND
,-1);
1384 char *lastpath
= shp
->lastpath
;
1385 sh_machere(shp
,infile
,outfile
,iop
->ioname
);
1386 shp
->lastpath
= lastpath
;
1391 /* close stream outfile, but save file descriptor */
1392 fd
= sffileno(outfile
);
1393 sfsetfd(outfile
,-1);
1395 if(traceon
&& !(iop
->iofile
&IOSTRG
))
1396 sfputr(sfstderr
,iop
->ioname
,'\n');
1397 lseek(fd
,(off_t
)0,SEEK_SET
);
1398 shp
->fdstatus
[fd
] = IOREAD
;
1403 * This write discipline also writes the output on standard error
1404 * This is used when tracing here-documents
1406 static ssize_t
tee_write(Sfio_t
*iop
,const void *buff
,size_t n
,Sfdisc_t
*unused
)
1409 sfwrite(sfstderr
,buff
,n
);
1410 return(write(sffileno(iop
),buff
,n
));
1414 * copy file <origfd> into a save place
1415 * The saved file is set close-on-exec
1416 * if <origfd> < 0, then -origfd is saved, but not duped so that it
1417 * will be closed with sh_iorestore.
1419 void sh_iosave(Shell_t
*shp
, register int origfd
, int oldtop
, char *name
)
1422 assume oldtop>=0 && oldtop<shp->lim.open_max;
1425 register int savefd
;
1426 int flag
= (oldtop
&IOSUBSHELL
);
1427 oldtop
&= ~IOSUBSHELL
;
1428 /* see if already saved, only save once */
1429 for(savefd
=shp
->topfd
; --savefd
>=oldtop
; )
1431 if(filemap
[savefd
].orig_fd
== origfd
)
1434 /* make sure table is large enough */
1435 if(shp
->topfd
>= filemapsize
)
1437 char *cp
, *oldptr
= (char*)filemap
;
1438 char *oldend
= (char*)&filemap
[filemapsize
];
1441 if(!(filemap
= (struct fdsave
*)realloc(filemap
,filemapsize
*sizeof(struct fdsave
))))
1442 errormsg(SH_DICT
,ERROR_exit(4),e_nospace
);
1443 if(moved
= (char*)filemap
- oldptr
)
1446 for(savefd
=shp
->lim
.open_max
+2; --savefd
>=0; )
1448 for(savefd
=shp
->lim
.open_max
; --savefd
>=0; )
1449 #endif /* SHOPT_FASTPIPE */
1451 cp
= (char*)shp
->fdptrs
[savefd
];
1452 if(cp
>= oldptr
&& cp
< oldend
)
1453 shp
->fdptrs
[savefd
] = (int*)(oldptr
+moved
);
1464 #endif /* SHOPT_DEVFD */
1466 if((savefd
= sh_fcntl(origfd
, F_DUPFD
, 10)) < 0 && errno
!=EBADF
)
1469 ((struct checkpt
*)shp
->jmplist
)->mode
= SH_JMPERREXIT
;
1470 errormsg(SH_DICT
,ERROR_system(1),e_toomany
);
1473 filemap
[shp
->topfd
].tname
= name
;
1474 filemap
[shp
->topfd
].subshell
= flag
;
1475 filemap
[shp
->topfd
].orig_fd
= origfd
;
1476 filemap
[shp
->topfd
++].save_fd
= savefd
;
1479 register Sfio_t
* sp
= shp
->sftable
[origfd
];
1480 /* make saved file close-on-exec */
1481 sh_fcntl(savefd
,F_SETFD
,FD_CLOEXEC
);
1484 shp
->fdstatus
[savefd
] = shp
->fdstatus
[origfd
];
1485 shp
->fdptrs
[savefd
] = &filemap
[shp
->topfd
-1].save_fd
;
1486 if(!(shp
->sftable
[savefd
]=sp
))
1491 /* copy standard stream to new stream */
1492 sp
= sfswap(sp
,NIL(Sfio_t
*));
1493 shp
->sftable
[savefd
] = sp
;
1496 shp
->sftable
[origfd
] = 0;
1501 * close all saved file descriptors
1503 void sh_iounsave(Shell_t
* shp
)
1505 register int fd
, savefd
, newfd
;
1506 for(newfd
=fd
=0; fd
< shp
->topfd
; fd
++)
1508 if((savefd
= filemap
[fd
].save_fd
)< 0)
1509 filemap
[newfd
++] = filemap
[fd
];
1512 shp
->sftable
[savefd
] = 0;
1520 * restore saved file descriptors from <last> on
1522 void sh_iorestore(Shell_t
*shp
, int last
, int jmpval
)
1524 register int origfd
, savefd
, fd
;
1525 int flag
= (last
&IOSUBSHELL
);
1526 last
&= ~IOSUBSHELL
;
1527 for (fd
= shp
->topfd
- 1; fd
>= last
; fd
--)
1529 if(!flag
&& filemap
[fd
].subshell
)
1531 if(jmpval
==SH_JMPSCRIPT
)
1533 if ((savefd
= filemap
[fd
].save_fd
) >= 0)
1535 shp
->sftable
[savefd
] = 0;
1540 origfd
= filemap
[fd
].orig_fd
;
1541 if(filemap
[fd
].tname
== Empty
&& shp
->exitval
==0)
1542 ftruncate(origfd
,lseek(origfd
,0,SEEK_CUR
));
1543 else if(filemap
[fd
].tname
)
1544 io_usename(filemap
[fd
].tname
,(int*)0,shp
->exitval
?2:1);
1546 if ((savefd
= filemap
[fd
].save_fd
) >= 0)
1548 sh_fcntl(savefd
, F_DUPFD
, origfd
);
1551 shp
->fdstatus
[origfd
] = shp
->fdstatus
[savefd
];
1552 /* turn off close-on-exec if flag if necessary */
1553 if(shp
->fdstatus
[origfd
]&IOCLEX
)
1554 fcntl(origfd
,F_SETFD
,FD_CLOEXEC
);
1557 sfswap(shp
->sftable
[savefd
],shp
->sftable
[origfd
]);
1562 shp
->sftable
[origfd
] = shp
->sftable
[savefd
];
1563 shp
->sftable
[savefd
] = 0;
1567 shp
->fdstatus
[origfd
] = IOCLOSE
;
1571 /* keep file descriptors for subshell restore */
1572 for (fd
= last
; fd
< shp
->topfd
; fd
++)
1574 if(filemap
[fd
].subshell
)
1575 filemap
[last
++] = filemap
[fd
];
1578 if(last
< shp
->topfd
)
1583 * returns access information on open file <fd>
1584 * returns -1 for failure, 0 for success
1585 * <mode> is the same as for access()
1587 int sh_ioaccess(int fd
,register int mode
)
1593 if((flags
=sh_iocheckfd(shp
,fd
))!=IOCLOSE
)
1597 if(mode
==R_OK
&& (flags
&IOREAD
))
1599 if(mode
==W_OK
&& (flags
&IOWRITE
))
1606 * Handle interrupts for slow streams
1608 static int slowexcept(register Sfio_t
*iop
,int type
,void *data
,Sfdisc_t
*handle
)
1612 if(type
==SF_DPOP
|| type
==SF_FINAL
)
1613 free((void*)handle
);
1616 if((sh
.trapnote
&(SH_SIGSET
|SH_SIGTRAP
)) && errno
!=EIO
&& errno
!=ENXIO
)
1618 fno
= sffileno(iop
);
1619 if((n
=sfvalue(iop
))<=0)
1623 if(errno
==0 && (n
=fcntl(fno
,F_GETFL
,0))&O_NDELAY
)
1626 fcntl(fno
, F_SETFL
, n
);
1629 # endif /* O_NDELAY */
1630 #endif /* !FNDELAY */
1634 n
= fcntl(fno
,F_GETFL
,0);
1636 fcntl(fno
, F_SETFL
, n
);
1639 #endif /* O_NONBLOCK */
1643 sh_onstate(SH_TTYWAIT
);
1647 if(sh
.bltinfun
&& sh
.bltindata
.sigset
)
1650 if(sh
.trapnote
&SH_SIGSET
)
1653 sfputc(sfstderr
,'\n');
1654 sh_exit(SH_EXITSIG
);
1656 if(sh
.trapnote
&SH_SIGTRAP
)
1662 * called when slowread times out
1664 static void time_grace(void *handle
)
1668 if(sh_isstate(SH_GRACE
))
1670 sh_offstate(SH_GRACE
);
1671 if(!sh_isstate(SH_INTERACTIVE
))
1673 ((struct checkpt
*)sh
.jmplist
)->mode
= SH_JMPEXIT
;
1674 errormsg(SH_DICT
,2,e_timeout
);
1675 sh
.trapnote
|= SH_SIGSET
;
1678 errormsg(SH_DICT
,0,e_timewarn
);
1679 sh_onstate(SH_GRACE
);
1680 sigrelease(SIGALRM
);
1681 sh
.trapnote
|= SH_SIGTRAP
;
1684 static ssize_t
piperead(Sfio_t
*iop
,void *buff
,register size_t size
,Sfdisc_t
*handle
)
1686 int fd
= sffileno(iop
);
1688 if(job
.waitsafe
&& job
.savesig
)
1698 if(sh_isstate(SH_INTERACTIVE
) && io_prompt(iop
,sh
.nextprompt
)<0 && errno
==EIO
)
1700 sh_onstate(SH_TTYWAIT
);
1701 if(!(sh
.fdstatus
[sffileno(iop
)]&IOCLEX
) && (sfset(iop
,0,0)&SF_SHARE
))
1702 size
= ed_read(sh
.ed_context
, fd
, (char*)buff
, size
,0);
1704 size
= sfrd(iop
,buff
,size
,handle
);
1705 sh_offstate(SH_TTYWAIT
);
1709 * This is the read discipline that is applied to slow devices
1710 * This routine takes care of prompting for input
1712 static ssize_t
slowread(Sfio_t
*iop
,void *buff
,register size_t size
,Sfdisc_t
*handle
)
1714 int (*readf
)(void*, int, char*, int, int);
1715 int reedit
=0, rsize
;
1716 #if SHOPT_HISTEXPAND
1721 if(sh_isoption(SH_EMACS
) || sh_isoption(SH_GMACS
))
1722 readf
= ed_emacsread
;
1724 # endif /* SHOPT_ESH */
1727 if(sh_isoption(SH_VI
) || ((SHOPT_RAWONLY
-0) && mbwide()))
1729 if(sh_isoption(SH_VI
))
1733 # endif /* SHOPT_VSH */
1742 if(io_prompt(iop
,sh
.nextprompt
)<0 && errno
==EIO
)
1745 timeout
= (void*)sh_timeradd(sh_isstate(SH_GRACE
)?1000L*TGRACE
:1000L*sh
.timeout
,0,time_grace
,NIL(void*));
1746 rsize
= (*readf
)(sh
.ed_context
, sffileno(iop
), (char*)buff
, size
, reedit
);
1750 #if SHOPT_HISTEXPAND
1751 if(rsize
&& *(char*)buff
!= '\n' && sh
.nextprompt
==1 && sh_isoption(SH_HISTEXPAND
))
1754 ((char*)buff
)[rsize
] = '\0';
1760 r
= hist_expand(buff
, &xp
);
1761 if((r
& (HIST_EVENT
|HIST_PRINT
)) && !(r
& HIST_ERROR
) && xp
)
1763 strlcpy(buff
, xp
, size
);
1764 rsize
= strlen(buff
);
1765 if(!sh_isoption(SH_HISTVERIFY
) || readf
==ed_read
)
1767 sfputr(sfstderr
, xp
, -1);
1773 if((r
& HIST_ERROR
) && sh_isoption(SH_HISTREEDIT
))
1778 if(r
& (HIST_ERROR
|HIST_PRINT
))
1780 *(char*)buff
= '\n';
1791 * check and return the attributes for a file descriptor
1794 int sh_iocheckfd(Shell_t
*shp
, register int fd
)
1796 register int flags
, n
;
1797 if((n
=sh
.fdstatus
[fd
])&IOCLOSE
)
1799 if(!(n
&(IOREAD
|IOWRITE
)))
1802 if((flags
=fcntl(fd
,F_GETFL
,0)) < 0)
1803 return(sh
.fdstatus
[fd
]=IOCLOSE
);
1804 if((flags
&O_ACCMODE
)!=O_WRONLY
)
1806 if((flags
&O_ACCMODE
)!=O_RDONLY
)
1810 if((flags
= fstat(fd
,&statb
))< 0)
1811 return(sh
.fdstatus
[fd
]=IOCLOSE
);
1812 n
|= (IOREAD
|IOWRITE
);
1813 if(read(fd
,"",0) < 0)
1815 #endif /* F_GETFL */
1817 if(!(n
&(IOSEEK
|IONOSEEK
)))
1820 /* /dev/null check is a workaround for select bug */
1821 static ino_t null_ino
;
1822 static dev_t null_dev
;
1823 if(null_ino
==0 && stat(e_devnull
,&statb
) >=0)
1825 null_ino
= statb
.st_ino
;
1826 null_dev
= statb
.st_dev
;
1830 if(lseek(fd
,NIL(off_t
),SEEK_CUR
)<0)
1834 if((fstat(fd
,&statb
)>=0) && S_ISSOCK(statb
.st_mode
))
1835 n
|= IOREAD
|IOWRITE
;
1836 #endif /* S_ISSOCK */
1838 else if((fstat(fd
,&statb
)>=0) && (
1839 S_ISFIFO(statb
.st_mode
) ||
1841 S_ISSOCK(statb
.st_mode
) ||
1842 #endif /* S_ISSOCK */
1843 /* The following is for sockets on the sgi */
1844 (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) ||
1845 (S_ISCHR(statb
.st_mode
) && (statb
.st_ino
!=null_ino
|| statb
.st_dev
!=null_dev
))
1851 sh
.fdstatus
[fd
] = n
;
1856 * Display prompt PS<flag> on standard error
1859 static int io_prompt(Sfio_t
*iop
,register int flag
)
1867 if(flag
<3 && !sh_isstate(SH_INTERACTIVE
))
1869 if(flag
==2 && sfpkrd(sffileno(iop
),buff
,1,'\n',0,1) >= 0)
1872 return(sfsync(sfstderr
));
1873 sfflags
= sfset(sfstderr
,SF_SHARE
|SF_PUBLIC
|SF_READ
,0);
1874 if(!(sh
.prompt
=(char*)sfreserve(sfstderr
,0,0)))
1881 #if defined(TIOCLBIC) && defined(LFLUSHO)
1882 if(!sh_isoption(SH_VI
) && !sh_isoption(SH_EMACS
) && !sh_isoption(SH_GMACS
))
1885 * re-enable output in case the user has
1886 * disabled it. Not needed with edit mode
1889 ioctl(sffileno(sfstderr
),TIOCLBIC
,&mode
);
1891 #endif /* TIOCLBIC */
1892 cp
= sh_mactry(shp
,nv_getval(sh_scoped(shp
,PS1NOD
)));
1897 /* look at next character */
1899 /* print out line number if not !! */
1902 sfprintf(sfstderr
,"%d", sh
.hist_ptr
?(int)sh
.hist_ptr
->histind
:++cmdno
);
1912 cp
= nv_getval(sh_scoped(shp
,PS2NOD
));
1915 cp
= nv_getval(sh_scoped(shp
,PS3NOD
));
1921 sfputr(sfstderr
,cp
,-1);
1923 if(*sh
.prompt
&& (endprompt
=(char*)sfreserve(sfstderr
,0,0)))
1925 sfset(sfstderr
,sfflags
&SF_READ
|SF_SHARE
|SF_PUBLIC
,1);
1926 return(sfsync(sfstderr
));
1930 * This discipline is inserted on write pipes to prevent SIGPIPE
1931 * from causing an infinite loop
1933 static int pipeexcept(Sfio_t
* iop
, int mode
, void *data
, Sfdisc_t
* handle
)
1936 if(mode
==SF_DPOP
|| mode
==SF_FINAL
)
1937 free((void*)handle
);
1938 else if(mode
==SF_WRITE
&& errno
==EINTR
&& sh
.lastsig
==SIGPIPE
)
1944 * keep track of each stream that is opened and closed
1946 static void sftrack(Sfio_t
* sp
, int flag
, void* data
)
1949 register int fd
= sffileno(sp
);
1950 register struct checkpt
*pp
;
1952 int newfd
= integralof(data
);
1953 if(flag
==SF_SETFD
|| flag
==SF_CLOSING
)
1958 (*fdnotify
)(sffileno(sp
),flag
==SF_CLOSING
?-1:newfd
);
1961 if(flag
==SF_READ
|| flag
==SF_WRITE
)
1963 char *z
= fmtbase((long)getpid(),0,0);
1964 write(ERRIO
,z
,strlen(z
));
1965 write(ERRIO
,": ",2);
1966 write(ERRIO
,"attempt to ",11);
1968 write(ERRIO
,"read from",9);
1970 write(ERRIO
,"write to",8);
1971 write(ERRIO
," locked stream\n",15);
1975 if((unsigned)fd
>= shp
->lim
.open_max
)
1977 if(sh_isstate(SH_NOTRACK
))
1979 mode
= sfset(sp
,0,0);
1980 if(sp
==shp
->heredocs
&& fd
< 10 && flag
==SF_NEW
)
1982 fd
= sfsetfd(sp
,10);
1983 fcntl(fd
,F_SETFD
,FD_CLOEXEC
);
1989 if(!shp
->sftable
[fd
] && shp
->fdstatus
[fd
]==IOCLOSE
)
1991 shp
->sftable
[fd
] = sp
;
1992 flag
= (mode
&SF_WRITE
)?IOWRITE
:0;
1995 shp
->fdstatus
[fd
] = flag
;
1996 sh_iostream(shp
,fd
);
1998 if((pp
=(struct checkpt
*)shp
->jmplist
) && pp
->mode
==SH_JMPCMD
)
2000 struct openlist
*item
;
2002 * record open file descriptors so they can
2003 * be closed in case a longjmp prevents
2004 * built-ins from cleanup
2006 item
= new_of(struct openlist
, 0);
2008 item
->next
= pp
->olist
;
2012 (*fdnotify
)(-1,sffileno(sp
));
2014 else if(flag
==SF_CLOSING
|| (flag
==SF_SETFD
&& newfd
<=2))
2016 shp
->sftable
[fd
] = 0;
2017 shp
->fdstatus
[fd
]=IOCLOSE
;
2018 if(pp
=(struct checkpt
*)shp
->jmplist
)
2020 struct openlist
*item
;
2021 for(item
=pp
->olist
; item
; item
=item
->next
)
2023 if(item
->strm
== sp
)
2042 * Create a stream consisting of a space separated argv[] list
2045 Sfio_t
*sh_sfeval(register char *argv
[])
2047 register Sfio_t
*iop
;
2053 iop
= sfopen(NIL(Sfio_t
*),(char*)cp
,"s");
2056 register struct eval
*ep
;
2057 if(!(ep
= new_of(struct eval
,0)))
2058 return(NIL(Sfio_t
*));
2059 ep
->disc
= eval_disc
;
2063 sfdisc(iop
,&ep
->disc
);
2069 * This code gets called whenever an end of string is found with eval
2072 static int eval_exceptf(Sfio_t
*iop
,int type
, void *data
, Sfdisc_t
*handle
)
2074 register struct eval
*ep
= (struct eval
*)handle
;
2079 if(type
!=SF_READ
|| !(cp
= ep
->argv
[0]))
2081 if(type
==SF_CLOSING
)
2082 sfdisc(iop
,SF_POPDISC
);
2083 else if(ep
&& (type
==SF_DPOP
|| type
==SF_FINAL
))
2090 /* get the length of this string */
2091 ep
->slen
= len
= strlen(cp
);
2092 /* move to next string */
2095 else /* insert space between arguments */
2100 /* insert the new string */
2101 sfsetbuf(iop
,cp
,len
);
2102 ep
->addspace
= !ep
->addspace
;
2107 * This routine returns a stream pointer to a segment of length <size> from
2108 * the stream <sp> starting at offset <offset>
2109 * The stream can be read with the normal stream operations
2112 static Sfio_t
*subopen(Shell_t
*shp
,Sfio_t
* sp
, off_t offset
, long size
)
2114 register struct subfile
*disp
;
2115 if(sfseek(sp
,offset
,SEEK_SET
) <0)
2116 return(NIL(Sfio_t
*));
2117 if(!(disp
= (struct subfile
*)malloc(sizeof(struct subfile
)+IOBSIZE
+1)))
2118 return(NIL(Sfio_t
*));
2119 disp
->disc
= sub_disc
;
2121 disp
->offset
= offset
;
2122 disp
->size
= disp
->left
= size
;
2123 sp
= sfnew(NIL(Sfio_t
*),(char*)(disp
+1),IOBSIZE
,shp
->lim
.open_max
,SF_READ
);
2124 sfdisc(sp
,&disp
->disc
);
2129 * read function for subfile discipline
2131 static ssize_t
subread(Sfio_t
* sp
,void* buff
,register size_t size
,Sfdisc_t
* handle
)
2133 register struct subfile
*disp
= (struct subfile
*)handle
;
2137 if(size
> disp
->left
)
2140 return(sfread(disp
->oldsp
,buff
,size
));
2144 * exception handler for subfile discipline
2146 static int subexcept(Sfio_t
* sp
,register int mode
, void *data
, Sfdisc_t
* handle
)
2148 register struct subfile
*disp
= (struct subfile
*)handle
;
2149 if(mode
==SF_CLOSING
)
2151 sfdisc(sp
,SF_POPDISC
);
2154 else if(disp
&& (mode
==SF_DPOP
|| mode
==SF_FINAL
))
2160 else if (mode
==SF_ATEXIT
)
2162 sfdisc(sp
, SF_POPDISC
);
2166 else if(mode
==SF_READ
)
2171 #define NROW 15 /* number of rows before going to multi-columns */
2172 #define LBLSIZ 3 /* size of label field and interfield spacing */
2174 * print a list of arguments in columns
2176 void sh_menu(Sfio_t
*outfile
,int argn
,char *argv
[])
2180 register char **arg
;
2181 int nrow
, ncol
=1, ndigits
=1;
2182 int fldsize
, wsize
= ed_window();
2183 char *cp
= nv_getval(sh_scoped(shp
,LINES
));
2184 nrow
= (cp
?1+2*((int)strtol(cp
, (char**)0, 10)/3):NROW
);
2185 for(i
=argn
;i
>= 10;i
/= 10)
2193 for(arg
=argv
; *arg
;arg
++)
2195 if((j
=strlen(*arg
)) > i
)
2198 i
+= (ndigits
+LBLSIZ
);
2201 if(argn
> nrow
*ncol
)
2203 nrow
= 1 + (argn
-1)/ncol
;
2207 ncol
= 1 + (argn
-1)/nrow
;
2208 nrow
= 1 + (argn
-1)/ncol
;
2211 fldsize
= (wsize
/ncol
)-(ndigits
+LBLSIZ
);
2214 if(sh
.trapnote
&SH_SIGSET
)
2220 sfprintf(outfile
,"%*d) %s",ndigits
,j
+1,*arg
);
2224 sfnputc(outfile
,' ',fldsize
-strlen(*arg
));
2226 sfputc(outfile
,'\n');
2232 * shell version of read() for user added builtins
2234 ssize_t
sh_read(register int fd
, void* buff
, size_t n
)
2236 register Sfio_t
*sp
;
2237 if(sp
=sh
.sftable
[fd
])
2238 return(sfread(sp
,buff
,n
));
2240 return(read(fd
,buff
,n
));
2245 * shell version of write() for user added builtins
2247 ssize_t
sh_write(register int fd
, const void* buff
, size_t n
)
2249 register Sfio_t
*sp
;
2250 if(sp
=sh
.sftable
[fd
])
2251 return(sfwrite(sp
,buff
,n
));
2253 return(write(fd
,buff
,n
));
2258 * shell version of lseek() for user added builtins
2260 off_t
sh_seek(register int fd
, off_t offset
, int whence
)
2262 register Sfio_t
*sp
;
2263 if((sp
=sh
.sftable
[fd
]) && (sfset(sp
,0,0)&(SF_READ
|SF_WRITE
)))
2264 return(sfseek(sp
,offset
,whence
));
2266 return(lseek(fd
,offset
,whence
));
2270 int sh_dup(register int old
)
2272 register int fd
= dup(old
);
2275 if(sh
.fdstatus
[old
] == IOCLOSE
)
2276 sh
.fdstatus
[old
] = 0;
2277 sh
.fdstatus
[fd
] = (sh
.fdstatus
[old
]&~IOCLEX
);
2279 (*fdnotify
)(old
,fd
);
2285 int sh_fcntl(register int fd
, int op
, ...)
2290 arg
= va_arg(ap
, int) ;
2292 newfd
= fcntl(fd
,op
,arg
);
2293 if(newfd
>=0) switch(op
)
2296 if(sh
.fdstatus
[fd
] == IOCLOSE
)
2297 sh
.fdstatus
[fd
] = 0;
2298 sh
.fdstatus
[newfd
] = (sh
.fdstatus
[fd
]&~IOCLEX
);
2300 (*fdnotify
)(fd
,newfd
);
2303 if(sh
.fdstatus
[fd
] == IOCLOSE
)
2304 sh
.fdstatus
[fd
] = 0;
2306 sh
.fdstatus
[fd
] |= IOCLEX
;
2308 sh
.fdstatus
[fd
] &= ~IOCLEX
;
2314 mode_t
sh_umask(mode_t m
)
2321 * give file descriptor <fd> and <mode>, return an iostream pointer
2322 * <mode> must be SF_READ or SF_WRITE
2323 * <fd> must be a non-negative number ofr SH_IOCOPROCESS or SH_IOHISTFILE.
2324 * returns NULL on failure and may set errno.
2327 Sfio_t
*sh_iogetiop(int fd
, int mode
)
2332 if(mode
!=SF_READ
&& mode
!=SF_WRITE
)
2340 if(!sh_histinit((void*)shp
))
2342 fd
= sffileno(shp
->hist_ptr
->histfp
);
2344 case SH_IOCOPROCESS
:
2351 if(fd
<0 || fd
>= shp
->lim
.open_max
)
2359 if(!(n
=shp
->fdstatus
[fd
]))
2360 n
= sh_iocheckfd(shp
,fd
);
2361 if(mode
==SF_WRITE
&& !(n
&IOWRITE
))
2363 if(mode
==SF_READ
&& !(n
&IOREAD
))
2365 if(!(iop
= shp
->sftable
[fd
]))
2366 iop
=sh_iostream(shp
,fd
);
2370 typedef int (*Notify_f
)(int,int);
2372 Notify_f
sh_fdnotify(Notify_f notify
)
2380 Sfio_t
*sh_fd2sfio(int fd
)
2383 register int status
;
2384 Sfio_t
*sp
= sh
.sftable
[fd
];
2385 if(!sp
&& (status
= sh_iocheckfd(shp
,fd
))!=IOCLOSE
)
2387 register int flags
=0;
2392 sp
= sfnew(NULL
, NULL
, -1, fd
,flags
);
2393 sh
.sftable
[fd
] = sp
;
2398 Sfio_t
*sh_pathopen(const char *cp
)
2403 if((n
=path_open(cp
,path_get(cp
))) < 0)
2404 n
= path_open(cp
,(Pathcomp_t
*)0);
2406 if((n
=path_open(cp
,path_get(cp
))) < 0)
2407 n
= path_open(cp
,"");
2410 errormsg(SH_DICT
,ERROR_system(1),e_open
,cp
);
2411 return(sh_iostream(shp
,n
));