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