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
)
200 * return <protocol>/<host>/<service> fd
203 typedef int (*Inetintr_f
)(struct addrinfo
*, void*);
206 inetopen(const char* path
, int server
, Inetintr_f onintr
, void* handle
)
212 struct addrinfo hint
;
213 struct addrinfo
* addr
;
216 memset(&hint
, 0, sizeof(hint
));
217 hint
.ai_family
= PF_UNSPEC
;
222 if (path
[1]!='c' || path
[2]!='t' || path
[3]!='p' || path
[4]!='/')
227 hint
.ai_socktype
= SOCK_STREAM
;
228 hint
.ai_protocol
= IPPROTO_SCTP
;
233 if (path
[1]!='c' || path
[2]!='p' || path
[3]!='/')
238 hint
.ai_socktype
= SOCK_STREAM
;
242 if (path
[1]!='d' || path
[2]!='p' || path
[3]!='/')
247 hint
.ai_socktype
= SOCK_DGRAM
;
254 if (!(s
= strdup(path
)))
256 if (t
= strchr(s
, '/'))
259 if (streq(s
, "local"))
261 fd
= getaddrinfo(s
, t
, &hint
, &addr
);
268 if (fd
!= EAI_SYSTEM
)
275 for (p
= addr
; p
; p
= p
->ai_next
)
278 * some api's don't take the hint
282 p
->ai_protocol
= hint
.ai_protocol
;
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
))
291 if (errno
!= EINTR
|| !onintr
)
293 if ((*onintr
)(addr
, handle
))
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 };
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
);
354 return((Sfdouble_t
)cur
);
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)
371 static int matchf(void *handle
, char *ptr
, size_t size
)
373 struct Match
*mp
= (struct Match
*)handle
;
374 mp
->offset
+= (ptr
-mp
->base
);
379 static struct fdsave
*filemap
;
380 static short filemapsize
;
382 /* ======== input output and file copying ======== */
384 void sh_ioinit(Shell_t
*shp
)
388 filemap
= (struct fdsave
*)malloc(filemapsize
*sizeof(struct fdsave
));
390 n
= shp
->lim
.open_max
+2;
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
;
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;
426 if(type
==SF_DPOP
|| type
==SF_FINAL
)
428 else if(type
==SF_WRITE
&& (*(ssize_t
*)data
)<0 && sffileno(iop
)!=2)
443 int mode
= ((struct checkpt
*)sh
.jmplist
)->mode
;
446 ((struct checkpt
*)sh
.jmplist
)->mode
= 0;
448 sfpool(iop
,NIL(Sfio_t
*),SF_WRITE
);
450 errormsg(SH_DICT
,ERROR_system(1),e_badwrite
,sffileno(iop
));
452 ((struct checkpt
*)sh
.jmplist
)->mode
= mode
;
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
;
475 if(fd
>=shp
->lim
.open_max
)
476 return(shp
->sftable
[fd
]);
477 #endif /* SHOPT_FASTPIPE */
489 return(NIL(Sfio_t
*));
493 if(!(bp
= (char *)malloc(IOBSIZE
+1)))
494 return(NIL(Sfio_t
*));
496 if(!(status
&IOWRITE
))
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);
510 sfset(iop
,SF_MALLOC
,1);
511 if(!(status
&IOWRITE
))
512 sfset(iop
,SF_IOCHECK
,1);
513 dp
->exceptf
= slowexcept
;
515 dp
->readf
= slowread
;
516 else if(status
&IONOSEEK
)
518 dp
->readf
= piperead
;
519 sfset(iop
, SF_IOINTR
,1);
528 dp
->exceptf
= outexcept
;
529 sfpool(iop
,shp
->outpool
,SF_WRITE
);
532 shp
->sftable
[fd
] = 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
)
545 fd
= sh_fcntl(f2
,F_DUPFD
,10);
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
])
558 *shp
->fdptrs
[fd
] = fd
;
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
];
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
);
594 register Sfio_t
*spnew
= sh_iostream(shp
,f1
);
595 shp
->fdstatus
[f2
] = (shp
->fdstatus
[f1
]&~IOCLEX
);
598 sfset(sp
,SF_SHARE
|SF_PUBLIC
,1);
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);
609 shp
->sftable
[f1
] = 0;
616 * close a file descriptor and update stream table and attributes
618 int sh_close(register int fd
)
624 if(!(sp
=sh
.sftable
[fd
]) || sfclose(sp
) < 0)
627 (*fdnotify
)(fd
,SH_FDCLOSE
);
632 sh
.fdstatus
[fd
] = IOCLOSE
;
637 sh
.inuse_bits
&= ~(1<<fd
);
644 onintr(struct addrinfo
* addr
, void* handle
)
646 Shell_t
* sh
= (Shell_t
*)handle
;
648 if (sh
->trapnote
&SH_SIGSET
)
662 * Mimic open(2) with checks for pseudo /dev/ files.
664 int sh_open(register const char *path
, int flags
, ...)
667 register int fd
= -1;
672 mode
= (flags
& O_CREAT
) ? va_arg(ap
, int) : 0;
680 if (path
[0]=='/' && path
[1]=='d' && path
[2]=='e' && path
[3]=='v' && path
[4]=='/')
685 if (path
[6]=='d' && path
[7]=='/')
687 fd
= (int)strtol(path
+8, &e
, 10);
693 if (path
[6]=='t' && path
[7]=='d')
697 if (path
[9]=='r' && path
[10]=='r' && !path
[11])
701 if (path
[9]=='n' && !path
[10])
705 if (path
[9]=='u' && path
[10]=='t' && !path
[11])
713 if ((fd
= inetopen(path
+5, !!(flags
& O_SERVICE
), onintr
, &sh
)) < 0 && errno
!= ENOTDIR
)
726 if (stat(path
,&st
) >=0)
727 nfd
= open(path
,flags
,st
.st_mode
);
730 nfd
= open(path
,flags
);
736 if((mode
=sh_iocheckfd(shp
,fd
))==IOCLOSE
)
739 if(!(mode
&IOWRITE
) && ((flags
==O_WRONLY
) || (flags
==O_RDWR
)))
741 if(!(mode
&IOREAD
) && ((flags
==O_RDONLY
) || (flags
==O_RDWR
)))
750 if(strncmp(path
,"/etc/",5)==0)
752 sfsprintf(buf
, sizeof(buf
), "%s%s", sh_regress_etc(path
, __LINE__
, __FILE__
), path
+4);
756 while((fd
= open(path
, flags
, mode
)) < 0)
757 if(errno
!=EINTR
|| sh
.trapnote
)
764 else if(flags
==O_RDWR
)
765 mode
= (IOREAD
|IOWRITE
);
768 sh
.fdstatus
[fd
] = mode
;
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);
780 errormsg(SH_DICT
,ERROR_system(1),e_open
,name
);
785 * move open file descriptor to a number > 2
787 int sh_iomovefd(register int fdold
)
790 if(fdold
<0 || fdold
>2)
792 fdnew
= sh_iomovefd(dup(fdold
));
793 sh
.fdstatus
[fdnew
] = (sh
.fdstatus
[fdold
]&~IOCLEX
);
795 sh
.fdstatus
[fdold
] = IOCLOSE
;
800 * create a pipe and print message on failure
802 int sh_pipe(register int pv
[])
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
;
816 static int pat_seek(void *handle
, const char *str
, size_t sz
)
818 char **bp
= (char**)handle
;
823 static int pat_line(const regex_t
* rp
, const char *buff
, register size_t n
)
825 register const char *cp
=buff
, *sp
;
828 for(sp
=cp
; n
-->0 && *cp
++ != '\n';);
829 if(regnexec(rp
,sp
,cp
-sp
, 0, (regmatch_t
*)0, 0)==0)
835 static int io_patseek(Shell_t
*shp
, regex_t
*rp
, Sfio_t
* sp
, int flags
)
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
);
841 shp
->fdstatus
[sffileno(sp
)] |= IOCLEX
;
843 was_share
= sfset(sp
,SF_SHARE
,1);
844 while((cp
=sfreserve(sp
, -s
, SF_LOCKR
)) || (cp
=sfreserve(sp
,SF_UNBOUND
, SF_LOCKR
)))
847 while(n
>0 && cp
[n
-1]!='\n')
851 r
= regrexec(rp
,cp
,m
,0,(regmatch_t
*)0, 0, '\n', (void*)&match
, pat_seek
);
856 if((m
= pat_line(rp
,cp
,m
)) < n
)
859 if(m
&& (flags
&IOCOPY
))
860 sfwrite(sfstdout
,cp
,m
);
866 shp
->fdstatus
[sffileno(sp
)] &= ~IOCLEX
;
867 if(fd
==0 && !(was_share
&SF_SHARE
))
868 sfset(sp
, SF_SHARE
,0);
872 static Sfoff_t
file_offset(Shell_t
*shp
, int fn
, char *fname
)
874 Sfio_t
*sp
= shp
->sftable
[fn
];
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
));
882 endf
.hdr
.disc
= &EOF_disc
;
885 nv_stack(mp
, &endf
.hdr
);
887 nv_stack(pp
, &endf
.hdr
);
890 off
= sh_strnum(fname
, &cp
, 0);
895 return(*cp
?(Sfoff_t
)-1:off
);
901 void sh_pclose(register int pv
[])
910 static char *io_usename(char *name
, int *perm
, int mode
)
913 char *tname
, *sp
, *ep
;
917 if((fd
= sh_open(name
,O_RDONLY
,0)) > 0)
919 if(fstat(fd
,&statb
) < 0)
921 if(!S_ISREG(statb
.st_mode
))
923 *perm
= statb
.st_mode
&(RW_ALL
|(S_IXUSR
|S_IXGRP
|S_IXOTH
));
925 else if(fd
< 0 && errno
!=ENOENT
)
928 tname
= sp
= (char*)stakalloc((len
=strlen(name
)) + 5);
929 if(ep
= strrchr(name
,'/'))
931 memcpy(sp
,name
,n
=++ep
-name
);
939 strcpy(sp
+len
,".tmp");
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
)
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
];
971 int isstring
= shp
->subshell
?(sfset(sfstdout
,0,0)&SF_STRING
):0;
975 traceon
= sh_trace(NIL(char**),0);
976 for(;iop
;iop
=iop
->ionxt
)
980 if(fn
==1 && shp
->subshell
&& !shp
->subshare
&& (flag
==2 || isstring
))
982 io_op
[0] = '0'+(iof
&IOUFD
);
986 o_mode
= O_WRONLY
|O_CREAT
;
991 o_mode
= O_RDONLY
|O_NONBLOCK
;
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
);
1012 ap
->argflag
= ARG_RAW
;
1013 ap
->argchn
.ap
= (struct argnod
*)fname
;
1014 ap
= sh_argprocsub(shp
,ap
);
1018 fname
=sh_mactrim(shp
,fname
,(!sh_isoption(SH_NOGLOB
)&&sh_isoption(SH_INTERACTIVE
))?2:0);
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
));
1028 if((iof
&IOLSEEK
) || ((iof
&IOMOV
) && *fname
=='-'))
1036 strcpy(&io_op
[3]," ((");
1048 sfputr(sfstderr
,io_op
,'<');
1049 fd
= io_heredoc(shp
,iop
,fname
,traceon
);
1050 if(traceon
&& (flag
==SH_SHOWME
))
1056 int dupfd
,toclose
= -1;
1058 if((fd
=fname
[0])>='0' && fd
<='9')
1060 char *number
= fname
;
1061 dupfd
= strtol(fname
,&number
,10);
1067 if(*number
|| dupfd
> IOUFD
)
1072 if(shp
->subshell
&& dupfd
==1 && (sfset(sfstdout
,0,0)&SF_STRING
))
1075 dupfd
= sffileno(sfstdout
);
1077 else if(shp
->sftable
[dupfd
])
1078 sfsync(shp
->sftable
[dupfd
]);
1080 else if(fd
=='-' && fname
[1]==0)
1085 else if(fd
=='p' && fname
[1]==0)
1088 dupfd
= shp
->coutpipe
;
1090 dupfd
= shp
->cpipe
[0];
1101 if((fd
=sh_fcntl(dupfd
,F_DUPFD
,3))<0)
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
);
1112 sh_iosave(shp
,toclose
,indx
,(char*)0); /* save file descriptor */
1118 if(sh_isoption(SH_RESTRICTED
))
1119 errormsg(SH_DICT
,ERROR_exit(1),e_restricted
,fname
);
1121 o_mode
= O_RDWR
|O_CREAT
;
1123 trunc
= io_op
[2] = ';';
1126 else if(!(iof
&IOPUT
))
1130 fd
=sh_chkopen(fname
);
1132 else if(sh_isoption(SH_RESTRICTED
))
1133 errormsg(SH_DICT
,ERROR_exit(1),e_restricted
,fname
);
1141 else if((iof
&IOREWRITE
) && (flag
==0 || flag
==1 || sh_subsavefd(fn
)))
1145 tname
= io_usename(fname
,&perm
,0);
1152 else if(sh_isoption(SH_NOCLOBBER
))
1155 if(stat(fname
,&sb
)>=0)
1158 if(S_ISREG(sb
.st_mode
)&&
1159 (!shp
->lim
.fs3d
|| iview(&sb
)==0))
1161 if(S_ISREG(sb
.st_mode
))
1162 #endif /* SHOPT_FS_3D */
1165 errormsg(SH_DICT
,ERROR_system(1),e_exists
,fname
);
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
);
1186 if(traceon
&& fname
)
1189 sfprintf(sfstderr
,"{%s",nv_name(np
));
1190 sfprintf(sfstderr
,"%s %s%s%c",io_op
,fname
,after
,iop
->ionxt
?' ':'\n');
1196 char *argv
[7], **av
=argv
;
1206 av
[1] = nv_name(np
);
1211 sh_debug(shp
,trace
,(char*)0,(char*)0,av
,ARG_NOGLOB
);
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
);
1231 message
= e_notseek
;
1234 message
= e_badseek
;
1235 if((off
= file_offset(shp
,fn
,fname
))<0)
1239 off
=sfseek(sp
, off
, SEEK_SET
);
1243 off
=lseek(fn
, off
, SEEK_SET
);
1250 extern const char e_notimp
[];
1256 if(!(rp
= regcache(fname
, REG_SHELL
|REG_NOSUB
|REG_NEWLINE
|REG_AUGMENTED
|REG_FIRST
|REG_LEFT
|REG_RIGHT
, &r
)))
1258 message
= e_badpattern
;
1262 sp
= sh_iostream(shp
,fn
);
1263 r
=io_patseek(shp
,rp
,sp
,iof
);
1266 /* close stream but not fn */
1279 if(flag
==0 || tname
)
1283 if((r
=sh_fcntl(fd
,F_DUPFD
,10)) > 0)
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);
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
);
1313 if((fn
=fcntl(fd
,F_DUPFD
,10)) < 0)
1315 shp
->fdstatus
[fn
] = shp
->fdstatus
[fd
];
1320 nv_onattr(np
,NV_INT32
);
1322 nv_putval(np
,(char*)&v
, NV_INT32
);
1323 sh_iocheckfd(shp
,fd
);
1327 fd
= sh_iorenumber(shp
,sh_iomovefd(fd
),fn
);
1329 shp
->inuse_bits
|= (1<<fn
);
1334 fcntl(fd
,F_SETFD
,FD_CLOEXEC
);
1335 shp
->fdstatus
[fd
] |= IOCLEX
;
1343 errormsg(SH_DICT
,ERROR_system(1),message
,fname
);
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
;
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
)
1362 sfprintf(sfstderr
,"< %s\n",name
);
1363 sfputr(outfile
,name
,'\n');
1367 infile
= subopen(shp
,shp
->heredocs
,iop
->iooffset
,iop
->iosize
);
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);
1383 char *lastpath
= shp
->lastpath
;
1384 sh_machere(shp
,infile
,outfile
,iop
->ioname
);
1385 shp
->lastpath
= lastpath
;
1390 /* close stream outfile, but save file descriptor */
1391 fd
= sffileno(outfile
);
1392 sfsetfd(outfile
,-1);
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
;
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
)
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
)
1433 /* make sure table is large enough */
1434 if(shp
->topfd
>= filemapsize
)
1436 char *cp
, *oldptr
= (char*)filemap
;
1437 char *oldend
= (char*)&filemap
[filemapsize
];
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
)
1445 for(savefd
=shp
->lim
.open_max
+2; --savefd
>=0; )
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
);
1463 #endif /* SHOPT_DEVFD */
1465 if((savefd
= sh_fcntl(origfd
, F_DUPFD
, 10)) < 0 && errno
!=EBADF
)
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
;
1478 register Sfio_t
* sp
= shp
->sftable
[origfd
];
1479 /* make saved file close-on-exec */
1480 sh_fcntl(savefd
,F_SETFD
,FD_CLOEXEC
);
1483 shp
->fdstatus
[savefd
] = shp
->fdstatus
[origfd
];
1484 shp
->fdptrs
[savefd
] = &filemap
[shp
->topfd
-1].save_fd
;
1485 if(!(shp
->sftable
[savefd
]=sp
))
1490 /* copy standard stream to new stream */
1491 sp
= sfswap(sp
,NIL(Sfio_t
*));
1492 shp
->sftable
[savefd
] = sp
;
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
];
1511 shp
->sftable
[savefd
] = 0;
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
)
1530 if(jmpval
==SH_JMPSCRIPT
)
1532 if ((savefd
= filemap
[fd
].save_fd
) >= 0)
1534 shp
->sftable
[savefd
] = 0;
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);
1545 if ((savefd
= filemap
[fd
].save_fd
) >= 0)
1547 sh_fcntl(savefd
, F_DUPFD
, 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
);
1556 sfswap(shp
->sftable
[savefd
],shp
->sftable
[origfd
]);
1561 shp
->sftable
[origfd
] = shp
->sftable
[savefd
];
1562 shp
->sftable
[savefd
] = 0;
1566 shp
->fdstatus
[origfd
] = IOCLOSE
;
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
)
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
)
1592 if((flags
=sh_iocheckfd(shp
,fd
))!=IOCLOSE
)
1596 if(mode
==R_OK
&& (flags
&IOREAD
))
1598 if(mode
==W_OK
&& (flags
&IOWRITE
))
1605 * Handle interrupts for slow streams
1607 static int slowexcept(register Sfio_t
*iop
,int type
,void *data
,Sfdisc_t
*handle
)
1611 if(type
==SF_DPOP
|| type
==SF_FINAL
)
1612 free((void*)handle
);
1615 if((sh
.trapnote
&(SH_SIGSET
|SH_SIGTRAP
)) && errno
!=EIO
&& errno
!=ENXIO
)
1617 fno
= sffileno(iop
);
1618 if((n
=sfvalue(iop
))<=0)
1622 if(errno
==0 && (n
=fcntl(fno
,F_GETFL
,0))&O_NDELAY
)
1625 fcntl(fno
, F_SETFL
, n
);
1628 # endif /* O_NDELAY */
1629 #endif /* !FNDELAY */
1633 n
= fcntl(fno
,F_GETFL
,0);
1635 fcntl(fno
, F_SETFL
, n
);
1638 #endif /* O_NONBLOCK */
1642 sh_onstate(SH_TTYWAIT
);
1646 if(sh
.bltinfun
&& sh
.bltindata
.sigset
)
1649 if(sh
.trapnote
&SH_SIGSET
)
1652 sfputc(sfstderr
,'\n');
1653 sh_exit(SH_EXITSIG
);
1655 if(sh
.trapnote
&SH_SIGTRAP
)
1661 * called when slowread times out
1663 static void time_grace(void *handle
)
1667 if(sh_isstate(SH_GRACE
))
1669 sh_offstate(SH_GRACE
);
1670 if(!sh_isstate(SH_INTERACTIVE
))
1672 ((struct checkpt
*)sh
.jmplist
)->mode
= SH_JMPEXIT
;
1673 errormsg(SH_DICT
,2,e_timeout
);
1674 sh
.trapnote
|= SH_SIGSET
;
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
);
1687 if(job
.waitsafe
&& job
.savesig
)
1697 if(sh_isstate(SH_INTERACTIVE
) && io_prompt(iop
,sh
.nextprompt
)<0 && errno
==EIO
)
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);
1703 size
= sfrd(iop
,buff
,size
,handle
);
1704 sh_offstate(SH_TTYWAIT
);
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
1720 if(sh_isoption(SH_EMACS
) || sh_isoption(SH_GMACS
))
1721 readf
= ed_emacsread
;
1723 # endif /* SHOPT_ESH */
1726 if(sh_isoption(SH_VI
) || ((SHOPT_RAWONLY
-0) && mbwide()))
1728 if(sh_isoption(SH_VI
))
1732 # endif /* SHOPT_VSH */
1741 if(io_prompt(iop
,sh
.nextprompt
)<0 && errno
==EIO
)
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
);
1749 #if SHOPT_HISTEXPAND
1750 if(rsize
&& *(char*)buff
!= '\n' && sh
.nextprompt
==1 && sh_isoption(SH_HISTEXPAND
))
1753 ((char*)buff
)[rsize
] = '\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);
1772 if((r
& HIST_ERROR
) && sh_isoption(SH_HISTREEDIT
))
1777 if(r
& (HIST_ERROR
|HIST_PRINT
))
1779 *(char*)buff
= '\n';
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
)
1798 if(!(n
&(IOREAD
|IOWRITE
)))
1801 if((flags
=fcntl(fd
,F_GETFL
,0)) < 0)
1802 return(sh
.fdstatus
[fd
]=IOCLOSE
);
1803 if((flags
&O_ACCMODE
)!=O_WRONLY
)
1805 if((flags
&O_ACCMODE
)!=O_RDONLY
)
1809 if((flags
= fstat(fd
,&statb
))< 0)
1810 return(sh
.fdstatus
[fd
]=IOCLOSE
);
1811 n
|= (IOREAD
|IOWRITE
);
1812 if(read(fd
,"",0) < 0)
1814 #endif /* F_GETFL */
1816 if(!(n
&(IOSEEK
|IONOSEEK
)))
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
;
1829 if(lseek(fd
,NIL(off_t
),SEEK_CUR
)<0)
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
) ||
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
))
1850 sh
.fdstatus
[fd
] = n
;
1855 * Display prompt PS<flag> on standard error
1858 static int io_prompt(Sfio_t
*iop
,register int flag
)
1866 if(flag
<3 && !sh_isstate(SH_INTERACTIVE
))
1868 if(flag
==2 && sfpkrd(sffileno(iop
),buff
,1,'\n',0,1) >= 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)))
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
1888 ioctl(sffileno(sfstderr
),TIOCLBIC
,&mode
);
1890 #endif /* TIOCLBIC */
1891 cp
= sh_mactry(shp
,nv_getval(sh_scoped(shp
,PS1NOD
)));
1896 /* look at next character */
1898 /* print out line number if not !! */
1901 sfprintf(sfstderr
,"%d", sh
.hist_ptr
?(int)sh
.hist_ptr
->histind
:++cmdno
);
1911 cp
= nv_getval(sh_scoped(shp
,PS2NOD
));
1914 cp
= nv_getval(sh_scoped(shp
,PS3NOD
));
1920 sfputr(sfstderr
,cp
,-1);
1922 if(*sh
.prompt
&& (endprompt
=(char*)sfreserve(sfstderr
,0,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
)
1935 if(mode
==SF_DPOP
|| mode
==SF_FINAL
)
1936 free((void*)handle
);
1937 else if(mode
==SF_WRITE
&& errno
==EINTR
&& sh
.lastsig
==SIGPIPE
)
1943 * keep track of each stream that is opened and closed
1945 static void sftrack(Sfio_t
* sp
, int flag
, void* data
)
1948 register int fd
= sffileno(sp
);
1949 register struct checkpt
*pp
;
1951 int newfd
= integralof(data
);
1952 if(flag
==SF_SETFD
|| flag
==SF_CLOSING
)
1957 (*fdnotify
)(sffileno(sp
),flag
==SF_CLOSING
?-1:newfd
);
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);
1967 write(ERRIO
,"read from",9);
1969 write(ERRIO
,"write to",8);
1970 write(ERRIO
," locked stream\n",15);
1974 if((unsigned)fd
>= shp
->lim
.open_max
)
1976 if(sh_isstate(SH_NOTRACK
))
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
);
1988 if(!shp
->sftable
[fd
] && shp
->fdstatus
[fd
]==IOCLOSE
)
1990 shp
->sftable
[fd
] = sp
;
1991 flag
= (mode
&SF_WRITE
)?IOWRITE
:0;
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);
2007 item
->next
= pp
->olist
;
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
)
2041 * Create a stream consisting of a space separated argv[] list
2044 Sfio_t
*sh_sfeval(register char *argv
[])
2046 register Sfio_t
*iop
;
2052 iop
= sfopen(NIL(Sfio_t
*),(char*)cp
,"s");
2055 register struct eval
*ep
;
2056 if(!(ep
= new_of(struct eval
,0)))
2057 return(NIL(Sfio_t
*));
2058 ep
->disc
= eval_disc
;
2062 sfdisc(iop
,&ep
->disc
);
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
;
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
))
2089 /* get the length of this string */
2090 ep
->slen
= len
= strlen(cp
);
2091 /* move to next string */
2094 else /* insert space between arguments */
2099 /* insert the new string */
2100 sfsetbuf(iop
,cp
,len
);
2101 ep
->addspace
= !ep
->addspace
;
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
;
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
);
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
;
2136 if(size
> disp
->left
)
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
);
2153 else if(disp
&& (mode
==SF_DPOP
|| mode
==SF_FINAL
))
2159 else if (mode
==SF_ATEXIT
)
2161 sfdisc(sp
, SF_POPDISC
);
2165 else if(mode
==SF_READ
)
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
[])
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)
2192 for(arg
=argv
; *arg
;arg
++)
2194 if((j
=strlen(*arg
)) > i
)
2197 i
+= (ndigits
+LBLSIZ
);
2200 if(argn
> nrow
*ncol
)
2202 nrow
= 1 + (argn
-1)/ncol
;
2206 ncol
= 1 + (argn
-1)/nrow
;
2207 nrow
= 1 + (argn
-1)/ncol
;
2210 fldsize
= (wsize
/ncol
)-(ndigits
+LBLSIZ
);
2213 if(sh
.trapnote
&SH_SIGSET
)
2219 sfprintf(outfile
,"%*d) %s",ndigits
,j
+1,*arg
);
2223 sfnputc(outfile
,' ',fldsize
-strlen(*arg
));
2225 sfputc(outfile
,'\n');
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
));
2239 return(read(fd
,buff
,n
));
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
));
2252 return(write(fd
,buff
,n
));
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
));
2265 return(lseek(fd
,offset
,whence
));
2269 int sh_dup(register int old
)
2271 register int fd
= dup(old
);
2274 if(sh
.fdstatus
[old
] == IOCLOSE
)
2275 sh
.fdstatus
[old
] = 0;
2276 sh
.fdstatus
[fd
] = (sh
.fdstatus
[old
]&~IOCLEX
);
2278 (*fdnotify
)(old
,fd
);
2284 int sh_fcntl(register int fd
, int op
, ...)
2289 arg
= va_arg(ap
, int) ;
2291 newfd
= fcntl(fd
,op
,arg
);
2292 if(newfd
>=0) switch(op
)
2295 if(sh
.fdstatus
[fd
] == IOCLOSE
)
2296 sh
.fdstatus
[fd
] = 0;
2297 sh
.fdstatus
[newfd
] = (sh
.fdstatus
[fd
]&~IOCLEX
);
2299 (*fdnotify
)(fd
,newfd
);
2302 if(sh
.fdstatus
[fd
] == IOCLOSE
)
2303 sh
.fdstatus
[fd
] = 0;
2305 sh
.fdstatus
[fd
] |= IOCLEX
;
2307 sh
.fdstatus
[fd
] &= ~IOCLEX
;
2313 mode_t
sh_umask(mode_t 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
)
2331 if(mode
!=SF_READ
&& mode
!=SF_WRITE
)
2339 if(!sh_histinit((void*)shp
))
2341 fd
= sffileno(shp
->hist_ptr
->histfp
);
2343 case SH_IOCOPROCESS
:
2350 if(fd
<0 || fd
>= shp
->lim
.open_max
)
2358 if(!(n
=shp
->fdstatus
[fd
]))
2359 n
= sh_iocheckfd(shp
,fd
);
2360 if(mode
==SF_WRITE
&& !(n
&IOWRITE
))
2362 if(mode
==SF_READ
&& !(n
&IOREAD
))
2364 if(!(iop
= shp
->sftable
[fd
]))
2365 iop
=sh_iostream(shp
,fd
);
2369 typedef int (*Notify_f
)(int,int);
2371 Notify_f
sh_fdnotify(Notify_f notify
)
2379 Sfio_t
*sh_fd2sfio(int fd
)
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;
2391 sp
= sfnew(NULL
, NULL
, -1, fd
,flags
);
2392 sh
.sftable
[fd
] = sp
;
2397 Sfio_t
*sh_pathopen(const char *cp
)
2402 if((n
=path_open(cp
,path_get(cp
))) < 0)
2403 n
= path_open(cp
,(Pathcomp_t
*)0);
2405 if((n
=path_open(cp
,path_get(cp
))) < 0)
2406 n
= path_open(cp
,"");
2409 errormsg(SH_DICT
,ERROR_system(1),e_open
,cp
);
2410 return(sh_iostream(shp
,n
));