diff -up ksh-20100621/src/cmd/ksh93/include/io.h.iotry1 ksh-20100621/src/cmd/ksh93/include/io.h --- ksh-20100621/src/cmd/ksh93/include/io.h.iotry1 2009-04-12 10:05:46.000000000 +0200 +++ ksh-20100621/src/cmd/ksh93/include/io.h 2010-10-19 13:36:41.597091989 +0200 @@ -63,8 +63,6 @@ struct ionod; #endif /* !ARG_RAW */ -#define sh_inuse(f2) (sh.fdptrs[f2]) - extern int sh_iocheckfd(Shell_t*,int); extern void sh_ioinit(Shell_t*); extern int sh_iomovefd(int); @@ -77,6 +75,8 @@ extern void sh_iorestore(Shell_t*,int,i extern Sfio_t *sh_iostream(Shell_t*,int); extern int sh_redirect(Shell_t*,struct ionod*,int); extern void sh_iosave(Shell_t *, int,int,char*); +extern int sh_iovalidfd(Shell_t*, int); +extern int sh_inuse(int); extern void sh_iounsave(Shell_t*); extern int sh_chkopen(const char*); extern int sh_ioaccess(int,int); diff -up ksh-20100621/src/cmd/ksh93/sh/init.c.iotry1 ksh-20100621/src/cmd/ksh93/sh/init.c --- ksh-20100621/src/cmd/ksh93/sh/init.c.iotry1 2010-10-19 16:01:31.124585914 +0200 +++ ksh-20100621/src/cmd/ksh93/sh/init.c 2010-10-19 16:02:19.813260073 +0200 @@ -1102,7 +1102,6 @@ Shell_t *sh_init(register int argc,regis } shp->lim.clk_tck = getconf("CLK_TCK"); shp->lim.arg_max = getconf("ARG_MAX"); - shp->lim.open_max = getconf("OPEN_MAX"); shp->lim.child_max = getconf("CHILD_MAX"); shp->lim.ngroups_max = getconf("NGROUPS_MAX"); shp->lim.posix_version = getconf("VERSION"); diff -up ksh-20100621/src/cmd/ksh93/sh/io.c.iotry1 ksh-20100621/src/cmd/ksh93/sh/io.c --- ksh-20100621/src/cmd/ksh93/sh/io.c.iotry1 2010-06-10 21:09:46.000000000 +0200 +++ ksh-20100621/src/cmd/ksh93/sh/io.c 2010-10-19 13:36:41.599091685 +0200 @@ -316,6 +316,12 @@ struct fdsave char *tname; /* name used with >; */ }; +struct Iodisc +{ + Sfdisc_t disc; + Shell_t *sh; +}; + static int subexcept(Sfio_t*, int, void*, Sfdisc_t*); static int eval_exceptf(Sfio_t*, int, void*, Sfdisc_t*); static int slowexcept(Sfio_t*, int, void*, Sfdisc_t*); @@ -380,29 +386,60 @@ static int matchf(void *handle, char *pt static struct fdsave *filemap; static short filemapsize; +#define PSEUDOFD (SHRT_MAX) + /* ======== input output and file copying ======== */ +int sh_iovalidfd(Shell_t *shp, int fd) +{ + Sfio_t **sftable = shp->sftable; + int max,n, **fdptrs = shp->fdptrs; + unsigned char *fdstatus = shp->fdstatus; + if(fd<0) + return(0); + if(fd < sh.lim.open_max) + return(1); + max = strtol(astconf("OPEN_MAX",NiL,NiL),NiL,0); + if(fd >= max) + { + errno = EBADF; + return(0); + } + n = (fd+16)&~0xf; + if(n > max) + n = max; + max = sh.lim.open_max; + shp->sftable = (Sfio_t**)calloc(n*(sizeof(int*)+sizeof(Sfio_t*)+1),1); + if(max) + memcpy(shp->sftable,sftable,max*sizeof(Sfio_t*)); + shp->fdptrs = (int**)(&shp->sftable[n]); + if(max) + memcpy(shp->fdptrs,fdptrs,max*sizeof(int*)); + shp->fdstatus = (unsigned char*)(&shp->fdptrs[n]); + if(max) + memcpy(shp->fdstatus,fdstatus,max); + if(sftable) + free((void*)sftable); + sh.lim.open_max = n; + return(1); +} + +int sh_inuse(int fd) +{ + return(fd < sh.lim.open_max && sh.fdptrs[fd]); +} + void sh_ioinit(Shell_t *shp) { - register int n; filemapsize = 8; filemap = (struct fdsave*)malloc(filemapsize*sizeof(struct fdsave)); -#if SHOPT_FASTPIPE - n = shp->lim.open_max+2; -#else - n = shp->lim.open_max; -#endif /* SHOPT_FASTPIPE */ - shp->fdstatus = (unsigned char*)malloc((unsigned)n); - memset((char*)shp->fdstatus,0,n); - shp->fdptrs = (int**)malloc(n*sizeof(int*)); - memset((char*)shp->fdptrs,0,n*sizeof(int*)); - shp->sftable = (Sfio_t**)malloc(n*sizeof(Sfio_t*)); - memset((char*)shp->sftable,0,n*sizeof(Sfio_t*)); + sh_iovalidfd(shp,16); shp->sftable[0] = sfstdin; shp->sftable[1] = sfstdout; shp->sftable[2] = sfstderr; sfnotify(sftrack); sh_iostream(shp,0); + sh_iostream(shp,1); /* all write steams are in the same pool and share outbuff */ shp->outpool = sfopen(NIL(Sfio_t*),NIL(char*),"sw"); /* pool identifier */ shp->outbuff = (char*)malloc(IOBSIZE+4); @@ -471,11 +508,7 @@ Sfio_t *sh_iostream(Shell_t *shp, regist register int status = sh_iocheckfd(shp,fd); register int flags = SF_WRITE; char *bp; - Sfdisc_t *dp; -#if SHOPT_FASTPIPE - if(fd>=shp->lim.open_max) - return(shp->sftable[fd]); -#endif /* SHOPT_FASTPIPE */ + struct Iodisc *dp; if(status==IOCLOSE) { switch(fd) @@ -505,31 +538,35 @@ Sfio_t *sh_iostream(Shell_t *shp, regist sfsetbuf(iop, bp, IOBSIZE); else if(!(iop=sfnew((fd<=2?iop:0),bp,IOBSIZE,fd,flags))) return(NIL(Sfio_t*)); - dp = newof(0,Sfdisc_t,1,0); + dp = newof(0,struct Iodisc,1,0); + dp->sh = shp; if(status&IOREAD) { sfset(iop,SF_MALLOC,1); if(!(status&IOWRITE)) sfset(iop,SF_IOCHECK,1); - dp->exceptf = slowexcept; + dp->disc.exceptf = slowexcept; if(status&IOTTY) - dp->readf = slowread; + dp->disc.readf = slowread; else if(status&IONOSEEK) { - dp->readf = piperead; + dp->disc.readf = piperead; sfset(iop, SF_IOINTR,1); } else - dp->readf = 0; - dp->seekf = 0; - dp->writef = 0; + dp->disc.readf = 0; + dp->disc.seekf = 0; + dp->disc.writef = 0; } else { - dp->exceptf = outexcept; + if((status&(IONOSEEK|IOTTY)) == IONOSEEK) + dp->disc.exceptf = pipeexcept; + else + dp->disc.exceptf = outexcept; sfpool(iop,shp->outpool,SF_WRITE); } - sfdisc(iop,dp); + sfdisc(iop,&dp->disc); shp->sftable[fd] = iop; return(iop); } @@ -552,6 +589,8 @@ static void io_preserve(Shell_t* shp, re ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT; errormsg(SH_DICT,ERROR_system(1),e_toomany); } + if(f2 >= sh.lim.open_max) + sh_iovalidfd(shp,f2); if(shp->fdptrs[fd]=shp->fdptrs[f2]) { if(f2==job.fd) @@ -610,6 +649,8 @@ int sh_iorenumber(Shell_t *shp, register shp->sftable[f1] = 0; sh_close(f1); } + if(f2>=sh.lim.open_max) + sh_iovalidfd(shp,f2); return(f2); } @@ -618,11 +659,14 @@ int sh_iorenumber(Shell_t *shp, register */ int sh_close(register int fd) { + Shell_t *shp = sh_getinterp(); register Sfio_t *sp; register int r = 0; if(fd<0) return(-1); - if(!(sp=sh.sftable[fd]) || sfclose(sp) < 0) + if(fd >= sh.lim.open_max) + sh_iovalidfd(shp,fd); + if(!(sp=shp->sftable[fd]) || sfclose(sp) < 0) { if(fdnotify) (*fdnotify)(fd,SH_FDCLOSE); @@ -912,7 +956,7 @@ static char *io_usename(char *name, int { struct stat statb; char *tname, *sp, *ep; - int fd,len,n=0; + int fd; if(mode==0) { if((fd = sh_open(name,O_RDONLY,0)) > 0) @@ -926,18 +970,25 @@ static char *io_usename(char *name, int else if(fd < 0 && errno!=ENOENT) return(0); } - tname = sp = (char*)stakalloc((len=strlen(name)) + 5); - if(ep = strrchr(name,'/')) + stakseek(1); + stakputs(name); + stakputc(0); + pathcanon(stakptr(1),PATH_PHYSICAL); + sp = ep = stakptr(1); + if(ep = strrchr(sp,'/')) { - memcpy(sp,name,n=++ep-name); - len -=n; - sp += n; + memcpy(stakptr(0),sp,++ep-sp); + stakseek(ep-sp); } else - ep = name; - *sp++ = '.'; - memcpy(sp,ep,len); - strcpy(sp+len,".tmp"); + { + ep = sp; + stakseek(0); + } + stakputc('.'); + stakputs(ep); + stakputs(".tmp"); + tname = stakfreeze(1); switch(mode) { case 1: @@ -1029,6 +1080,8 @@ int sh_redirect(Shell_t *shp,struct iono if((iof&IOLSEEK) || ((iof&IOMOV) && *fname=='-')) fn = nv_getnum(np); } + if(fn>=sh.lim.open_max && !sh_iovalidfd(shp,fn)) + errormsg(SH_DICT,ERROR_system(1),e_file+4); if(iof&IOLSEEK) { io_op[2] = '#'; @@ -1070,7 +1123,7 @@ int sh_redirect(Shell_t *shp,struct iono message = e_file; goto fail; } - if(shp->subshell && dupfd==1 && (sfset(sfstdout,0,0)&SF_STRING)) + if(shp->subshell && dupfd==1) { if(sfset(sfstdout,0,0)&SF_STRING) sh_subtmpfile(shp); @@ -1103,6 +1156,8 @@ int sh_redirect(Shell_t *shp,struct iono goto traceit; if((fd=sh_fcntl(dupfd,F_DUPFD,3))<0) goto fail; + if(fd>= sh.lim.open_max) + sh_iovalidfd(shp,fd); sh_iocheckfd(shp,dupfd); shp->fdstatus[fd] = (shp->fdstatus[dupfd]&~IOCLEX); if(toclose<0 && shp->fdstatus[fd]&IOREAD) @@ -1159,7 +1214,7 @@ int sh_redirect(Shell_t *shp,struct iono { #if SHOPT_FS_3D if(S_ISREG(sb.st_mode)&& - (!shp->lim.fs3d || iview(&sb)==0)) + (!sh.lim.fs3d || iview(&sb)==0)) #else if(S_ISREG(sb.st_mode)) #endif /* SHOPT_FS_3D */ @@ -1315,6 +1370,8 @@ int sh_redirect(Shell_t *shp,struct iono { if((fn=fcntl(fd,F_DUPFD,10)) < 0) goto fail; + if(fn>=sh.lim.open_max && !sh_iovalidfd(shp,fn)) + goto fail; shp->fdstatus[fn] = shp->fdstatus[fd]; sh_close(fd); fd = fn; @@ -1447,11 +1504,7 @@ void sh_iosave(Shell_t *shp, register in errormsg(SH_DICT,ERROR_exit(4),e_nospace); if(moved = (char*)filemap - oldptr) { -#if SHOPT_FASTPIPE - for(savefd=shp->lim.open_max+2; --savefd>=0; ) -#else - for(savefd=shp->lim.open_max; --savefd>=0; ) -#endif /* SHOPT_FASTPIPE */ + for(savefd=sh.lim.open_max; --savefd>=0; ) { cp = (char*)shp->fdptrs[savefd]; if(cp >= oldptr && cp < oldend) @@ -1612,10 +1665,16 @@ int sh_ioaccess(int fd,register int mode */ static int slowexcept(register Sfio_t *iop,int type,void *data,Sfdisc_t *handle) { + Shell_t *shp = sh_getinterp(); register int n,fno; NOT_USED(handle); if(type==SF_DPOP || type==SF_FINAL) free((void*)handle); + if(type==SF_WRITE && errno==EPIPE) + { + sfpurge(iop); + return(-1); + } if(type!=SF_READ) return(0); if((sh.trapnote&(SH_SIGSET|SH_SIGTRAP)) && errno!=EIO && errno!=ENXIO) @@ -1837,7 +1896,15 @@ int sh_iocheckfd(Shell_t *shp, register n |= IONOSEEK; #ifdef S_ISSOCK if((fstat(fd,&statb)>=0) && S_ISSOCK(statb.st_mode)) + { n |= IOREAD|IOWRITE; +# if _socketpair_shutdown_mode + if(!(statb.st_mode&S_IRUSR)) + n &= ~IOREAD; + else if(!(statb.st_mode&S_IWUSR)) + n &= ~IOWRITE; +# endif + } #endif /* S_ISSOCK */ } else if((fstat(fd,&statb)>=0) && ( @@ -1853,7 +1920,11 @@ int sh_iocheckfd(Shell_t *shp, register else n |= IOSEEK; } - sh.fdstatus[fd] = n; + if(fd==0) + n &= ~IOWRITE; + else if(fd==1) + n &= ~IOREAD; + shp->fdstatus[fd] = n; return(n); } @@ -1940,8 +2011,11 @@ static int pipeexcept(Sfio_t* iop, int m NOT_USED(iop); if(mode==SF_DPOP || mode==SF_FINAL) free((void*)handle); - else if(mode==SF_WRITE && errno==EINTR) + else if(mode==SF_WRITE && errno==EPIPE) + { + sfpurge(iop); return(-1); + } return(0); } @@ -1977,7 +2051,7 @@ static void sftrack(Sfio_t* sp, int flag return; } #endif - if((unsigned)fd >= shp->lim.open_max) + if(fd<0 || (fd>=sh.lim.open_max && !sh_iovalidfd(shp,fd))) return; if(sh_isstate(SH_NOTRACK)) return; @@ -2125,7 +2199,7 @@ static Sfio_t *subopen(Shell_t *shp,Sfio disp->oldsp = sp; disp->offset = offset; disp->size = disp->left = size; - sp = sfnew(NIL(Sfio_t*),(char*)(disp+1),IOBSIZE,shp->lim.open_max,SF_READ); + sp = sfnew(NIL(Sfio_t*),(char*)(disp+1),IOBSIZE,PSEUDOFD,SF_READ); sfdisc(sp,&disp->disc); return(sp); } @@ -2136,13 +2210,18 @@ static Sfio_t *subopen(Shell_t *shp,Sfio static ssize_t subread(Sfio_t* sp,void* buff,register size_t size,Sfdisc_t* handle) { register struct subfile *disp = (struct subfile*)handle; + ssize_t n; NOT_USED(sp); + sfseek(disp->oldsp,disp->offset,SEEK_SET); if(disp->left == 0) return(0); if(size > disp->left) size = disp->left; disp->left -= size; - return(sfread(disp->oldsp,buff,size)); + n = sfread(disp->oldsp,buff,size); + if(size>0) + disp->offset += size; + return(n); } /* @@ -2300,6 +2379,8 @@ int sh_fcntl(register int fd, int op, .. case F_DUPFD: if(sh.fdstatus[fd] == IOCLOSE) sh.fdstatus[fd] = 0; + if(newfd>=sh.lim.open_max) + sh_iovalidfd(&sh,newfd); sh.fdstatus[newfd] = (sh.fdstatus[fd]&~IOCLEX); if(fdnotify) (*fdnotify)(fd,newfd); @@ -2353,7 +2434,7 @@ Sfio_t *sh_iogetiop(int fd, int mode) fd = shp->cpipe[0]; break; default: - if(fd<0 || fd >= shp->lim.open_max) + if(fd<0 || !sh_iovalidfd(shp,fd)) fd = -1; } if(fd<0)