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