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