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 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 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 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 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 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 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 440 int sh_inuse(Shell_t *shp, int fd) 441 { 442 return(fd < shp->gd->lim.open_max && shp->fdptrs[fd]); 443 } 444 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 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 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 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 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 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 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 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 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 */ 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 2692 Notify_f sh_fdnotify(Notify_f notify) 2693 { 2694 Notify_f old; 2695 old = fdnotify; 2696 fdnotify = notify; 2697 return(old); 2698 } 2699 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 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 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 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 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. 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