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