#include "sam.h" Rune genbuf[BLOCKSIZE];int io;int panicking;int rescuing;Mod modnum;String genstr;String rhs;String wd;String cmdstr;Rune empty[] = { 0 };char *genc;File *curfile;File *flist;File *cmd;jmp_buf mainloop;List tempfile;int quitok = TRUE;int downloaded;int dflag;int Rflag;char *machine;char *home;int bpipeok;int termlocked;char *samterm = SAMTERM;char *rsamname = RSAM; Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; void usage(void); voidmain(int argc, char *argv[]){ int i; String *t; char **ap, **arg; arg = argv++; ap = argv; while(argc>1 && argv[0] && argv[0][0]=='-'){ switch(argv[0][1]){ case 'd': dflag++; break; case 'r': --argc, argv++; if(argc == 1) usage(); machine = *argv; break; case 'R': Rflag++; break; case 't': --argc, argv++; if(argc == 1) usage(); samterm = *argv; break; case 's': --argc, argv++; if(argc == 1) usage(); rsamname = *argv; break; default: dprint("sam: unknown flag %c\n", argv[0][1]); exits("usage"); } --argc, argv++; } Strinit(&cmdstr); Strinit0(&lastpat); Strinit0(&lastregexp); Strinit0(&genstr); Strinit0(&rhs); Strinit0(&wd); tempfile.listptr = emalloc(0); Strinit0(&plan9cmd); home = getenv(HOME); if(home == 0) home = "/"; if(!dflag) startup(machine, Rflag, arg, ap); Fstart(); notify(notifyf); if(argc>1){ for(i=0; i<argc-1; i++) if(!setjmp(mainloop)){ t = tmpcstr(argv[i]); Straddc(t, '\0'); Strduplstr(&genstr, t); freetmpstr(t); Fsetname(newfile(), &genstr); } }else if(!downloaded) newfile()->state = Clean; modnum++; 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->nrunes==0 || f->state!=Dirty) 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->nrunes; 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){ if(rescuing) exits("rescue"); if(s) dprint("%s\n", s); resetcmd(); resetxec(); resetsys(); if(io > 0) close(io); if(undobuf->nrunes) Bdelete(undobuf, (Posn)0, undobuf->nrunes); update(); if (curfile) { if (curfile->state==Unread) curfile->state = Clean; 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(f->state==Dirty && !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 && f->state==Dirty){ 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->state = Clean; Fupdate(f, TRUE, TRUE);} voidcmdupdate(void){ if(cmd && cmd->mod!=0){ Fupdate(cmd, FALSE, downloaded); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nrunes; 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); if(f->mod==modnum && Fupdate(f, FALSE, downloaded)) anymod++; if(f->rasp) telldot(f); } if(anymod) modnum++;} File *current(File *f){ return curfile = f;} voidedit(File *f, int cmd){ int empty = TRUE; Posn p; int nulls; if(cmd == 'r') Fdelete(f, addr.r.p1, addr.r.p2); if(cmd=='e' || cmd=='I'){ Fdelete(f, (Posn)0, f->nrunes); addr.r.p2 = f->nrunes; }else if(f->nrunes!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0)) empty = FALSE; if((io = open(genc, OREAD))<0) { if (curfile && curfile->state == Unread) curfile->state = Clean; error_s(Eopen, genc); } p = readio(f, &nulls, empty); 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(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); else Straddc(&genstr, '\0'); 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); Straddc(&genstr, '\0'); if(f && (save || f->name.s[0]==0)){ Fsetname(f, &genstr); if(Strcmp(&f->name, &genstr)){ quitok = f->closeok = FALSE; f->qid = 0; f->date = 0; state(f, Dirty); /* if it's 'e', fix later */ } } Return: genc = Strtoc(&genstr); return genstr.n-1; /* strlen(name) */} voidfilename(File *f){ if(genc) free(genc); genc = Strtoc(&genstr); dprint("%c%c%c %s\n", " '"[f->state==Dirty], "-+"[f->rasp!=0], " ."[f==curfile], genc);} voidundostep(File *f){ Buffer *t; int changes; Mark mark; t = f->transcript; changes = Fupdate(f, TRUE, TRUE); Bread(t, (Rune*)&mark, (sizeof mark)/RUNESIZE, f->markp); Bdelete(t, f->markp, t->nrunes); f->markp = mark.p; f->dot.r = mark.dot; f->ndot.r = mark.dot; f->mark = mark.mark; f->mod = mark.m; f->closeok = mark.s1!=Dirty; if(mark.s1==Dirty) quitok = FALSE; if(f->state==Clean && mark.s1==Clean && changes) state(f, Dirty); else state(f, mark.s1);} intundo(void){ File *f; int i; Mod max; if((max = curfile->mod)==0) return 0; settempfile(); for(i = 0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && f->mod==max) undostep(f); } return 1;} intreadcmd(String *s){ int retcode; if(flist == 0) (flist = Fopen())->state = Clean; addr.r.p1 = 0, addr.r.p2 = flist->nrunes; retcode = plan9(flist, '<', s, FALSE); Fupdate(flist, FALSE, FALSE); flist->mod = 0; if (flist->nrunes > BLOCKSIZE) error(Etoolong); Strzero(&genstr); Strinsure(&genstr, flist->nrunes); Fchars(flist, genbuf, (Posn)0, flist->nrunes); memmove(genstr.s, genbuf, flist->nrunes*RUNESIZE); genstr.n = flist->nrunes; Straddc(&genstr, '\0'); return retcode;} voidcd(String *str){ int i; File *f; String *t; t = tmpcstr("/bin/pwd"); Straddc(t, '\0'); if (flist) { Fclose(flist); flist = 0; } if (readcmd(t) != 0) { Strduplstr(&genstr, tmprstr(baddir, sizeof(baddir)/sizeof(Rune))); Straddc(&genstr, '\0'); } freetmpstr(t); Strduplstr(&wd, &genstr); if(wd.s[0] == 0){ wd.n = 0; warn(Wpwd); }else if(wd.s[wd.n-2] == '\n'){ --wd.n; wd.s[wd.n-1]='/'; } if(chdir(getname((File *)0, str, FALSE)? genc : home)) syserror("chdir"); settempfile(); for(i=0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){ Strinsert(&f->name, &wd, (Posn)0); sortname(f); } }} intloadflist(String *s){ int c, i; Lines 1–500 of 676. Load more
#include "sam.h" Rune genbuf[BLOCKSIZE]; int io; int panicking; int rescuing; Mod modnum; String genstr; String rhs; String wd; String cmdstr; Rune empty[] = { 0 }; char *genc; File *curfile; File *flist; File *cmd; jmp_buf mainloop; List tempfile; int quitok = TRUE; int downloaded; int dflag; int Rflag; char *machine; char *home; int bpipeok; int termlocked; char *samterm = SAMTERM; char *rsamname = RSAM; Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; void usage(void); void main(int argc, char *argv[]) { int i; String *t; char **ap, **arg; arg = argv++; ap = argv; while(argc>1 && argv[0] && argv[0][0]=='-'){ switch(argv[0][1]){ case 'd': dflag++; break; case 'r': --argc, argv++; if(argc == 1) usage(); machine = *argv; break; case 'R': Rflag++; break; case 't': --argc, argv++; if(argc == 1) usage(); samterm = *argv; break; case 's': --argc, argv++; if(argc == 1) usage(); rsamname = *argv; break; default: dprint("sam: unknown flag %c\n", argv[0][1]); exits("usage"); } --argc, argv++; } Strinit(&cmdstr); Strinit0(&lastpat); Strinit0(&lastregexp); Strinit0(&genstr); Strinit0(&rhs); Strinit0(&wd); tempfile.listptr = emalloc(0); Strinit0(&plan9cmd); home = getenv(HOME); if(home == 0) home = "/"; if(!dflag) startup(machine, Rflag, arg, ap); Fstart(); notify(notifyf); if(argc>1){ for(i=0; i<argc-1; i++) if(!setjmp(mainloop)){ t = tmpcstr(argv[i]); Straddc(t, '\0'); Strduplstr(&genstr, t); freetmpstr(t); Fsetname(newfile(), &genstr); } }else if(!downloaded) newfile()->state = Clean; modnum++; 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->nrunes==0 || f->state!=Dirty) 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->nrunes; 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) { if(rescuing) exits("rescue"); if(s) dprint("%s\n", s); resetcmd(); resetxec(); resetsys(); if(io > 0) close(io); if(undobuf->nrunes) Bdelete(undobuf, (Posn)0, undobuf->nrunes); update(); if (curfile) { if (curfile->state==Unread) curfile->state = Clean; 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(f->state==Dirty && !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 && f->state==Dirty){ 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->state = Clean; Fupdate(f, TRUE, TRUE); } void cmdupdate(void) { if(cmd && cmd->mod!=0){ Fupdate(cmd, FALSE, downloaded); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nrunes; 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); if(f->mod==modnum && Fupdate(f, FALSE, downloaded)) anymod++; if(f->rasp) telldot(f); } if(anymod) modnum++; } File * current(File *f) { return curfile = f; } void edit(File *f, int cmd) { int empty = TRUE; Posn p; int nulls; if(cmd == 'r') Fdelete(f, addr.r.p1, addr.r.p2); if(cmd=='e' || cmd=='I'){ Fdelete(f, (Posn)0, f->nrunes); addr.r.p2 = f->nrunes; }else if(f->nrunes!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0)) empty = FALSE; if((io = open(genc, OREAD))<0) { if (curfile && curfile->state == Unread) curfile->state = Clean; error_s(Eopen, genc); } p = readio(f, &nulls, empty); 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(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); else Straddc(&genstr, '\0'); 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); Straddc(&genstr, '\0'); if(f && (save || f->name.s[0]==0)){ Fsetname(f, &genstr); if(Strcmp(&f->name, &genstr)){ quitok = f->closeok = FALSE; f->qid = 0; f->date = 0; state(f, Dirty); /* if it's 'e', fix later */ } } Return: genc = Strtoc(&genstr); return genstr.n-1; /* strlen(name) */ } void filename(File *f) { if(genc) free(genc); genc = Strtoc(&genstr); dprint("%c%c%c %s\n", " '"[f->state==Dirty], "-+"[f->rasp!=0], " ."[f==curfile], genc); } void undostep(File *f) { Buffer *t; int changes; Mark mark; t = f->transcript; changes = Fupdate(f, TRUE, TRUE); Bread(t, (Rune*)&mark, (sizeof mark)/RUNESIZE, f->markp); Bdelete(t, f->markp, t->nrunes); f->markp = mark.p; f->dot.r = mark.dot; f->ndot.r = mark.dot; f->mark = mark.mark; f->mod = mark.m; f->closeok = mark.s1!=Dirty; if(mark.s1==Dirty) quitok = FALSE; if(f->state==Clean && mark.s1==Clean && changes) state(f, Dirty); else state(f, mark.s1); } int undo(void) { File *f; int i; Mod max; if((max = curfile->mod)==0) return 0; settempfile(); for(i = 0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && f->mod==max) undostep(f); } return 1; } int readcmd(String *s) { int retcode; if(flist == 0) (flist = Fopen())->state = Clean; addr.r.p1 = 0, addr.r.p2 = flist->nrunes; retcode = plan9(flist, '<', s, FALSE); Fupdate(flist, FALSE, FALSE); flist->mod = 0; if (flist->nrunes > BLOCKSIZE) error(Etoolong); Strzero(&genstr); Strinsure(&genstr, flist->nrunes); Fchars(flist, genbuf, (Posn)0, flist->nrunes); memmove(genstr.s, genbuf, flist->nrunes*RUNESIZE); genstr.n = flist->nrunes; Straddc(&genstr, '\0'); return retcode; } void cd(String *str) { int i; File *f; String *t; t = tmpcstr("/bin/pwd"); Straddc(t, '\0'); if (flist) { Fclose(flist); flist = 0; } if (readcmd(t) != 0) { Strduplstr(&genstr, tmprstr(baddir, sizeof(baddir)/sizeof(Rune))); Straddc(&genstr, '\0'); } freetmpstr(t); Strduplstr(&wd, &genstr); if(wd.s[0] == 0){ wd.n = 0; warn(Wpwd); }else if(wd.s[wd.n-2] == '\n'){ --wd.n; wd.s[wd.n-1]='/'; } if(chdir(getname((File *)0, str, FALSE)? genc : home)) syserror("chdir"); settempfile(); for(i=0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){ Strinsert(&f->name, &wd, (Posn)0); sortname(f); } } } int loadflist(String *s) { int c, i;