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