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
21
22 /*
23 * Input/output file processing
24 *
25 * David Korn
26 * AT&T Labs
27 *
28 */
29
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"
46
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 */
60
61 #ifndef O_SERVICE
62 # define O_SERVICE O_NOCTTY
63 #endif
64
65 #define RW_ALL (S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR|S_IWGRP|S_IWOTH)
66
67 static void *timeout;
68 static int (*fdnotify)(int,int);
69
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
93
94 #if !_lib_getaddrinfo
95
96 #undef EAI_SYSTEM
97
98 #define EAI_SYSTEM 1
99
100 #undef addrinfo
101 #undef getaddrinfo
102 #undef freeaddrinfo
103
104 #define addrinfo local_addrinfo
105 #define getaddrinfo local_getaddrinfo
106 #define freeaddrinfo local_freeaddrinfo
107
108 struct addrinfo
109 {
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;
117 };
118
119 static int
getaddrinfo(const char * node,const char * service,const struct addrinfo * hint,struct addrinfo ** addr)120 getaddrinfo(const char* node, const char* service, const struct addrinfo* hint, struct addrinfo **addr)
121 {
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;
129
130 if (!(hp = gethostbyname(node)) || hp->h_addrtype!=AF_INET || hp->h_length>sizeof(struct in_addr))
131 {
132 errno = EADDRNOTAVAIL;
133 return EAI_SYSTEM;
134 }
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
139 {
140 struct servent* sp;
141 const char* protocol = 0;
142
143 if (hint)
144 switch (hint->ai_socktype)
145 {
146 case SOCK_STREAM:
147 switch (hint->ai_protocol)
148 {
149 case 0:
150 protocol = "tcp";
151 break;
152 #ifdef IPPROTO_SCTP
153 case IPPROTO_SCTP:
154 protocol = "sctp";
155 break;
156 #endif
157 }
158 break;
159 case SOCK_DGRAM:
160 protocol = "udp";
161 break;
162 }
163 if (!protocol)
164 {
165 errno = EPROTONOSUPPORT;
166 return 1;
167 }
168 if (sp = getservbyname(service, protocol))
169 ip_port = sp->s_port;
170 }
171 if (!ip_port)
172 {
173 errno = EADDRNOTAVAIL;
174 return EAI_SYSTEM;
175 }
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;
189 }
190
191 static void
freeaddrinfo(struct addrinfo * ap)192 freeaddrinfo(struct addrinfo* ap)
193 {
194 if (ap)
195 free(ap);
196 }
197
198 #endif
199
200 /*
201 * return <protocol>/<host>/<service> fd
202 */
203
204 typedef int (*Inetintr_f)(struct addrinfo*, void*);
205
206 static int
inetopen(const char * path,int server,Inetintr_f onintr,void * handle)207 inetopen(const char* path, int server, Inetintr_f onintr, void* handle)
208 {
209 register char* s;
210 register char* t;
211 int fd;
212 int oerrno;
213 struct addrinfo hint;
214 struct addrinfo* addr;
215 struct addrinfo* p;
216
217 memset(&hint, 0, sizeof(hint));
218 hint.ai_family = PF_UNSPEC;
219 switch (path[0])
220 {
221 #ifdef IPPROTO_SCTP
222 case 's':
223 if (path[1]!='c' || path[2]!='t' || path[3]!='p' || path[4]!='/')
224 {
225 errno = ENOTDIR;
226 return -1;
227 }
228 hint.ai_socktype = SOCK_STREAM;
229 hint.ai_protocol = IPPROTO_SCTP;
230 path += 5;
231 break;
232 #endif
233 case 't':
234 if (path[1]!='c' || path[2]!='p' || path[3]!='/')
235 {
236 errno = ENOTDIR;
237 return -1;
238 }
239 hint.ai_socktype = SOCK_STREAM;
240 path += 4;
241 break;
242 case 'u':
243 if (path[1]!='d' || path[2]!='p' || path[3]!='/')
244 {
245 errno = ENOTDIR;
246 return -1;
247 }
248 hint.ai_socktype = SOCK_DGRAM;
249 path += 4;
250 break;
251 default:
252 errno = ENOTDIR;
253 return -1;
254 }
255 if (!(s = strdup(path)))
256 return -1;
257 if (t = strchr(s, '/'))
258 {
259 *t++ = 0;
260 if (streq(s, "local"))
261 s = "localhost";
262 fd = getaddrinfo(s, t, &hint, &addr);
263 }
264 else
265 fd = -1;
266 free(s);
267 if (fd)
268 {
269 if (fd != EAI_SYSTEM)
270 errno = ENOTDIR;
271 return -1;
272 }
273 oerrno = errno;
274 errno = 0;
275 fd = -1;
276 for (p = addr; p; p = p->ai_next)
277 {
278 /*
279 * some api's don't take the hint
280 */
281
282 if (!p->ai_protocol)
283 p->ai_protocol = hint.ai_protocol;
284 if (!p->ai_socktype)
285 p->ai_socktype = hint.ai_socktype;
286 while ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) >= 0)
287 {
288 if (server && !bind(fd, p->ai_addr, p->ai_addrlen) && !listen(fd, 5) || !server && !connect(fd, p->ai_addr, p->ai_addrlen))
289 goto done;
290 close(fd);
291 fd = -1;
292 if (errno != EINTR || !onintr)
293 break;
294 if ((*onintr)(addr, handle))
295 return -1;
296 }
297 }
298 done:
299 freeaddrinfo(addr);
300 if (fd >= 0)
301 errno = oerrno;
302 return fd;
303 }
304
305 #else
306
307 #undef O_SERVICE
308
309 #endif
310
311 struct fdsave
312 {
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 >; */
317 };
318
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 };
334
335 struct subfile
336 {
337 Sfdisc_t disc;
338 Sfio_t *oldsp;
339 off_t offset;
340 long size;
341 long left;
342 };
343
344 struct Eof
345 {
346 Namfun_t hdr;
347 int fd;
348 };
349
nget_cur_eof(register Namval_t * np,Namfun_t * fp)350 static Sfdouble_t nget_cur_eof(register Namval_t* np, Namfun_t *fp)
351 {
352 struct Eof *ep = (struct Eof*)fp;
353 Sfoff_t end, cur =lseek(ep->fd, (Sfoff_t)0, SEEK_CUR);
354 if(*np->nvname=='C')
355 return((Sfdouble_t)cur);
356 if(cur<0)
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);
361 }
362
363 static const Namdisc_t EOF_disc = { sizeof(struct Eof), 0, 0, nget_cur_eof};
364
365 #define MATCH_BUFF (64*1024)
366 struct Match
367 {
368 Sfoff_t offset;
369 char *base;
370 };
371
matchf(void * handle,char * ptr,size_t size)372 static int matchf(void *handle, char *ptr, size_t size)
373 {
374 struct Match *mp = (struct Match*)handle;
375 mp->offset += (ptr-mp->base);
376 return(1);
377 }
378
379
380 static struct fdsave *filemap;
381 static short filemapsize;
382
383 /* ======== input output and file copying ======== */
384
sh_ioinit(Shell_t * shp)385 void sh_ioinit(Shell_t *shp)
386 {
387 register int n;
388 filemapsize = 8;
389 filemap = (struct fdsave*)malloc(filemapsize*sizeof(struct fdsave));
390 #if SHOPT_FASTPIPE
391 n = shp->lim.open_max+2;
392 #else
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;
404 sfnotify(sftrack);
405 sh_iostream(shp,0);
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);
417 }
418
419 /*
420 * Handle output stream exceptions
421 */
outexcept(register Sfio_t * iop,int type,void * data,Sfdisc_t * handle)422 static int outexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
423 {
424 static int active = 0;
425
426 NOT_USED(handle);
427 if(type==SF_DPOP || type==SF_FINAL)
428 free((void*)handle);
429 else if(type==SF_WRITE && (*(ssize_t*)data)<0 && sffileno(iop)!=2)
430 switch (errno)
431 {
432 case EINTR:
433 case EPIPE:
434 #ifdef ECONNRESET
435 case ECONNRESET:
436 #endif
437 #ifdef ESHUTDOWN
438 case ESHUTDOWN:
439 #endif
440 break;
441 default:
442 if(!active)
443 {
444 int mode = ((struct checkpt*)sh.jmplist)->mode;
445 int save = errno;
446 active = 1;
447 ((struct checkpt*)sh.jmplist)->mode = 0;
448 sfpurge(iop);
449 sfpool(iop,NIL(Sfio_t*),SF_WRITE);
450 errno = save;
451 errormsg(SH_DICT,ERROR_system(1),e_badwrite,sffileno(iop));
452 active = 0;
453 ((struct checkpt*)sh.jmplist)->mode = mode;
454 sh_exit(1);
455 }
456 return(-1);
457 }
458 return(0);
459 }
460
461 /*
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
467 */
sh_iostream(Shell_t * shp,register int fd)468 Sfio_t *sh_iostream(Shell_t *shp, register int fd)
469 {
470 register Sfio_t *iop;
471 register int status = sh_iocheckfd(shp,fd);
472 register int flags = SF_WRITE;
473 char *bp;
474 Sfdisc_t *dp;
475 #if SHOPT_FASTPIPE
476 if(fd>=shp->lim.open_max)
477 return(shp->sftable[fd]);
478 #endif /* SHOPT_FASTPIPE */
479 if(status==IOCLOSE)
480 {
481 switch(fd)
482 {
483 case 0:
484 return(sfstdin);
485 case 1:
486 return(sfstdout);
487 case 2:
488 return(sfstderr);
489 }
490 return(NIL(Sfio_t*));
491 }
492 if(status&IOREAD)
493 {
494 if(!(bp = (char *)malloc(IOBSIZE+1)))
495 return(NIL(Sfio_t*));
496 flags |= SF_READ;
497 if(!(status&IOWRITE))
498 flags &= ~SF_WRITE;
499 }
500 else
501 bp = shp->outbuff;
502 if(status&IODUP)
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);
509 if(status&IOREAD)
510 {
511 sfset(iop,SF_MALLOC,1);
512 if(!(status&IOWRITE))
513 sfset(iop,SF_IOCHECK,1);
514 dp->exceptf = slowexcept;
515 if(status&IOTTY)
516 dp->readf = slowread;
517 else if(status&IONOSEEK)
518 {
519 dp->readf = piperead;
520 sfset(iop, SF_IOINTR,1);
521 }
522 else
523 dp->readf = 0;
524 dp->seekf = 0;
525 dp->writef = 0;
526 }
527 else
528 {
529 dp->exceptf = outexcept;
530 sfpool(iop,shp->outpool,SF_WRITE);
531 }
532 sfdisc(iop,dp);
533 shp->sftable[fd] = iop;
534 return(iop);
535 }
536
537 /*
538 * preserve the file descriptor or stream by moving it
539 */
io_preserve(Shell_t * shp,register Sfio_t * sp,register int f2)540 static void io_preserve(Shell_t* shp, register Sfio_t *sp, register int f2)
541 {
542 register int fd;
543 if(sp)
544 fd = sfsetfd(sp,10);
545 else
546 fd = sh_fcntl(f2,F_DUPFD,10);
547 if(f2==shp->infd)
548 shp->infd = fd;
549 if(fd<0)
550 {
551 shp->toomany = 1;
552 ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
553 errormsg(SH_DICT,ERROR_system(1),e_toomany);
554 }
555 if(shp->fdptrs[fd]=shp->fdptrs[f2])
556 {
557 if(f2==job.fd)
558 job.fd=fd;
559 *shp->fdptrs[fd] = fd;
560 shp->fdptrs[f2] = 0;
561 }
562 shp->sftable[fd] = sp;
563 shp->fdstatus[fd] = shp->fdstatus[f2];
564 if(fcntl(f2,F_GETFD,0)&1)
565 {
566 fcntl(fd,F_SETFD,FD_CLOEXEC);
567 shp->fdstatus[fd] |= IOCLEX;
568 }
569 shp->sftable[f2] = 0;
570 }
571
572 /*
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;
577 */
sh_iorenumber(Shell_t * shp,register int f1,register int f2)578 int sh_iorenumber(Shell_t *shp, register int f1,register int f2)
579 {
580 register Sfio_t *sp = shp->sftable[f2];
581 if(f1!=f2)
582 {
583 /* see whether file descriptor is in use */
584 if(sh_inuse(f2) || (f2>2 && sp))
585 {
586 if(!(shp->inuse_bits&(1<<f2)))
587 io_preserve(shp,sp,f2);
588 sp = 0;
589 }
590 else if(f2==0)
591 shp->st.ioset = 1;
592 sh_close(f2);
593 if(f2<=2 && sp)
594 {
595 register Sfio_t *spnew = sh_iostream(shp,f1);
596 shp->fdstatus[f2] = (shp->fdstatus[f1]&~IOCLEX);
597 sfsetfd(spnew,f2);
598 sfswap(spnew,sp);
599 sfset(sp,SF_SHARE|SF_PUBLIC,1);
600 }
601 else
602 {
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);
606 else if(f2 <= 2)
607 sh_iostream(shp,f2);
608 }
609 if(sp)
610 shp->sftable[f1] = 0;
611 sh_close(f1);
612 }
613 return(f2);
614 }
615
616 /*
617 * close a file descriptor and update stream table and attributes
618 */
sh_close(register int fd)619 int sh_close(register int fd)
620 {
621 register Sfio_t *sp;
622 register int r = 0;
623 if(fd<0)
624 return(-1);
625 if(!(sp=sh.sftable[fd]) || sfclose(sp) < 0)
626 {
627 if(fdnotify)
628 (*fdnotify)(fd,SH_FDCLOSE);
629 r=close(fd);
630 }
631 if(fd>2)
632 sh.sftable[fd] = 0;
633 sh.fdstatus[fd] = IOCLOSE;
634 if(sh.fdptrs[fd])
635 *sh.fdptrs[fd] = -1;
636 sh.fdptrs[fd] = 0;
637 if(fd < 10)
638 sh.inuse_bits &= ~(1<<fd);
639 return(r);
640 }
641
642 #ifdef O_SERVICE
643
644 static int
onintr(struct addrinfo * addr,void * handle)645 onintr(struct addrinfo* addr, void* handle)
646 {
647 Shell_t* sh = (Shell_t*)handle;
648
649 if (sh->trapnote&SH_SIGSET)
650 {
651 freeaddrinfo(addr);
652 sh_exit(SH_EXITSIG);
653 return -1;
654 }
655 if (sh->trapnote)
656 sh_chktrap();
657 return 0;
658 }
659
660 #endif
661
662 /*
663 * Mimic open(2) with checks for pseudo /dev/ files.
664 */
sh_open(register const char * path,int flags,...)665 int sh_open(register const char *path, int flags, ...)
666 {
667 Shell_t *shp = &sh;
668 register int fd = -1;
669 mode_t mode;
670 char *e;
671 va_list ap;
672 va_start(ap, flags);
673 mode = (flags & O_CREAT) ? va_arg(ap, int) : 0;
674 va_end(ap);
675 errno = 0;
676 if(*path==0)
677 {
678 errno = ENOENT;
679 return(-1);
680 }
681 if (path[0]=='/' && path[1]=='d' && path[2]=='e' && path[3]=='v' && path[4]=='/')
682 {
683 switch (path[5])
684 {
685 case 'f':
686 if (path[6]=='d' && path[7]=='/')
687 {
688 fd = (int)strtol(path+8, &e, 10);
689 if (*e)
690 fd = -1;
691 }
692 break;
693 case 's':
694 if (path[6]=='t' && path[7]=='d')
695 switch (path[8])
696 {
697 case 'e':
698 if (path[9]=='r' && path[10]=='r' && !path[11])
699 fd = 2;
700 break;
701 case 'i':
702 if (path[9]=='n' && !path[10])
703 fd = 0;
704 break;
705 case 'o':
706 if (path[9]=='u' && path[10]=='t' && !path[11])
707 fd = 1;
708 break;
709 }
710 }
711 #ifdef O_SERVICE
712 if (fd < 0)
713 {
714 if ((fd = inetopen(path+5, !!(flags & O_SERVICE), onintr, &sh)) < 0 && errno != ENOTDIR)
715 return -1;
716 if (fd >= 0)
717 goto ok;
718 }
719 #endif
720 }
721 if (fd >= 0)
722 {
723 int nfd= -1;
724 if (flags & O_CREAT)
725 {
726 struct stat st;
727 if (stat(path,&st) >=0)
728 nfd = open(path,flags,st.st_mode);
729 }
730 else
731 nfd = open(path,flags);
732 if(nfd>=0)
733 {
734 fd = nfd;
735 goto ok;
736 }
737 if((mode=sh_iocheckfd(shp,fd))==IOCLOSE)
738 return(-1);
739 flags &= O_ACCMODE;
740 if(!(mode&IOWRITE) && ((flags==O_WRONLY) || (flags==O_RDWR)))
741 return(-1);
742 if(!(mode&IOREAD) && ((flags==O_RDONLY) || (flags==O_RDWR)))
743 return(-1);
744 if((fd=dup(fd))<0)
745 return(-1);
746 }
747 else
748 {
749 #if SHOPT_REGRESS
750 char buf[PATH_MAX];
751 if(strncmp(path,"/etc/",5)==0)
752 {
753 sfsprintf(buf, sizeof(buf), "%s%s", sh_regress_etc(path, __LINE__, __FILE__), path+4);
754 path = buf;
755 }
756 #endif
757 while((fd = open(path, flags, mode)) < 0)
758 if(errno!=EINTR || sh.trapnote)
759 return(-1);
760 }
761 ok:
762 flags &= O_ACCMODE;
763 if(flags==O_WRONLY)
764 mode = IOWRITE;
765 else if(flags==O_RDWR)
766 mode = (IOREAD|IOWRITE);
767 else
768 mode = IOREAD;
769 sh.fdstatus[fd] = mode;
770 return(fd);
771 }
772
773 /*
774 * Open a file for reading
775 * On failure, print message.
776 */
sh_chkopen(register const char * name)777 int sh_chkopen(register const char *name)
778 {
779 register int fd = sh_open(name,O_RDONLY,0);
780 if(fd < 0)
781 errormsg(SH_DICT,ERROR_system(1),e_open,name);
782 return(fd);
783 }
784
785 /*
786 * move open file descriptor to a number > 2
787 */
sh_iomovefd(register int fdold)788 int sh_iomovefd(register int fdold)
789 {
790 register int fdnew;
791 if(fdold<0 || fdold>2)
792 return(fdold);
793 fdnew = sh_iomovefd(dup(fdold));
794 sh.fdstatus[fdnew] = (sh.fdstatus[fdold]&~IOCLEX);
795 close(fdold);
796 sh.fdstatus[fdold] = IOCLOSE;
797 return(fdnew);
798 }
799
800 /*
801 * create a pipe and print message on failure
802 */
sh_pipe(register int pv[])803 int sh_pipe(register int pv[])
804 {
805 int fd[2];
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;
812 sh_subsavefd(pv[0]);
813 sh_subsavefd(pv[1]);
814 return(0);
815 }
816
pat_seek(void * handle,const char * str,size_t sz)817 static int pat_seek(void *handle, const char *str, size_t sz)
818 {
819 char **bp = (char**)handle;
820 *bp = (char*)str;
821 return(-1);
822 }
823
pat_line(const regex_t * rp,const char * buff,register size_t n)824 static int pat_line(const regex_t* rp, const char *buff, register size_t n)
825 {
826 register const char *cp=buff, *sp;
827 while(n>0)
828 {
829 for(sp=cp; n-->0 && *cp++ != '\n';);
830 if(regnexec(rp,sp,cp-sp, 0, (regmatch_t*)0, 0)==0)
831 return(sp-buff);
832 }
833 return(cp-buff);
834 }
835
io_patseek(Shell_t * shp,regex_t * rp,Sfio_t * sp,int flags)836 static int io_patseek(Shell_t *shp, regex_t *rp, Sfio_t* sp, int flags)
837 {
838 char *cp, *match;
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);
841 size_t n,m;
842 shp->fdstatus[sffileno(sp)] |= IOCLEX;
843 if(fd==0)
844 was_share = sfset(sp,SF_SHARE,1);
845 while((cp=sfreserve(sp, -s, SF_LOCKR)) || (cp=sfreserve(sp,SF_UNBOUND, SF_LOCKR)))
846 {
847 m = n = sfvalue(sp);
848 while(n>0 && cp[n-1]!='\n')
849 n--;
850 if(n)
851 m = n;
852 r = regrexec(rp,cp,m,0,(regmatch_t*)0, 0, '\n', (void*)&match, pat_seek);
853 if(r<0)
854 m = match-cp;
855 else if(r==2)
856 {
857 if((m = pat_line(rp,cp,m)) < n)
858 r = -1;
859 }
860 if(m && (flags&IOCOPY))
861 sfwrite(sfstdout,cp,m);
862 sfread(sp,cp,m);
863 if(r<0)
864 break;
865 }
866 if(!close_exec)
867 shp->fdstatus[sffileno(sp)] &= ~IOCLEX;
868 if(fd==0 && !(was_share&SF_SHARE))
869 sfset(sp, SF_SHARE,0);
870 return(0);
871 }
872
file_offset(Shell_t * shp,int fn,char * fname)873 static Sfoff_t file_offset(Shell_t *shp, int fn, char *fname)
874 {
875 Sfio_t *sp = shp->sftable[fn];
876 char *cp;
877 Sfoff_t off;
878 struct Eof endf;
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));
882 endf.fd = fn;
883 endf.hdr.disc = &EOF_disc;
884 endf.hdr.nofree = 1;
885 if(mp)
886 nv_stack(mp, &endf.hdr);
887 if(pp)
888 nv_stack(pp, &endf.hdr);
889 if(sp)
890 sfsync(sp);
891 off = sh_strnum(fname, &cp, 0);
892 if(mp)
893 nv_stack(mp, NiL);
894 if(pp)
895 nv_stack(pp, NiL);
896 return(*cp?(Sfoff_t)-1:off);
897 }
898
899 /*
900 * close a pipe
901 */
sh_pclose(register int pv[])902 void sh_pclose(register int pv[])
903 {
904 if(pv[0]>=2)
905 sh_close(pv[0]);
906 if(pv[1]>=2)
907 sh_close(pv[1]);
908 pv[0] = pv[1] = -1;
909 }
910
io_usename(char * name,int * perm,int mode)911 static char *io_usename(char *name, int *perm, int mode)
912 {
913 struct stat statb;
914 char *tname, *sp, *ep;
915 int fd,len,n=0;
916 if(mode==0)
917 {
918 if((fd = sh_open(name,O_RDONLY,0)) > 0)
919 {
920 if(fstat(fd,&statb) < 0)
921 return(0);
922 if(!S_ISREG(statb.st_mode))
923 return(0);
924 *perm = statb.st_mode&(RW_ALL|(S_IXUSR|S_IXGRP|S_IXOTH));
925 }
926 else if(fd < 0 && errno!=ENOENT)
927 return(0);
928 }
929 tname = sp = (char*)stakalloc((len=strlen(name)) + 5);
930 if(ep = strrchr(name,'/'))
931 {
932 memcpy(sp,name,n=++ep-name);
933 len -=n;
934 sp += n;
935 }
936 else
937 ep = name;
938 *sp++ = '.';
939 memcpy(sp,ep,len);
940 strcpy(sp+len,".tmp");
941 switch(mode)
942 {
943 case 1:
944 rename(tname,name);
945 break;
946 case 2:
947 unlink(tname);
948 break;
949 }
950 return(tname);
951 }
952
953 /*
954 * I/O redirection
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
959 */
sh_redirect(Shell_t * shp,struct ionod * iop,int flag)960 int sh_redirect(Shell_t *shp,struct ionod *iop, int flag)
961 {
962 Sfoff_t off;
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];
971 Namval_t *np=0;
972 int isstring = shp->subshell?(sfset(sfstdout,0,0)&SF_STRING):0;
973 if(flag==2)
974 clexec = 1;
975 if(iop)
976 traceon = sh_trace(NIL(char**),0);
977 for(;iop;iop=iop->ionxt)
978 {
979 iof=iop->iofile;
980 fn = (iof&IOUFD);
981 if(fn==1 && shp->subshell && !shp->subshare && (flag==2 || isstring))
982 sh_subfork();
983 io_op[0] = '0'+(iof&IOUFD);
984 if(iof&IOPUT)
985 {
986 io_op[1] = '>';
987 o_mode = O_WRONLY|O_CREAT;
988 }
989 else
990 {
991 io_op[1] = '<';
992 o_mode = O_RDONLY|O_NONBLOCK;
993 }
994 io_op[2] = 0;
995 io_op[3] = 0;
996 io_op[4] = 0;
997 fname = iop->ioname;
998 if(!(iof&IORAW))
999 {
1000 if(iof&IOLSEEK)
1001 {
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);
1007 }
1008 else if(iof&IOPROCSUB)
1009 {
1010 struct argnod *ap = (struct argnod*)stakalloc(ARGVAL+strlen(iop->ioname));
1011 memset(ap, 0, ARGVAL);
1012 if(iof&IOPUT)
1013 ap->argflag = ARG_RAW;
1014 ap->argchn.ap = (struct argnod*)fname;
1015 ap = sh_argprocsub(shp,ap);
1016 fname = ap->argval;
1017 }
1018 else
1019 fname=sh_mactrim(shp,fname,(!sh_isoption(SH_NOGLOB)&&sh_isoption(SH_INTERACTIVE))?2:0);
1020 }
1021 errno=0;
1022 np = 0;
1023 if(iop->iovname)
1024 {
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));
1028 io_op[0] = '}';
1029 if((iof&IOLSEEK) || ((iof&IOMOV) && *fname=='-'))
1030 fn = nv_getnum(np);
1031 }
1032 if(iof&IOLSEEK)
1033 {
1034 io_op[2] = '#';
1035 if(iof&IOARITH)
1036 {
1037 strcpy(&io_op[3]," ((");
1038 after = "))";
1039 }
1040 else if(iof&IOCOPY)
1041 io_op[3] = '#';
1042 goto traceit;
1043 }
1044 if(*fname)
1045 {
1046 if(iof&IODOC)
1047 {
1048 if(traceon)
1049 sfputr(sfstderr,io_op,'<');
1050 fd = io_heredoc(shp,iop,fname,traceon);
1051 if(traceon && (flag==SH_SHOWME))
1052 sh_close(fd);
1053 fname = 0;
1054 }
1055 else if(iof&IOMOV)
1056 {
1057 int dupfd,toclose= -1;
1058 io_op[2] = '&';
1059 if((fd=fname[0])>='0' && fd<='9')
1060 {
1061 char *number = fname;
1062 dupfd = strtol(fname,&number,10);
1063 if(*number=='-')
1064 {
1065 toclose = dupfd;
1066 number++;
1067 }
1068 if(*number || dupfd > IOUFD)
1069 {
1070 message = e_file;
1071 goto fail;
1072 }
1073 if(shp->subshell && dupfd==1 && (sfset(sfstdout,0,0)&SF_STRING))
1074 {
1075 sh_subtmpfile(0);
1076 dupfd = sffileno(sfstdout);
1077 }
1078 else if(shp->sftable[dupfd])
1079 sfsync(shp->sftable[dupfd]);
1080 }
1081 else if(fd=='-' && fname[1]==0)
1082 {
1083 fd= -1;
1084 goto traceit;
1085 }
1086 else if(fd=='p' && fname[1]==0)
1087 {
1088 if(iof&IOPUT)
1089 dupfd = shp->coutpipe;
1090 else
1091 dupfd = shp->cpipe[0];
1092 if(flag)
1093 toclose = dupfd;
1094 }
1095 else
1096 {
1097 message = e_file;
1098 goto fail;
1099 }
1100 if(flag==SH_SHOWME)
1101 goto traceit;
1102 if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0)
1103 goto fail;
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);
1110 else if(toclose>=0)
1111 {
1112 if(flag==0)
1113 sh_iosave(shp,toclose,indx,(char*)0); /* save file descriptor */
1114 sh_close(toclose);
1115 }
1116 }
1117 else if(iof&IORDW)
1118 {
1119 if(sh_isoption(SH_RESTRICTED))
1120 errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1121 io_op[2] = '>';
1122 o_mode = O_RDWR|O_CREAT;
1123 if(iof&IOREWRITE)
1124 trunc = io_op[2] = ';';
1125 goto openit;
1126 }
1127 else if(!(iof&IOPUT))
1128 {
1129 if(flag==SH_SHOWME)
1130 goto traceit;
1131 fd=sh_chkopen(fname);
1132 }
1133 else if(sh_isoption(SH_RESTRICTED))
1134 errormsg(SH_DICT,ERROR_exit(1),e_restricted,fname);
1135 else
1136 {
1137 if(iof&IOAPP)
1138 {
1139 io_op[2] = '>';
1140 o_mode |= O_APPEND;
1141 }
1142 else if((iof&IOREWRITE) && (flag==0 || flag==1 || sh_subsavefd(fn)))
1143 {
1144 io_op[2] = ';';
1145 o_mode |= O_TRUNC;
1146 tname = io_usename(fname,&perm,0);
1147 }
1148 else
1149 {
1150 o_mode |= O_TRUNC;
1151 if(iof&IOCLOB)
1152 io_op[2] = '|';
1153 else if(sh_isoption(SH_NOCLOBBER))
1154 {
1155 struct stat sb;
1156 if(stat(fname,&sb)>=0)
1157 {
1158 #if SHOPT_FS_3D
1159 if(S_ISREG(sb.st_mode)&&
1160 (!shp->lim.fs3d || iview(&sb)==0))
1161 #else
1162 if(S_ISREG(sb.st_mode))
1163 #endif /* SHOPT_FS_3D */
1164 {
1165 errno = EEXIST;
1166 errormsg(SH_DICT,ERROR_system(1),e_exists,fname);
1167 }
1168 }
1169 else
1170 o_mode |= O_EXCL;
1171 }
1172 }
1173 openit:
1174 if(flag!=SH_SHOWME)
1175 {
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);
1178 if(perm>0)
1179 #if _lib_fchmod
1180 fchmod(fd,perm);
1181 #else
1182 chmod(tname,perm);
1183 #endif
1184 }
1185 }
1186 traceit:
1187 if(traceon && fname)
1188 {
1189 if(np)
1190 sfprintf(sfstderr,"{%s",nv_name(np));
1191 sfprintf(sfstderr,"%s %s%s%c",io_op,fname,after,iop->ionxt?' ':'\n');
1192 }
1193 if(flag==SH_SHOWME)
1194 return(indx);
1195 if(trace && fname)
1196 {
1197 char *argv[7], **av=argv;
1198 av[3] = io_op;
1199 av[4] = fname;
1200 av[5] = 0;
1201 av[6] = 0;
1202 if(iof&IOARITH)
1203 av[5] = after;
1204 if(np)
1205 {
1206 av[0] = "{";
1207 av[1] = nv_name(np);
1208 av[2] = "}";
1209 }
1210 else
1211 av +=3;
1212 sh_debug(shp,trace,(char*)0,(char*)0,av,ARG_NOGLOB);
1213 }
1214 if(iof&IOLSEEK)
1215 {
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);
1221 if(r==IOCLOSE)
1222 {
1223 fname = io_op;
1224 message = e_file;
1225 goto fail;
1226 }
1227 if(iof&IOARITH)
1228 {
1229 if(r&IONOSEEK)
1230 {
1231 fname = io_op;
1232 message = e_notseek;
1233 goto fail;
1234 }
1235 message = e_badseek;
1236 if((off = file_offset(shp,fn,fname))<0)
1237 goto fail;
1238 if(sp)
1239 {
1240 off=sfseek(sp, off, SEEK_SET);
1241 sfsync(sp);
1242 }
1243 else
1244 off=lseek(fn, off, SEEK_SET);
1245 if(off<0)
1246 r = -1;
1247 }
1248 else
1249 {
1250 regex_t *rp;
1251 extern const char e_notimp[];
1252 if(!(r&IOREAD))
1253 {
1254 message = e_noread;
1255 goto fail;
1256 }
1257 if(!(rp = regcache(fname, REG_SHELL|REG_NOSUB|REG_NEWLINE|REG_AUGMENTED|REG_FIRST|REG_LEFT|REG_RIGHT, &r)))
1258 {
1259 message = e_badpattern;
1260 goto fail;
1261 }
1262 if(!sp)
1263 sp = sh_iostream(shp,fn);
1264 r=io_patseek(shp,rp,sp,iof);
1265 if(sp && flag==3)
1266 {
1267 /* close stream but not fn */
1268 sfsetfd(sp,-1);
1269 sfclose(sp);
1270 }
1271 }
1272 if(r<0)
1273 goto fail;
1274 if(flag==3)
1275 return(fn);
1276 continue;
1277 }
1278 if(!np)
1279 {
1280 if(flag==0 || tname)
1281 {
1282 if(fd==fn)
1283 {
1284 if((r=sh_fcntl(fd,F_DUPFD,10)) > 0)
1285 {
1286 fd = r;
1287 sh_close(fn);
1288 }
1289 }
1290 sh_iosave(shp,fn,indx,tname?fname:(trunc?Empty:0));
1291 }
1292 else if(sh_subsavefd(fn))
1293 sh_iosave(shp,fn,indx|IOSUBSHELL,tname?fname:0);
1294 }
1295 if(fd<0)
1296 {
1297 if(sh_inuse(fn) || (fn && fn==shp->infd))
1298 {
1299 if(fn>9 || !(shp->inuse_bits&(1<<fn)))
1300 io_preserve(shp,shp->sftable[fn],fn);
1301 }
1302 sh_close(fn);
1303 }
1304 if(flag==3)
1305 return(fd);
1306 if(fd>=0)
1307 {
1308 if(np)
1309 {
1310 int32_t v;
1311 fn = fd;
1312 if(fd<10)
1313 {
1314 if((fn=fcntl(fd,F_DUPFD,10)) < 0)
1315 goto fail;
1316 shp->fdstatus[fn] = shp->fdstatus[fd];
1317 sh_close(fd);
1318 fd = fn;
1319 }
1320 nv_unset(np);
1321 nv_onattr(np,NV_INT32);
1322 v = fn;
1323 nv_putval(np,(char*)&v, NV_INT32);
1324 sh_iocheckfd(shp,fd);
1325 }
1326 else
1327 {
1328 fd = sh_iorenumber(shp,sh_iomovefd(fd),fn);
1329 if(fn>2 && fn<10)
1330 shp->inuse_bits |= (1<<fn);
1331 }
1332 }
1333 if(fd >2 && clexec)
1334 {
1335 fcntl(fd,F_SETFD,FD_CLOEXEC);
1336 shp->fdstatus[fd] |= IOCLEX;
1337 }
1338 }
1339 else
1340 goto fail;
1341 }
1342 return(indx);
1343 fail:
1344 errormsg(SH_DICT,ERROR_system(1),message,fname);
1345 /* NOTREACHED */
1346 return(0);
1347 }
1348 /*
1349 * Create a tmp file for the here-document
1350 */
io_heredoc(Shell_t * shp,register struct ionod * iop,const char * name,int traceon)1351 static int io_heredoc(Shell_t *shp,register struct ionod *iop, const char *name, int traceon)
1352 {
1353 register Sfio_t *infile = 0, *outfile;
1354 register int fd;
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)
1361 {
1362 if(traceon)
1363 sfprintf(sfstderr,"< %s\n",name);
1364 sfputr(outfile,name,'\n');
1365 }
1366 else
1367 {
1368 infile = subopen(shp,shp->heredocs,iop->iooffset,iop->iosize);
1369 if(traceon)
1370 {
1371 char *cp = sh_fmtq(iop->iodelim);
1372 fd = (*cp=='$' || *cp=='\'')?' ':'\\';
1373 sfprintf(sfstderr," %c%s\n",fd,cp);
1374 sfdisc(outfile,&tee_disc);
1375 }
1376 if(iop->iofile&IOQUOTE)
1377 {
1378 /* This is a quoted here-document, not expansion */
1379 sfmove(infile,outfile,SF_UNBOUND,-1);
1380 sfclose(infile);
1381 }
1382 else
1383 {
1384 char *lastpath = shp->lastpath;
1385 sh_machere(shp,infile,outfile,iop->ioname);
1386 shp->lastpath = lastpath;
1387 if(infile)
1388 sfclose(infile);
1389 }
1390 }
1391 /* close stream outfile, but save file descriptor */
1392 fd = sffileno(outfile);
1393 sfsetfd(outfile,-1);
1394 sfclose(outfile);
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;
1399 return(fd);
1400 }
1401
1402 /*
1403 * This write discipline also writes the output on standard error
1404 * This is used when tracing here-documents
1405 */
tee_write(Sfio_t * iop,const void * buff,size_t n,Sfdisc_t * unused)1406 static ssize_t tee_write(Sfio_t *iop,const void *buff,size_t n,Sfdisc_t *unused)
1407 {
1408 NOT_USED(unused);
1409 sfwrite(sfstderr,buff,n);
1410 return(write(sffileno(iop),buff,n));
1411 }
1412
1413 /*
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.
1418 */
sh_iosave(Shell_t * shp,register int origfd,int oldtop,char * name)1419 void sh_iosave(Shell_t *shp, register int origfd, int oldtop, char *name)
1420 {
1421 /*@
1422 assume oldtop>=0 && oldtop<shp->lim.open_max;
1423 @*/
1424
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; )
1430 {
1431 if(filemap[savefd].orig_fd == origfd)
1432 return;
1433 }
1434 /* make sure table is large enough */
1435 if(shp->topfd >= filemapsize)
1436 {
1437 char *cp, *oldptr = (char*)filemap;
1438 char *oldend = (char*)&filemap[filemapsize];
1439 long moved;
1440 filemapsize += 8;
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)
1444 {
1445 #if SHOPT_FASTPIPE
1446 for(savefd=shp->lim.open_max+2; --savefd>=0; )
1447 #else
1448 for(savefd=shp->lim.open_max; --savefd>=0; )
1449 #endif /* SHOPT_FASTPIPE */
1450 {
1451 cp = (char*)shp->fdptrs[savefd];
1452 if(cp >= oldptr && cp < oldend)
1453 shp->fdptrs[savefd] = (int*)(oldptr+moved);
1454 }
1455 }
1456 }
1457 #if SHOPT_DEVFD
1458 if(origfd <0)
1459 {
1460 savefd = origfd;
1461 origfd = -origfd;
1462 }
1463 else
1464 #endif /* SHOPT_DEVFD */
1465 {
1466 if((savefd = sh_fcntl(origfd, F_DUPFD, 10)) < 0 && errno!=EBADF)
1467 {
1468 shp->toomany=1;
1469 ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT;
1470 errormsg(SH_DICT,ERROR_system(1),e_toomany);
1471 }
1472 }
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;
1477 if(savefd >=0)
1478 {
1479 register Sfio_t* sp = shp->sftable[origfd];
1480 /* make saved file close-on-exec */
1481 sh_fcntl(savefd,F_SETFD,FD_CLOEXEC);
1482 if(origfd==job.fd)
1483 job.fd = savefd;
1484 shp->fdstatus[savefd] = shp->fdstatus[origfd];
1485 shp->fdptrs[savefd] = &filemap[shp->topfd-1].save_fd;
1486 if(!(shp->sftable[savefd]=sp))
1487 return;
1488 sfsync(sp);
1489 if(origfd <=2)
1490 {
1491 /* copy standard stream to new stream */
1492 sp = sfswap(sp,NIL(Sfio_t*));
1493 shp->sftable[savefd] = sp;
1494 }
1495 else
1496 shp->sftable[origfd] = 0;
1497 }
1498 }
1499
1500 /*
1501 * close all saved file descriptors
1502 */
sh_iounsave(Shell_t * shp)1503 void sh_iounsave(Shell_t* shp)
1504 {
1505 register int fd, savefd, newfd;
1506 for(newfd=fd=0; fd < shp->topfd; fd++)
1507 {
1508 if((savefd = filemap[fd].save_fd)< 0)
1509 filemap[newfd++] = filemap[fd];
1510 else
1511 {
1512 shp->sftable[savefd] = 0;
1513 sh_close(savefd);
1514 }
1515 }
1516 shp->topfd = newfd;
1517 }
1518
1519 /*
1520 * restore saved file descriptors from <last> on
1521 */
sh_iorestore(Shell_t * shp,int last,int jmpval)1522 void sh_iorestore(Shell_t *shp, int last, int jmpval)
1523 {
1524 register int origfd, savefd, fd;
1525 int flag = (last&IOSUBSHELL);
1526 last &= ~IOSUBSHELL;
1527 for (fd = shp->topfd - 1; fd >= last; fd--)
1528 {
1529 if(!flag && filemap[fd].subshell)
1530 continue;
1531 if(jmpval==SH_JMPSCRIPT)
1532 {
1533 if ((savefd = filemap[fd].save_fd) >= 0)
1534 {
1535 shp->sftable[savefd] = 0;
1536 sh_close(savefd);
1537 }
1538 continue;
1539 }
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);
1545 sh_close(origfd);
1546 if ((savefd = filemap[fd].save_fd) >= 0)
1547 {
1548 sh_fcntl(savefd, F_DUPFD, origfd);
1549 if(savefd==job.fd)
1550 job.fd=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);
1555 if(origfd<=2)
1556 {
1557 sfswap(shp->sftable[savefd],shp->sftable[origfd]);
1558 if(origfd==0)
1559 shp->st.ioset = 0;
1560 }
1561 else
1562 shp->sftable[origfd] = shp->sftable[savefd];
1563 shp->sftable[savefd] = 0;
1564 sh_close(savefd);
1565 }
1566 else
1567 shp->fdstatus[origfd] = IOCLOSE;
1568 }
1569 if(!flag)
1570 {
1571 /* keep file descriptors for subshell restore */
1572 for (fd = last ; fd < shp->topfd; fd++)
1573 {
1574 if(filemap[fd].subshell)
1575 filemap[last++] = filemap[fd];
1576 }
1577 }
1578 if(last < shp->topfd)
1579 shp->topfd = last;
1580 }
1581
1582 /*
1583 * returns access information on open file <fd>
1584 * returns -1 for failure, 0 for success
1585 * <mode> is the same as for access()
1586 */
sh_ioaccess(int fd,register int mode)1587 int sh_ioaccess(int fd,register int mode)
1588 {
1589 Shell_t *shp = &sh;
1590 register int flags;
1591 if(mode==X_OK)
1592 return(-1);
1593 if((flags=sh_iocheckfd(shp,fd))!=IOCLOSE)
1594 {
1595 if(mode==F_OK)
1596 return(0);
1597 if(mode==R_OK && (flags&IOREAD))
1598 return(0);
1599 if(mode==W_OK && (flags&IOWRITE))
1600 return(0);
1601 }
1602 return(-1);
1603 }
1604
1605 /*
1606 * Handle interrupts for slow streams
1607 */
slowexcept(register Sfio_t * iop,int type,void * data,Sfdisc_t * handle)1608 static int slowexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle)
1609 {
1610 register int n,fno;
1611 NOT_USED(handle);
1612 if(type==SF_DPOP || type==SF_FINAL)
1613 free((void*)handle);
1614 if(type!=SF_READ)
1615 return(0);
1616 if((sh.trapnote&(SH_SIGSET|SH_SIGTRAP)) && errno!=EIO && errno!=ENXIO)
1617 errno = EINTR;
1618 fno = sffileno(iop);
1619 if((n=sfvalue(iop))<=0)
1620 {
1621 #ifndef FNDELAY
1622 # ifdef O_NDELAY
1623 if(errno==0 && (n=fcntl(fno,F_GETFL,0))&O_NDELAY)
1624 {
1625 n &= ~O_NDELAY;
1626 fcntl(fno, F_SETFL, n);
1627 return(1);
1628 }
1629 # endif /* O_NDELAY */
1630 #endif /* !FNDELAY */
1631 #ifdef O_NONBLOCK
1632 if(errno==EAGAIN)
1633 {
1634 n = fcntl(fno,F_GETFL,0);
1635 n &= ~O_NONBLOCK;
1636 fcntl(fno, F_SETFL, n);
1637 return(1);
1638 }
1639 #endif /* O_NONBLOCK */
1640 if(errno!=EINTR)
1641 return(0);
1642 n=1;
1643 sh_onstate(SH_TTYWAIT);
1644 }
1645 else
1646 n = 0;
1647 if(sh.bltinfun && sh.bltindata.sigset)
1648 return(-1);
1649 errno = 0;
1650 if(sh.trapnote&SH_SIGSET)
1651 {
1652 if(isatty(fno))
1653 sfputc(sfstderr,'\n');
1654 sh_exit(SH_EXITSIG);
1655 }
1656 if(sh.trapnote&SH_SIGTRAP)
1657 sh_chktrap();
1658 return(n);
1659 }
1660
1661 /*
1662 * called when slowread times out
1663 */
time_grace(void * handle)1664 static void time_grace(void *handle)
1665 {
1666 NOT_USED(handle);
1667 timeout = 0;
1668 if(sh_isstate(SH_GRACE))
1669 {
1670 sh_offstate(SH_GRACE);
1671 if(!sh_isstate(SH_INTERACTIVE))
1672 return;
1673 ((struct checkpt*)sh.jmplist)->mode = SH_JMPEXIT;
1674 errormsg(SH_DICT,2,e_timeout);
1675 sh.trapnote |= SH_SIGSET;
1676 return;
1677 }
1678 errormsg(SH_DICT,0,e_timewarn);
1679 sh_onstate(SH_GRACE);
1680 sigrelease(SIGALRM);
1681 sh.trapnote |= SH_SIGTRAP;
1682 }
1683
piperead(Sfio_t * iop,void * buff,register size_t size,Sfdisc_t * handle)1684 static ssize_t piperead(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1685 {
1686 int fd = sffileno(iop);
1687 NOT_USED(handle);
1688 if(job.waitsafe && job.savesig)
1689 {
1690 job_lock();
1691 job_unlock();
1692 }
1693 if(sh.trapnote)
1694 {
1695 errno = EINTR;
1696 return(-1);
1697 }
1698 if(sh_isstate(SH_INTERACTIVE) && io_prompt(iop,sh.nextprompt)<0 && errno==EIO)
1699 return(0);
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);
1703 else
1704 size = sfrd(iop,buff,size,handle);
1705 sh_offstate(SH_TTYWAIT);
1706 return(size);
1707 }
1708 /*
1709 * This is the read discipline that is applied to slow devices
1710 * This routine takes care of prompting for input
1711 */
slowread(Sfio_t * iop,void * buff,register size_t size,Sfdisc_t * handle)1712 static ssize_t slowread(Sfio_t *iop,void *buff,register size_t size,Sfdisc_t *handle)
1713 {
1714 int (*readf)(void*, int, char*, int, int);
1715 int reedit=0, rsize;
1716 #if SHOPT_HISTEXPAND
1717 char *xp=0;
1718 #endif
1719 NOT_USED(handle);
1720 # if SHOPT_ESH
1721 if(sh_isoption(SH_EMACS) || sh_isoption(SH_GMACS))
1722 readf = ed_emacsread;
1723 else
1724 # endif /* SHOPT_ESH */
1725 # if SHOPT_VSH
1726 # if SHOPT_RAWONLY
1727 if(sh_isoption(SH_VI) || ((SHOPT_RAWONLY-0) && mbwide()))
1728 # else
1729 if(sh_isoption(SH_VI))
1730 # endif
1731 readf = ed_viread;
1732 else
1733 # endif /* SHOPT_VSH */
1734 readf = ed_read;
1735 if(sh.trapnote)
1736 {
1737 errno = EINTR;
1738 return(-1);
1739 }
1740 while(1)
1741 {
1742 if(io_prompt(iop,sh.nextprompt)<0 && errno==EIO)
1743 return(0);
1744 if(sh.timeout)
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);
1747 if(timeout)
1748 timerdel(timeout);
1749 timeout=0;
1750 #if SHOPT_HISTEXPAND
1751 if(rsize && *(char*)buff != '\n' && sh.nextprompt==1 && sh_isoption(SH_HISTEXPAND))
1752 {
1753 int r;
1754 ((char*)buff)[rsize] = '\0';
1755 if(xp)
1756 {
1757 free(xp);
1758 xp = 0;
1759 }
1760 r = hist_expand(buff, &xp);
1761 if((r & (HIST_EVENT|HIST_PRINT)) && !(r & HIST_ERROR) && xp)
1762 {
1763 strlcpy(buff, xp, size);
1764 rsize = strlen(buff);
1765 if(!sh_isoption(SH_HISTVERIFY) || readf==ed_read)
1766 {
1767 sfputr(sfstderr, xp, -1);
1768 break;
1769 }
1770 reedit = rsize - 1;
1771 continue;
1772 }
1773 if((r & HIST_ERROR) && sh_isoption(SH_HISTREEDIT))
1774 {
1775 reedit = rsize - 1;
1776 continue;
1777 }
1778 if(r & (HIST_ERROR|HIST_PRINT))
1779 {
1780 *(char*)buff = '\n';
1781 rsize = 1;
1782 }
1783 }
1784 #endif
1785 break;
1786 }
1787 return(rsize);
1788 }
1789
1790 /*
1791 * check and return the attributes for a file descriptor
1792 */
1793
sh_iocheckfd(Shell_t * shp,register int fd)1794 int sh_iocheckfd(Shell_t *shp, register int fd)
1795 {
1796 register int flags, n;
1797 if((n=sh.fdstatus[fd])&IOCLOSE)
1798 return(n);
1799 if(!(n&(IOREAD|IOWRITE)))
1800 {
1801 #ifdef F_GETFL
1802 if((flags=fcntl(fd,F_GETFL,0)) < 0)
1803 return(sh.fdstatus[fd]=IOCLOSE);
1804 if((flags&O_ACCMODE)!=O_WRONLY)
1805 n |= IOREAD;
1806 if((flags&O_ACCMODE)!=O_RDONLY)
1807 n |= IOWRITE;
1808 #else
1809 struct stat statb;
1810 if((flags = fstat(fd,&statb))< 0)
1811 return(sh.fdstatus[fd]=IOCLOSE);
1812 n |= (IOREAD|IOWRITE);
1813 if(read(fd,"",0) < 0)
1814 n &= ~IOREAD;
1815 #endif /* F_GETFL */
1816 }
1817 if(!(n&(IOSEEK|IONOSEEK)))
1818 {
1819 struct stat statb;
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)
1824 {
1825 null_ino = statb.st_ino;
1826 null_dev = statb.st_dev;
1827 }
1828 if(tty_check(fd))
1829 n |= IOTTY;
1830 if(lseek(fd,NIL(off_t),SEEK_CUR)<0)
1831 {
1832 n |= IONOSEEK;
1833 #ifdef S_ISSOCK
1834 if((fstat(fd,&statb)>=0) && S_ISSOCK(statb.st_mode))
1835 n |= IOREAD|IOWRITE;
1836 #endif /* S_ISSOCK */
1837 }
1838 else if((fstat(fd,&statb)>=0) && (
1839 S_ISFIFO(statb.st_mode) ||
1840 #ifdef S_ISSOCK
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))
1846 ))
1847 n |= IONOSEEK;
1848 else
1849 n |= IOSEEK;
1850 }
1851 sh.fdstatus[fd] = n;
1852 return(n);
1853 }
1854
1855 /*
1856 * Display prompt PS<flag> on standard error
1857 */
1858
io_prompt(Sfio_t * iop,register int flag)1859 static int io_prompt(Sfio_t *iop,register int flag)
1860 {
1861 Shell_t *shp = &sh;
1862 register char *cp;
1863 char buff[1];
1864 char *endprompt;
1865 static short cmdno;
1866 int sfflags;
1867 if(flag<3 && !sh_isstate(SH_INTERACTIVE))
1868 flag = 0;
1869 if(flag==2 && sfpkrd(sffileno(iop),buff,1,'\n',0,1) >= 0)
1870 flag = 0;
1871 if(flag==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)))
1875 sh.prompt = "";
1876 switch(flag)
1877 {
1878 case 1:
1879 {
1880 register int c;
1881 #if defined(TIOCLBIC) && defined(LFLUSHO)
1882 if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS))
1883 {
1884 /*
1885 * re-enable output in case the user has
1886 * disabled it. Not needed with edit mode
1887 */
1888 int mode = LFLUSHO;
1889 ioctl(sffileno(sfstderr),TIOCLBIC,&mode);
1890 }
1891 #endif /* TIOCLBIC */
1892 cp = sh_mactry(shp,nv_getval(sh_scoped(shp,PS1NOD)));
1893 for(;c= *cp;cp++)
1894 {
1895 if(c==HIST_CHAR)
1896 {
1897 /* look at next character */
1898 c = *++cp;
1899 /* print out line number if not !! */
1900 if(c!= HIST_CHAR)
1901 {
1902 sfprintf(sfstderr,"%d", sh.hist_ptr?(int)sh.hist_ptr->histind:++cmdno);
1903 }
1904 if(c==0)
1905 goto done;
1906 }
1907 sfputc(sfstderr,c);
1908 }
1909 goto done;
1910 }
1911 case 2:
1912 cp = nv_getval(sh_scoped(shp,PS2NOD));
1913 break;
1914 case 3:
1915 cp = nv_getval(sh_scoped(shp,PS3NOD));
1916 break;
1917 default:
1918 goto done;
1919 }
1920 if(cp)
1921 sfputr(sfstderr,cp,-1);
1922 done:
1923 if(*sh.prompt && (endprompt=(char*)sfreserve(sfstderr,0,0)))
1924 *endprompt = 0;
1925 sfset(sfstderr,sfflags&SF_READ|SF_SHARE|SF_PUBLIC,1);
1926 return(sfsync(sfstderr));
1927 }
1928
1929 /*
1930 * This discipline is inserted on write pipes to prevent SIGPIPE
1931 * from causing an infinite loop
1932 */
pipeexcept(Sfio_t * iop,int mode,void * data,Sfdisc_t * handle)1933 static int pipeexcept(Sfio_t* iop, int mode, void *data, Sfdisc_t* handle)
1934 {
1935 NOT_USED(iop);
1936 if(mode==SF_DPOP || mode==SF_FINAL)
1937 free((void*)handle);
1938 else if(mode==SF_WRITE && errno==EINTR && sh.lastsig==SIGPIPE)
1939 return(-1);
1940 return(0);
1941 }
1942
1943 /*
1944 * keep track of each stream that is opened and closed
1945 */
sftrack(Sfio_t * sp,int flag,void * data)1946 static void sftrack(Sfio_t* sp, int flag, void* data)
1947 {
1948 Shell_t *shp = &sh;
1949 register int fd = sffileno(sp);
1950 register struct checkpt *pp;
1951 register int mode;
1952 int newfd = integralof(data);
1953 if(flag==SF_SETFD || flag==SF_CLOSING)
1954 {
1955 if(newfd<0)
1956 flag = SF_CLOSING;
1957 if(fdnotify)
1958 (*fdnotify)(sffileno(sp),flag==SF_CLOSING?-1:newfd);
1959 }
1960 #ifdef DEBUG
1961 if(flag==SF_READ || flag==SF_WRITE)
1962 {
1963 char *z = fmtbase((long)getpid(),0,0);
1964 write(ERRIO,z,strlen(z));
1965 write(ERRIO,": ",2);
1966 write(ERRIO,"attempt to ",11);
1967 if(flag==SF_READ)
1968 write(ERRIO,"read from",9);
1969 else
1970 write(ERRIO,"write to",8);
1971 write(ERRIO," locked stream\n",15);
1972 return;
1973 }
1974 #endif
1975 if((unsigned)fd >= shp->lim.open_max)
1976 return;
1977 if(sh_isstate(SH_NOTRACK))
1978 return;
1979 mode = sfset(sp,0,0);
1980 if(sp==shp->heredocs && fd < 10 && flag==SF_NEW)
1981 {
1982 fd = sfsetfd(sp,10);
1983 fcntl(fd,F_SETFD,FD_CLOEXEC);
1984 }
1985 if(fd < 3)
1986 return;
1987 if(flag==SF_NEW)
1988 {
1989 if(!shp->sftable[fd] && shp->fdstatus[fd]==IOCLOSE)
1990 {
1991 shp->sftable[fd] = sp;
1992 flag = (mode&SF_WRITE)?IOWRITE:0;
1993 if(mode&SF_READ)
1994 flag |= IOREAD;
1995 shp->fdstatus[fd] = flag;
1996 sh_iostream(shp,fd);
1997 }
1998 if((pp=(struct checkpt*)shp->jmplist) && pp->mode==SH_JMPCMD)
1999 {
2000 struct openlist *item;
2001 /*
2002 * record open file descriptors so they can
2003 * be closed in case a longjmp prevents
2004 * built-ins from cleanup
2005 */
2006 item = new_of(struct openlist, 0);
2007 item->strm = sp;
2008 item->next = pp->olist;
2009 pp->olist = item;
2010 }
2011 if(fdnotify)
2012 (*fdnotify)(-1,sffileno(sp));
2013 }
2014 else if(flag==SF_CLOSING || (flag==SF_SETFD && newfd<=2))
2015 {
2016 shp->sftable[fd] = 0;
2017 shp->fdstatus[fd]=IOCLOSE;
2018 if(pp=(struct checkpt*)shp->jmplist)
2019 {
2020 struct openlist *item;
2021 for(item=pp->olist; item; item=item->next)
2022 {
2023 if(item->strm == sp)
2024 {
2025 item->strm = 0;
2026 break;
2027 }
2028 }
2029 }
2030 }
2031 }
2032
2033 struct eval
2034 {
2035 Sfdisc_t disc;
2036 char **argv;
2037 short slen;
2038 char addspace;
2039 };
2040
2041 /*
2042 * Create a stream consisting of a space separated argv[] list
2043 */
2044
sh_sfeval(register char * argv[])2045 Sfio_t *sh_sfeval(register char *argv[])
2046 {
2047 register Sfio_t *iop;
2048 register char *cp;
2049 if(argv[1])
2050 cp = "";
2051 else
2052 cp = argv[0];
2053 iop = sfopen(NIL(Sfio_t*),(char*)cp,"s");
2054 if(argv[1])
2055 {
2056 register struct eval *ep;
2057 if(!(ep = new_of(struct eval,0)))
2058 return(NIL(Sfio_t*));
2059 ep->disc = eval_disc;
2060 ep->argv = argv;
2061 ep->slen = -1;
2062 ep->addspace = 0;
2063 sfdisc(iop,&ep->disc);
2064 }
2065 return(iop);
2066 }
2067
2068 /*
2069 * This code gets called whenever an end of string is found with eval
2070 */
2071
eval_exceptf(Sfio_t * iop,int type,void * data,Sfdisc_t * handle)2072 static int eval_exceptf(Sfio_t *iop,int type, void *data, Sfdisc_t *handle)
2073 {
2074 register struct eval *ep = (struct eval*)handle;
2075 register char *cp;
2076 register int len;
2077
2078 /* no more to do */
2079 if(type!=SF_READ || !(cp = ep->argv[0]))
2080 {
2081 if(type==SF_CLOSING)
2082 sfdisc(iop,SF_POPDISC);
2083 else if(ep && (type==SF_DPOP || type==SF_FINAL))
2084 free((void*)ep);
2085 return(0);
2086 }
2087
2088 if(!ep->addspace)
2089 {
2090 /* get the length of this string */
2091 ep->slen = len = strlen(cp);
2092 /* move to next string */
2093 ep->argv++;
2094 }
2095 else /* insert space between arguments */
2096 {
2097 len = 1;
2098 cp = " ";
2099 }
2100 /* insert the new string */
2101 sfsetbuf(iop,cp,len);
2102 ep->addspace = !ep->addspace;
2103 return(1);
2104 }
2105
2106 /*
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
2110 */
2111
subopen(Shell_t * shp,Sfio_t * sp,off_t offset,long size)2112 static Sfio_t *subopen(Shell_t *shp,Sfio_t* sp, off_t offset, long size)
2113 {
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;
2120 disp->oldsp = sp;
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);
2125 return(sp);
2126 }
2127
2128 /*
2129 * read function for subfile discipline
2130 */
subread(Sfio_t * sp,void * buff,register size_t size,Sfdisc_t * handle)2131 static ssize_t subread(Sfio_t* sp,void* buff,register size_t size,Sfdisc_t* handle)
2132 {
2133 register struct subfile *disp = (struct subfile*)handle;
2134 NOT_USED(sp);
2135 if(disp->left == 0)
2136 return(0);
2137 if(size > disp->left)
2138 size = disp->left;
2139 disp->left -= size;
2140 return(sfread(disp->oldsp,buff,size));
2141 }
2142
2143 /*
2144 * exception handler for subfile discipline
2145 */
subexcept(Sfio_t * sp,register int mode,void * data,Sfdisc_t * handle)2146 static int subexcept(Sfio_t* sp,register int mode, void *data, Sfdisc_t* handle)
2147 {
2148 register struct subfile *disp = (struct subfile*)handle;
2149 if(mode==SF_CLOSING)
2150 {
2151 sfdisc(sp,SF_POPDISC);
2152 return(0);
2153 }
2154 else if(disp && (mode==SF_DPOP || mode==SF_FINAL))
2155 {
2156 free((void*)disp);
2157 return(0);
2158 }
2159 #ifdef SF_ATEXIT
2160 else if (mode==SF_ATEXIT)
2161 {
2162 sfdisc(sp, SF_POPDISC);
2163 return(0);
2164 }
2165 #endif
2166 else if(mode==SF_READ)
2167 return(0);
2168 return(-1);
2169 }
2170
2171 #define NROW 15 /* number of rows before going to multi-columns */
2172 #define LBLSIZ 3 /* size of label field and interfield spacing */
2173 /*
2174 * print a list of arguments in columns
2175 */
sh_menu(Sfio_t * outfile,int argn,char * argv[])2176 void sh_menu(Sfio_t *outfile,int argn,char *argv[])
2177 {
2178 Shell_t *shp = &sh;
2179 register int i,j;
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)
2186 ndigits++;
2187 if(argn < nrow)
2188 {
2189 nrow = argn;
2190 goto skip;
2191 }
2192 i = 0;
2193 for(arg=argv; *arg;arg++)
2194 {
2195 if((j=strlen(*arg)) > i)
2196 i = j;
2197 }
2198 i += (ndigits+LBLSIZ);
2199 if(i < wsize)
2200 ncol = wsize/i;
2201 if(argn > nrow*ncol)
2202 {
2203 nrow = 1 + (argn-1)/ncol;
2204 }
2205 else
2206 {
2207 ncol = 1 + (argn-1)/nrow;
2208 nrow = 1 + (argn-1)/ncol;
2209 }
2210 skip:
2211 fldsize = (wsize/ncol)-(ndigits+LBLSIZ);
2212 for(i=0;i<nrow;i++)
2213 {
2214 if(sh.trapnote&SH_SIGSET)
2215 return;
2216 j = i;
2217 while(1)
2218 {
2219 arg = argv+j;
2220 sfprintf(outfile,"%*d) %s",ndigits,j+1,*arg);
2221 j += nrow;
2222 if(j >= argn)
2223 break;
2224 sfnputc(outfile,' ',fldsize-strlen(*arg));
2225 }
2226 sfputc(outfile,'\n');
2227 }
2228 }
2229
2230 #undef read
2231 /*
2232 * shell version of read() for user added builtins
2233 */
sh_read(register int fd,void * buff,size_t n)2234 ssize_t sh_read(register int fd, void* buff, size_t n)
2235 {
2236 register Sfio_t *sp;
2237 if(sp=sh.sftable[fd])
2238 return(sfread(sp,buff,n));
2239 else
2240 return(read(fd,buff,n));
2241 }
2242
2243 #undef write
2244 /*
2245 * shell version of write() for user added builtins
2246 */
sh_write(register int fd,const void * buff,size_t n)2247 ssize_t sh_write(register int fd, const void* buff, size_t n)
2248 {
2249 register Sfio_t *sp;
2250 if(sp=sh.sftable[fd])
2251 return(sfwrite(sp,buff,n));
2252 else
2253 return(write(fd,buff,n));
2254 }
2255
2256 #undef lseek
2257 /*
2258 * shell version of lseek() for user added builtins
2259 */
sh_seek(register int fd,off_t offset,int whence)2260 off_t sh_seek(register int fd, off_t offset, int whence)
2261 {
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));
2265 else
2266 return(lseek(fd,offset,whence));
2267 }
2268
2269 #undef dup
sh_dup(register int old)2270 int sh_dup(register int old)
2271 {
2272 register int fd = dup(old);
2273 if(fd>=0)
2274 {
2275 if(sh.fdstatus[old] == IOCLOSE)
2276 sh.fdstatus[old] = 0;
2277 sh.fdstatus[fd] = (sh.fdstatus[old]&~IOCLEX);
2278 if(fdnotify)
2279 (*fdnotify)(old,fd);
2280 }
2281 return(fd);
2282 }
2283
2284 #undef fcntl
sh_fcntl(register int fd,int op,...)2285 int sh_fcntl(register int fd, int op, ...)
2286 {
2287 int newfd, arg;
2288 va_list ap;
2289 va_start(ap, op);
2290 arg = va_arg(ap, int) ;
2291 va_end(ap);
2292 newfd = fcntl(fd,op,arg);
2293 if(newfd>=0) switch(op)
2294 {
2295 case F_DUPFD:
2296 if(sh.fdstatus[fd] == IOCLOSE)
2297 sh.fdstatus[fd] = 0;
2298 sh.fdstatus[newfd] = (sh.fdstatus[fd]&~IOCLEX);
2299 if(fdnotify)
2300 (*fdnotify)(fd,newfd);
2301 break;
2302 case F_SETFD:
2303 if(sh.fdstatus[fd] == IOCLOSE)
2304 sh.fdstatus[fd] = 0;
2305 if(arg&FD_CLOEXEC)
2306 sh.fdstatus[fd] |= IOCLEX;
2307 else
2308 sh.fdstatus[fd] &= ~IOCLEX;
2309 }
2310 return(newfd);
2311 }
2312
2313 #undef umask
sh_umask(mode_t m)2314 mode_t sh_umask(mode_t m)
2315 {
2316 sh.mask = m;
2317 return(umask(m));
2318 }
2319
2320 /*
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.
2325 */
2326
sh_iogetiop(int fd,int mode)2327 Sfio_t *sh_iogetiop(int fd, int mode)
2328 {
2329 Shell_t *shp = &sh;
2330 int n;
2331 Sfio_t *iop=0;
2332 if(mode!=SF_READ && mode!=SF_WRITE)
2333 {
2334 errno = EINVAL;
2335 return(iop);
2336 }
2337 switch(fd)
2338 {
2339 case SH_IOHISTFILE:
2340 if(!sh_histinit((void*)shp))
2341 return(iop);
2342 fd = sffileno(shp->hist_ptr->histfp);
2343 break;
2344 case SH_IOCOPROCESS:
2345 if(mode==SF_WRITE)
2346 fd = shp->coutpipe;
2347 else
2348 fd = shp->cpipe[0];
2349 break;
2350 default:
2351 if(fd<0 || fd >= shp->lim.open_max)
2352 fd = -1;
2353 }
2354 if(fd<0)
2355 {
2356 errno = EBADF;
2357 return(iop);
2358 }
2359 if(!(n=shp->fdstatus[fd]))
2360 n = sh_iocheckfd(shp,fd);
2361 if(mode==SF_WRITE && !(n&IOWRITE))
2362 return(iop);
2363 if(mode==SF_READ && !(n&IOREAD))
2364 return(iop);
2365 if(!(iop = shp->sftable[fd]))
2366 iop=sh_iostream(shp,fd);
2367 return(iop);
2368 }
2369
2370 typedef int (*Notify_f)(int,int);
2371
sh_fdnotify(Notify_f notify)2372 Notify_f sh_fdnotify(Notify_f notify)
2373 {
2374 Notify_f old;
2375 old = fdnotify;
2376 fdnotify = notify;
2377 return(old);
2378 }
2379
sh_fd2sfio(int fd)2380 Sfio_t *sh_fd2sfio(int fd)
2381 {
2382 Shell_t *shp = &sh;
2383 register int status;
2384 Sfio_t *sp = sh.sftable[fd];
2385 if(!sp && (status = sh_iocheckfd(shp,fd))!=IOCLOSE)
2386 {
2387 register int flags=0;
2388 if(status&IOREAD)
2389 flags |= SF_READ;
2390 if(status&IOWRITE)
2391 flags |= SF_WRITE;
2392 sp = sfnew(NULL, NULL, -1, fd,flags);
2393 sh.sftable[fd] = sp;
2394 }
2395 return(sp);
2396 }
2397
sh_pathopen(const char * cp)2398 Sfio_t *sh_pathopen(const char *cp)
2399 {
2400 Shell_t *shp = &sh;
2401 int n;
2402 #ifdef PATH_BFPATH
2403 if((n=path_open(cp,path_get(cp))) < 0)
2404 n = path_open(cp,(Pathcomp_t*)0);
2405 #else
2406 if((n=path_open(cp,path_get(cp))) < 0)
2407 n = path_open(cp,"");
2408 #endif
2409 if(n < 0)
2410 errormsg(SH_DICT,ERROR_system(1),e_open,cp);
2411 return(sh_iostream(shp,n));
2412 }
2413