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; }
int dssfclose(Dssfile_t* file) { int r; Dss_t* dss; if (!file) return -1; dss = file->dss; if (!file->io) r = -1; else { r = file->format ? (*file->format->closef)(file, dss->disc) : 0; if ((file->flags & DSS_FILE_WRITE) && sfsync(file->io)) { if (dss->disc->errorf) (*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: write error", file->path); r = -1; } if (!(file->flags & DSS_FILE_KEEP)) sfclose(file->io); if (!r && (file->flags & DSS_FILE_ERROR)) r = -1; } vmclose(file->vm); return r; }
tmain() { UNUSED(argc); UNUSED(argv); Sfio_t *f1, *f2; char *s; Sfoff_t p; char buf[1024]; int r, w; if (!(f1 = sfopen(NULL, tstfile("sf", 0), "w"))) terror("Can't open f1"); if (!(f1 = sfopen(f1, tstfile("sf", 0), "a+"))) terror("Can't open f1"); if (!(f2 = sfopen(NULL, tstfile("sf", 0), "a+"))) terror("Can't open f2"); if (sfwrite(f1, "012345678\n", 10) != 10 || sfsync(f1) < 0) terror("Writing to f1"); if ((p = sftell(f1)) != 10) terror("Bad sftell1 %ld", p); if (sfwrite(f2, "abcdefghi\n", 10) != 10 || sfsync(f2) < 0) terror("Writing to f2"); if ((p = sftell(f2)) != 20) terror("Bad sftell2"); if ((p = sfseek(f1, (Sfoff_t)0, 0)) != 0) terror("Bad seek"); if (!(s = sfgetr(f1, '\n', 1))) terror("Bad getr1"); if (strcmp(s, "012345678") != 0) terror("Bad input1"); if ((p = sftell(f1)) != 10) terror("Bad sftell3"); if (sfwrite(f1, "012345678\n", 10) != 10 || sfsync(f1) < 0) terror("Writing to f1"); if ((p = sftell(f1)) != 30) terror("Bad sftell4"); if ((p = sfseek(f2, (Sfoff_t)10, 0)) != 10) terror("Bad seek"); if (!(s = sfgetr(f2, '\n', 1))) terror("Bad getr2"); if (strcmp(s, "abcdefghi") != 0) terror("Bad input2"); if (!(s = sfgetr(f2, '\n', 1))) terror("Bad getr3"); if (strcmp(s, "012345678") != 0) terror("Bad input3"); if (!(f1 = sfopen(f1, tstfile("sf", 0), "w"))) terror("Can't open file to write"); for (r = 0; r < 1024; ++r) buf[r] = 'a'; if ((w = sfwrite(f1, buf, 1024)) != 1024) terror("writing w=%d", w); if (!(f1 = sfopen(f1, tstfile("sf", 0), "a"))) terror("Can't open file to append"); sfseek(f1, (Sfoff_t)0, 0); if ((w = sfwrite(f1, buf, 64)) != 64) terror("writing w=%d", w); if ((r = (int)sftell(f1)) != (1024 + 64)) terror("seek position wrong s=%d", r); texit(0); }
int ptdump(Pt_t* a, Sfio_t* sp) { Ptprefix_t* p; for (p = (Ptprefix_t*)dtfirst(a->dict); p; p = (Ptprefix_t*)dtnext(a->dict, p)) sfprintf(sp, "%0*I*x %0*I*x %-16s %-16s\n", sizeof(p->min) * 2, sizeof(p->min), p->min, sizeof(p->max) * 2, sizeof(p->max), p->max, fmtip4(p->min, -1), fmtip4(p->max, -1)); return sfsync(sp); }
// // This routine will cause the previous command to be cancelled. // void hist_cancel(History_t *hp) { int c; if (!hp) return; sfputc(hp->histfp, HIST_UNDO); sfputc(hp->histfp, 0); sfsync(hp->histfp); hp->histcnt += 2; c = hist_ind(hp, --hp->histind); hp->histcmds[c] = hp->histcnt; }
main() { if(sfopen(sfstdout,"xxx","w") != sfstdout) terror("Can't open xxx to write\n"); if(sfputr(sfstdout,"012345678\n",-1) != 10) terror("Can't write to xxx\n"); sfsync(sfstdout); if(sfopen(sfstdout,"yyy","w") != sfstdout) terror("Can't open yyy to write\n"); sfclose(sfstdout); return 0; }
static int _sfall() #endif { reg Sfpool_t *p, *next; reg Sfio_t* f; reg int n, rv; reg int nsync, count, loop; #define MAXLOOP 3 for(loop = 0; loop < MAXLOOP; ++loop) { rv = nsync = count = 0; for(p = &_Sfpool; p; p = next) { /* find the next legitimate pool */ for(next = p->next; next; next = next->next) if(next->n_sf > 0) break; /* walk the streams for _Sfpool only */ for(n = 0; n < ((p == &_Sfpool) ? p->n_sf : 1); ++n) { count += 1; f = p->sf[n]; if(f->flags&SF_STRING ) goto did_sync; if(SFFROZEN(f)) continue; if((f->mode&SF_READ) && (f->mode&SF_SYNCED) ) goto did_sync; if((f->mode&SF_READ) && !(f->bits&SF_MMAP) && f->next == f->endb) goto did_sync; if((f->mode&SF_WRITE) && !(f->bits&SF_HOLE) && f->next == f->data) goto did_sync; if(sfsync(f) < 0) rv = -1; did_sync: nsync += 1; } } if(nsync == count) break; } return rv; }
static void putfile(void) { register Line_t* a1; register int n; ed.bytes = 0; ed.lines = 0; a1 = ed.addr1; do { if ((n = sfputr(ed.iop, lineget((a1++)->offset), '\n')) < 0) error(ERROR_SYSTEM|2, "write error"); ed.bytes += n; ed.lines++; } while (a1 <= ed.addr2); if (sfsync(ed.iop)) error(ERROR_SYSTEM|2, "write error"); }
// // Flush the current history command. // void hist_flush(History_t *hp) { char *buff; if (hp) { buff = (char *)sfreserve(hp->histfp, 0, SF_LOCKR); if (buff) { hp->histflush = sfvalue(hp->histfp) + 1; sfwrite(hp->histfp, buff, 0); } else { hp->histflush = 0; } if (sfsync(hp->histfp) < 0) { Shell_t *shp = hp->histshell; hist_close(hp); if (!sh_histinit(shp)) sh_offoption(shp, SH_HISTORY); } else { hp->histflush = 0; } } }
static int flush(Sfio_t* op) { register Col_t* col; register size_t n; if ((col = state.cols) && sfstrtell(col->sp)) { do { n = sfstrtell(col->sp); if (sfwrite(op, sfstrseek(col->sp, 0, SEEK_SET), n) != n || sfsync(op)) { error(ERROR_SYSTEM|2, "write error"); return -1; } } while (col = col->next); } state.cache = state.window; return 0; }
int ptvprint(Ptv_t* a, Sfio_t* sp) { PTVSCAN(a, b, sfprintf(sp, "%s\n", fmtip6(a->r[0], b))); return sfsync(sp); }
int b_cut(int argc, char** argv, void* context) { register char* cp = 0; register Sfio_t* fp; char* s; int n; Cut_t* cut; int mode = 0; Delim_t wdelim; Delim_t ldelim; size_t reclen = 0; cmdinit(argc, argv, context, ERROR_CATALOG, 0); wdelim.chr = '\t'; ldelim.chr = '\n'; wdelim.len = ldelim.len = 1; for (;;) { switch (n = optget(argv, usage)) { case 0: break; case 'b': case 'c': if(mode&C_FIELDS) { error(2, "f option already specified"); continue; } cp = opt_info.arg; if(n=='b') mode |= C_BYTES; else mode |= C_CHARS; continue; case 'D': ldelim.str = opt_info.arg; if (mbwide()) { s = opt_info.arg; ldelim.chr = mbchar(s); if ((n = s - opt_info.arg) > 1) { ldelim.len = n; continue; } } ldelim.chr = *(unsigned char*)opt_info.arg; ldelim.len = 1; continue; case 'd': wdelim.str = opt_info.arg; if (mbwide()) { s = opt_info.arg; wdelim.chr = mbchar(s); if ((n = s - opt_info.arg) > 1) { wdelim.len = n; continue; } } wdelim.chr = *(unsigned char*)opt_info.arg; wdelim.len = 1; continue; case 'f': if(mode&(C_CHARS|C_BYTES)) { error(2, "c option already specified"); continue; } cp = opt_info.arg; mode |= C_FIELDS; continue; case 'n': mode |= C_NOSPLIT; continue; case 'N': mode |= C_NONEWLINE; continue; case 'R': case 'r': if(opt_info.num>0) reclen = opt_info.num; continue; case 's': mode |= C_SUPRESS; continue; case ':': error(2, "%s", opt_info.arg); break; case '?': error(ERROR_usage(2), "%s", opt_info.arg); break; } break; } argv += opt_info.index; if (error_info.errors) error(ERROR_usage(2), "%s",optusage(NiL)); if(!cp) { error(2, "b, c or f option must be specified"); error(ERROR_usage(2), "%s", optusage(NiL)); } if(!*cp) error(3, "non-empty b, c or f option must be specified"); if((mode & (C_FIELDS|C_SUPRESS)) == C_SUPRESS) error(3, "s option requires f option"); cut = cutinit(mode, cp, &wdelim, &ldelim, reclen); if(cp = *argv) argv++; do { if(!cp || streq(cp,"-")) fp = sfstdin; else if(!(fp = sfopen(NiL,cp,"r"))) { error(ERROR_system(0),"%s: cannot open",cp); continue; } if(mode&C_FIELDS) cutfields(cut,fp,sfstdout); else cutcols(cut,fp,sfstdout); if(fp!=sfstdin) sfclose(fp); } while(cp = *argv++); if (sfsync(sfstdout)) error(ERROR_system(0), "write error"); return error_info.errors != 0; }
static pid_t runve(int mode, const char* path, char* const* argv, char* const* envv) { register char* s; register char** p; register char** v; void* m1; void* m2; pid_t pid; int oerrno; int ux; int n; #if defined(_P_DETACH) && defined(_P_NOWAIT) int pgrp; #endif #if CONVERT char* d; char* t; int m; #endif struct stat st; char buf[PATH_MAX]; char tmp[PATH_MAX]; #if DEBUG static int trace; #endif #if defined(_P_DETACH) && defined(_P_NOWAIT) if (mode == _P_DETACH) { /* * 2004-02-29 cygwin _P_DETACH is useless: * spawn*() returns 0 instead of the spawned pid * spawned { pgid sid } are the same as the parent */ mode = _P_NOWAIT; pgrp = 1; } else pgrp = 0; #endif if (!envv) envv = (char* const*)environ; m1 = m2 = 0; oerrno = errno; #if DEBUG if (!trace) trace = (s = getenv("_AST_exec_trace")) ? *s : 'n'; #endif if (execrate(path, buf, sizeof(buf), 0)) { if (!sysstat(buf, &st)) path = (const char*)buf; else errno = oerrno; } if (path != (const char*)buf && sysstat(path, &st)) return -1; if (!S_ISREG(st.st_mode) || !(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) { errno = EACCES; return -1; } if (magic(path, &ux)) { #if _CYGWIN_fork_works errno = ENOEXEC; return -1; #else ux = 1; p = (char**)argv; while (*p++); if (!(v = (char**)malloc((p - (char**)argv + 2) * sizeof(char*)))) { errno = EAGAIN; return -1; } m1 = v; p = v; *p++ = (char*)path; *p++ = (char*)path; path = (const char*)pathshell(); if (*argv) argv++; while (*p++ = (char*)*argv++); argv = (char* const*)v; #endif } /* * the win32 dll search order is * (1) the directory of path * (2) . * (3) /c/(WINNT|WINDOWS)/system32 /c/(WINNT|WINDOWS) * (4) the directories on $PATH * there are no cygwin dlls in (3), so if (1) and (2) fail * to produce the required dlls its up to (4) * * the standard allows PATH to be anything once the path * to an executable is determined; this code ensures that PATH * contains /bin so that at least the cygwin dll, required * by all cygwin executables, will be found */ if (p = (char**)envv) { n = 1; while (s = *p++) if (strneq(s, "PATH=", 5)) { s += 5; do { s = pathcat(s, ':', NiL, "", tmp, sizeof(tmp)); if (streq(tmp, "/usr/bin/") || streq(tmp, "/bin/")) { n = 0; break; } } while (s); if (n) { n = 0; snprintf(tmp, sizeof(tmp), "%s:/bin", *(p - 1)); *(p - 1) = tmp; } break; } if (n) { n = p - (char**)envv + 1; p = (char**)envv; if (v = (char**)malloc(n * sizeof(char*))) { m2 = v; envv = (char* const*)v; *v++ = strcpy(tmp, "PATH=/bin"); while (*v++ = *p++); } } #if CONVERT if (!ux && (d = getenv(convertvars[0]))) for (p = (char**)envv; s = *p; p++) if ((n = convert(d, s)) && (m = cygwin_posix_to_win32_path_list_buf_size(s + n)) > 0) { if (!(t = malloc(n + m + 1))) break; *p = t; memcpy(t, s, n); cygwin_posix_to_win32_path_list(s + n, t + n); } #endif } #if DEBUG if (trace == 'a' || trace == 'e') { sfprintf(sfstderr, "%s %s [", mode == _P_OVERLAY ? "_execve" : "_spawnve", path); for (n = 0; argv[n]; n++) sfprintf(sfstderr, " '%s'", argv[n]); if (trace == 'e') { sfprintf(sfstderr, " ] ["); for (n = 0; envv[n]; n++) sfprintf(sfstderr, " '%s'", envv[n]); } sfprintf(sfstderr, " ]\n"); sfsync(sfstderr); } #endif #if _lib_spawn_mode if (mode != _P_OVERLAY) { pid = sysspawnve(mode, path, argv, envv); #if defined(_P_DETACH) && defined(_P_NOWAIT) if (pid > 0 && pgrp) setpgid(pid, 0); #endif } else #endif { #if defined(_P_DETACH) && defined(_P_NOWAIT) if (pgrp) setpgid(0, 0); #endif pid = sysexecve(path, argv, envv); } if (m1) free(m1); if (m2) free(m2); return pid; }
int pzinflate(register Pz_t* pz, Sfio_t* op) { register Pzpart_t* pp; register int i; register int j; register int k; register size_t n; register size_t m; register unsigned char* pat; ssize_t r; Pzwrite_f writef; if (!(pz->flags & PZ_READ)) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: cannot inflate -- not open for read", pz->path); return -1; } if (pz->flags & PZ_SPLIT) return pzssplit(pz); if (pz->flags & PZ_FORCE) { if (writef = pz->disc->writef) { n = pz->part->row; do { if (!(pat = (unsigned char*)sfreserve(pz->io, n, 0))) { if (sfvalue(pz->io)) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, 2, "%s: data corrupted", pz->path); return -1; } break; } } while ((r = (*writef)(pz, op, pat, pz->disc)) >= 0); if (r < 0) return -1; } else if (sfmove(pz->io, op, SF_UNBOUND, -1) < 0 || sferror(pz->io)) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, 2, "%s: data corrupted", pz->path); return -1; } if (sfsync(op)) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, 2, "%s: output write error", pz->path); return -1; } return 0; } /* * copy the prefix */ if (pz->prefix.count) { if (!pz->prefix.skip && pz->prefix.data && sfwrite(op, pz->prefix.data, pz->prefix.count) != pz->prefix.count) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, 2, "%s: output write error", pz->path); return -1; } pz->prefix.count = 0; } if ((pz->split.flags & (PZ_SPLIT_INFLATE|PZ_SPLIT_PART)) == PZ_SPLIT_INFLATE) i = pzsinflate(pz, op); else { /* * inflate each file */ do { /* * inflate each window */ pp = pz->part; pat = pz->pat; while (m = sfgetu(pz->io)) { /* * hi frequency data in pz->buf */ if (pp->nmap) { if (m > pz->win || (m % pp->nmap) || sfread(pz->io, pz->buf, m) != m) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: data corrupted", pz->path); return -1; } n = m / pp->nmap; m = 0; j = 0; k = 0; for (i = 0; i < pp->nmap; i++) { if (i > 0 && pp->lab[i] == pp->lab[i - 1]) j++; else j = m; if (!pp->value || pp->value[i] < 0) pp->mix[k++] = pz->buf + j; m += n; } } else if (m != 1) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: data corrupted", pz->path); return -1; } /* * lo frequency */ m = sfgetu(pz->io); if (m < pp->row || sfread(pz->io, pat, pp->row) != pp->row) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: data corrupted", pz->path); return -1; } m -= pp->row; if (sfread(pz->io, pz->nxt = pz->val, m) != m) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: data corrupted", pz->path); return -1; } /* * restore lo+hi on op */ if (restore(pz, pp, pz->io, op, pat, pz->wrk, pp->row, k, pp->map, pp->mix, pp->inc)) return -1; } if (!(pz->flags & PZ_SECTION)) { if ((k = sfgetc(pz->io)) == PZ_MARK_PART) { if ((m = sfgetu(pz->io)) && !sferror(pz->io) && !sfeof(pz->io) && (pat = (unsigned char*)sfreserve(pz->io, m, 0))) sfwrite(op, pat, m); } else if (k != EOF) sfungetc(pz->io, k); } if (sferror(op)) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "write error"); return -1; } } while ((i = !(pz->flags & PZ_SECTION)) && (i = pzfile(pz)) > 0); } if (i >= 0 && !(pz->split.flags & PZ_SPLIT_PART) && sfsync(op)) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "write error"); return -1; } return i; }
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; } }
int main(int argc, register char** argv) { register int n; register char* s; char* args; char* codes; char** av; char** ap; int i; int count; int len; int traverse; int size; Dir_t* firstdir; Dir_t* lastdir; Exnode_t* x; Exnode_t* y; Ftw_t ftw; Finddisc_t disc; setlocale(LC_ALL, ""); error_info.id = "tw"; av = argv + 1; args = 0; codes = 0; count = 0; size = 0; traverse = 1; firstdir = lastdir = newof(0, Dir_t, 1, 0); firstdir->name = "."; state.action = LIST; state.cmdflags = CMD_EXIT|CMD_IGNORE|CMD_IMPLICIT|CMD_NEWLINE; state.errexit = EXIT_QUIT; state.ftwflags = ftwflags()|FTW_DELAY; state.select = ALL; state.separator = '\n'; memset(&disc, 0, sizeof(disc)); for (;;) { switch (optget(argv, usage)) { case 'a': args = opt_info.arg; state.cmdflags |= CMD_POST; continue; case 'c': if ((count = opt_info.num) < 0) error(3, "argument count must be >= 0"); continue; case 'd': lastdir = lastdir->next = newof(0, Dir_t, 1, 0); lastdir->name = opt_info.arg; continue; case 'e': compile(opt_info.arg, 0); continue; case 'f': state.pattern = opt_info.arg; continue; case 'i': state.ignore = 1; continue; case 'l': state.localfs = 1; continue; case 'm': state.intermediate = 1; continue; case 'n': traverse = 0; continue; case 'p': state.ftwflags |= FTW_TWICE; continue; case 'q': state.cmdflags |= CMD_QUERY; continue; case 'r': state.ftwflags |= FTW_RECURSIVE; continue; case 's': if ((size = opt_info.num) < 0) error(3, "command size must be >= 0"); continue; case 't': state.cmdflags |= CMD_TRACE; continue; case 'x': state.errexit = opt_info.arg ? opt_info.num : EXIT_QUIT; continue; case 'z': if (s = sfgetr(sfstdin, '\n', 1)) { if (!(s = strdup(s))) error(ERROR_SYSTEM|3, "out of space"); n = state.snapshot.format.delim = *s++; state.snapshot.format.path = s; if (!(s = strchr(s, n))) { osnap: error(3, "invalid snapshot on standard input"); } *s++ = 0; if (!streq(state.snapshot.format.path, SNAPSHOT_ID)) goto osnap; state.snapshot.format.path = s; if (!(s = strchr(s, n))) goto osnap; *s++ = 0; state.snapshot.format.easy = s; if (!(s = strchr(s, n))) goto osnap; *s++ = 0; if (*(state.snapshot.format.hard = s)) { if (!(s = strchr(s, n))) goto osnap; *s = 0; } else state.snapshot.format.hard = 0; state.snapshot.sp = sfstdin; state.snapshot.prev = sfgetr(sfstdin, '\n', 0); } else { state.snapshot.format.path = SNAPSHOT_PATH; state.snapshot.format.easy = SNAPSHOT_EASY; state.snapshot.format.hard = SNAPSHOT_HARD; state.snapshot.format.delim = SNAPSHOT_DELIM[0]; } if (!(state.snapshot.tmp = sfstropen())) error(ERROR_SYSTEM|3, "out of space"); compile("sort:name;", 0); continue; case 'C': state.ftwflags |= FTW_NOSEEDOTDIR; continue; case 'D': error_info.trace = -opt_info.num; continue; case 'E': compile(opt_info.arg, 1); continue; case 'F': codes = opt_info.arg; continue; case 'G': disc.flags |= FIND_GENERATE; if (streq(opt_info.arg, "old")) disc.flags |= FIND_OLD; else if (streq(opt_info.arg, "gnu") || streq(opt_info.arg, "locate")) disc.flags |= FIND_GNU; else if (streq(opt_info.arg, "type")) disc.flags |= FIND_TYPE; else if (streq(opt_info.arg, "?")) { error(2, "formats are { default|dir type old gnu|locate }"); return 0; } else if (!streq(opt_info.arg, "-") && !streq(opt_info.arg, "default") && !streq(opt_info.arg, "dir")) error(3, "%s: invalid find codes format -- { default|dir type old gnu|locate } expected", opt_info.arg); continue; case 'H': state.ftwflags |= FTW_META|FTW_PHYSICAL; continue; case 'I': state.icase = 1; continue; case 'L': state.ftwflags &= ~(FTW_META|FTW_PHYSICAL|FTW_SEEDOTDIR); continue; case 'P': state.ftwflags &= ~FTW_META; state.ftwflags |= FTW_PHYSICAL; continue; case 'S': state.separator = *opt_info.arg; continue; case 'X': state.ftwflags |= FTW_MOUNT; continue; case '?': error(ERROR_USAGE|4, "%s", opt_info.arg); continue; case ':': error(2, "%s", opt_info.arg); continue; } break; } argv += opt_info.index; argc -= opt_info.index; if (error_info.errors) error(ERROR_USAGE|4, "%s", optusage(NiL)); /* * do it */ if (state.snapshot.tmp) sfprintf(sfstdout, "%c%s%c%s%c%s%c%s%c\n", state.snapshot.format.delim, SNAPSHOT_ID, state.snapshot.format.delim, state.snapshot.format.path, state.snapshot.format.delim, state.snapshot.format.easy, state.snapshot.format.delim, state.snapshot.format.hard ? state.snapshot.format.hard : "", state.snapshot.format.delim); if (x = exexpr(state.program, "begin", NiL, 0)) eval(x, NiL); if ((x = exexpr(state.program, "select", NiL, INTEGER)) || (x = exexpr(state.program, NiL, NiL, INTEGER))) state.select = x; if (!(state.ftwflags & FTW_PHYSICAL)) state.ftwflags &= ~FTW_DELAY; memset(&ftw, 0, sizeof(ftw)); ftw.path = ftw.name = ""; if (traverse) { if (x = exexpr(state.program, "action", NiL, 0)) state.action = x; if (x = exexpr(state.program, "sort", NiL, 0)) { state.sortkey = x; y = 0; for (;;) { switch (x->op) { case ',': y = x->data.operand.right; /*FALLTHROUGH*/ case '!': case '~': case S2B: case X2I: x = x->data.operand.left; continue; case ID: if (!(x = y)) break; y = 0; continue; default: error(3, "invalid sort identifier (op 0x%02x)", x->op); break; } break; } state.sort = order; } if (*argv && (*argv)[0] == '-' && (*argv)[1] == 0) { state.ftwflags |= FTW_LIST; argv++; argc--; } if (*argv || args || count || !(state.cmdflags & CMD_IMPLICIT)) { Cmddisc_t disc; CMDDISC(&disc, state.cmdflags, errorf); state.cmd = cmdopen(argv, count, size, args, &disc); state.ftwflags |= FTW_DOT; } else state.cmdflags &= ~CMD_IMPLICIT; if (codes && (disc.flags & FIND_GENERATE)) { char* p; Dir_t* dp; char pwd[PATH_MAX]; char tmp[PATH_MAX]; disc.version = FIND_VERSION; if (state.cmdflags & CMD_TRACE) disc.flags |= FIND_TYPE; if (state.cmdflags & CMD_QUERY) disc.flags |= FIND_OLD; disc.errorf = errorf; if (!(state.find = findopen(codes, NiL, NiL, &disc))) exit(2); if (disc.flags & FIND_TYPE) { state.act = ACT_CODETYPE; compile("_tw_init:mime;", 0); state.magicdisc.flags |= MAGIC_MIME; } else state.act = ACT_CODE; state.icase = 1; state.pattern = 0; state.sort = order; if (!state.program) compile("1", 0); if (!(state.sortkey = newof(0, Exnode_t, 1, 0)) || !(state.sortkey->data.variable.symbol = (Exid_t*)dtmatch(state.program->symbols, "name"))) error(ERROR_SYSTEM|3, "out of space"); state.sortkey->op = ID; s = p = 0; for (dp = (firstdir == lastdir) ? firstdir : firstdir->next; dp; dp = dp->next) { if (*(s = dp->name) == '/') sfsprintf(tmp, sizeof(tmp), "%s", s); else if (!p && !(p = getcwd(pwd, sizeof(pwd)))) error(ERROR_SYSTEM|3, "cannot determine pwd path"); else sfsprintf(tmp, sizeof(tmp), "%s/%s", p, s); pathcanon(tmp, sizeof(tmp), PATH_PHYSICAL); if (!(dp->name = strdup(tmp))) error(ERROR_SYSTEM|3, "out of space [PATH_PHYSICAL]"); } } else if (state.snapshot.tmp) state.act = ACT_SNAPSHOT; else if (state.cmdflags & CMD_IMPLICIT) state.act = ACT_CMDARG; else if (state.action == LIST) state.act = ACT_LIST; else if (state.action) state.act = ACT_EVAL; if (state.intermediate) { state.actII = state.act; state.act = ACT_INTERMEDIATE; } if (state.pattern) { disc.version = FIND_VERSION; if (state.icase) disc.flags |= FIND_ICASE; disc.errorf = errorf; disc.dirs = ap = av; if (firstdir != lastdir) firstdir = firstdir->next; do {*ap++ = firstdir->name;} while (firstdir = firstdir->next); *ap = 0; if (!(state.find = findopen(codes, state.pattern, NiL, &disc))) exit(1); state.ftwflags |= FTW_TOP; n = state.select == ALL ? state.act : ACT_EVAL; while (s = findread(state.find)) { switch (n) { case ACT_CMDARG: if ((i = cmdarg(state.cmd, s, strlen(s))) >= state.errexit) exit(i); break; case ACT_LIST: sfputr(sfstdout, s, '\n'); break; default: ftwalk(s, tw, state.ftwflags, NiL); break; } } } else if (state.ftwflags & FTW_LIST) { sfopen(sfstdin, NiL, "rt"); n = state.select == ALL && state.act == ACT_CMDARG; for (;;) { if (s = sfgetr(sfstdin, state.separator, 1)) len = sfvalue(sfstdin) - 1; else if (state.separator != '\n') { state.separator = '\n'; continue; } else if (s = sfgetr(sfstdin, state.separator, -1)) len = sfvalue(sfstdin); else break; if (!n) ftwalk(s, tw, state.ftwflags, NiL); else if ((i = cmdarg(state.cmd, s, len)) >= state.errexit) exit(i); } if (sferror(sfstdin)) error(ERROR_SYSTEM|2, "input read error"); } else if (firstdir == lastdir) ftwalk(firstdir->name, tw, state.ftwflags, state.sort); else { ap = av; while (firstdir = firstdir->next) *ap++ = firstdir->name; *ap = 0; ftwalk((char*)av, tw, state.ftwflags|FTW_MULTIPLE, state.sort); } if (state.cmd && (i = cmdflush(state.cmd)) >= state.errexit) exit(i); if (state.find && (findclose(state.find) || state.finderror)) exit(2); } else if (state.select) error_info.errors = eval(state.select, &ftw) == 0; if (x = exexpr(state.program, "end", NiL, 0)) eval(x, &ftw); if (sfsync(sfstdout)) error(ERROR_SYSTEM|2, "write error"); exit(error_info.errors != 0); }
int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count) { struct comnod *comptr; struct argnod *ap; register char *out; char *av[2], *begin , *dir=0; int addstar=0, rval=0, var=0, strip=1; int nomarkdirs = !sh_isoption(SH_MARKDIRS); sh_onstate(SH_FCOMPLETE); if(ep->e_nlist) { if(mode=='=' && count>0) { if(count> ep->e_nlist) return(-1); mode = '?'; av[0] = ep->e_clist[count-1]; av[1] = 0; } else { stakset(ep->e_stkptr,ep->e_stkoff); ep->e_nlist = 0; } } comptr = (struct comnod*)stakalloc(sizeof(struct comnod)); ap = (struct argnod*)stakseek(ARGVAL); #if SHOPT_MULTIBYTE { register int c = *cur; register genchar *cp; /* adjust cur */ cp = (genchar *)outbuff + *cur; c = *cp; *cp = 0; *cur = ed_external((genchar*)outbuff,(char*)stakptr(0)); *cp = c; *eol = ed_external((genchar*)outbuff,outbuff); } #endif /* SHOPT_MULTIBYTE */ out = outbuff + *cur + (sh_isoption(SH_VI)!=0); if(out[-1]=='"' || out[-1]=='\'') { rval = -(sh_isoption(SH_VI)!=0); goto done; } comptr->comtyp = COMSCAN; comptr->comarg = ap; ap->argflag = (ARG_MAC|ARG_EXP); ap->argnxt.ap = 0; ap->argchn.cp = 0; { register int c; char *last = out; c = *(unsigned char*)out; var = mode; begin = out = find_begin(outbuff,last,0,&var); /* addstar set to zero if * should not be added */ if(var=='$') { stakputs("${!"); stakwrite(out,last-out); stakputs("@}"); out = last; } else { addstar = '*'; while(out < last) { c = *(unsigned char*)out; if(isexp(c)) addstar = 0; if (c == '/') { if(addstar == 0) strip = 0; dir = out+1; } stakputc(c); out++; } } if(mode=='?') mode = '*'; if(var!='$' && mode=='\\' && out[-1]!='*') addstar = '*'; if(*begin=='~' && !strchr(begin,'/')) addstar = 0; stakputc(addstar); ap = (struct argnod*)stakfreeze(1); } if(mode!='*') sh_onoption(SH_MARKDIRS); { register char **com; char *cp=begin, *left=0, *saveout="."; int nocase=0,narg,cmd_completion=0; register int size='x'; while(cp>outbuff && ((size=cp[-1])==' ' || size=='\t')) cp--; if(!var && !strchr(ap->argval,'/') && (((cp==outbuff&&ep->sh->nextprompt==1) || (strchr(";&|(",size)) && (cp==outbuff+1||size=='('||cp[-2]!='>') && *begin!='~' ))) { cmd_completion=1; sh_onstate(SH_COMPLETE); } if(ep->e_nlist) { narg = 1; com = av; if(dir) begin += (dir-begin); } else { com = sh_argbuild(ep->sh,&narg,comptr,0); /* special handling for leading quotes */ if(begin>outbuff && (begin[-1]=='"' || begin[-1]=='\'')) begin--; } sh_offstate(SH_COMPLETE); /* allow a search to be aborted */ if(ep->sh->trapnote&SH_SIGSET) { rval = -1; goto done; } /* match? */ if (*com==0 || (narg <= 1 && (strcmp(ap->argval,*com)==0) || (addstar && com[0][strlen(*com)-1]=='*'))) { rval = -1; goto done; } if(mode=='\\' && out[-1]=='/' && narg>1) mode = '='; if(mode=='=') { if (strip && !cmd_completion) { register char **ptrcom; for(ptrcom=com;*ptrcom;ptrcom++) /* trim directory prefix */ *ptrcom = path_basename(*ptrcom); } sfputc(sfstderr,'\n'); sh_menu(sfstderr,narg,com); sfsync(sfstderr); ep->e_nlist = narg; ep->e_clist = com; goto done; } /* see if there is enough room */ size = *eol - (out-begin); if(mode=='\\') { int c; if(dir) { c = *dir; *dir = 0; saveout = begin; } if(saveout=astconf("PATH_ATTRIBUTES",saveout,(char*)0)) nocase = (strchr(saveout,'c')!=0); if(dir) *dir = c; /* just expand until name is unique */ size += strlen(*com); } else { size += narg; { char **savcom = com; while (*com) size += strlen(cp=fmtx(*com++)); com = savcom; } } /* see if room for expansion */ if(outbuff+size >= &outbuff[MAXLINE]) { com[0] = ap->argval; com[1] = 0; } /* save remainder of the buffer */ if(*out) left=stakcopy(out); if(cmd_completion && mode=='\\') out = strcopy(begin,path_basename(cp= *com++)); else if(mode=='*') { if(ep->e_nlist && dir && var) { if(*cp==var) cp++; else *begin++ = var; out = strcopy(begin,cp); var = 0; } else out = strcopy(begin,fmtx(*com)); com++; } else out = strcopy(begin,*com++); if(mode=='\\') { saveout= ++out; while (*com && *begin) { if(cmd_completion) out = overlaid(begin,path_basename(*com++),nocase); else out = overlaid(begin,*com++,nocase); } mode = (out==saveout); if(out[-1]==0) out--; if(mode && out[-1]!='/') { if(cmd_completion) { Namval_t *np; /* add as tracked alias */ Pathcomp_t *pp; if(*cp=='/' && (pp=path_dirfind(ep->sh->pathlist,cp,'/')) && (np=nv_search(begin,ep->sh->track_tree,NV_ADD))) path_alias(np,pp); out = strcopy(begin,cp); } /* add quotes if necessary */ if((cp=fmtx(begin))!=begin) out = strcopy(begin,cp); if(var=='$' && begin[-1]=='{') *out = '}'; else *out = ' '; *++out = 0; } else if((cp=fmtx(begin))!=begin) { out = strcopy(begin,cp); if(out[-1] =='"' || out[-1]=='\'') *--out = 0; } if(*begin==0) ed_ringbell(); } else { while (*com) { *out++ = ' '; out = strcopy(out,fmtx(*com++)); } } if(ep->e_nlist) { cp = com[-1]; if(cp[strlen(cp)-1]!='/') { if(var=='$' && begin[-1]=='{') *out = '}'; else *out = ' '; out++; } else if(out[-1] =='"' || out[-1]=='\'') out--; *out = 0; } *cur = (out-outbuff); /* restore rest of buffer */ if(left) out = strcopy(out,left); *eol = (out-outbuff); } done: sh_offstate(SH_FCOMPLETE); if(!ep->e_nlist) stakset(ep->e_stkptr,ep->e_stkoff); if(nomarkdirs) sh_offoption(SH_MARKDIRS); #if SHOPT_MULTIBYTE { register int c,n=0; /* first re-adjust cur */ c = outbuff[*cur]; outbuff[*cur] = 0; for(out=outbuff; *out;n++) mbchar(out); outbuff[*cur] = c; *cur = n; outbuff[*eol+1] = 0; *eol = ed_internal(outbuff,(genchar*)outbuff); } #endif /* SHOPT_MULTIBYTE */ return(rval); }
int b_head(int argc, register char** argv, void* context) { static const char header_fmt[] = "\n==> %s <==\n"; register Sfio_t* fp; register char* cp; register off_t keep = 10; register off_t skip = 0; register int delim = '\n'; int header = 1; char* format = (char*)header_fmt+1; cmdinit(argc, argv, context, ERROR_CATALOG, 0); for (;;) { switch (optget(argv, usage)) { case 'c': delim = -1; /*FALLTHROUGH*/ case 'n': if (opt_info.offset && argv[opt_info.index][opt_info.offset] == 'c') { delim = -1; opt_info.offset++; } if ((keep = opt_info.number) <=0) error(2, "%s: %I*d: positive numeric option argument expected", opt_info.name, sizeof(keep), keep); continue; case 'q': header = argc; continue; case 'v': header = 0; continue; case 's': skip = opt_info.number; continue; case '?': error(ERROR_usage(2), "%s", opt_info.arg); continue; case ':': error(2, "%s", opt_info.arg); continue; } break; } argv += opt_info.index; argc -= opt_info.index; if (error_info.errors) error(ERROR_usage(2), "%s", optusage(NiL)); if (cp = *argv) argv++; do { if (!cp || streq(cp, "-")) { cp = "/dev/stdin"; fp = sfstdin; sfset(fp, SF_SHARE, 1); } else if (!(fp = sfopen(NiL, cp, "r"))) { error(ERROR_system(0), "%s: cannot open", cp); continue; } if (argc > header) sfprintf(sfstdout, format, cp); format = (char*)header_fmt; if (skip > 0) sfmove(fp, NiL, skip, delim); if (sfmove(fp, sfstdout, keep, delim) < 0 && errno != EPIPE) error(ERROR_system(0), "%s: read error", cp); if (fp != sfstdin) sfclose(fp); } while (cp = *argv++); if (sfsync(sfstdout)) error(ERROR_system(0), "write error"); return error_info.errors != 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; }
/* * 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); }
/* test compliance of certain stdio behaviors */ tmain() { FILE *f, *f2; long s1, s2; int i, k, fd; char buf[128*1024], rbuf[1024], *sp; if(argc > 1) { if(sfwrite(sfstdout,argv[1],strlen(argv[1])) != strlen(argv[1])) terror("Can't write to stdout"); sfsync(sfstdout); return 0; } /* test for shared streams and seek behavior */ if(!(f = fopen(tstfile("sf", 0),"w+")) ) terror("Opening file to read&write"); /* change stdout to a dup of fileno(f) */ fd = dup(1); close(1); dup(fileno(f)); /* write something to the dup file descriptor */ system(sfprints("%s 0123456789", argv[0])); /* change stdout back */ close(1); dup(fd); close(fd); /* this fseek should reset the stream back to where we can read */ fseek(f, 0L, SEEK_SET); /* see if data is any good */ fread(buf, sizeof(buf), 1, f); for(i = 0; i < 10; ++i) if(buf[i] != '0'+i) terror("Bad data0"); /* construct a bunch of lines and out put to f */ sp = buf; for(k = 0; k < sizeof(buf)/10; ++k) { for(i = 0; i < 9; ++i) *sp++ = '0' + i; *sp++ = '\n'; } /* write out a bunch of thing */ fseek(f, 0L, SEEK_SET); if(fwrite(buf, sizeof(buf), 1, f) != 1) terror("Writing data"); if((fd = dup(fileno(f))) < 0) terror("Can't dup file descriptor"); if(!(f2 = fdopen(fd, "r")) ) terror("Can't create stream"); /* read a few bytes from this dup stream */ fseek(f2, 0L, SEEK_SET); rbuf[0] = 0; if(fread(rbuf, 1, 7, f2) != 7) terror("Bad read"); for(i = 0; i < 7; ++i) if(rbuf[i] != '0'+i) terror("Bad data1"); if((s2 = ftell(f2)) != 7) terror("Bad tell location in f2"); /* now seek way off on f */ fseek(f, 1005L, SEEK_SET); rbuf[0] = 0; fread(rbuf, 5, 1, f); for(i = 5; i < 9; ++i) if(rbuf[i-5] != '0'+i) terror("Bad data2"); if(rbuf[i-5] != '\n') terror("Bad data: did not get new-line"); if((s1 = ftell(f)) != 1010) terror("Bad location in f: s1=%lld", (Sflong_t)s1); fseek(f, 0L, SEEK_CUR); /* switch mode so we can write */ if(fputc('x',f) < 0) terror("fputc failed"); if(fflush(f) < 0) terror("fflush failed"); if((s1 = ftell(f)) != 1011) terror("Bad location in f: s1=%lld", (Sflong_t)s1); fseek(f, -1L, SEEK_CUR); /* set the seek location in the file descriptor */ fflush(f2); /* assuming POSIX conformance and to set seek location to 1010 */ if((s2 = ftell(f2)) != 1010) terror("Bad location in f2: s2=%lld", (Sflong_t)s2); fread(rbuf, 10, 1, f2); if(rbuf[0] != 'x') terror("Didn't get x"); for(i = 1; i < 9; ++i) if(rbuf[i] != '0'+i) terror("Bad data3"); if(rbuf[i] != '\n') terror("Did not get new-line"); texit(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; }
int test_unop(Shell_t *shp,register int op,register const char *arg) { struct stat statb; int f; switch(op) { case 'r': return(permission(arg, R_OK)); case 'w': return(permission(arg, W_OK)); case 'x': return(permission(arg, X_OK)); case 'V': #if SHOPT_FS_3D { register int offset = staktell(); if(stat(arg,&statb)<0 || !S_ISREG(statb.st_mode)) return(0); /* add trailing / */ stakputs(arg); stakputc('/'); stakputc(0); arg = (const char*)stakptr(offset); stakseek(offset); /* FALL THRU */ } #else return(0); #endif /* SHOPT_FS_3D */ case 'd': return(test_stat(arg,&statb)>=0 && S_ISDIR(statb.st_mode)); case 'c': return(test_stat(arg,&statb)>=0 && S_ISCHR(statb.st_mode)); case 'b': return(test_stat(arg,&statb)>=0 && S_ISBLK(statb.st_mode)); case 'f': return(test_stat(arg,&statb)>=0 && S_ISREG(statb.st_mode)); case 'u': return(test_mode(arg)&S_ISUID); case 'g': return(test_mode(arg)&S_ISGID); case 'k': #ifdef S_ISVTX return(test_mode(arg)&S_ISVTX); #else return(0); #endif /* S_ISVTX */ #if SHOPT_TEST_L case 'l': #endif case 'L': case 'h': /* undocumented, and hopefully will disappear */ if(*arg==0 || arg[strlen(arg)-1]=='/' || lstat(arg,&statb)<0) return(0); return(S_ISLNK(statb.st_mode)); case 'C': #ifdef S_ISCTG return(test_stat(arg,&statb)>=0 && S_ISCTG(statb.st_mode)); #else return(0); #endif /* S_ISCTG */ case 'H': #ifdef S_ISCDF { register int offset = staktell(); if(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode)) return(1); stakputs(arg); stakputc('+'); stakputc(0); arg = (const char*)stakptr(offset); stakseek(offset); return(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode)); } #else return(0); #endif /* S_ISCDF */ case 'S': return(isasock(arg,&statb)); case 'N': return(test_stat(arg,&statb)>=0 && tmxgetmtime(&statb) > tmxgetatime(&statb)); case 'p': return(isapipe(arg,&statb)); case 'n': return(*arg != 0); case 'z': return(*arg == 0); case 's': sfsync(sfstdout); case 'O': case 'G': if(*arg==0 || test_stat(arg,&statb)<0) return(0); if(op=='s') return(statb.st_size>0); else if(op=='O') return(statb.st_uid==shp->gd->userid); return(statb.st_gid==shp->gd->groupid); case 'a': case 'e': if(memcmp(arg,"/dev/",5)==0 && sh_open(arg,O_NONBLOCK)) return(1); return(permission(arg, F_OK)); case 'o': f=1; if(*arg=='?') return(sh_lookopt(arg+1,&f)>0); op = sh_lookopt(arg,&f); return(op && (f==(sh_isoption(op)!=0))); case 't': { char *last; op = strtol(arg,&last, 10); return(*last?0:tty_check(op)); } case 'v': case 'R': { Namval_t *np; Namarr_t *ap; int isref; if(!(np = nv_open(arg,shp->var_tree,NV_VARNAME|NV_NOFAIL|NV_NOADD|NV_NOREF))) return(0); isref = nv_isref(np); if(op=='R') return(isref); if(isref) { if(np->nvalue.cp) np = nv_refnode(np); else return(0); } if(ap = nv_arrayptr(np)) return(nv_arrayisset(np,ap)); return(!nv_isnull(np) || nv_isattr(np,NV_INTEGER)); } default: { static char a[3] = "-?"; a[1]= op; errormsg(SH_DICT,ERROR_exit(2),e_badop,a); /* NOTREACHED */ return(0); } } }
// // File name generation for edit modes. // Non-zero exit for error, <0 ring bell. // Don't search back past beginning of the buffer. // Mode is '*' for inline expansion. // Mode is '\' for filename completion. // Mode is '=' cause files to be listed in select format. // int ed_expand(Edit_t *ep, char outbuff[], int *cur, int *eol, int mode, int count) { struct comnod *comptr; struct argnod *ap; char *out; char *av[2], *begin; char *dir = NULL; int addstar = 0, rval = 0, var = 0, strip = 1, narg = 0; int nomarkdirs = !sh_isoption(ep->sh, SH_MARKDIRS); Shell_t *shp = ep->sh; char **com = NULL; sh_onstate(shp, SH_FCOMPLETE); if (ep->e_nlist) { if (mode == '=' && count > 0) { if (count > ep->e_nlist) return -1; mode = '?'; av[0] = ep->e_clist[count - 1]; av[1] = 0; } else { stkset(shp->stk, ep->e_stkptr, ep->e_stkoff); ep->e_nlist = 0; } } comptr = stkalloc(shp->stk, sizeof(struct comnod)); ap = (struct argnod *)stkseek(shp->stk, ARGVAL); { // Adjust cur. int c; genchar *cp; cp = (genchar *)outbuff + *cur; c = *cp; *cp = 0; *cur = ed_external((genchar *)outbuff, (char *)stkptr(shp->stk, 0)); *cp = c; *eol = ed_external((genchar *)outbuff, outbuff); } out = outbuff + *cur + (sh_isoption(shp, SH_VI) != 0); #if 0 if(out[-1]=='"' || out[-1]=='\'') { rval = -(sh_isoption(shp,SH_VI)!=0); goto done; } #endif comptr->comtyp = COMSCAN; comptr->comarg = ap; ap->argflag = (ARG_MAC | ARG_EXP); ap->argnxt.ap = NULL; ap->argchn.cp = NULL; { char *last = out; Namval_t *np = nv_search("COMP_KEY", shp->var_tree, 0); if (np) STORE_VT(np->nvalue, i16, '\t'); np = nv_search("COMP_TYPE", shp->var_tree, 0); if (np) STORE_VT(np->nvalue, i16, mode == '\\' ? '\t' : '?'); var = mode; begin = out = find_begin(outbuff, last, 0, &var); if (ep->compdict && mode != '?' && (com = prog_complete(ep->compdict, outbuff, out, *cur))) { char **av; for (av = com; *av; av++) { ; // empty loop } narg = av - com; } // Addstar set to zero if * should not be added. if (var == '$') { sfwrite(shp->stk, "${!", 3); sfwrite(shp->stk, out, last - out); sfwrite(shp->stk, "$@}", 2); out = last; } else { addstar = '*'; while (out < last) { char c = *out; if (c == 0) break; if (isexp(c)) addstar = 0; if (c == '/') { if (addstar == 0) strip = 0; dir = out + 1; } sfputc(shp->stk, c); out++; } } if (mode == '?') mode = '*'; if (var != '$' && mode == '\\' && out[-1] != '*') addstar = '*'; if (*begin == '~' && !strchr(begin, '/')) addstar = 0; sfputc(shp->stk, addstar); ap = (struct argnod *)stkfreeze(shp->stk, 1); } if (mode != '*') sh_onoption(shp, SH_MARKDIRS); { char *cp = begin, *left = NULL; int cmd_completion = 0; int size = 'x'; while (cp > outbuff && ((size = cp[-1]) == ' ' || size == '\t')) cp--; if (!var && !strchr(ap->argval, '/') && ((cp == outbuff && shp->nextprompt == 1) || (strchr(";&|(", size) && (cp == outbuff + 1 || size == '(' || cp[-2] != '>') && *begin != '~'))) { cmd_completion = 1; sh_onstate(shp, SH_COMPLETE); } if (ep->e_nlist) { narg = 1; com = av; if (dir) begin += (dir - begin); } else { if (!com) com = sh_argbuild(shp, &narg, comptr, 0); // Special handling for leading quotes. if (begin > outbuff && (begin[-1] == '"' || begin[-1] == '\'')) begin--; } sh_offstate(shp, SH_COMPLETE); // Allow a search to be aborted. if (shp->trapnote & SH_SIGSET) { rval = -1; goto done; } // Match? if (*com == 0 || ((narg <= 1 && (strcmp(ap->argval, *com) == 0)) || (addstar && com[0][strlen(*com) - 1] == '*'))) { rval = -1; goto done; } if (mode == '\\' && out[-1] == '/' && narg > 1) mode = '='; if (mode == '=') { if (strip && !cmd_completion) { char **ptrcom; for (ptrcom = com; *ptrcom; ptrcom++) { // trim directory prefix *ptrcom = path_basename(*ptrcom); } } sfputc(sfstderr, '\n'); sh_menu(shp, sfstderr, narg, com); sfsync(sfstderr); ep->e_nlist = narg; ep->e_clist = com; goto done; } // See if there is enough room. size = *eol - (out - begin); if (mode == '\\') { int c; if (dir) { c = *dir; *dir = 0; } if (dir) *dir = c; // Just expand until name is unique. size += strlen(*com); } else { char **tmpcom = com; size += narg; while (*tmpcom) { cp = fmtx(shp, *tmpcom++); size += strlen(cp); } } // See if room for expansion. if (outbuff + size >= &outbuff[MAXLINE]) { com[0] = ap->argval; com[1] = 0; } // Save remainder of the buffer. if (*out) left = stkcopy(shp->stk, out); if (cmd_completion && mode == '\\') { cp = *com++; out = stpcpy(begin, path_basename(cp)); } else if (mode == '*') { if (ep->e_nlist && dir && var) { if (*cp == var) { cp++; } else { *begin++ = var; } out = stpcpy(begin, cp); var = 0; } else { out = stpcpy(begin, fmtx(shp, *com)); } com++; } else { out = stpcpy(begin, *com++); } if (mode == '\\') { char *saveout = ++out; while (*com && *begin) { if (cmd_completion) { out = overlaid(begin, path_basename(*com++), false); } else { out = overlaid(begin, *com++, false); } } mode = (out == saveout); if (out[-1] == 0) out--; if (mode && out[-1] != '/') { if (cmd_completion) { Namval_t *np; // Add as tracked alias. Pathcomp_t *pp; if (*cp == '/' && (pp = path_dirfind(shp->pathlist, cp, '/')) && (np = nv_search(begin, shp->track_tree, NV_ADD))) { path_alias(np, pp); } out = stpcpy(begin, cp); } // Add quotes if necessary. if ((cp = fmtx(shp, begin)) != begin) out = stpcpy(begin, cp); if (var == '$' && begin[-1] == '{') { *out = '}'; } else { *out = ' '; } *++out = 0; } else if ((cp = fmtx(shp, begin)) != begin) { out = stpcpy(begin, cp); if (out[-1] == '"' || out[-1] == '\'') *--out = 0; } if (*begin == 0 && begin[-1] != ' ') ed_ringbell(); } else { while (*com) { *out++ = ' '; out = stpcpy(out, fmtx(shp, *com++)); } } if (ep->e_nlist) { cp = com[-1]; if (cp[strlen(cp) - 1] != '/') { if (var == '$' && begin[-1] == '{') { *out = '}'; } else { *out = ' '; } out++; } else if (out[-1] == '"' || out[-1] == '\'') { out--; } *out = 0; } *cur = (out - outbuff); // Restore rest of buffer. if (left) out = stpcpy(out, left); *eol = (out - outbuff); } done: sh_offstate(shp, SH_FCOMPLETE); if (!ep->e_nlist) stkset(shp->stk, ep->e_stkptr, ep->e_stkoff); if (nomarkdirs) sh_offoption(shp, SH_MARKDIRS); { // First re-adjust cur. int c, n = 0; c = outbuff[*cur]; outbuff[*cur] = 0; for (out = outbuff; *out; n++) mb1char(&out); outbuff[*cur] = c; *cur = n; outbuff[*eol + 1] = 0; *eol = ed_internal(outbuff, (genchar *)outbuff); } return rval; }
// // 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; }
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; }
int pzheadwrite(Pz_t* pz, Sfio_t* op) { register size_t i; register size_t m; register size_t n; register char* s; if (pz->flags & PZ_HEAD) return 0; pz->oop = op; if (!(pz->flags & PZ_NOGZIP)) sfdcgzip(op, 0); if (pz->flags & PZ_NOPZIP) return 0; sfputc(op, PZ_MAGIC_1); sfputc(op, PZ_MAGIC_2); if (sfsync(op)) return -1; sfputc(op, pz->major = PZ_MAJOR); sfputc(op, pz->minor = PZ_MINOR); sfputu(op, pz->win); if (pz->disc->comment) { sfputc(op, PZ_HDR_comment); m = strlen(pz->disc->comment) + 1; sfputu(op, m); sfwrite(op, pz->disc->comment, m); } if (pz->det && (m = sfstrtell(pz->det))) { sfputc(op, PZ_HDR_options); if (!(s = sfstruse(pz->det))) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "out of space"); return -1; } m++; sfputu(op, m); sfwrite(op, s, m); } if (i = pz->prefix.count) { sfputc(op, PZ_HDR_prefix); if (pz->prefix.terminator >= 0) { m = 0; while (i-- > 0) { if (!(s = sfgetr(pz->io, pz->prefix.terminator, 0))) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, 2, "%s: cannot read %I*u prefix record%s from data", pz->path, sizeof(pz->prefix.count), pz->prefix.count, pz->prefix.count == 1 ? "" : "s"); return -1; } m += n = sfvalue(pz->io); sfwrite(pz->tmp, s, n); } s = sfstrseek(pz->tmp, 0, SEEK_SET); } else { m = i; if (!(s = (char*)sfreserve(pz->io, m, 0))) { if (pz->disc->errorf) (*pz->disc->errorf)(pz, pz->disc, 2, "%s: cannot read %I*u prefix byte%s from data", pz->path, sizeof(pz->prefix.count), pz->prefix.count, pz->prefix.count == 1 ? "" : "s"); return -1; } } sfputu(op, m); sfwrite(op, s, m); } pz->flags |= PZ_HEAD; return pzpartwrite(pz, op); }
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 b_kill(int argc,char *argv[],void *extra) { register char *signame; register int sig=SIGTERM, flag=0, n; register Shell_t *shp = ((Shbltin_t*)extra)->shp; NOT_USED(argc); while((n = optget(argv,sh_optkill))) switch(n) { case ':': if((signame=argv[opt_info.index++]) && (sig=sig_number(shp,signame+1))>=0) goto endopts; opt_info.index--; errormsg(SH_DICT,2, "%s", opt_info.arg); break; case 'n': sig = (int)opt_info.num; goto endopts; case 's': flag |= S_FLAG; signame = opt_info.arg; goto endopts; case 'l': flag |= L_FLAG; break; case '?': errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); break; } endopts: argv += opt_info.index; if(*argv && strcmp(*argv,"--")==0 && strcmp(*(argv-1),"--")!=0) argv++; if(error_info.errors || flag==(L_FLAG|S_FLAG) || (!(*argv) && !(flag&L_FLAG))) errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0)); /* just in case we send a kill -9 $$ */ sfsync(sfstderr); if(flag&L_FLAG) { if(!(*argv)) sig_list(shp,0); else while(signame = *argv++) { if(isdigit(*signame)) sig_list(shp,((int)strtol(signame, (char**)0, 10)&0177)+1); else { if((sig=sig_number(shp,signame))<0) { shp->exitval = 2; errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame); } sfprintf(sfstdout,"%d\n",sig); } } return(shp->exitval); } if(flag&S_FLAG) { if((sig=sig_number(shp,signame)) < 0 || sig > shp->gd->sigmax) errormsg(SH_DICT,ERROR_exit(1),e_nosignal,signame); } if(job_walk(sfstdout,job_kill,sig,argv)) shp->exitval = 1; return(shp->exitval); }
int b_date(int argc, register char** argv, void* context) { register int n; register char* s; register Fmt_t* f; char* t; unsigned long u; Time_t now; Time_t ts; Time_t te; Time_t e; char buf[1024]; Fmt_t* fmts; Fmt_t fmt; struct stat st; char* cmd = argv[0]; /* original command path */ char* format = 0; /* tmxfmt() format */ char* string = 0; /* date string */ int elapsed = 0; /* args are start/stop pairs */ int filetime = 0; /* use this st_ time field */ int increment = 0; /* incrementally adjust time */ int last = 0; /* display the last time arg */ Tm_zone_t* listzones = 0; /* known time zone table */ int network = 0; /* don't set network time */ int show = 0; /* show date and don't set */ int unelapsed = 0; /* fmtelapsed() => strelapsed */ cmdinit(argc, argv, context, ERROR_CATALOG, 0); tm_info.flags = TM_DATESTYLE; fmts = &fmt; fmt.format = ""; fmt.next = 0; for (;;) { switch (optget(argv, usage)) { case 'a': case 'c': case 'm': filetime = opt_info.option[1]; continue; case 'd': string = opt_info.arg; show = 1; continue; case 'e': format = "%#"; continue; case 'E': elapsed = 1; continue; case 'f': format = opt_info.arg; continue; case 'i': increment = 1; continue; case 'l': tm_info.flags |= TM_LEAP; continue; case 'L': last = 1; continue; case 'n': network = 1; continue; case 'p': if (!(f = newof(0, Fmt_t, 1, 0))) error(ERROR_SYSTEM|3, "out of space [format]"); f->next = fmts; f->format = opt_info.arg; fmts = f; continue; case 's': show = 1; continue; case 'u': tm_info.flags |= TM_UTC; continue; case 'U': unelapsed = (int)opt_info.num; continue; case 'z': listzones = tm_data.zone; continue; case '?': error(ERROR_USAGE|4, "%s", opt_info.arg); continue; case ':': error(2, "%s", opt_info.arg); continue; } break; } argv += opt_info.index; if (error_info.errors) error(ERROR_USAGE|4, "%s", optusage(NiL)); now = tmxgettime(); if (listzones) { s = "-"; while (listzones->standard) { if (listzones->type) s = listzones->type; sfprintf(sfstdout, "%3s %4s %4s %4d %4d\n", s, *listzones->standard ? listzones->standard : "-", listzones->daylight ? listzones->daylight : "-", listzones->west, listzones->dst); listzones++; show = 1; } } else if (elapsed) { e = 0; while (s = *argv++) { if (!(t = *argv++)) { argv--; t = "now"; } ts = convert(fmts, s, now); te = convert(fmts, t, now); if (te > ts) e += te - ts; else e += ts - te; } sfputr(sfstdout, fmtelapsed((unsigned long)tmxsec(e), 1), '\n'); show = 1; } else if (unelapsed) { while (s = *argv++) { u = strelapsed(s, &t, unelapsed); if (*t) error(3, "%s: invalid elapsed time", s); sfprintf(sfstdout, "%lu\n", u); } show = 1; } else if (filetime) { if (!*argv) error(ERROR_USAGE|4, "%s", optusage(NiL)); n = argv[1] != 0; while (s = *argv++) { if (stat(s, &st)) error(2, "%s: not found", s); else { switch (filetime) { case 'a': now = tmxgetatime(&st); break; case 'c': now = tmxgetctime(&st); break; default: now = tmxgetmtime(&st); break; } tmxfmt(buf, sizeof(buf), format, now); if (n) sfprintf(sfstdout, "%s: %s\n", s, buf); else sfprintf(sfstdout, "%s\n", buf); show = 1; } } } else { if ((s = *argv) && !format && *s == '+') { format = s + 1; argv++; s = *argv; } if (s || (s = string)) { if (*argv && string) error(ERROR_USAGE|4, "%s", optusage(NiL)); now = convert(fmts, s, now); if (*argv && (s = *++argv)) { show = 1; do { if (!last) { tmxfmt(buf, sizeof(buf), format, now); sfprintf(sfstdout, "%s\n", buf); } now = convert(fmts, s, now); } while (s = *++argv); } } else show = 1; if (format || show) { tmxfmt(buf, sizeof(buf), format, now); sfprintf(sfstdout, "%s\n", buf); } else if (settime(context, cmd, now, increment, network)) error(ERROR_SYSTEM|3, "cannot set system time"); } while (fmts != &fmt) { f = fmts; fmts = fmts->next; free(f); } tm_info.flags = 0; if (show && sfsync(sfstdout)) error(ERROR_system(0), "write error"); return error_info.errors != 0; }