#include "sam.h" Rune genbuf[BLOCKSIZE];int io;int panicking;int rescuing;String genstr;String rhs;String curwd;String cmdstr;Rune empty[] = { 0 };char *genc;File *curfile;File *flist;File *cmd;jmp_buf mainloop;List tempfile = { 'p' };int quitok = TRUE;int downloaded;int dflag;int Rflag;char *machine;char *home;int bpipeok;int termlocked;char *samterm = SAMTERM;char *rsamname = RSAM;File *lastfile;Disk *disk;long seq; Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; void usage(void); void main(int argc, char *argv[]){ int i; String *t; char *termargs[10], **ap; ap = termargs; *ap++ = "samterm"; ARGBEGIN{ case 'd': dflag++; break; case 'r': machine = EARGF(usage()); break; case 'R': Rflag++; break; case 't': samterm = EARGF(usage()); break; case 's': rsamname = EARGF(usage()); break; default: dprint("sam: unknown flag %c\n", ARGC()); usage(); /* options for samterm */ case 'a': *ap++ = "-a"; break; }ARGEND *ap = nil; Strinit(&cmdstr); Strinit0(&lastpat); Strinit0(&lastregexp); Strinit0(&genstr); Strinit0(&rhs); Strinit0(&curwd); Strinit0(&plan9cmd); home = getenv(HOME); disk = diskinit(); if(home == 0) home = "/"; if(!dflag) startup(machine, Rflag, termargs, argv); notify(notifyf); getcurwd(); if(argc>0){ for(i=0; i<argc; i++){ if(!setjmp(mainloop)){ t = tmpcstr(argv[i]); Straddc(t, '\0'); Strduplstr(&genstr, t); freetmpstr(t); fixname(&genstr); logsetname(newfile(), &genstr); } } }else if(!downloaded) newfile(); seq++; if(file.nused) current(file.filepptr[0]); setjmp(mainloop); cmdloop(); trytoquit(); /* if we already q'ed, quitok will be TRUE */ exits(0);} voidusage(void){ dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n"); exits("usage");} voidrescue(void){ int i, nblank = 0; File *f; char *c; char buf[256]; if(rescuing++) return; io = -1; for(i=0; i<file.nused; i++){ f = file.filepptr[i]; if(f==cmd || f->nc==0 || !fileisdirty(f)) continue; if(io == -1){ sprint(buf, "%s/sam.save", home); io = create(buf, 1, 0777); if(io<0) return; } if(f->name.s[0]){ c = Strtoc(&f->name); strncpy(buf, c, sizeof buf-1); buf[sizeof buf-1] = 0; free(c); }else sprint(buf, "nameless.%d", nblank++); fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf); addr.r.p1 = 0, addr.r.p2 = f->nc; writeio(f); fprint(io, "\n---%s\n", (char *)buf); }} voidpanic(char *s){ int wasd; if(!panicking++ && !setjmp(mainloop)){ wasd = downloaded; downloaded = 0; dprint("sam: panic: %s: %r\n", s); if(wasd) fprint(2, "sam: panic: %s: %r\n", s); rescue(); abort(); }} voidhiccough(char *s){ File *f; int i; if(rescuing) exits("rescue"); if(s) dprint("%s\n", s); resetcmd(); resetxec(); resetsys(); if(io > 0) close(io); /* * back out any logged changes & restore old sequences */ for(i=0; i<file.nused; i++){ f = file.filepptr[i]; if(f==cmd) continue; if(f->seq==seq){ bufdelete(&f->epsilon, 0, f->epsilon.nc); f->seq = f->prevseq; f->dot.r = f->prevdot; f->mark = f->prevmark; state(f, f->prevmod ? Dirty: Clean); } } update(); if (curfile) { if (curfile->unread) curfile->unread = FALSE; else if (downloaded) outTs(Hcurrent, curfile->tag); } longjmp(mainloop, 1);} voidintr(void){ error(Eintr);} voidtrytoclose(File *f){ char *t; char buf[256]; if(f == cmd) /* possible? */ return; if(f->deleted) return; if(fileisdirty(f) && !f->closeok){ f->closeok = TRUE; if(f->name.s[0]){ t = Strtoc(&f->name); strncpy(buf, t, sizeof buf-1); free(t); }else strcpy(buf, "nameless file"); error_s(Emodified, buf); } f->deleted = TRUE;} voidtrytoquit(void){ int c; File *f; if(!quitok){ for(c = 0; c<file.nused; c++){ f = file.filepptr[c]; if(f!=cmd && fileisdirty(f)){ quitok = TRUE; eof = FALSE; error(Echanges); } } }} voidload(File *f){ Address saveaddr; Strduplstr(&genstr, &f->name); filename(f); if(f->name.s[0]){ saveaddr = addr; edit(f, 'I'); addr = saveaddr; }else{ f->unread = 0; f->cleanseq = f->seq; } fileupdate(f, TRUE, TRUE);} voidcmdupdate(void){ if(cmd && cmd->seq!=0){ fileupdate(cmd, FALSE, downloaded); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc; telldot(cmd); }} voiddelete(File *f){ if(downloaded && f->rasp) outTs(Hclose, f->tag); delfile(f); if(f == curfile) current(0);} voidupdate(void){ int i, anymod; File *f; settempfile(); for(anymod = i=0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f==cmd) /* cmd gets done in main() */ continue; if(f->deleted) { delete(f); continue; } if(f->seq==seq && fileupdate(f, FALSE, downloaded)) anymod++; if(f->rasp) telldot(f); } if(anymod) seq++;} File *current(File *f){ return curfile = f;} voidedit(File *f, int cmd){ int empty = TRUE; Posn p; int nulls; if(cmd == 'r') logdelete(f, addr.r.p1, addr.r.p2); if(cmd=='e' || cmd=='I'){ logdelete(f, (Posn)0, f->nc); addr.r.p2 = f->nc; }else if(f->nc!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0)) empty = FALSE; if((io = open(genc, OREAD))<0) { if (curfile && curfile->unread) curfile->unread = FALSE; error_r(Eopen, genc); } p = readio(f, &nulls, empty, TRUE); closeio((cmd=='e' || cmd=='I')? -1 : p); if(cmd == 'r') f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p; else f->ndot.r.p1 = f->ndot.r.p2 = 0; f->closeok = empty; if (quitok) quitok = empty; else quitok = FALSE; state(f, empty && !nulls? Clean : Dirty); if(empty && !nulls) f->cleanseq = f->seq; if(cmd == 'e') filename(f);} intgetname(File *f, String *s, int save){ int c, i; Strzero(&genstr); if(genc){ free(genc); genc = 0; } if(s==0 || (c = s->s[0])==0){ /* no name provided */ if(f) Strduplstr(&genstr, &f->name); goto Return; } if(c!=' ' && c!='\t') error(Eblank); for(i=0; (c=s->s[i])==' ' || c=='\t'; i++) ; while(s->s[i] > ' ') Straddc(&genstr, s->s[i++]); if(s->s[i]) error(Enewline); fixname(&genstr); if(f && (save || f->name.s[0]==0)){ logsetname(f, &genstr); if(Strcmp(&f->name, &genstr)){ quitok = f->closeok = FALSE; f->qidpath = 0; f->mtime = 0; state(f, Dirty); /* if it's 'e', fix later */ } } Return: genc = Strtoc(&genstr); i = genstr.n; if(i && genstr.s[i-1]==0) i--; return i; /* strlen(name) */} voidfilename(File *f){ if(genc) free(genc); genc = Strtoc(&genstr); dprint("%c%c%c %s\n", " '"[f->mod], "-+"[f->rasp!=0], " ."[f==curfile], genc);} voidundostep(File *f, int isundo){ uint p1, p2; int mod; mod = f->mod; fileundo(f, isundo, 1, &p1, &p2, TRUE); f->ndot = f->dot; if(f->mod){ f->closeok = 0; quitok = 0; }else f->closeok = 1; if(f->mod != mod){ f->mod = mod; if(mod) mod = Clean; else mod = Dirty; state(f, mod); }} intundo(int isundo){ File *f; int i; Mod max; max = undoseq(curfile, isundo); if(max == 0) return 0; settempfile(); for(i = 0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && undoseq(f, isundo)==max) undostep(f, isundo); } return 1;} intreadcmd(String *s){ int retcode; if(flist != 0) fileclose(flist); flist = fileopen(); addr.r.p1 = 0, addr.r.p2 = flist->nc; retcode = plan9(flist, '<', s, FALSE); fileupdate(flist, FALSE, FALSE); flist->seq = 0; if (flist->nc > BLOCKSIZE) error(Etoolong); Strzero(&genstr); Strinsure(&genstr, flist->nc); bufread(flist, (Posn)0, genbuf, flist->nc); memmove(genstr.s, genbuf, flist->nc*RUNESIZE); genstr.n = flist->nc; Straddc(&genstr, '\0'); return retcode;} voidgetcurwd(void){ String *t; char buf[256]; buf[0] = 0; getwd(buf, sizeof(buf)); t = tmpcstr(buf); Strduplstr(&curwd, t); freetmpstr(t); if(curwd.n == 0) warn(Wpwd); else if(curwd.s[curwd.n-1] != '/') Straddc(&curwd, '/');} voidcd(String *str){ int i, fd; char *s;Lines 1–500 of 716. Load more
#include "sam.h" Rune genbuf[BLOCKSIZE]; int io; int panicking; int rescuing; String genstr; String rhs; String curwd; String cmdstr; Rune empty[] = { 0 }; char *genc; File *curfile; File *flist; File *cmd; jmp_buf mainloop; List tempfile = { 'p' }; int quitok = TRUE; int downloaded; int dflag; int Rflag; char *machine; char *home; int bpipeok; int termlocked; char *samterm = SAMTERM; char *rsamname = RSAM; File *lastfile; Disk *disk; long seq; Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; void usage(void); void main(int argc, char *argv[]) { int i; String *t; char *termargs[10], **ap; ap = termargs; *ap++ = "samterm"; ARGBEGIN{ case 'd': dflag++; break; case 'r': machine = EARGF(usage()); break; case 'R': Rflag++; break; case 't': samterm = EARGF(usage()); break; case 's': rsamname = EARGF(usage()); break; default: dprint("sam: unknown flag %c\n", ARGC()); usage(); /* options for samterm */ case 'a': *ap++ = "-a"; break; }ARGEND *ap = nil; Strinit(&cmdstr); Strinit0(&lastpat); Strinit0(&lastregexp); Strinit0(&genstr); Strinit0(&rhs); Strinit0(&curwd); Strinit0(&plan9cmd); home = getenv(HOME); disk = diskinit(); if(home == 0) home = "/"; if(!dflag) startup(machine, Rflag, termargs, argv); notify(notifyf); getcurwd(); if(argc>0){ for(i=0; i<argc; i++){ if(!setjmp(mainloop)){ t = tmpcstr(argv[i]); Straddc(t, '\0'); Strduplstr(&genstr, t); freetmpstr(t); fixname(&genstr); logsetname(newfile(), &genstr); } } }else if(!downloaded) newfile(); seq++; if(file.nused) current(file.filepptr[0]); setjmp(mainloop); cmdloop(); trytoquit(); /* if we already q'ed, quitok will be TRUE */ exits(0); } void usage(void) { dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n"); exits("usage"); } void rescue(void) { int i, nblank = 0; File *f; char *c; char buf[256]; if(rescuing++) return; io = -1; for(i=0; i<file.nused; i++){ f = file.filepptr[i]; if(f==cmd || f->nc==0 || !fileisdirty(f)) continue; if(io == -1){ sprint(buf, "%s/sam.save", home); io = create(buf, 1, 0777); if(io<0) return; } if(f->name.s[0]){ c = Strtoc(&f->name); strncpy(buf, c, sizeof buf-1); buf[sizeof buf-1] = 0; free(c); }else sprint(buf, "nameless.%d", nblank++); fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf); addr.r.p1 = 0, addr.r.p2 = f->nc; writeio(f); fprint(io, "\n---%s\n", (char *)buf); } } void panic(char *s) { int wasd; if(!panicking++ && !setjmp(mainloop)){ wasd = downloaded; downloaded = 0; dprint("sam: panic: %s: %r\n", s); if(wasd) fprint(2, "sam: panic: %s: %r\n", s); rescue(); abort(); } } void hiccough(char *s) { File *f; int i; if(rescuing) exits("rescue"); if(s) dprint("%s\n", s); resetcmd(); resetxec(); resetsys(); if(io > 0) close(io); /* * back out any logged changes & restore old sequences */ for(i=0; i<file.nused; i++){ f = file.filepptr[i]; if(f==cmd) continue; if(f->seq==seq){ bufdelete(&f->epsilon, 0, f->epsilon.nc); f->seq = f->prevseq; f->dot.r = f->prevdot; f->mark = f->prevmark; state(f, f->prevmod ? Dirty: Clean); } } update(); if (curfile) { if (curfile->unread) curfile->unread = FALSE; else if (downloaded) outTs(Hcurrent, curfile->tag); } longjmp(mainloop, 1); } void intr(void) { error(Eintr); } void trytoclose(File *f) { char *t; char buf[256]; if(f == cmd) /* possible? */ return; if(f->deleted) return; if(fileisdirty(f) && !f->closeok){ f->closeok = TRUE; if(f->name.s[0]){ t = Strtoc(&f->name); strncpy(buf, t, sizeof buf-1); free(t); }else strcpy(buf, "nameless file"); error_s(Emodified, buf); } f->deleted = TRUE; } void trytoquit(void) { int c; File *f; if(!quitok){ for(c = 0; c<file.nused; c++){ f = file.filepptr[c]; if(f!=cmd && fileisdirty(f)){ quitok = TRUE; eof = FALSE; error(Echanges); } } } } void load(File *f) { Address saveaddr; Strduplstr(&genstr, &f->name); filename(f); if(f->name.s[0]){ saveaddr = addr; edit(f, 'I'); addr = saveaddr; }else{ f->unread = 0; f->cleanseq = f->seq; } fileupdate(f, TRUE, TRUE); } void cmdupdate(void) { if(cmd && cmd->seq!=0){ fileupdate(cmd, FALSE, downloaded); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc; telldot(cmd); } } void delete(File *f) { if(downloaded && f->rasp) outTs(Hclose, f->tag); delfile(f); if(f == curfile) current(0); } void update(void) { int i, anymod; File *f; settempfile(); for(anymod = i=0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f==cmd) /* cmd gets done in main() */ continue; if(f->deleted) { delete(f); continue; } if(f->seq==seq && fileupdate(f, FALSE, downloaded)) anymod++; if(f->rasp) telldot(f); } if(anymod) seq++; } File * current(File *f) { return curfile = f; } void edit(File *f, int cmd) { int empty = TRUE; Posn p; int nulls; if(cmd == 'r') logdelete(f, addr.r.p1, addr.r.p2); if(cmd=='e' || cmd=='I'){ logdelete(f, (Posn)0, f->nc); addr.r.p2 = f->nc; }else if(f->nc!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0)) empty = FALSE; if((io = open(genc, OREAD))<0) { if (curfile && curfile->unread) curfile->unread = FALSE; error_r(Eopen, genc); } p = readio(f, &nulls, empty, TRUE); closeio((cmd=='e' || cmd=='I')? -1 : p); if(cmd == 'r') f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p; else f->ndot.r.p1 = f->ndot.r.p2 = 0; f->closeok = empty; if (quitok) quitok = empty; else quitok = FALSE; state(f, empty && !nulls? Clean : Dirty); if(empty && !nulls) f->cleanseq = f->seq; if(cmd == 'e') filename(f); } int getname(File *f, String *s, int save) { int c, i; Strzero(&genstr); if(genc){ free(genc); genc = 0; } if(s==0 || (c = s->s[0])==0){ /* no name provided */ if(f) Strduplstr(&genstr, &f->name); goto Return; } if(c!=' ' && c!='\t') error(Eblank); for(i=0; (c=s->s[i])==' ' || c=='\t'; i++) ; while(s->s[i] > ' ') Straddc(&genstr, s->s[i++]); if(s->s[i]) error(Enewline); fixname(&genstr); if(f && (save || f->name.s[0]==0)){ logsetname(f, &genstr); if(Strcmp(&f->name, &genstr)){ quitok = f->closeok = FALSE; f->qidpath = 0; f->mtime = 0; state(f, Dirty); /* if it's 'e', fix later */ } } Return: genc = Strtoc(&genstr); i = genstr.n; if(i && genstr.s[i-1]==0) i--; return i; /* strlen(name) */ } void filename(File *f) { if(genc) free(genc); genc = Strtoc(&genstr); dprint("%c%c%c %s\n", " '"[f->mod], "-+"[f->rasp!=0], " ."[f==curfile], genc); } void undostep(File *f, int isundo) { uint p1, p2; int mod; mod = f->mod; fileundo(f, isundo, 1, &p1, &p2, TRUE); f->ndot = f->dot; if(f->mod){ f->closeok = 0; quitok = 0; }else f->closeok = 1; if(f->mod != mod){ f->mod = mod; if(mod) mod = Clean; else mod = Dirty; state(f, mod); } } int undo(int isundo) { File *f; int i; Mod max; max = undoseq(curfile, isundo); if(max == 0) return 0; settempfile(); for(i = 0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && undoseq(f, isundo)==max) undostep(f, isundo); } return 1; } int readcmd(String *s) { int retcode; if(flist != 0) fileclose(flist); flist = fileopen(); addr.r.p1 = 0, addr.r.p2 = flist->nc; retcode = plan9(flist, '<', s, FALSE); fileupdate(flist, FALSE, FALSE); flist->seq = 0; if (flist->nc > BLOCKSIZE) error(Etoolong); Strzero(&genstr); Strinsure(&genstr, flist->nc); bufread(flist, (Posn)0, genbuf, flist->nc); memmove(genstr.s, genbuf, flist->nc*RUNESIZE); genstr.n = flist->nc; Straddc(&genstr, '\0'); return retcode; } void getcurwd(void) { String *t; char buf[256]; buf[0] = 0; getwd(buf, sizeof(buf)); t = tmpcstr(buf); Strduplstr(&curwd, t); freetmpstr(t); if(curwd.n == 0) warn(Wpwd); else if(curwd.s[curwd.n-1] != '/') Straddc(&curwd, '/'); } void cd(String *str) { int i, fd; char *s;