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