static int sfpzexcept(Sfio_t* sp, int op, void* val, Sfdisc_t* dp) { register Sfpzip_t* pz = (Sfpzip_t*)dp; int r; NoP(sp); switch (op) { case SF_ATEXIT: sfdisc(sp, SF_POPDISC); return 0; case SF_CLOSING: case SF_DPOP: case SF_FINAL: if (pz->pz) { pz->pz->flags &= ~PZ_STREAM; r = pzclose(pz->pz); pz->pz = 0; } else r = 0; if (op != SF_CLOSING) free(dp); return r; case SF_DBUFFER: return 1; case SF_SYNC: return val ? 0 : pzsync(pz->pz); case SFPZ_HANDLE: return (*((Pz_t**)val) = pz->pz) ? 1 : -1; } return 0; }
int sfdcsasl(Sfio_t *f, sasl_conn_t *conn) { Sasldisc_t *sasl; if (conn == NULL) { /* no need to do anything */ return 0; } if(!(sasl = (Sasldisc_t*)malloc(sizeof(Sasldisc_t))) ) return -1; sasl->disc.readf = sasl_read; sasl->disc.writef = sasl_write; sasl->disc.seekf = NULL; sasl->disc.exceptf = NULL; sasl->conn = conn; if (sfdisc(f, (Sfdisc_t *) sasl) != (Sfdisc_t *) sasl) { free(sasl); return -1; } return 0; }
tmain() { UNUSED(argc); UNUSED(argv); char buf[1024]; sfsetbuf(sfstdout, buf, sizeof(buf)); sfset(sfstdout, SF_LINE, 0); if (sfdisc(sfstdout, &seekable) != &seekable) terror("Can't set discipline"); if (sfseek(sfstdout, (Sfoff_t)0, 0) < 0) terror("Sfstdout should be seekable"); if (sfwrite(sfstdout, "123\n", 4) != 4) terror("Can't write"); if (sfwrite(sfstdout, "123\n", 4) != 4) terror("Can't write"); if (sfdisc(sfstdout, NULL) != &seekable) terror("Can't pop discipline"); if (buffer != buf || size != 8 || count != 1) terror("Wrong calls to write"); texit(0); }
tmain() { char buf[100]; Sfio_t *fp; int i; char *s; if(!(fp = sftmp(8))) terror("Can't open temp file"); sfset(fp,SF_LINE,1); for(i = 0; i < 1000; ++i) { sfsprintf(buf,sizeof(buf),"Number: %d",i); if(sfputr(fp,buf,'\n') <= 0) terror("Writing %s",buf); } sfseek(fp,(Sfoff_t)0,0); for(i = 0; i < 1000; ++i) { sfsprintf(buf,sizeof(buf),"Number: %d",i); if(!(s = sfgetr(fp,'\n',1))) terror("Reading %s",buf); if(strcmp(s,buf) != 0) terror("Input=%s, Expect=%s",s,buf); } sfseek(fp,(Sfoff_t)0,0); s = sfgetr(fp,'\0',1); if(s) terror("Expecting a null string"); s = sfgetr(fp,'\0',-1); if(!s) terror("Expecting a non-null string"); if(sfvalue(fp) != sfsize(fp)) terror("Wrong size"); sfclose(fp); if(!(fp = sfnew(0, buf, 12, 1, SF_WRITE)) ) terror("Opening a test stream"); sfsetbuf(fp, buf, 12); sfset(fp, SF_LINE, 0); sfdisc(fp, &Disc); if(sfputr(fp, "0123456789", '\n') != 11) terror("Sfputr failed1"); if(sfputr(fp, "0", -1) != 1) terror("Sfputr failed2"); if(sfputr(fp, "1", -1) != 1) terror("Sfputr failed3"); texit(0); }
static void tee_cleanup(register Tee_t* tp) { register int* hp; register int n; if (tp) { sfdisc(sfstdout, NiL); if (tp->line >= 0) sfset(sfstdout, SF_LINE, tp->line); for (hp = tp->fd; (n = *hp) >= 0; hp++) close(n); } }
Sfio_t* tokline(const char* arg, int flags, int* line) { Sfio_t* f; Sfio_t* s; Splice_t* d; char* p; char* e; static int hidden; if (!(d = newof(0, Splice_t, 1, 0))) return 0; if (!(s = sfopen(NiL, NiL, "s"))) { free(d); return 0; } if (!(flags & (SF_STRING|SF_READ))) f = (Sfio_t*)arg; else if (!(f = sfopen(NiL, arg, (flags & SF_STRING) ? "s" : "r"))) { free(d); sfclose(s); return 0; } else if ((p = sfreserve(f, 0, 0)) && sfvalue(f) > 11 && strmatch(p, "#!!! +([-0-9]) *([!\n]) !!!\n*") && (e = strchr(p, '\n'))) { flags = strtol(p + 5, &p, 10); error(flags, "%s:%-.*s", arg, e - p - 4, p); } d->disc.exceptf = spliceline; d->sp = f; *(d->line = line ? line : &hidden) = 0; sfdisc(s, (Sfdisc_t*)d); return s; }
static Sfio_t* paxpart(Pax_t* pax, Paxarchive_t* ap, off_t n) { register Part_t* part; static int fd = -1; if (!(part = ap->partio)) { if (!(part = newof(0, Part_t, 1, 0)) || !(part->sp = sfstropen())) { paxnospace(pax); return 0; } part->sp->_flags &= ~(SF_READ|SF_WRITE|SF_STRING); if (ap->flags & PAX_IN) part->sp->_flags |= SF_READ; else part->sp->_flags |= SF_WRITE; if (fd < 0) fd = open("/dev/null", O_RDWR); part->sp->_file = fd; part->disc.readf = part_read; part->disc.writef = part_write; if (sfdisc(part->sp, &part->disc) != &part->disc) { sfclose(part->sp); free(part); return 0; } part->pax = pax; part->ap = ap; ap->partio = part; } part->n = n; return part->sp; }
// // Open the history file. If HISTNAME is not given and userid==0 then no history file. If login_sh // and HISTFILE is longer than HIST_MAX bytes then it is cleaned up. // // hist_open() returns 1, if history file is opened. // int sh_histinit(void *sh_context) { Shell_t *shp = sh_context; int fd; History_t *hp; char *histname; char *fname = NULL; int histmask, maxlines, hist_start = 0; char *cp; off_t hsize = 0; shgd->hist_ptr = hist_ptr; if (shgd->hist_ptr) return 1; if (!(histname = nv_getval(HISTFILE))) { int offset = stktell(shp->stk); cp = nv_getval(HOME); if (cp) sfputr(shp->stk, cp, -1); sfputr(shp->stk, hist_fname, 0); stkseek(shp->stk, offset); histname = stkptr(shp->stk, offset); } #if 0 // TODO: Figure out if this should be enabled. Originally excluded via `#ifdef future`. if (hp = wasopen) { // Reuse history file if same name. wasopen = 0; shgd->hist_ptr = hist_ptr = hp; if (strcmp(histname, hp->histname) == 0) { return 1; } else { hist_free(); } } #endif // future retry: cp = path_relative(shp, histname); if (!histinit) histmode = S_IRUSR | S_IWUSR; if ((fd = open(cp, O_BINARY | O_APPEND | O_RDWR | O_CREAT | O_CLOEXEC, histmode)) >= 0) { hsize = lseek(fd, (off_t)0, SEEK_END); } if ((unsigned)fd < 10) { int n; if ((n = sh_fcntl(fd, F_DUPFD_CLOEXEC, 10)) >= 0) { sh_close(fd); fd = n; } } // Make sure that file has history file format. if (hsize && hist_check(fd)) { sh_close(fd); hsize = 0; if (unlink(cp) >= 0) goto retry; fd = -1; } // Don't allow root a history_file in /tmp. if (fd < 0 && shgd->userid) { fname = ast_temp_file(NULL, NULL, &fd, O_APPEND | O_CLOEXEC); if (!fname) return 0; } if (fd < 0) return 0; // Set the file to close-on-exec. (void)fcntl(fd, F_SETFD, FD_CLOEXEC); cp = nv_getval(HISTSIZE); if (cp) { maxlines = (unsigned)strtol(cp, NULL, 10); } else { maxlines = HIST_DFLT; } for (histmask = 16; histmask <= maxlines; histmask <<= 1) { ; // empty loop } histmask -= 1; hp = calloc(1, sizeof(History_t) + histmask * sizeof(off_t)); if (!hp) { sh_close(fd); return 0; } shgd->hist_ptr = hist_ptr = hp; hp->histshell = shp; hp->histsize = maxlines; hp->histmask = histmask; hp->histfp = sfnew(NULL, NULL, HIST_BSIZE, fd, SF_READ | SF_WRITE | SF_APPENDWR | SF_SHARE); hp->histind = 1; hp->histcmds[1] = 2; hp->histcnt = 2; hp->histname = strdup(histname); hp->histdisc = hist_disc; if (hsize == 0) { // Put special characters at front of file. sfwrite(hp->histfp, (char *)hist_stamp, 2); sfsync(hp->histfp); } else { // Initialize history list. int first, last; off_t mark, size = (HIST_MAX / 4) + maxlines * HIST_LINE; hp->histind = first = hist_nearend(hp, hp->histfp, hsize - size); histinit = 1; hist_eof(hp); // this sets histind to last command if ((hist_start = (last = (int)hp->histind) - maxlines) <= 0) hist_start = 1; mark = hp->histmarker; while (first > hist_start) { size += size; first = hist_nearend(hp, hp->histfp, hsize - size); hp->histind = first; } histinit = hist_start; hist_eof(hp); if (!histinit) { sfseek(hp->histfp, hp->histcnt = hsize, SEEK_SET); hp->histind = last; hp->histmarker = mark; } histinit = 0; } if (fname) { unlink(fname); free(fname); } if (hist_clean(fd) && hist_start > 1 && hsize > HIST_MAX) { #ifdef DEBUG sfprintf(sfstderr, "%d: hist_trim hsize=%d\n", getpid(), hsize); sfsync(sfstderr); #endif // DEBUG hp = hist_trim(hp, (int)hp->histind - maxlines); } sfdisc(hp->histfp, &hp->histdisc); STORE_VT((HISTCUR)->nvalue, i32p, &hp->histind); sh_timeradd(1000L * (HIST_RECENT - 30), 1, hist_touch, hp->histname); hp->auditfp = NULL; char buff[SF_BUFSIZE]; if (!sh_isstate(shp, SH_INTERACTIVE)) return 1; hp->auditmask = sh_checkaudit(hp, AUDIT_FILE, buff, sizeof(buff)); if (!hp->auditmask) return 1; if ((fd = sh_open(buff, O_BINARY | O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR)) >= 0 && fd < 10) { int n; if ((n = sh_fcntl(fd, F_DUPFD_CLOEXEC, 10)) >= 0) { sh_close(fd); fd = n; } } if (fd >= 0) { (void)fcntl(fd, F_SETFD, FD_CLOEXEC); hp->tty = strdup(isatty(2) ? ttyname(2) : "notty"); hp->auditfp = sfnew(NULL, NULL, -1, fd, SF_WRITE); } return 1; }
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; }
/* * open the history file * if HISTNAME is not given and userid==0 then no history file. * if login_sh and HISTFILE is longer than HIST_MAX bytes then it is * cleaned up. * hist_open() returns 1, if history file is open */ int sh_histinit(void *sh_context) { Shell_t *shp = (Shell_t*)sh_context; register int fd; register History_t *hp; register char *histname; char *fname=0; int histmask, maxlines, hist_start=0; register char *cp; register off_t hsize = 0; if(shgd->hist_ptr=hist_ptr) return(1); if(!(histname = nv_getval(HISTFILE))) { int offset = staktell(); if(cp=nv_getval(HOME)) stakputs(cp); stakputs(hist_fname); stakputc(0); stakseek(offset); histname = stakptr(offset); } #ifdef future if(hp=wasopen) { /* reuse history file if same name */ wasopen = 0; shgd->hist_ptr = hist_ptr = hp; if(strcmp(histname,hp->histname)==0) return(1); else hist_free(); } #endif retry: cp = path_relative(shp,histname); if(!histinit) histmode = S_IRUSR|S_IWUSR; if((fd=open(cp,O_BINARY|O_APPEND|O_RDWR|O_CREAT,histmode))>=0) { hsize=lseek(fd,(off_t)0,SEEK_END); } if((unsigned)fd <=2) { int n; if((n=fcntl(fd,F_DUPFD,10))>=0) { close(fd); fd=n; } } /* make sure that file has history file format */ if(hsize && hist_check(fd)) { close(fd); hsize = 0; if(unlink(cp)>=0) goto retry; fd = -1; } if(fd < 0) { #if KSHELL /* don't allow root a history_file in /tmp */ if(shgd->userid) #endif /* KSHELL */ { if(!(fname = pathtmp(NIL(char*),0,0,NIL(int*)))) return(0); fd = open(fname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR); } } if(fd<0) return(0); /* set the file to close-on-exec */ fcntl(fd,F_SETFD,FD_CLOEXEC); if(cp=nv_getval(HISTSIZE)) maxlines = (unsigned)strtol(cp, (char**)0, 10); else maxlines = HIST_DFLT; for(histmask=16;histmask <= maxlines; histmask <<=1 ); if(!(hp=new_of(History_t,(--histmask)*sizeof(off_t)))) { close(fd); return(0); } shgd->hist_ptr = hist_ptr = hp; hp->histshell = (void*)shp; hp->histsize = maxlines; hp->histmask = histmask; hp->histfp= sfnew(NIL(Sfio_t*),hp->histbuff,HIST_BSIZE,fd,SF_READ|SF_WRITE|SF_APPENDWR|SF_SHARE); memset((char*)hp->histcmds,0,sizeof(off_t)*(hp->histmask+1)); hp->histind = 1; hp->histcmds[1] = 2; hp->histcnt = 2; hp->histname = strdup(histname); hp->histdisc = hist_disc; if(hsize==0) { /* put special characters at front of file */ sfwrite(hp->histfp,(char*)hist_stamp,2); sfsync(hp->histfp); } /* initialize history list */ else { int first,last; off_t mark,size = (HIST_MAX/4)+maxlines*HIST_LINE; hp->histind = first = hist_nearend(hp,hp->histfp,hsize-size); histinit = 1; hist_eof(hp); /* this sets histind to last command */ if((hist_start = (last=(int)hp->histind)-maxlines) <=0) hist_start = 1; mark = hp->histmarker; while(first > hist_start) { size += size; first = hist_nearend(hp,hp->histfp,hsize-size); hp->histind = first; } histinit = hist_start; hist_eof(hp); if(!histinit) { sfseek(hp->histfp,hp->histcnt=hsize,SEEK_SET); hp->histind = last; hp->histmarker = mark; } histinit = 0; } if(fname) { unlink(fname); free((void*)fname); } if(hist_clean(fd) && hist_start>1 && hsize > HIST_MAX) { #ifdef DEBUG sfprintf(sfstderr,"%d: hist_trim hsize=%d\n",getpid(),hsize); sfsync(sfstderr); #endif /* DEBUG */ hp = hist_trim(hp,(int)hp->histind-maxlines); } sfdisc(hp->histfp,&hp->histdisc); #if KSHELL (HISTCUR)->nvalue.lp = (&hp->histind); #endif /* KSHELL */ sh_timeradd(1000L*(HIST_RECENT-30), 1, hist_touch, (void*)hp->histname); #if SHOPT_ACCTFILE if(sh_isstate(SH_INTERACTIVE)) acctinit(hp); #endif /* SHOPT_ACCTFILE */ #if SHOPT_AUDIT { char buff[SF_BUFSIZE]; hp->auditfp = 0; if(sh_isstate(SH_INTERACTIVE) && (hp->auditmask=sh_checkaudit(hp,SHOPT_AUDITFILE, buff, sizeof(buff)))) { if((fd=sh_open(buff,O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 && fd < 10) { int n; if((n = sh_fcntl(fd,F_DUPFD, 10)) >= 0) { sh_close(fd); fd = n; } } if(fd>=0) { fcntl(fd,F_SETFD,FD_CLOEXEC); hp->tty = strdup(ttyname(2)); hp->auditfp = sfnew((Sfio_t*)0,NULL,-1,fd,SF_WRITE); } } } #endif return(1); }
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; }
/* * 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 b_tee(int argc, register char** argv, void* context) { register Tee_t* tp = 0; register int oflag = O_WRONLY|O_TRUNC|O_CREAT|O_BINARY; register int* hp; register char* cp; int line; if (argc <= 0) { if (context && (tp = (Tee_t*)sh_context(context)->data)) { sh_context(context)->data = 0; tee_cleanup(tp); } return 0; } cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_CALLBACK); line = -1; for (;;) { switch (optget(argv, usage)) { case 'a': oflag &= ~O_TRUNC; oflag |= O_APPEND; continue; case 'i': signal(SIGINT, SIG_IGN); continue; case 'l': line = sfset(sfstdout, 0, 0) & SF_LINE; if ((line == 0) == (opt_info.num == 0)) line = -1; else sfset(sfstdout, SF_LINE, !!opt_info.num); continue; case ':': error(2, "%s", opt_info.arg); break; case '?': error(ERROR_usage(2), "%s", opt_info.arg); break; } break; } if (error_info.errors) error(ERROR_usage(2), "%s", optusage(NiL)); argv += opt_info.index; argc -= opt_info.index; #if _ANCIENT_BSD_COMPATIBILITY if (*argv && streq(*argv, "-")) { signal(SIGINT, SIG_IGN); argv++; argc--; } #endif if (argc > 0) { if (tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int))) { memset(&tp->disc, 0, sizeof(tp->disc)); tp->disc.writef = tee_write; if (context) sh_context(context)->data = (void*)tp; tp->line = line; hp = tp->fd; while (cp = *argv++) { if ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0) error(ERROR_system(0), "%s: cannot create", cp); else hp++; } if (hp == tp->fd) tp = 0; else { *hp = -1; sfdisc(sfstdout, &tp->disc); } } else error(ERROR_exit(0), "out of space"); } if ((sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin)) && errno != EPIPE) error(ERROR_system(0), "read error"); if (sfsync(sfstdout)) error(ERROR_system(0), "write error"); tee_cleanup(tp); return error_info.errors; }
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); }
main() { int n, fd; Sfio_t *f; char *s, buf[1024]; int fdv[100]; buf[0] = 0; sfsetbuf(sfstdout,buf,sizeof(buf)); if(!sfstdout->pool) terror("No pool\n"); sfdisc(sfstdout,&Disc); sfset(sfstdout,SF_SHARE,0); sfputr(sfstdout,"123456789",0); if(strcmp(buf,"123456789") != 0) terror("Setting own buffer for stdout\n"); if(sfpurge(sfstdout) < 0) terror("Purging sfstdout\n"); if((fd = creat("xxx",0666)) < 0) terror("Creating xxx\n"); if(write(fd,buf,sizeof(buf)) != sizeof(buf)) terror("Writing to xxx\n"); if(lseek(fd,0L,0) < 0) terror("Seeking back to origin\n"); if(!(f = sfnew((Sfio_t*)0,buf,sizeof(buf),fd,SF_WRITE))) terror("Making stream\n"); if(!(s = sfreserve(f,SF_UNBOUND,1)) || s != buf) terror("sfreserve1 returns the wrong pointer\n"); sfwrite(f,s,0); #define NEXTFD 12 if((fd+NEXTFD) < (sizeof(fdv)/sizeof(fdv[0])) ) { struct stat st; int i; for(i = 0; i < fd+NEXTFD; ++i) fdv[i] = fstat(i,&st); } if((n = sfsetfd(f,fd+NEXTFD)) != fd+NEXTFD) terror("Try to set file descriptor to %d but get %d\n",fd+NEXTFD,n); if((fd+NEXTFD) < (sizeof(fdv)/sizeof(fdv[0])) ) { struct stat st; int i; for(i = 0; i < fd+NEXTFD; ++i) if(i != fd && fdv[i] != fstat(i,&st)) terror("Fd %d changes status after sfsetfd %d->%d\n", i, fd, fd+NEXTFD); } if(!(s = sfreserve(f,SF_UNBOUND,1)) || s != buf) terror("sfreserve2 returns the wrong pointer\n"); sfwrite(f,s,0); if(sfsetbuf(f,NIL(Void_t*),(size_t)SF_UNBOUND) != buf) terror("sfsetbuf didnot returns last buffer\n"); sfsetbuf(f,buf,sizeof(buf)); if(sfreserve(f,SF_UNBOUND,1) != buf || sfvalue(f) != sizeof(buf) ) terror("sfreserve3 returns the wrong value\n"); sfwrite(f,s,0); system("rm xxx >/dev/null 2>&1"); return 0; }