extern char* getpass(const char *prompt) { struct termios told,tnew; Sfio_t *iop; static char *cp, passwd[32]; void (*savesig)(int); if(!(iop = sfopen((Sfio_t*)0, "/dev/tty", "r"))) return(0); if(tcgetattr(sffileno(iop),&told) < 0) return(0); interrupt = 0; tnew = told; tnew.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL); if(tcsetattr(sffileno(iop),TCSANOW,&tnew) < 0) return(0); savesig = signal(SIGINT, handler); sfputr(sfstderr,prompt,-1); if(cp = sfgetr(iop,'\n',1)) strncpy(passwd,cp,sizeof(passwd)-1); tcsetattr(sffileno(iop),TCSANOW,&told); sfputc(sfstderr,'\n'); sfclose(iop); signal(SIGINT, savesig); if(interrupt) kill(getpid(),SIGINT); return(cp?passwd:0); }
// // Open stream <f> for fast character input. // int fcfopen(Sfio_t *f) { int n; char *buff; Fcin_t save; errno = 0; _Fcin.fcbuff = _Fcin.fcptr; _Fcin._fcfile = f; fcsave(&save); if (!(buff = (char *)sfreserve(f, SF_UNBOUND, SF_LOCKR))) { fcrestore(&save); _Fcin.fcchar = 0; _Fcin.fcptr = _Fcin.fcbuff = &_Fcin.fcchar; _Fcin.fclast = NULL; _Fcin._fcfile = NULL; return EOF; } n = sfvalue(f); fcrestore(&save); sfread(f, buff, 0); _Fcin.fcoff = sftell(f); buff = (char *)sfreserve(f, SF_UNBOUND, SF_LOCKR); _Fcin.fclast = (_Fcin.fcptr = _Fcin.fcbuff = (unsigned char *)buff) + n; if (sffileno(f) >= 0) *_Fcin.fclast = 0; return n; }
tmain() { Sfio_t *f; int fd; off_t sk; if(!(f = sfopen((Sfio_t*)0,tstfile("sf", 0),"w+"))) terror("Opening file"); fd = sffileno(f); if(sfsetfd(f,-1) != -1 || sffileno(f) != -1) terror("setfd1"); if(sfputc(f,'a') >= 0) terror("sfputc"); if(sfsetfd(f,fd) != fd) terror("setfd2"); if(sfwrite(f,"123456789\n",10) != 10) terror("sfwrite"); sfseek(f,(Sfoff_t)0,0); if(sfgetc(f) != '1') terror("sfgetc1"); if(sfsetfd(f,-1) != -1 || sffileno(f) != -1) terror("setfd2"); if((sk = lseek(fd, (off_t)0, 1)) != (off_t)1) terror("Bad seek address %lld", (Sfoff_t)sk ); if(sfgetc(f) >= 0) terror("sfgetc2"); if(sfsetfd(f,fd) != fd) terror("setfd2"); if(sfgetc(f) != '2') terror("sfgetc3"); texit(0); }
MAIN() { Sfio_t *f; int fd; off_t sk; if(!(f = sfopen((Sfio_t*)0,tstfile(0),"w+"))) terror("Opening file\n"); fd = sffileno(f); if(sfsetfd(f,-1) != -1 || sffileno(f) != -1) terror("setfd1\n"); if(sfputc(f,'a') >= 0) terror("sfputc\n"); if(sfsetfd(f,fd) != fd) terror("setfd2\n"); if(sfwrite(f,"123456789\n",10) != 10) terror("sfwrite\n"); sfseek(f,(Sfoff_t)0,0); if(sfgetc(f) != '1') terror("sfgetc1\n"); if(sfsetfd(f,-1) != -1 || sffileno(f) != -1) terror("setfd2\n"); if((sk = lseek(fd, (off_t)0, 1)) != (off_t)1) terror("Bad seek address %lld\n", (Sfoff_t)sk ); if(sfgetc(f) >= 0) terror("sfgetc2\n"); if(sfsetfd(f,fd) != fd) terror("setfd2\n"); if(sfgetc(f) != '2') terror("sfgetc3\n"); TSTEXIT(0); }
main() { Sfio_t* null; Sfio_t* f; char buf[256*1024], b[256*1024]; int k, n; if(!(null = sfopen(NIL(Sfio_t*),"/dev/null","w")) ) terror("Opening /dev/null"); sfsetbuf(null,NIL(char*),(size_t)SF_UNBOUND); if(!SFISNULL(null) ) terror("Not /dev/null?"); if(!(f = sfopen(NIL(Sfio_t*), Kpv[0], "w+")) ) terror("Creating %s", Kpv[0]); sfwrite(f,"1234",4); sfseek(f,(Sfoff_t)1,0); sfsync(f); sfsetfd(null,-1); sfsetfd(null,sffileno(f)); sfsync(null); sfseek(f,(Sfoff_t)0,0); if(sfread(f,buf,4) != 4 || strncmp(buf,"1234",4) != 0) terror("Bad data"); for(k = 0; k < sizeof(buf); ++k) buf[k] = 1; for(k = sizeof(buf)/4; k < sizeof(buf)/2; ++k) /* make a big hole */ buf[k] = 0; if(!(f = sfopen(f, Kpv[0], "w+")) ) terror("Creating %s", Kpv[0]); n = sizeof(buf)-127; if(sfwrite(f,buf,n) != n) terror("Writing large buffer"); sfseek(f,(Sfoff_t)0,0); if(sfread(f,b,n) != n) terror("Reading large buffer"); for(k = 0; k < n; ++k) if(b[k] != buf[k]) terror("Bad data"); rmkpv(); return 0; }
static int hist_exceptf(Sfio_t *fp, int type, Sfdisc_t *handle) #endif { UNUSED(data); History_t *hp = (History_t *)handle; if (type == SF_WRITE) { if (errno == ENOSPC || hp->histwfail++ >= 10) return 0; // Write failure could be NFS problem, try to re-open. int newfd = open(hp->histname, O_BINARY | O_APPEND | O_CREAT | O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR); int oldfd = sffileno(fp); sh_close(oldfd); if (newfd == -1) goto fail; if (sh_fcntl(newfd, F_DUPFD_CLOEXEC, oldfd) != oldfd) { close(newfd); goto fail; } (void)fcntl(oldfd, F_SETFD, FD_CLOEXEC); close(newfd); if (lseek(oldfd, 0, SEEK_END) < hp->histcnt) { int index = hp->histind; // The return value of this lseek() has historically been ignored. It is unclear if that // is correct. That is, is there any scenario in which this lseek() could fail but the // overall behavior of the shell still be correct if we ignore that failure? The void // cast is to silence Coverity CID #253581. (void)lseek(oldfd, 2, SEEK_SET); hp->histcnt = 2; hp->histind = 1; hp->histcmds[1] = 2; hist_eof(hp); hp->histmarker = hp->histcnt; hp->histind = index; } return 1; } return 0; fail: errormsg(SH_DICT, 2, "History file write error-%d %s: file unrecoverable", errno, hp->histname); return -1; }
static ssize_t tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle) { register const char* bp; register const char* ep; register int* hp = ((Tee_t*)handle)->fd; register int fd = sffileno(fp); register ssize_t r; do { bp = (const char*)buf; ep = bp + n; while (bp < ep) { if ((r = write(fd, bp, ep - bp)) <= 0) return -1; bp += r; } } while ((fd = *hp++) >= 0); return n; }
static History_t* hist_trim(History_t *hp, int n) { register char *cp; register int incmd=1, c=0; register History_t *hist_new, *hist_old = hp; char *buff, *endbuff, *tmpname=0; off_t oldp,newp; struct stat statb; unlink(hist_old->histname); if(access(hist_old->histname,F_OK) >= 0) { /* The unlink can fail on windows 95 */ int fd; char *last, *name=hist_old->histname; close(sffileno(hist_old->histfp)); tmpname = (char*)malloc(strlen(name)+14); if(last = strrchr(name,'/')) { *last = 0; pathtmp(tmpname,name,"hist",NIL(int*)); *last = '/'; }
static pid_t _spawnveg(Shell_t *shp,const char *path, char* const argv[], char* const envp[], pid_t pgid) { pid_t pid; #ifdef SIGTSTP if(job.jobcontrol) { signal(SIGTTIN,SIG_DFL); signal(SIGTTOU,SIG_DFL); } #endif /* SIGTSTP */ while(1) { sh_stats(STAT_SPAWN); #ifdef SPAWN_cwd { char *arg0 = argv[0], **av0= (char**)&argv[0]; int fd; pid = spawnvex(path,argv,envp,shp->vex); *av0 = arg0; if(pid>0 && shp->comsub && (fd=sffileno(sfstdout))!=1 && fd>=0) spawnvex_add(shp->vex, fd, 1,0,0); } #else pid = spawnveg(path,argv,envp,pgid); #endif /* SPAWN_cwd */ if(pid>=0 || errno!=EAGAIN) break; } #ifdef SIGTSTP if(job.jobcontrol) { signal(SIGTTIN,SIG_IGN); signal(SIGTTOU,SIG_IGN); } #endif /* SIGTSTP */ return(pid); }
void ed_setup(register Edit_t *ep, int fd, int reedit) { Shell_t *shp = ep->sh; register char *pp; register char *last, *prev; char *ppmax; int myquote = 0, n; register int qlen = 1, qwid; char inquote = 0; ep->e_fd = fd; ep->e_multiline = sh_isoption(SH_MULTILINE)!=0; #ifdef SIGWINCH if(!(shp->sigflag[SIGWINCH]&SH_SIGFAULT)) { signal(SIGWINCH,sh_fault); shp->sigflag[SIGWINCH] |= SH_SIGFAULT; } pp = shp->st.trapcom[SIGWINCH]; shp->st.trapcom[SIGWINCH] = 0; sh_fault(SIGWINCH); shp->st.trapcom[SIGWINCH] = pp; ep->sh->winch = 0; #endif #if SHOPT_EDPREDICT ep->hlist = 0; ep->nhlist = 0; ep->hoff = 0; #endif /* SHOPT_EDPREDICT */ #if KSHELL ep->e_stkptr = stakptr(0); ep->e_stkoff = staktell(); if(!(last = shp->prompt)) last = ""; shp->prompt = 0; #else last = ep->e_prbuff; #endif /* KSHELL */ if(shp->gd->hist_ptr) { register History_t *hp = shp->gd->hist_ptr; ep->e_hismax = hist_max(hp); ep->e_hismin = hist_min(hp); } else { ep->e_hismax = ep->e_hismin = ep->e_hloff = 0; } ep->e_hline = ep->e_hismax; if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS)) ep->e_wsize = MAXLINE; else ep->e_wsize = ed_window()-2; ep->e_winsz = ep->e_wsize+2; ep->e_crlf = 1; ep->e_plen = 0; pp = ep->e_prompt; ppmax = pp+PRSIZE-1; *pp++ = '\r'; { register int c; while(prev = last, c = mbchar(last)) switch(c) { case ESC: { int skip=0; ep->e_crlf = 0; *pp++ = c; for(n=1; c = *last++; n++) { if(pp < ppmax) *pp++ = c; if(c=='\a' || c==ESC || c=='\r') break; if(skip || (c>='0' && c<='9')) { skip = 0; continue; } if(n>1 && c==';') skip = 1; else if(n>2 || (c!= '[' && c!= ']')) break; } if(c==0 || c==ESC || c=='\r') last--; qlen += (n+1); break; } case '\b': if(pp>ep->e_prompt+1) pp--; break; case '\r': if(pp == (ep->e_prompt+2)) /* quote char */ myquote = *(pp-1); /*FALLTHROUGH*/ case '\n': /* start again */ ep->e_crlf = 1; qlen = 1; inquote = 0; pp = ep->e_prompt+1; break; case '\t': /* expand tabs */ while((pp-ep->e_prompt)%TABSIZE) { if(pp >= ppmax) break; *pp++ = ' '; } break; case '\a': /* cut out bells */ break; default: if(c==myquote) { qlen += inquote; inquote ^= 1; } if(pp < ppmax) { if(inquote) qlen++; else if(!is_print(c)) ep->e_crlf = 0; if((qwid = last - prev) > 1) qlen += qwid - mbwidth(c); while(prev < last && pp < ppmax) *pp++ = *prev++; } break; } } if(pp-ep->e_prompt > qlen) ep->e_plen = pp - ep->e_prompt - qlen; *pp = 0; if(!ep->e_multiline && (ep->e_wsize -= ep->e_plen) < 7) { register int shift = 7-ep->e_wsize; ep->e_wsize = 7; pp = ep->e_prompt+1; strcpy(pp,pp+shift); ep->e_plen -= shift; last[-ep->e_plen-2] = '\r'; } sfsync(sfstderr); if(fd == sffileno(sfstderr)) { /* can't use output buffer when reading from stderr */ static char *buff; if(!buff) buff = (char*)malloc(MAXLINE); ep->e_outbase = ep->e_outptr = buff; ep->e_outlast = ep->e_outptr + MAXLINE; return; } qlen = sfset(sfstderr,SF_READ,0); /* make sure SF_READ not on */ ep->e_outbase = ep->e_outptr = (char*)sfreserve(sfstderr,SF_UNBOUND,SF_LOCKR); ep->e_outlast = ep->e_outptr + sfvalue(sfstderr); if(qlen) sfset(sfstderr,SF_READ,1); sfwrite(sfstderr,ep->e_outptr,0); ep->e_eol = reedit; if(ep->e_multiline) { #ifdef _cmd_tput char *term; if(!ep->e_term) ep->e_term = nv_search("TERM",shp->var_tree,0); if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname)) { sh_trap(".sh.subscript=$(tput cuu1 2>/dev/null)",0); if(pp=nv_getval(SH_SUBSCRNOD)) strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1); nv_unset(SH_SUBSCRNOD); strcpy(ep->e_termname,term); } #endif ep->e_wsize = MAXLINE - (ep->e_plen+1); } if(ep->e_default && (pp = nv_getval(ep->e_default))) { n = strlen(pp); if(n > LOOKAHEAD) n = LOOKAHEAD; ep->e_lookahead = n; while(n-- > 0) ep->e_lbuf[n] = *pp++; ep->e_default = 0; } }
main(int argc, char *argv[]) { register int n; register char *cp; Sfio_t *in, *out; error_info.id = argv[0]; NoP(id[0]); #if _AST_VERSION >= 20060701L cmdinit(argc, argv,0, NULL, 0); #else cmdinit(argv,0, NULL, 0); #endif while (n = optget(argv, " [file ...]")) switch (n) { case ':': error(2, opt_info.arg); break; case '?': error(ERROR_usage(2), opt_info.arg); break; } argv += opt_info.index; if(error_info.errors) error(ERROR_usage(2),optusage((char*)0)); if(cp = *argv) argv++; do { if(!cp || strcmp(cp,"-")==0) { in = sfstdin; out = sfstdout; } else { if(!(in = sfopen((Sfio_t*)0,cp,"rb"))) { error(ERROR_system(0),"%s: cannot open for input",cp); error_info.errors = 1; continue; } if(!(out = sfopen((Sfio_t*)0,cp,"r+b"))) { error(ERROR_system(0),"%s: cannot open for writing",cp); error_info.errors = 1; continue; } } nocrnl(in,out); if(in!=sfstdin) sfclose(in); if(out!=sfstdout) { sfsync(out); ftruncate(sffileno(out),sftell(out)); sfclose(out); } } while(cp= *argv++); return(error_info.errors); }
int astquery(int quit, const char* format, ...) { va_list ap; register int n; register int c; Sfio_t* ip; Sfio_t* op; static Sfio_t* rfp; static Sfio_t* wfp; va_start(ap, format); if (!format) return 0; if (!rfp) { c = errno; if (isatty(sffileno(sfstdin))) rfp = sfstdin; else if (!(rfp = sfopen(NiL, "/dev/tty", "r"))) return -1; if (isatty(sffileno(sfstderr))) wfp = sfstderr; else if (!(wfp = sfopen(NiL, "/dev/tty", "w"))) return -1; errno = c; } if (quit & ERROR_PROMPT) { quit &= ~ERROR_PROMPT; ip = rfp; op = wfp; } else { ip = sfstdin; op = sfstderr; } sfsync(sfstdout); sfvprintf(op, format, ap); sfsync(op); for (n = c = sfgetc(ip);; c = sfgetc(ip)) switch (c) { case EOF: n = c; /*FALLTHROUGH*/ case '\n': switch (n) { case EOF: case 'q': case 'Q': if (quit >= 0) exit(quit); return -1; case '1': case 'y': case 'Y': case '+': return 0; } return 1; } va_end(ap); /*NOTREACHED*/ }
/* * This routine will turn the sftmp() file into a real /tmp file or pipe */ void sh_subtmpfile(int pflag) { Shell_t *shp = &sh; int fds[2]; Sfoff_t off; register struct checkpt *pp = (struct checkpt*)shp->jmplist; register struct subshell *sp = subshell_data->pipe; if(sfset(sfstdout,0,0)&SF_STRING) { register int fd; /* save file descriptor 1 if open */ if((sp->tmpfd = fd = fcntl(1,F_DUPFD,10)) >= 0) { fcntl(fd,F_SETFD,FD_CLOEXEC); shp->fdstatus[fd] = shp->fdstatus[1]|IOCLEX; close(1); shp->fdstatus[1] = IOCLOSE; } else if(errno!=EBADF) { ((struct checkpt*)shp->jmplist)->mode = SH_JMPERREXIT; shp->toomany = 1; errormsg(SH_DICT,ERROR_system(1),e_toomany); } if(shp->subshare || !pflag) { sfdisc(sfstdout,SF_POPDISC); if((fd=sffileno(sfstdout))>=0) { shp->fdstatus[fd] = IOREAD|IOWRITE; sfsync(sfstdout); if(fd==1) fcntl(1,F_SETFD,0); else { sfsetfd(sfstdout,1); shp->fdstatus[1] = shp->fdstatus[fd]; shp->fdstatus[fd] = IOCLOSE; } goto skip; } } } if(sp && (shp->fdstatus[1]==IOCLOSE || (!shp->subshare && !(shp->fdstatus[1]&IONOSEEK)))) { struct stat statb,statx; int fd; sh_pipe(fds); sp->pipefd = fds[0]; sh_fcntl(sp->pipefd,F_SETFD,FD_CLOEXEC); /* write the data to the pipe */ if(off = sftell(sfstdout)) { write(fds[1],sfsetbuf(sfstdout,(Void_t*)sfstdout,0),(size_t)off); sfpurge(sfstdout); } if((sfset(sfstdout,0,0)&SF_STRING) || fstat(1,&statb)<0) statb.st_ino = 0; sfclose(sfstdout); if((sh_fcntl(fds[1],F_DUPFD, 1)) != 1) errormsg(SH_DICT,ERROR_system(1),e_redirect); sh_close(fds[1]); if(statb.st_ino) for(fd=0; fd < 10; fd++) { if(fd==1 || ((shp->fdstatus[fd]&(IONOSEEK|IOSEEK|IOWRITE))!=(IOSEEK|IOWRITE)) || fstat(fd,&statx)<0) continue; if(statb.st_ino==statx.st_ino && statb.st_dev==statx.st_dev) { sh_close(fd); fcntl(1,F_DUPFD, fd); } } skip: sh_iostream(shp,1); sfset(sfstdout,SF_SHARE|SF_PUBLIC,1); sfpool(sfstdout,shp->outpool,SF_WRITE); if(pp && pp->olist && pp->olist->strm == sfstdout) pp->olist->strm = 0; } }
int main(int argc, char *argv[]) { Sfio_t *in, *out; Shell_t *shp; Namval_t *np; Shnode_t *t; char *cp; int n, nflag=0, vflag=0, dflag=0; error_info.id = argv[0]; while(n = optget(argv, usage )) switch(n) { case 'D': dflag=1; break; case 'v': vflag=1; break; case 'n': nflag=1; break; case ':': errormsg(SH_DICT,2,"%s",opt_info.arg); break; case '?': errormsg(SH_DICT,ERROR_usage(2),"%s",opt_info.arg); break; } shp = sh_init(argc,argv,(Shinit_f)0); shp->shcomp = 1; argv += opt_info.index; argc -= opt_info.index; if(error_info.errors || argc>2) errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); if(cp= *argv) { argv++; in = sh_pathopen(cp); } else in = sfstdin; if(cp= *argv) { struct stat statb; if(!(out = sfopen((Sfio_t*)0,cp,"w"))) errormsg(SH_DICT,ERROR_system(1),"%s: cannot create",cp); if(fstat(sffileno(out),&statb) >=0) chmod(cp,(statb.st_mode&~S_IFMT)|S_IXUSR|S_IXGRP|S_IXOTH); } else out = sfstdout; if(dflag) { sh_onoption(SH_DICTIONARY); sh_onoption(SH_NOEXEC); } if(nflag) sh_onoption(SH_NOEXEC); if(vflag) sh_onoption(SH_VERBOSE); if(!dflag) sfwrite(out,header,sizeof(header)); shp->inlineno = 1; #if SHOPT_BRACEPAT sh_onoption(SH_BRACEEXPAND); #endif while(1) { stakset((char*)0,0); if(t = (Shnode_t*)sh_parse(shp,in,0)) { if((t->tre.tretyp&(COMMSK|COMSCAN))==0 && t->com.comnamp && strcmp(nv_name((Namval_t*)t->com.comnamp),"alias")==0) sh_exec(t,0); if(!dflag && sh_tdump(out,t) < 0) errormsg(SH_DICT,ERROR_exit(1),"dump failed"); } else if(sfeof(in)) break; if(sferror(in)) errormsg(SH_DICT,ERROR_system(1),"I/O error"); if(t && ((t->tre.tretyp&COMMSK)==TCOM) && (np=t->com.comnamp) && (cp=nv_name(np))) { if(strcmp(cp,"exit")==0) break; /* check for exec of a command */ if(strcmp(cp,"exec")==0) { if(t->com.comtyp&COMSCAN) { if(t->com.comarg->argnxt.ap) break; } else { struct dolnod *ap = (struct dolnod*)t->com.comarg; if(ap->dolnum>1) break; } } } } /* copy any remaining input */ sfmove(in,out,SF_UNBOUND,-1); if(in!=sfstdin) sfclose(in); if(out!=sfstdout) sfclose(out); return(0); }
static int hist_write(Sfio_t *iop, const void *buff, int insize, Sfdisc_t *handle) #endif { History_t *hp = (History_t *)handle; char *bufptr = ((char *)buff) + insize; int c, size = insize; off_t cur; Shell_t *shp = hp->histshell; int saved = 0; char saveptr[HIST_MARKSZ]; if (!hp->histflush) return write(sffileno(iop), (char *)buff, size); if ((cur = lseek(sffileno(iop), (off_t)0, SEEK_END)) < 0) { errormsg(SH_DICT, 2, "hist_flush: EOF seek failed errno=%d", errno); return -1; } hp->histcnt = cur; // Remove whitespace from end of commands. while (--bufptr >= (char *)buff) { c = *bufptr; if (!isspace(c)) { if (c == '\\' && *(bufptr + 1) != '\n') bufptr++; break; } } // Don't count empty lines. if (++bufptr <= (char *)buff) return insize; *bufptr++ = '\n'; *bufptr++ = 0; size = bufptr - (char *)buff; if (hp->auditfp) { time_t t = time(NULL); sfprintf(hp->auditfp, "%u;%u;%s;%*s%c", sh_isoption(shp, SH_PRIVILEGED) ? shgd->euserid : shgd->userid, t, hp->tty, size, buff, 0); sfsync(hp->auditfp); } if (size & 01) { size++; *bufptr++ = 0; } hp->histcnt += size; c = hist_ind(hp, ++hp->histind); hp->histcmds[c] = hp->histcnt; if (hp->histflush > HIST_MARKSZ && hp->histcnt > hp->histmarker + HIST_BSIZE / 2) { memcpy(saveptr, bufptr, HIST_MARKSZ); saved = 1; hp->histcnt += HIST_MARKSZ; hist_marker(bufptr, hp->histind); hp->histmarker = hp->histcmds[hist_ind(hp, c)] = hp->histcnt; size += HIST_MARKSZ; } errno = 0; size = write(sffileno(iop), (char *)buff, size); if (saved) memcpy(bufptr, saveptr, HIST_MARKSZ); if (size >= 0) { hp->histwfail = 0; return insize; } return -1; }
tmain() { UNUSED(argc); UNUSED(argv); Sfio_t *f1, *f2, *f3, *f; char *s, *s1, *s2, *s3, *s4; int n; int fd[2]; if (!(f1 = sfopen(NULL, tstfile("sf", 0), "w+"))) terror("Opening file1"); if (!(f2 = sfopen(NULL, tstfile("sf", 0), "w+"))) terror("Opening file2"); Fclose = f2; sfdisc(f1, &Disc); sfdisc(f2, &Disc); sfstack(f1, f2); if ((n = sfgetc(f1)) >= 0 || !sfeof(f1)) terror("There should be no data n=%d", n); if (sfstacked(f1)) terror("There should be no stack"); Fclose = f1; if (sfclose(f1) < 0) terror("Can't close f1"); tcleanup(); s1 = "1234567890"; s2 = "abcdefghijklmnopqrstuvwxyz"; s3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; s4 = "!@#$%^&*()_-+={}[]~`':;?/><,|"; if (!(f1 = sfopen(NULL, s1, "s")) || !(f2 = sfopen(NULL, s2, "s")) || !(f3 = sfopen(NULL, s3, "s"))) { terror("Opening strings"); } sfdisc(sfstdin, &Disc); sfclose(sfstdin); if (sffileno(sfstdin) != 0) terror("Bad fd for stdin"); if (!(f = sfopen(NULL, tstfile("sf", 0), "w+"))) terror("Opening file"); if (sfwrite(f, "0123456789", 10) != 10) terror("Write file"); if (sfseek(f, (Sfoff_t)0, 0) != 0) terror("Seek file"); if (sfstack(sfstdin, f) != sfstdin) terror("Stacking on stdin2"); if (sfopen(sfstdout, "/dev/null", "w") != sfstdout) terror("Opening sfstdout"); if (sfmove(sfstdin, sfstdout, (Sfoff_t)SF_UNBOUND, -1) != 10 || !sfeof(sfstdin) || sferror(sfstdout)) { terror("Bad sfmove"); } tcleanup(); if (!(f = sftmp(0))) terror("Opening temp file"); if (sfputr(f, s4, -1) != (ssize_t)strlen(s4)) terror("Writing s4"); sfseek(f, (Sfoff_t)0, 0); #if FIX_THIS_TEST_2008_08_11 if (sfstack(f, f3) != f) terror("Stacking s3"); if (sfstack(f, f2) != f) terror("Stacking s2"); if (sfstack(f, f1) != f) terror("Stacking s1"); sfsprintf(str, sizeof(str), "%s%s%s%s", s1, s2, s3, s4); if ((ss = sfgetr(f, '\n', 1))) terror("There shouldn't have been any new-line"); else { if (!(ss = sfgetr(f, '\n', -1))) terror("Reading streams"); n = sfvalue(f); if (ss[n]) ss[n] = 0; } if (strcmp(ss, str) != 0) terror("Expect=%s Got=%s", str, ss); #endif if (!(f1 = sfopen(NULL, s1, "s")) || !(f2 = sfopen(NULL, s2, "s")) || !(f3 = sfopen(NULL, s3, "s"))) { terror("Opening strings2"); } sfseek(f, (Sfoff_t)0, 0); if (sfstack(f, f3) != f || sfstack(f, f2) != f || sfstack(f, f1) != f) { terror("Stacking streams2"); } if (!(s = sfreserve(f, SF_UNBOUND, 0)) || s != s1) terror("Sfpeek1"); if (!(s = sfreserve(f, SF_UNBOUND, 0)) || s != s2) terror("Sfpeek2"); if (!(s = sfreserve(f, SF_UNBOUND, 0)) || s != s3) terror("Sfpeek3"); if (!(s = sfreserve(f, SF_UNBOUND, 0)) || strncmp(s, s4, strlen(s4)) != 0) terror("Sfpeek4"); /* test to see if hidden read data still accessible */ if (pipe(fd) < 0) terror("Can't create pipe"); if (!(f1 = sfnew(0, NULL, (size_t)SF_UNBOUND, fd[0], SF_READ | SF_WRITE))) { terror("Can't create stream"); } if (write(fd[1], "0123", 4) != 4) terror("Can't write to pipe"); if (sfgetc(f1) != '0') terror("sfgetc failed"); /* hack to create hidden reserved buffer */ f1->file = fd[1]; if (sfwrite(f1, "4", 1) != 1) terror("Can't write to stream"); sfsync(f1); f1->file = fd[0]; close(fd[1]); /* now stack stream */ if (!(f2 = sfopen(0, "abcd\n", "s"))) terror("Can't open string stream"); sfstack(f2, f1); if (!(s = sfgetr(f2, '\n', 1))) terror("sfgetr failed"); if (strcmp(s, "1234abcd") != 0) terror("sfgetr got wrong data"); texit(0); }
Dssfile_t* dssfopen(Dss_t* dss, const char* path, Sfio_t* io, Dssflags_t flags, Dssformat_t* format) { Dssfile_t* file; Vmalloc_t* vm; char* s; size_t n; int i; struct stat st; Sfdisc_t top; char buf[PATH_MAX]; if (flags & DSS_FILE_WRITE) { if (io) { memset(&top, 0, sizeof(top)); if (sfdisc(io, &top)) { n = top.disc == &dss->state->compress_preferred; sfdisc(io, SF_POPDISC); if (n) { sfdisc(io, SF_POPDISC); sfdczip(io, path, dss->meth->compress ? dss->meth->compress : "gzip", dss->disc->errorf); } } } if (dss->flags & DSS_APPEND) flags |= DSS_FILE_APPEND; } if (!path || !*path || streq(path, "-")) { if (flags & DSS_FILE_WRITE) { if (io) path = "output-stream"; else { path = "/dev/stdout"; io = sfstdout; } } else if (io) path = "input-stream"; else { path = "/dev/stdin"; io = sfstdin; } flags |= DSS_FILE_KEEP; } else if (io) flags |= DSS_FILE_KEEP; else if (flags & DSS_FILE_WRITE) { if (!(io = sfopen(NiL, path, (flags & DSS_FILE_APPEND) ? "a" : "w"))) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: cannot open", path); return 0; } } else if (!(io = dssfind(path, "", DSS_VERBOSE, buf, sizeof(buf), dss->disc))) return 0; else path = (const char*)buf; if (!(vm = vmopen(Vmdcheap, Vmbest, 0))) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "out of space"); return 0; } if (!(file = vmnewof(vm, 0, Dssfile_t, 1, strlen(path) + 1))) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "out of space"); if (!(flags & DSS_FILE_KEEP)) sfclose(io); vmclose(vm); return 0; } strcpy(file->path = (char*)(file + 1), path); file->dss = dss; file->vm = vm; file->io = io; file->flags = flags; if (flags & DSS_FILE_WRITE) { if (!(file->format = format) && !(file->format = dss->format)) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, 2, "output method format must be specified"); if (!(flags & DSS_FILE_KEEP)) sfclose(io); return 0; } file->readf = noreadf; file->writef = file->format->writef; } else { if (sfsize(file->io) || !fstat(sffileno(file->io), &st) && (S_ISFIFO(st.st_mode) #ifdef S_ISSOCK || S_ISSOCK(st.st_mode) #endif )) { if (sfdczip(file->io, file->path, NiL, dss->disc->errorf) < 0) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: inflate error", file->path); dssfclose(file); return 0; } s = sfreserve(file->io, SF_UNBOUND, SF_LOCKR); n = sfvalue(file->io); if (!s) { if (n && dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: cannot peek", file->path); dssfclose(file); return 0; } for (file->format = (Dssformat_t*)dtfirst(dss->meth->formats); file->format && !(i = (*file->format->identf)(file, s, n, dss->disc)); file->format = (Dssformat_t*)dtnext(dss->meth->formats, file->format)); sfread(file->io, s, 0); if (!file->format) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, 2, "%s: unknown %s format", file->path, dss->meth->name); dssfclose(file); return 0; } if (i < 0) return 0; if (format && format != file->format) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, 2, "%s: %s file format %s incompatible with %s", file->path, dss->meth->name, file->format->name, format->name); dssfclose(file); return 0; } if ((dss->flags & DSS_VERBOSE) && dss->disc->errorf) (*dss->disc->errorf)(dss, dss->disc, 1, "%s: %s method %s format", file->path, dss->meth->name, file->format->name); file->readf = file->format->readf; } else { file->format = format ? format : dss->format ? dss->format : (Dssformat_t*)dtfirst(dss->meth->formats); file->readf = nullreadf; } file->writef = nowritef; if (!dss->format) dss->format = file->format; } if (!file->format) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, 2, "%s: %s method did not set file format", file->path, dss->meth->name); dssfclose(file); return 0; } file->record.file = file; if ((*file->format->openf)(file, dss->disc)) { dssfclose(file); return 0; } return file; }
int main(int argc, register char *argv[]) { static char command[] = "pack"; register Huff_t *hp; register char *infile,*outfile; Sfio_t *fpin,*fpout; int nfile=0, npack=0, force=0, verbose=0; int out, deleted, dsize, n; struct stat statb; NOT_USED(argc); error_info.id = command; while(n = optget(argv,usage)) switch(n) { case 'f': force++; break; case 'v': verbose = !verbose; break; case ':': error(2, opt_info.arg); break; case '?': error(ERROR_usage(2), "%s", opt_info.arg); break; } argv += opt_info.index; if(error_info.errors || !*argv) error(ERROR_usage(2), "%s", optusage((char*)0)); while (infile = *argv++) { if(*infile == '-') { /* awful way to handle options, but preserves SVID */ switch(infile[1]) { case 'f': force++; continue; case 0: verbose = !verbose; continue; } } nfile++; fpin = fpout = (Sfio_t*)0; hp = (Huff_t*)0; deleted = 0; if(!(outfile = outname(infile))) continue; if (!(fpin=sfopen((Sfio_t*)0,infile,"r"))) error(ERROR_system(0), "%s: cannot open", infile); else if(fstat(sffileno(fpin),&statb) < 0) error(ERROR_system(0), "%s: cannot stat", infile); else if(S_ISDIR(statb.st_mode)) error(2, "%s: cannot pack a directory", infile); else if(statb.st_nlink > 1) error(2, "%s: has links", infile); else if(statb.st_size ==0) error(2, "%s: cannot pack a zero length file", infile); else if(access(outfile,F_OK) ==0) error(ERROR_system(0), "%s: already exists", outfile); else if(((out=open(outfile,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,PERM(statb.st_mode))) < 0) || !(fpout = sfnew((Sfio_t*)0,(char*)0,SF_UNBOUND,out,SF_WRITE))) error(ERROR_system(0), "%s: cannot create", outfile); else if((deleted++,chmod(outfile,statb.st_mode)) < 0) error(ERROR_system(0), "%s: cannot change mode to %o",outfile,statb.st_mode); else { chown(outfile,statb.st_uid,statb.st_gid); if(!(hp = huffinit(fpin,(Sfoff_t)-1))) error(2, "%s: read error", infile); else if(sfseek(fpin,(Sfoff_t)0,0) < 0) error(ERROR_system(0),"%s: seek error", infile); else if((dsize = huffputhdr(hp,fpout)) < 0) error(2, "%s: write error", infile); else if(!force && block(huffisize(hp)) <= block(huffosize(hp)+dsize)) error(2, "%s:no savings - file unchanged", infile); else if(huffencode(hp,fpin,fpout,SF_UNBOUND)<0) error(2, "%s: read error", infile); else { double diff; if(remove(infile) < 0) error(ERROR_system(0), "%s: cannot remove", infile); diff = huffisize(hp) - (dsize+huffosize(hp)); sfprintf(sfstdout,"%s: %s : %.1f%% Compression\n",command, infile,(100*diff)/((double)huffisize(hp))); if(verbose) vprint(hp,dsize); npack++; deleted = 0; } } if(hp) huffend(hp); if(fpin) sfclose(fpin); if(fpout) sfclose(fpout); if(deleted) remove(outfile); if(outfile) free(outfile); } nfile -= npack; if(nfile > 125) nfile = 125; exit(nfile); }
int b_print(int argc, char *argv[], Shbltin_t *context) { register Sfio_t *outfile; register int exitval=0,n, fd = 1; register Shell_t *shp = context->shp; const char *options, *msg = e_file+4; char *format = 0, *fmttype=0; int sflag = 0, nflag=0, rflag=0, vflag=0; Namval_t *vname=0; Optdisc_t disc; disc.version = OPT_VERSION; disc.infof = infof; opt_info.disc = &disc; if(argc>0) { options = sh_optprint; nflag = rflag = 0; format = 0; } else { struct print *pp = (struct print*)context; shp = pp->sh; options = pp->options; if(argc==0) { nflag = pp->echon; rflag = pp->raw; argv++; goto skip; } } while((n = optget(argv,options))) switch(n) { case 'n': nflag++; break; case 'p': fd = shp->coutpipe; msg = e_query; break; case 'f': format = opt_info.arg; break; case 's': /* print to history file */ if(!sh_histinit((void*)shp)) errormsg(SH_DICT,ERROR_system(1),e_history); fd = sffileno(shp->gd->hist_ptr->histfp); sh_onstate(shp,SH_HISTORY); sflag++; break; case 'e': rflag = 0; break; case 'r': rflag = 1; break; case 'u': if(opt_info.arg[0]=='p' && opt_info.arg[1]==0) { fd = shp->coutpipe; msg = e_query; break; } fd = (int)strtol(opt_info.arg,&opt_info.arg,10); if(*opt_info.arg) fd = -1; else if(!sh_iovalidfd(shp,fd)) fd = -1; else if(!(shp->inuse_bits&(1<<fd)) && (sh_inuse(shp,fd) || (shp->gd->hist_ptr && fd==sffileno(shp->gd->hist_ptr->histfp)))) fd = -1; break; case 'j': fmttype = "json"; case 'v': if(argc < 0) { if(!(vname = nv_open(opt_info.arg, shp->var_tree,NV_VARNAME|NV_NOARRAY))) errormsg(SH_DICT,2, "Cannot create variable %s", opt_info.arg); } else vflag='v'; break; case 'C': vflag='C'; break; case ':': /* The following is for backward compatibility */ #if OPT_VERSION >= 19990123 if(strcmp(opt_info.name,"-R")==0) #else if(strcmp(opt_info.option,"-R")==0) #endif { rflag = 1; if(error_info.errors==0) { argv += opt_info.index+1; /* special case test for -Rn */ if(strchr(argv[-1],'n')) nflag++; if(*argv && strcmp(*argv,"-n")==0) { nflag++; argv++; } goto skip2; } } else errormsg(SH_DICT,2, "%s", opt_info.arg); break; case '?': errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); break; } argv += opt_info.index; if(error_info.errors || (argc<0 && !(format = *argv++))) errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); if(vflag && format) errormsg(SH_DICT,ERROR_usage(2),"-%c and -f are mutually exclusive",vflag); skip: if(format) format = genformat(shp,format); /* handle special case of '-' operand for print */ if(argc>0 && *argv && strcmp(*argv,"-")==0 && strcmp(argv[-1],"--")) argv++; if(vname) { if(!shp->strbuf2) shp->strbuf2 = sfstropen(); outfile = shp->strbuf2; goto printv; } skip2: if(fd < 0) { errno = EBADF; n = 0; } else if(!(n=shp->fdstatus[fd])) n = sh_iocheckfd(shp,fd,fd); if(!(n&IOWRITE)) { /* don't print error message for stdout for compatibility */ if(fd==1) return(1); errormsg(SH_DICT,ERROR_system(1),msg); } if(!(outfile=shp->sftable[fd])) { sh_onstate(shp,SH_NOTRACK); n = SF_WRITE|((n&IOREAD)?SF_READ:0); shp->sftable[fd] = outfile = sfnew(NIL(Sfio_t*),shp->outbuff,IOBSIZE,fd,n); sh_offstate(shp,SH_NOTRACK); sfpool(outfile,shp->outpool,SF_WRITE); }
tmain() { UNUSED(argc); UNUSED(argv); Sfio_t *f, *f2; char buf[1024]; char rbuf[4 * 1024]; off_t o; int i; if (!(f = sfopen(NULL, tstfile("sf", 0), "w"))) terror("Can't open file"); sfset(f, SF_IOCHECK, 1); Disc.exceptf = except; if (!sfdisc(f, &Disc)) terror("Pushing discipline failed"); sfdisc(f, &Disc); if (Type != SF_DPUSH) terror("Did not get push event"); /* this is to test sfraise(NULL,...) */ if (!(f2 = sfopen(NULL, tstfile("sf", 0), "w"))) terror("Can't open file"); sfdisc(f2, &Disc); Sfn = 0; if (sfraise(0, SF_WRITE, 0) < 0) terror("sfraise failed"); if (Sfn != 2) terror("Didn't get right event count"); sfdisc(f, NULL); if (Type != SF_DPOP) terror("Did not get pop event"); sfwrite(f, "123", 3); sfsync(f); if (Type != SF_SYNC) terror("Did not get sync event"); sfwrite(f, "123", 3); sfpurge(f); if (Type != SF_PURGE) terror("Did not get purge event"); sfclose(f); if (Type != SF_CLOSING) terror("Did not get close event"); sfclose(f); if (Type != SF_FINAL) terror("Did not get final event"); if (!(f = sfopen(NULL, tstfile("sf", 0), "r"))) terror("Can't open file"); Disc2.readf = readfunc; Disc2.exceptf = except3; sfdisc(f, &Disc2); if (sfgetc(f) >= 0) terror("There should be no data here"); if (Type != SF_LOCKED) terror("Did not get lock event"); /* test to see if sfclose() preserves seek location */ if (!(f = sftmp(0))) terror("Can't create temp file"); sfsetbuf(f, buf, sizeof(buf)); for (i = 0; i < sizeof(rbuf); ++i) rbuf[i] = i; sfwrite(f, rbuf, sizeof(rbuf)); sfset(f, SF_WRITE, 0); Disc.exceptf = except2; sfdisc(f, &Disc); sfseek(f, (Sfoff_t)0, 0); if (sfread(f, rbuf, 4) != 4) terror("reading 4 bytes"); for (i = 0; i < 4; ++i) { if (rbuf[i] != i) terror("wrong 4 bytes"); } sfsync(f); if ((o = lseek(sffileno(f), (off_t)0, SEEK_CUR)) != 4) { terror("Wrong seek location %lld", (Sfoff_t)o); } if ((i = dup(sffileno(f))) < 0) terror("Can't dup file descriptor"); if ((o = lseek(i, (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld", (Sfoff_t)o); sfclose(f); if ((o = lseek(i, (off_t)0, SEEK_CUR)) != 4) terror("Wrong seek location %lld", (Sfoff_t)o); texit(0); }
int sfdcpzip(Sfio_t* sp, const char* path, unsigned long flags, Pzdisc_t* disc) { Sfio_t* io; Sfpzip_t* pz; Pz_t* oz; if (flags & PZ_HANDLE) { oz = (Pz_t*)sp; sp = oz->io; } else oz = 0; if (sfset(sp, 0, 0) & SF_WRITE) { if (flags & PZ_STAT) return -1; } else if (!(flags & PZ_FORCE)) { unsigned char* s; int r; int m1; int m2; if (!(r = sfset(sp, 0, 0) & SF_SHARE)) sfset(sp, SF_SHARE, 1); s = (unsigned char*)sfreserve(sp, PZ_GZ_MAGOFF + 2, 1); if (!r) sfset(sp, SF_SHARE, 0); if (!s) return -1; m1 = s[0]; m2 = s[1]; r = m1 == PZ_MAGIC_1 && m2 == PZ_MAGIC_2 && s[2] > 0 && s[3] < 10 || m1 == GZ_MAGIC_1 && m2 == GZ_MAGIC_2 && s[PZ_GZ_MAGOFF] == PZ_GZ_MAGIC_1 && s[PZ_GZ_MAGOFF+1] == PZ_GZ_MAGIC_2; sfread(sp, s, 0); if (flags & PZ_STAT) return r; if (!r) { if (!(flags & PZ_NOGZIP)) { if (m1 == GZ_MAGIC_1) { if (m2 == GZ_MAGIC_2) r = sfdcgzip(sp, (flags & PZ_CRC) ? 0 : SFGZ_NOCRC); else if (m2 == LZ_MAGIC_2) r = sfdclzw(sp, 0); } else if (m1 == 'B' && m2 == 'Z' && s[2] == 'h' && s[3] >= '1' && s[3] <= '9') r = sfdcbzip(sp, 0); } return r; } sfsync(sp); } if (!(io = sfnew(NiL, NiL, SF_UNBOUND, sffileno(sp), (sfset(sp, 0, 0) & (SF_READ|SF_WRITE))))) return -1; if (!(pz = newof(0, Sfpzip_t, 1, 0))) { io->_file = -1; sfclose(io); return -1; } pz->disc.version = PZ_VERSION; flags &= ~(PZ_READ|PZ_WRITE|PZ_STAT|PZ_STREAM|PZ_INTERNAL); flags |= PZ_PUSHED|PZ_STREAM|((sfset(sp, 0, 0) & SF_READ) ? PZ_READ : PZ_WRITE); if (oz && (oz->flags & PZ_WRITE)) flags |= PZ_DELAY; if (disc) { pz->disc.errorf = disc->errorf; pz->disc.window = disc->window; pz->disc.options = disc->options; pz->disc.partition = disc->partition; if (disc->splitf) flags |= PZ_ACCEPT; } if (!(pz->pz = pzopen(&pz->disc, (char*)io, flags)) || (sp->_file = open("/dev/null", 0)) < 0) { io->_file = -1; sfclose(io); free(pz); return -1; } if (path) pz->pz->path = path; pz->sfdisc.exceptf = sfpzexcept; if (flags & PZ_WRITE) { pz->sfdisc.writef = sfpzwrite; pz->io = io; } else pz->sfdisc.readf = sfpzread; sfset(sp, SF_SHARE|SF_PUBLIC, 0); if (sfdisc(sp, &pz->sfdisc) != &pz->sfdisc) { close(sp->_file); sp->_file = io->_file; sfseek(sp, sftell(io), SEEK_SET); io->_file = -1; pzclose(pz->pz); free(pz); return -1; } if (oz) oz->flags |= pz->pz->flags & PZ_INTERNAL; return 1; }
tmain() { UNUSED(argc); UNUSED(argv); Sfio_t *f, *f2; char *s; int i, n; char buf[16 * 1024]; if (!(f = sfopen(NULL, tstfile("sf", 0), "w+"))) terror("Can't open file"); if (sfnputc(f, 'a', 1000) != 1000) terror("Writing"); if (sfseek(f, (Sfoff_t)0, 0) != 0) terror("Seeking"); if ((n = (int)sfsize(f)) != 1000) terror("Wrong size %d", n); if (!(f2 = sfnew(NULL, NULL, (size_t)SF_UNBOUND, sffileno(f), SF_WRITE))) { terror("Can't open stream"); } if (sfseek(f2, (Sfoff_t)1999, 0) != (Sfoff_t)1999) terror("Seeking2"); sfputc(f2, 'b'); sfsync(f2); if ((n = (int)sfsize(f2)) != 2000) terror("Wrong size2 %d", n); if ((n = (int)sfsize(f)) != 1000) terror("Wrong size3 %d", n); sfputc(f, 'a'); sfset(f, SF_SHARE, 1); if ((n = (int)sfsize(f)) != 2000) terror("Wrong size4 %d", n); if (!(f = sfopen(f, NULL, "srw"))) terror("Can't open string stream"); sfwrite(f, "0123456789", 10); if (sfsize(f) != 10) terror("String size is wrong1"); sfseek(f, (Sfoff_t)19, 0); if (sfsize(f) != 10) terror("String size is wrong2"); sfputc(f, 'a'); if (sfsize(f) != 20) terror("String size is wrong3"); sfseek(f, (Sfoff_t)0, 0); if (sfsize(f) != 20) terror("String size is wrong4"); sfseek(f, (Sfoff_t)0, 0); if (!(s = sfreserve(f, SF_UNBOUND, SF_LOCKR)) && sfvalue(f) != 20) { terror("String size is wrong5"); } sfread(f, s, 5); if (sfsize(f) != 20) terror("String size is wrong6"); sfwrite(f, "01234567890123456789", 20); if (sfsize(f) != 25) terror("String size is wrong7"); strcpy(buf, "0123456789"); if (!(f = sfopen(f, buf, "s+"))) terror("Can't open string stream2"); if (sfset(f, 0, 0) & SF_MALLOC) terror("SF_MALLOC should not have been set"); if (sfsize(f) != 10) terror("String size is wrong8"); sfread(f, buf, 5); if ((n = (int)sfwrite(f, "0123456789", 10)) != 5) terror("Write wrong amount %d", n); if (sfsize(f) != 10) terror("String size is wrong9"); if (!(f = sfopen(f, tstfile("sf", 0), "w"))) terror("Reopening file1"); for (i = 0; i < 10000; ++i) { if (sfputc(f, '0' + (i % 10)) != '0' + (i % 10)) terror("sfputc failed"); } if (!(f = sfopen(f, tstfile("sf", 0), "r+"))) terror("Reopening file2"); if (sfsize(f) != 10000) terror("Bad size of file1"); sfsetbuf(f, buf, 1024); for (i = 0; i < 20; ++i) { if (!sfreserve(f, 100, 0)) terror("Reserve failed"); } s = buf + 1024; for (i = 0; i < 20; ++i) s[i] = '0' + i % 10; sfseek(f, (Sfoff_t)(10000 - 10), 0); if (sfwrite(f, s, 20) != 20) terror("Write failed"); if (sfsize(f) != 10010) terror("Bad size of file2"); sfseek(f, (Sfoff_t)0, 0); for (i = 0; i < 10; ++i) { if (!(s = sfreserve(f, 1001, 0))) terror("Reserve failed2"); if (s[0] != '0' + i) terror("Bad data1"); } for (n = 0; n < 1001; ++n) { if (s[n] != ((n + i - 1) % 10 + '0')) terror("Bad data"); } /* test to see if a string stream extends ok during writes */ s = malloc(5); f = sfnew(NULL, (void *)s, 5, -1, SF_STRING | SF_READ | SF_WRITE | SF_MALLOC); if (!f) terror("Can't create string stream"); if (sfwrite(f, "01", 2) != 2) terror("Bad write to string stream"); if (sfwrite(f, "2345678", 7) != 7) terror("Bad write to string stream2"); if (sfputc(f, 0) != 0) terror("sfputc failed"); if (sfseek(f, (Sfoff_t)0, 0) != 0) terror("sfseek failed"); if ((n = (int)sfread(f, buf, 100)) != 10) terror("sfread gets wrong amount of data %d", n); if (strcmp(buf, "012345678") != 0) terror("Get wrong data"); texit(0); }
/* Test multiple processes reading/writing from same file ** descriptor. */ MAIN() { char* s; if(argc > 1) { if(strcmp(argv[1],"-r") == 0) /* doing sfgetr */ { if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line2") != 0) terror("Coprocess getr did not get Line2\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line3") != 0) terror("Coprocess getr did not get Line3\n"); } else /* doing sfmove */ { Sfio_t* f = sfopen(NIL(Sfio_t*),NIL(char*),"swr"); if(!f) terror("Can't open string stream\n"); if(sfmove(sfstdin,f,(Sfoff_t)2,'\n') != 2) terror("Coprocess sfmove failed\n"); sfseek(f,(Sfoff_t)0,0); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"Line2") != 0) terror("Coprocess move did not get Line2\n"); if(!(s = sfgetr(f,'\n',1)) || strcmp(s,"Line3") != 0) terror("Coprocess move did not get Line3\n"); } TSTEXIT(0); } if(sfopen(sfstdout, tstfile(0), "w") != sfstdout ) terror("Opening file\n"); if(sfputr(sfstdout,"Line1",'\n') < 0 || sfputr(sfstdout,"Line2",'\n') < 0 || sfputr(sfstdout,"Line3",'\n') < 0 || sfputr(sfstdout,"Line4",'\n') < 0) terror("Writing data\n"); sfopen(sfstdout,"/dev/null","w"); /* testing coprocess calling sfgetr */ if(sfopen(sfstdin, tstfile(0),"r") != sfstdin) terror("Opening to read\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line1") != 0) terror("Did not get Line1 for sfgetr\n"); sfsync(sfstdin); system(sfprints("%s -r",argv[0])); sfseek(sfstdin, (Sfoff_t)lseek(sffileno(sfstdin), (off_t)0, 1), 0); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line4") != 0) terror("Did not get Line4 for sfgetr\n"); /* testing coprocess calling sfmove */ if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Opening to read\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line1") != 0) terror("Did not get Line1 for sfmove\n"); sfsync(sfstdin); system(sfprints("%s -m",argv[0])); sfseek(sfstdin, (Sfoff_t)lseek(sffileno(sfstdin), (off_t)0, 1), 0); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line4") != 0) terror("Did not get Line4 for sfmove\n"); /* testing the head program */ #ifdef HEAD if(sfopen(sfstdin, tstfile(0), "r") != sfstdin) terror("Opening to read\n"); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line1") != 0) terror("Did not get Line1 for head\n"); sfsync(sfstdin); system("head -2 > /dev/null"); /* for testing the head program */ sfseek(sfstdin, (Sfoff_t)lseek(sffileno(sfstdin), (off_t)0, 1), 0); if(!(s = sfgetr(sfstdin,'\n',1)) || strcmp(s,"Line4") != 0) terror("Did not get Line4 for head\n"); #endif TSTEXIT(0); }
// // Copy the last <n> commands to a new file and make this the history file. // static History_t *hist_trim(History_t *hp, int n) { char *cp; int incmd = 1, c = 0; History_t *hist_new, *hist_old = hp; char *buff, *endbuff, *tmpname = NULL; off_t oldp, newp; struct stat statb; unlink(hist_old->histname); if (access(hist_old->histname, F_OK) >= 0) { // The unlink can fail on windows 95. int fd; char *last, *name = hist_old->histname; sh_close(sffileno(hist_old->histfp)); last = strrchr(name, '/'); if (last) { *last = 0; tmpname = ast_temp_file(name, "hist", &fd, 0); *last = '/'; } else { tmpname = ast_temp_file(".", "hist", &fd, 0); } if (!tmpname) { errormsg(SH_DICT, ERROR_exit(1), e_create, "hist"); __builtin_unreachable(); } close(fd); if (rename(name, tmpname) < 0) { free(tmpname); tmpname = name; } fd = open(tmpname, O_RDONLY | O_CLOEXEC); // What happens if this fails and returns -1? Coverity Scan #310940. (void)sfsetfd(hist_old->histfp, fd); if (tmpname == name) { free(tmpname); tmpname = NULL; } } hist_ptr = NULL; if (fstat(sffileno(hist_old->histfp), &statb) >= 0) { histinit = 1; histmode = statb.st_mode; } if (!sh_histinit(hp->histshell)) { // Use the old history file. hist_ptr = hist_old; return hist_ptr; } hist_new = hist_ptr; hist_ptr = hist_old; if (--n < 0) n = 0; newp = hist_seek(hist_old, ++n); while (1) { if (!incmd) { c = hist_ind(hist_new, ++hist_new->histind); hist_new->histcmds[c] = hist_new->histcnt; if (hist_new->histcnt > hist_new->histmarker + HIST_BSIZE / 2) { char locbuff[HIST_MARKSZ]; hist_marker(locbuff, hist_new->histind); sfwrite(hist_new->histfp, locbuff, HIST_MARKSZ); hist_new->histcnt += HIST_MARKSZ; hist_new->histmarker = hist_new->histcmds[hist_ind(hist_new, c)] = hist_new->histcnt; } oldp = newp; newp = hist_seek(hist_old, ++n); if (newp <= oldp) break; } if (!(buff = (char *)sfreserve(hist_old->histfp, SF_UNBOUND, 0))) break; *(endbuff = (cp = buff) + sfvalue(hist_old->histfp)) = 0; // Copy to null byte. incmd = 0; cp += strlen(cp) + 1; // point past the terminating null if (cp > endbuff) { incmd = 1; } else if (*cp == 0) { cp++; } if (cp > endbuff) cp = endbuff; c = cp - buff; hist_new->histcnt += c; sfwrite(hist_new->histfp, buff, c); } hist_cancel(hist_new); sfclose(hist_old->histfp); if (tmpname) { unlink(tmpname); free(tmpname); } free(hist_old); hist_ptr = hist_new; return hist_ptr; }
static int mkpty(int* master, int* slave) { struct termios tty; struct termios tst; struct termios* ttyp; #ifdef TIOCGWINSZ struct winsize win; struct winsize* winp; #endif #if !_lib_openpty char* sname; #endif /* * some systems hang hard during the handshake * if you know why then please let us know */ alarm(4); if (tcgetattr(sffileno(sfstderr), &tty) >= 0) ttyp = &tty; else { ttyp = 0; error(-1, "unable to get standard error terminal attributes"); } #ifdef TIOCGWINSZ if (ioctl(sffileno(sfstderr), TIOCGWINSZ, &win) >= 0) winp = &win; else { winp = 0; error(-1, "unable to get standard error window size"); } #endif #if _lib_openpty if (openpty(master, slave, NULL, ttyp, winp) < 0) return -1; #else #if _lib_grantpt && _lib_unlockpt #if !_lib_posix_openpt #ifndef _pty_clone #define _pty_clone "/dev/ptmx" #endif #define posix_openpt(m) open(_pty_clone,m) #endif if ((*master = posix_openpt(O_RDWR)) < 0) return -1; if (grantpt(*master) || unlockpt(*master) || !(sname = ptsname(*master)) || (*slave = open(sname, O_RDWR|O_cloexec)) < 0) { close(*master); return -1; } #else if (!(sname = ptymopen(master)) || (*slave = open(sname, O_RDWR|O_cloexec)) < 0) return -1; #endif #ifdef I_PUSH if (tcgetattr(*slave, &tst) < 0 && (ioctl(*slave, I_PUSH, "ptem") < 0 || ioctl(*slave, I_PUSH, "ldterm") < 0)) { close(*slave); close(*master); return -1; } #endif #endif if (ttyp && tcsetattr(*slave, TCSANOW, ttyp) < 0) error(ERROR_warn(0), "unable to set pty terminal attributes"); #ifdef TIOCSWINSZ if (winp && ioctl(*slave, TIOCSWINSZ, winp) < 0) error(ERROR_warn(0), "unable to set pty window size"); #endif fcntl(*master, F_SETFD, FD_CLOEXEC); #if !O_cloexec fcntl(*slave, F_SETFD, FD_CLOEXEC); #endif alarm(0); return 0; }
static int process(Sfio_t* mp, Sfio_t* lp, int delay, int timeout) { int i; int n; int t; ssize_t r; char* s; Sfio_t* ip; Sfio_t* sps[2]; struct stat dst; struct stat fst; ip = sfstdin; if (!fstat(sffileno(ip), &dst) && !stat("/dev/null", &fst) && dst.st_dev == fst.st_dev && dst.st_ino == fst.st_ino) ip = 0; do { i = 0; t = timeout; if (mp) sps[i++] = mp; if (ip) { sps[i++] = ip; t = -1; } if (!i) break; if ((n = sfpoll(sps, i, t)) <= 0) { if (n < 0) error(ERROR_SYSTEM|2, "poll failed"); break; } for (i = t = 0; i < n; i++) { if (!(sfvalue(sps[i]) & SF_READ)) /*skip*/; else if (sps[i] == mp) { t++; if (!(s = (char*)sfreserve(mp, SF_UNBOUND, -1))) { sfclose(mp); mp = 0; } else if ((r = sfvalue(mp)) > 0 && (sfwrite(sfstdout, s, r) != r || sfsync(sfstdout))) { error(ERROR_SYSTEM|2, "output write failed"); goto done; } } else { t++; if (!(s = sfgetr(ip, '\n', 1))) ip = 0; else if (sfputr(mp, s, '\r') < 0 || sfsync(mp)) { error(ERROR_SYSTEM|2, "write failed"); goto done; } } } } while (t); done: if (mp) sfclose(mp); return error_info.errors != 0; }
MAIN() { Sfio_t* fw; Sfio_t* fr; int fds[2]; int lseek_errno; int rv; if(!(fw = sfopen(NIL(Sfio_t*), tstfile(0), "w")) ) terror("Can't create temp file %s to write", tstfile(0)); if(!(fr = sfopen(NIL(Sfio_t*), tstfile(0), "r")) ) terror("Can't open temp file %s to read", tstfile(0)); sfseek(fr, (Sfoff_t)0, SEEK_END); if(sfgetc(fr) >= 0 || !sfeof(fr)) terror("Should have seen eof"); errno = 0; if((rv = sfwrite(fr, "a", 1)) == 1) terror("sfwrite returns %d, expecting 1", rv); if(errno != EBADF) twarn("Wrong errno %d after sfwrite(%d), expecting %d",errno,rv,EBADF); /* on some system (eg, apple), lseek does not set errno for this case */ errno = 0; lseek(sffileno(fw), (off_t)(-2), SEEK_SET); lseek_errno = errno; lseek(sffileno(fw), (off_t)0, SEEK_SET); errno = 0; if(sfseek(fw, (Sfoff_t)(-2), SEEK_SET) != (Sfoff_t)(-1) ) terror("sfseek should have failed"); if(errno != lseek_errno) twarn("Wrong errno %d after sfseek, expecting %d", errno, lseek_errno); errno = 0; if(sfseek(fw, (Sfoff_t)0, SEEK_SET|SEEK_CUR|SEEK_END) >= 0) terror("sfseek should not have succeeded"); if(errno != EINVAL) twarn("Wrong errno %d after sfseek, expecting %d", errno, EINVAL); if(pipe(fds) < 0) terror("Can't create pipes"); if(!(fw = sfnew(fw, NIL(Void_t*), (size_t)SF_UNBOUND, fds[1], SF_WRITE)) ) terror("Can't create stream for pipe"); errno = 0; if(sfseek(fw, (Sfoff_t)0, SEEK_SET) >= 0) terror("sfseek should have failed on a pipe"); if(errno != ESPIPE) twarn("Wrong errno %d after sfseek, expecting %d", ESPIPE); close(sffileno(fw)); errno = 0; if(sfseek(fw, (Sfoff_t)0, SEEK_END) >= 0) terror("sfseek should have failed on a closed file descriptor"); if(errno != EBADF) twarn("Wrong errno %d after sfseek, expecting %d", EBADF); TSTEXIT(0); }