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