13e12c5d1SDavid du Colombier #include "sam.h" 23e12c5d1SDavid du Colombier 33e12c5d1SDavid du Colombier Rune genbuf[BLOCKSIZE]; 43e12c5d1SDavid du Colombier int io; 53e12c5d1SDavid du Colombier int panicking; 63e12c5d1SDavid du Colombier int rescuing; 73e12c5d1SDavid du Colombier Mod modnum; 83e12c5d1SDavid du Colombier String genstr; 93e12c5d1SDavid du Colombier String rhs; 103e12c5d1SDavid du Colombier String wd; 113e12c5d1SDavid du Colombier String cmdstr; 123e12c5d1SDavid du Colombier Rune empty[] = { 0 }; 133e12c5d1SDavid du Colombier char *genc; 143e12c5d1SDavid du Colombier File *curfile; 153e12c5d1SDavid du Colombier File *flist; 163e12c5d1SDavid du Colombier File *cmd; 173e12c5d1SDavid du Colombier jmp_buf mainloop; 183e12c5d1SDavid du Colombier List tempfile; 193e12c5d1SDavid du Colombier int quitok = TRUE; 203e12c5d1SDavid du Colombier int downloaded; 213e12c5d1SDavid du Colombier int dflag; 223e12c5d1SDavid du Colombier int Rflag; 233e12c5d1SDavid du Colombier char *machine; 243e12c5d1SDavid du Colombier char *home; 253e12c5d1SDavid du Colombier int bpipeok; 263e12c5d1SDavid du Colombier int termlocked; 273e12c5d1SDavid du Colombier char *samterm = SAMTERM; 283e12c5d1SDavid du Colombier char *rsamname = RSAM; 293e12c5d1SDavid du Colombier 30*219b2ee8SDavid du Colombier Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'}; 31*219b2ee8SDavid du Colombier 323e12c5d1SDavid du Colombier void usage(void); 333e12c5d1SDavid du Colombier 343e12c5d1SDavid du Colombier void 353e12c5d1SDavid du Colombier main(int argc, char *argv[]) 363e12c5d1SDavid du Colombier { 373e12c5d1SDavid du Colombier int i; 383e12c5d1SDavid du Colombier String *t; 393e12c5d1SDavid du Colombier char **ap, **arg; 403e12c5d1SDavid du Colombier 413e12c5d1SDavid du Colombier arg = argv++; 423e12c5d1SDavid du Colombier ap = argv; 433e12c5d1SDavid du Colombier while(argc>1 && argv[0] && argv[0][0]=='-'){ 443e12c5d1SDavid du Colombier switch(argv[0][1]){ 453e12c5d1SDavid du Colombier case 'd': 463e12c5d1SDavid du Colombier dflag++; 473e12c5d1SDavid du Colombier break; 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier case 'r': 503e12c5d1SDavid du Colombier --argc, argv++; 513e12c5d1SDavid du Colombier if(argc == 1) 523e12c5d1SDavid du Colombier usage(); 533e12c5d1SDavid du Colombier machine = *argv; 543e12c5d1SDavid du Colombier break; 553e12c5d1SDavid du Colombier 563e12c5d1SDavid du Colombier case 'R': 573e12c5d1SDavid du Colombier Rflag++; 583e12c5d1SDavid du Colombier break; 593e12c5d1SDavid du Colombier 603e12c5d1SDavid du Colombier case 't': 613e12c5d1SDavid du Colombier --argc, argv++; 623e12c5d1SDavid du Colombier if(argc == 1) 633e12c5d1SDavid du Colombier usage(); 643e12c5d1SDavid du Colombier samterm = *argv; 653e12c5d1SDavid du Colombier break; 663e12c5d1SDavid du Colombier 673e12c5d1SDavid du Colombier case 's': 683e12c5d1SDavid du Colombier --argc, argv++; 693e12c5d1SDavid du Colombier if(argc == 1) 703e12c5d1SDavid du Colombier usage(); 713e12c5d1SDavid du Colombier rsamname = *argv; 723e12c5d1SDavid du Colombier break; 733e12c5d1SDavid du Colombier 743e12c5d1SDavid du Colombier default: 75bd389b36SDavid du Colombier dprint("sam: unknown flag %c\n", argv[0][1]); 763e12c5d1SDavid du Colombier exits("usage"); 773e12c5d1SDavid du Colombier } 783e12c5d1SDavid du Colombier --argc, argv++; 793e12c5d1SDavid du Colombier } 803e12c5d1SDavid du Colombier Strinit(&cmdstr); 813e12c5d1SDavid du Colombier Strinit0(&lastpat); 823e12c5d1SDavid du Colombier Strinit0(&lastregexp); 833e12c5d1SDavid du Colombier Strinit0(&genstr); 843e12c5d1SDavid du Colombier Strinit0(&rhs); 853e12c5d1SDavid du Colombier Strinit0(&wd); 863e12c5d1SDavid du Colombier tempfile.listptr = emalloc(0); 873e12c5d1SDavid du Colombier Strinit0(&plan9cmd); 883e12c5d1SDavid du Colombier home = getenv(HOME); 893e12c5d1SDavid du Colombier if(home == 0) 903e12c5d1SDavid du Colombier home = "/"; 913e12c5d1SDavid du Colombier if(!dflag) 923e12c5d1SDavid du Colombier startup(machine, Rflag, arg, ap); 933e12c5d1SDavid du Colombier Fstart(); 943e12c5d1SDavid du Colombier notify(notifyf); 953e12c5d1SDavid du Colombier if(argc>1){ 963e12c5d1SDavid du Colombier for(i=0; i<argc-1; i++) 973e12c5d1SDavid du Colombier if(!setjmp(mainloop)){ 983e12c5d1SDavid du Colombier t = tmpcstr(argv[i]); 993e12c5d1SDavid du Colombier Straddc(t, '\0'); 1003e12c5d1SDavid du Colombier Strduplstr(&genstr, t); 1013e12c5d1SDavid du Colombier freetmpstr(t); 1023e12c5d1SDavid du Colombier Fsetname(newfile(), &genstr); 1033e12c5d1SDavid du Colombier } 1043e12c5d1SDavid du Colombier }else if(!downloaded) 1053e12c5d1SDavid du Colombier newfile()->state = Clean; 1063e12c5d1SDavid du Colombier modnum++; 1073e12c5d1SDavid du Colombier if(file.nused) 1083e12c5d1SDavid du Colombier current(file.filepptr[0]); 1093e12c5d1SDavid du Colombier setjmp(mainloop); 1103e12c5d1SDavid du Colombier cmdloop(); 1113e12c5d1SDavid du Colombier trytoquit(); /* if we already q'ed, quitok will be TRUE */ 1123e12c5d1SDavid du Colombier exits(0); 1133e12c5d1SDavid du Colombier } 1143e12c5d1SDavid du Colombier 1153e12c5d1SDavid du Colombier void 1163e12c5d1SDavid du Colombier usage(void) 1173e12c5d1SDavid du Colombier { 1183e12c5d1SDavid du Colombier dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n"); 1193e12c5d1SDavid du Colombier exits("usage"); 1203e12c5d1SDavid du Colombier } 1213e12c5d1SDavid du Colombier 1223e12c5d1SDavid du Colombier void 1233e12c5d1SDavid du Colombier rescue(void) 1243e12c5d1SDavid du Colombier { 1253e12c5d1SDavid du Colombier int i, nblank = 0; 1263e12c5d1SDavid du Colombier File *f; 1273e12c5d1SDavid du Colombier char *c; 1283e12c5d1SDavid du Colombier char buf[256]; 1293e12c5d1SDavid du Colombier 1303e12c5d1SDavid du Colombier if(rescuing++) 1313e12c5d1SDavid du Colombier return; 1323e12c5d1SDavid du Colombier io = -1; 1333e12c5d1SDavid du Colombier for(i=0; i<file.nused; i++){ 1343e12c5d1SDavid du Colombier f = file.filepptr[i]; 1353e12c5d1SDavid du Colombier if(f==cmd || f->nrunes==0 || f->state!=Dirty) 1363e12c5d1SDavid du Colombier continue; 1373e12c5d1SDavid du Colombier if(io == -1){ 1383e12c5d1SDavid du Colombier sprint(buf, "%s/sam.save", home); 1393e12c5d1SDavid du Colombier io = create(buf, 1, 0777); 1403e12c5d1SDavid du Colombier if(io<0) 1413e12c5d1SDavid du Colombier return; 1423e12c5d1SDavid du Colombier } 1433e12c5d1SDavid du Colombier if(f->name.s[0]){ 1443e12c5d1SDavid du Colombier c = Strtoc(&f->name); 1453e12c5d1SDavid du Colombier strncpy(buf, c, sizeof buf-1); 1463e12c5d1SDavid du Colombier buf[sizeof buf-1] = 0; 1473e12c5d1SDavid du Colombier free(c); 1483e12c5d1SDavid du Colombier }else 1493e12c5d1SDavid du Colombier sprint(buf, "nameless.%d", nblank++); 150bd389b36SDavid du Colombier fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf); 1513e12c5d1SDavid du Colombier addr.r.p1 = 0, addr.r.p2 = f->nrunes; 1523e12c5d1SDavid du Colombier writeio(f); 1533e12c5d1SDavid du Colombier fprint(io, "\n---%s\n", (char *)buf); 1543e12c5d1SDavid du Colombier } 1553e12c5d1SDavid du Colombier } 1563e12c5d1SDavid du Colombier 1573e12c5d1SDavid du Colombier void 1583e12c5d1SDavid du Colombier panic(char *s) 1593e12c5d1SDavid du Colombier { 1603e12c5d1SDavid du Colombier int wasd; 1613e12c5d1SDavid du Colombier 1623e12c5d1SDavid du Colombier if(!panicking++ && !setjmp(mainloop)){ 1633e12c5d1SDavid du Colombier wasd = downloaded; 1643e12c5d1SDavid du Colombier downloaded = 0; 1653e12c5d1SDavid du Colombier dprint("sam: panic: %s: %r\n", s); 1663e12c5d1SDavid du Colombier if(wasd) 1673e12c5d1SDavid du Colombier fprint(2, "sam: panic: %s: %r\n", s); 1683e12c5d1SDavid du Colombier rescue(); 1693e12c5d1SDavid du Colombier abort(); 1703e12c5d1SDavid du Colombier } 1713e12c5d1SDavid du Colombier } 1723e12c5d1SDavid du Colombier 1733e12c5d1SDavid du Colombier void 1743e12c5d1SDavid du Colombier hiccough(char *s) 1753e12c5d1SDavid du Colombier { 1763e12c5d1SDavid du Colombier if(rescuing) 1773e12c5d1SDavid du Colombier exits("rescue"); 1783e12c5d1SDavid du Colombier if(s) 1793e12c5d1SDavid du Colombier dprint("%s\n", s); 1803e12c5d1SDavid du Colombier resetcmd(); 1813e12c5d1SDavid du Colombier resetxec(); 1823e12c5d1SDavid du Colombier resetsys(); 1833e12c5d1SDavid du Colombier if(io > 0) 1843e12c5d1SDavid du Colombier close(io); 1853e12c5d1SDavid du Colombier if(undobuf->nrunes) 1863e12c5d1SDavid du Colombier Bdelete(undobuf, (Posn)0, undobuf->nrunes); 1873e12c5d1SDavid du Colombier update(); 188*219b2ee8SDavid du Colombier if (curfile) { 189*219b2ee8SDavid du Colombier if (curfile->state==Unread) 1903e12c5d1SDavid du Colombier curfile->state = Clean; 191*219b2ee8SDavid du Colombier else if (downloaded) 1923e12c5d1SDavid du Colombier outTs(Hcurrent, curfile->tag); 193*219b2ee8SDavid du Colombier } 1943e12c5d1SDavid du Colombier longjmp(mainloop, 1); 1953e12c5d1SDavid du Colombier } 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier void 1983e12c5d1SDavid du Colombier intr(void) 1993e12c5d1SDavid du Colombier { 2003e12c5d1SDavid du Colombier error(Eintr); 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier 2033e12c5d1SDavid du Colombier void 2043e12c5d1SDavid du Colombier trytoclose(File *f) 2053e12c5d1SDavid du Colombier { 2063e12c5d1SDavid du Colombier char *t; 207*219b2ee8SDavid du Colombier char buf[256]; 2083e12c5d1SDavid du Colombier 2093e12c5d1SDavid du Colombier if(f == cmd) /* possible? */ 2103e12c5d1SDavid du Colombier return; 211*219b2ee8SDavid du Colombier if(f->deleted) 212*219b2ee8SDavid du Colombier return; 2133e12c5d1SDavid du Colombier if(f->state==Dirty && !f->closeok){ 2143e12c5d1SDavid du Colombier f->closeok = TRUE; 2153e12c5d1SDavid du Colombier if(f->name.s[0]){ 2163e12c5d1SDavid du Colombier t = Strtoc(&f->name); 217*219b2ee8SDavid du Colombier strncpy(buf, t, sizeof buf-1); 2183e12c5d1SDavid du Colombier free(t); 2193e12c5d1SDavid du Colombier }else 220*219b2ee8SDavid du Colombier strcpy(buf, "nameless file"); 221*219b2ee8SDavid du Colombier error_s(Emodified, buf); 2223e12c5d1SDavid du Colombier } 223*219b2ee8SDavid du Colombier f->deleted = TRUE; 2243e12c5d1SDavid du Colombier } 2253e12c5d1SDavid du Colombier 2263e12c5d1SDavid du Colombier void 2273e12c5d1SDavid du Colombier trytoquit(void) 2283e12c5d1SDavid du Colombier { 2293e12c5d1SDavid du Colombier int c; 2303e12c5d1SDavid du Colombier File *f; 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier if(!quitok) 233*219b2ee8SDavid du Colombier { 2343e12c5d1SDavid du Colombier for(c = 0; c<file.nused; c++){ 2353e12c5d1SDavid du Colombier f = file.filepptr[c]; 2363e12c5d1SDavid du Colombier if(f!=cmd && f->state==Dirty){ 2373e12c5d1SDavid du Colombier quitok = TRUE; 2383e12c5d1SDavid du Colombier eof = FALSE; 2393e12c5d1SDavid du Colombier error(Echanges); 2403e12c5d1SDavid du Colombier } 2413e12c5d1SDavid du Colombier } 2423e12c5d1SDavid du Colombier } 243*219b2ee8SDavid du Colombier } 2443e12c5d1SDavid du Colombier 2453e12c5d1SDavid du Colombier void 2463e12c5d1SDavid du Colombier load(File *f) 2473e12c5d1SDavid du Colombier { 2483e12c5d1SDavid du Colombier Address saveaddr; 2493e12c5d1SDavid du Colombier 2503e12c5d1SDavid du Colombier Strduplstr(&genstr, &f->name); 2513e12c5d1SDavid du Colombier filename(f); 2523e12c5d1SDavid du Colombier if(f->name.s[0]){ 2533e12c5d1SDavid du Colombier saveaddr = addr; 2543e12c5d1SDavid du Colombier edit(f, 'I'); 2553e12c5d1SDavid du Colombier addr = saveaddr; 2563e12c5d1SDavid du Colombier }else 2573e12c5d1SDavid du Colombier f->state = Clean; 2583e12c5d1SDavid du Colombier Fupdate(f, TRUE, TRUE); 2593e12c5d1SDavid du Colombier } 2603e12c5d1SDavid du Colombier 2613e12c5d1SDavid du Colombier void 2623e12c5d1SDavid du Colombier cmdupdate(void) 2633e12c5d1SDavid du Colombier { 2643e12c5d1SDavid du Colombier if(cmd && cmd->mod!=0){ 2653e12c5d1SDavid du Colombier Fupdate(cmd, FALSE, downloaded); 2663e12c5d1SDavid du Colombier cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nrunes; 2673e12c5d1SDavid du Colombier telldot(cmd); 2683e12c5d1SDavid du Colombier } 2693e12c5d1SDavid du Colombier } 2703e12c5d1SDavid du Colombier 2713e12c5d1SDavid du Colombier void 272*219b2ee8SDavid du Colombier delete(File *f) 273*219b2ee8SDavid du Colombier { 274*219b2ee8SDavid du Colombier if(downloaded && f->rasp) 275*219b2ee8SDavid du Colombier outTs(Hclose, f->tag); 276*219b2ee8SDavid du Colombier delfile(f); 277*219b2ee8SDavid du Colombier if(f == curfile) 278*219b2ee8SDavid du Colombier current(0); 279*219b2ee8SDavid du Colombier } 280*219b2ee8SDavid du Colombier 281*219b2ee8SDavid du Colombier void 2823e12c5d1SDavid du Colombier update(void) 2833e12c5d1SDavid du Colombier { 2843e12c5d1SDavid du Colombier int i, anymod; 2853e12c5d1SDavid du Colombier File *f; 2863e12c5d1SDavid du Colombier 2873e12c5d1SDavid du Colombier settempfile(); 2883e12c5d1SDavid du Colombier for(anymod = i=0; i<tempfile.nused; i++){ 2893e12c5d1SDavid du Colombier f = tempfile.filepptr[i]; 2903e12c5d1SDavid du Colombier if(f==cmd) /* cmd gets done in main() */ 2913e12c5d1SDavid du Colombier continue; 292*219b2ee8SDavid du Colombier if(f->deleted) 293*219b2ee8SDavid du Colombier delete(f); 2943e12c5d1SDavid du Colombier if(f->mod==modnum && Fupdate(f, FALSE, downloaded)) 2953e12c5d1SDavid du Colombier anymod++; 2963e12c5d1SDavid du Colombier if(f->rasp) 2973e12c5d1SDavid du Colombier telldot(f); 2983e12c5d1SDavid du Colombier } 2993e12c5d1SDavid du Colombier if(anymod) 3003e12c5d1SDavid du Colombier modnum++; 3013e12c5d1SDavid du Colombier } 3023e12c5d1SDavid du Colombier 3033e12c5d1SDavid du Colombier File * 3043e12c5d1SDavid du Colombier current(File *f) 3053e12c5d1SDavid du Colombier { 3063e12c5d1SDavid du Colombier return curfile = f; 3073e12c5d1SDavid du Colombier } 3083e12c5d1SDavid du Colombier 3093e12c5d1SDavid du Colombier void 3103e12c5d1SDavid du Colombier edit(File *f, int cmd) 3113e12c5d1SDavid du Colombier { 3123e12c5d1SDavid du Colombier int empty = TRUE; 3133e12c5d1SDavid du Colombier Posn p; 3143e12c5d1SDavid du Colombier int nulls; 3153e12c5d1SDavid du Colombier 3163e12c5d1SDavid du Colombier if(cmd == 'r') 3173e12c5d1SDavid du Colombier Fdelete(f, addr.r.p1, addr.r.p2); 3183e12c5d1SDavid du Colombier if(cmd=='e' || cmd=='I'){ 3193e12c5d1SDavid du Colombier Fdelete(f, (Posn)0, f->nrunes); 3203e12c5d1SDavid du Colombier addr.r.p2 = f->nrunes; 3213e12c5d1SDavid du Colombier }else if(f->nrunes!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0)) 3223e12c5d1SDavid du Colombier empty = FALSE; 323*219b2ee8SDavid du Colombier if((io = open(genc, OREAD))<0) { 324*219b2ee8SDavid du Colombier if (curfile && curfile->state == Unread) 325*219b2ee8SDavid du Colombier curfile->state = Clean; 3263e12c5d1SDavid du Colombier error_s(Eopen, genc); 327*219b2ee8SDavid du Colombier } 3283e12c5d1SDavid du Colombier p = readio(f, &nulls, empty); 3293e12c5d1SDavid du Colombier closeio((cmd=='e' || cmd=='I')? -1 : p); 3303e12c5d1SDavid du Colombier if(cmd == 'r') 3313e12c5d1SDavid du Colombier f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p; 3323e12c5d1SDavid du Colombier else 3333e12c5d1SDavid du Colombier f->ndot.r.p1 = f->ndot.r.p2 = 0; 334*219b2ee8SDavid du Colombier f->closeok = empty; 335*219b2ee8SDavid du Colombier if (quitok) 336*219b2ee8SDavid du Colombier quitok = empty; 337*219b2ee8SDavid du Colombier else 338*219b2ee8SDavid du Colombier quitok = FALSE; 3393e12c5d1SDavid du Colombier state(f, empty && !nulls? Clean : Dirty); 3403e12c5d1SDavid du Colombier if(cmd == 'e') 3413e12c5d1SDavid du Colombier filename(f); 3423e12c5d1SDavid du Colombier } 3433e12c5d1SDavid du Colombier 3443e12c5d1SDavid du Colombier int 3453e12c5d1SDavid du Colombier getname(File *f, String *s, int save) 3463e12c5d1SDavid du Colombier { 3473e12c5d1SDavid du Colombier int c, i; 3483e12c5d1SDavid du Colombier 3493e12c5d1SDavid du Colombier Strzero(&genstr); 3503e12c5d1SDavid du Colombier if(genc){ 3513e12c5d1SDavid du Colombier free(genc); 3523e12c5d1SDavid du Colombier genc = 0; 3533e12c5d1SDavid du Colombier } 3543e12c5d1SDavid du Colombier if(s==0 || (c = s->s[0])==0){ /* no name provided */ 3553e12c5d1SDavid du Colombier if(f) 3563e12c5d1SDavid du Colombier Strduplstr(&genstr, &f->name); 3573e12c5d1SDavid du Colombier else 3583e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 3593e12c5d1SDavid du Colombier goto Return; 3603e12c5d1SDavid du Colombier } 3613e12c5d1SDavid du Colombier if(c!=' ' && c!='\t') 3623e12c5d1SDavid du Colombier error(Eblank); 3633e12c5d1SDavid du Colombier for(i=0; (c=s->s[i])==' ' || c=='\t'; i++) 3643e12c5d1SDavid du Colombier ; 3653e12c5d1SDavid du Colombier while(s->s[i] > ' ') 3663e12c5d1SDavid du Colombier Straddc(&genstr, s->s[i++]); 3673e12c5d1SDavid du Colombier if(s->s[i]) 3683e12c5d1SDavid du Colombier error(Enewline); 3693e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 3703e12c5d1SDavid du Colombier if(f && (save || f->name.s[0]==0)){ 3713e12c5d1SDavid du Colombier Fsetname(f, &genstr); 3723e12c5d1SDavid du Colombier if(Strcmp(&f->name, &genstr)){ 3733e12c5d1SDavid du Colombier quitok = f->closeok = FALSE; 374bd389b36SDavid du Colombier f->qid = 0; 3753e12c5d1SDavid du Colombier f->date = 0; 3763e12c5d1SDavid du Colombier state(f, Dirty); /* if it's 'e', fix later */ 3773e12c5d1SDavid du Colombier } 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier Return: 3803e12c5d1SDavid du Colombier genc = Strtoc(&genstr); 3813e12c5d1SDavid du Colombier return genstr.n-1; /* strlen(name) */ 3823e12c5d1SDavid du Colombier } 3833e12c5d1SDavid du Colombier 3843e12c5d1SDavid du Colombier void 3853e12c5d1SDavid du Colombier filename(File *f) 3863e12c5d1SDavid du Colombier { 3873e12c5d1SDavid du Colombier if(genc) 3883e12c5d1SDavid du Colombier free(genc); 3893e12c5d1SDavid du Colombier genc = Strtoc(&genstr); 3903e12c5d1SDavid du Colombier dprint("%c%c%c %s\n", " '"[f->state==Dirty], 3913e12c5d1SDavid du Colombier "-+"[f->rasp!=0], " ."[f==curfile], genc); 3923e12c5d1SDavid du Colombier } 3933e12c5d1SDavid du Colombier 3943e12c5d1SDavid du Colombier void 3953e12c5d1SDavid du Colombier undostep(File *f) 3963e12c5d1SDavid du Colombier { 3973e12c5d1SDavid du Colombier Buffer *t; 3983e12c5d1SDavid du Colombier int changes; 3993e12c5d1SDavid du Colombier Mark mark; 4003e12c5d1SDavid du Colombier 4013e12c5d1SDavid du Colombier t = f->transcript; 4023e12c5d1SDavid du Colombier changes = Fupdate(f, TRUE, TRUE); 4033e12c5d1SDavid du Colombier Bread(t, (Rune*)&mark, (sizeof mark)/RUNESIZE, f->markp); 4043e12c5d1SDavid du Colombier Bdelete(t, f->markp, t->nrunes); 4053e12c5d1SDavid du Colombier f->markp = mark.p; 4063e12c5d1SDavid du Colombier f->dot.r = mark.dot; 4073e12c5d1SDavid du Colombier f->ndot.r = mark.dot; 4083e12c5d1SDavid du Colombier f->mark = mark.mark; 4093e12c5d1SDavid du Colombier f->mod = mark.m; 4103e12c5d1SDavid du Colombier f->closeok = mark.s1!=Dirty; 4113e12c5d1SDavid du Colombier if(mark.s1==Dirty) 4123e12c5d1SDavid du Colombier quitok = FALSE; 4133e12c5d1SDavid du Colombier if(f->state==Clean && mark.s1==Clean && changes) 4143e12c5d1SDavid du Colombier state(f, Dirty); 4153e12c5d1SDavid du Colombier else 4163e12c5d1SDavid du Colombier state(f, mark.s1); 4173e12c5d1SDavid du Colombier } 4183e12c5d1SDavid du Colombier 419bd389b36SDavid du Colombier int 4203e12c5d1SDavid du Colombier undo(void) 4213e12c5d1SDavid du Colombier { 4223e12c5d1SDavid du Colombier File *f; 4233e12c5d1SDavid du Colombier int i; 4243e12c5d1SDavid du Colombier Mod max; 4253e12c5d1SDavid du Colombier if((max = curfile->mod)==0) 426bd389b36SDavid du Colombier return 0; 4273e12c5d1SDavid du Colombier settempfile(); 4283e12c5d1SDavid du Colombier for(i = 0; i<tempfile.nused; i++){ 4293e12c5d1SDavid du Colombier f = tempfile.filepptr[i]; 4303e12c5d1SDavid du Colombier if(f!=cmd && f->mod==max) 4313e12c5d1SDavid du Colombier undostep(f); 4323e12c5d1SDavid du Colombier } 433bd389b36SDavid du Colombier return 1; 4343e12c5d1SDavid du Colombier } 4353e12c5d1SDavid du Colombier 436*219b2ee8SDavid du Colombier int 4373e12c5d1SDavid du Colombier readcmd(String *s) 4383e12c5d1SDavid du Colombier { 439*219b2ee8SDavid du Colombier int retcode; 440*219b2ee8SDavid du Colombier 4413e12c5d1SDavid du Colombier if(flist == 0) 4423e12c5d1SDavid du Colombier (flist = Fopen())->state = Clean; 4433e12c5d1SDavid du Colombier addr.r.p1 = 0, addr.r.p2 = flist->nrunes; 444*219b2ee8SDavid du Colombier retcode = plan9(flist, '<', s, FALSE); 4453e12c5d1SDavid du Colombier Fupdate(flist, FALSE, FALSE); 4463e12c5d1SDavid du Colombier flist->mod = 0; 447bd389b36SDavid du Colombier if (flist->nrunes > BLOCKSIZE) 448bd389b36SDavid du Colombier error(Etoolong); 4493e12c5d1SDavid du Colombier Strzero(&genstr); 4503e12c5d1SDavid du Colombier Strinsure(&genstr, flist->nrunes); 4513e12c5d1SDavid du Colombier Fchars(flist, genbuf, (Posn)0, flist->nrunes); 4523e12c5d1SDavid du Colombier memmove(genstr.s, genbuf, flist->nrunes*RUNESIZE); 4533e12c5d1SDavid du Colombier genstr.n = flist->nrunes; 4543e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 455*219b2ee8SDavid du Colombier return retcode; 4563e12c5d1SDavid du Colombier } 4573e12c5d1SDavid du Colombier 4583e12c5d1SDavid du Colombier void 4593e12c5d1SDavid du Colombier cd(String *str) 4603e12c5d1SDavid du Colombier { 4613e12c5d1SDavid du Colombier int i; 4623e12c5d1SDavid du Colombier File *f; 4633e12c5d1SDavid du Colombier String *t; 4643e12c5d1SDavid du Colombier 4653e12c5d1SDavid du Colombier t = tmpcstr("/bin/pwd"); 4663e12c5d1SDavid du Colombier Straddc(t, '\0'); 467*219b2ee8SDavid du Colombier if (flist) { 468*219b2ee8SDavid du Colombier Fclose(flist); 469*219b2ee8SDavid du Colombier flist = 0; 470*219b2ee8SDavid du Colombier } 471*219b2ee8SDavid du Colombier if (readcmd(t) != 0) { 472*219b2ee8SDavid du Colombier Strduplstr(&genstr, tmprstr(baddir, sizeof(baddir)/sizeof(Rune))); 473*219b2ee8SDavid du Colombier Straddc(&genstr, '\0'); 474*219b2ee8SDavid du Colombier } 4753e12c5d1SDavid du Colombier freetmpstr(t); 4763e12c5d1SDavid du Colombier Strduplstr(&wd, &genstr); 4773e12c5d1SDavid du Colombier if(wd.s[0] == 0){ 4783e12c5d1SDavid du Colombier wd.n = 0; 4793e12c5d1SDavid du Colombier warn(Wpwd); 4803e12c5d1SDavid du Colombier }else if(wd.s[wd.n-2] == '\n'){ 4813e12c5d1SDavid du Colombier --wd.n; 4823e12c5d1SDavid du Colombier wd.s[wd.n-1]='/'; 4833e12c5d1SDavid du Colombier } 4843e12c5d1SDavid du Colombier if(chdir(getname((File *)0, str, FALSE)? genc : home)) 4853e12c5d1SDavid du Colombier syserror("chdir"); 4863e12c5d1SDavid du Colombier settempfile(); 4873e12c5d1SDavid du Colombier for(i=0; i<tempfile.nused; i++){ 4883e12c5d1SDavid du Colombier f = tempfile.filepptr[i]; 4893e12c5d1SDavid du Colombier if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){ 4903e12c5d1SDavid du Colombier Strinsert(&f->name, &wd, (Posn)0); 4913e12c5d1SDavid du Colombier sortname(f); 4923e12c5d1SDavid du Colombier } 4933e12c5d1SDavid du Colombier } 4943e12c5d1SDavid du Colombier } 4953e12c5d1SDavid du Colombier 4963e12c5d1SDavid du Colombier int 4973e12c5d1SDavid du Colombier loadflist(String *s) 4983e12c5d1SDavid du Colombier { 4993e12c5d1SDavid du Colombier int c, i; 5003e12c5d1SDavid du Colombier 5013e12c5d1SDavid du Colombier c = s->s[0]; 5023e12c5d1SDavid du Colombier for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++) 5033e12c5d1SDavid du Colombier ; 5043e12c5d1SDavid du Colombier if((c==' ' || c=='\t') && s->s[i]!='\n'){ 5053e12c5d1SDavid du Colombier if(s->s[i]=='<'){ 5063e12c5d1SDavid du Colombier Strdelete(s, 0L, (long)i+1); 5073e12c5d1SDavid du Colombier readcmd(s); 5083e12c5d1SDavid du Colombier }else{ 5093e12c5d1SDavid du Colombier Strzero(&genstr); 5103e12c5d1SDavid du Colombier while((c = s->s[i++]) && c!='\n') 5113e12c5d1SDavid du Colombier Straddc(&genstr, c); 5123e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 5133e12c5d1SDavid du Colombier } 5143e12c5d1SDavid du Colombier }else{ 5153e12c5d1SDavid du Colombier if(c != '\n') 5163e12c5d1SDavid du Colombier error(Eblank); 5173e12c5d1SDavid du Colombier Strdupl(&genstr, empty); 5183e12c5d1SDavid du Colombier } 5193e12c5d1SDavid du Colombier if(genc) 5203e12c5d1SDavid du Colombier free(genc); 5213e12c5d1SDavid du Colombier genc = Strtoc(&genstr); 5223e12c5d1SDavid du Colombier return genstr.s[0]; 5233e12c5d1SDavid du Colombier } 5243e12c5d1SDavid du Colombier 5253e12c5d1SDavid du Colombier File * 5263e12c5d1SDavid du Colombier readflist(int readall, int delete) 5273e12c5d1SDavid du Colombier { 5283e12c5d1SDavid du Colombier Posn i; 5293e12c5d1SDavid du Colombier int c; 5303e12c5d1SDavid du Colombier File *f; 5313e12c5d1SDavid du Colombier String *t; 5323e12c5d1SDavid du Colombier 5333e12c5d1SDavid du Colombier for(i=0,f=0; f==0 || readall || delete; i++){ /* ++ skips blank */ 5343e12c5d1SDavid du Colombier Strdelete(&genstr, (Posn)0, i); 5353e12c5d1SDavid du Colombier for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++) 5363e12c5d1SDavid du Colombier ; 5373e12c5d1SDavid du Colombier if(i >= genstr.n) 5383e12c5d1SDavid du Colombier break; 5393e12c5d1SDavid du Colombier Strdelete(&genstr, (Posn)0, i); 5403e12c5d1SDavid du Colombier for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++) 5413e12c5d1SDavid du Colombier ; 5423e12c5d1SDavid du Colombier 5433e12c5d1SDavid du Colombier if(i == 0) 5443e12c5d1SDavid du Colombier break; 5453e12c5d1SDavid du Colombier genstr.s[i] = 0; 5463e12c5d1SDavid du Colombier t = tmprstr(genstr.s, i+1); 5473e12c5d1SDavid du Colombier f = lookfile(t); 5483e12c5d1SDavid du Colombier if(delete){ 5493e12c5d1SDavid du Colombier if(f == 0) 5503e12c5d1SDavid du Colombier warn_S(Wfile, t); 5513e12c5d1SDavid du Colombier else 5523e12c5d1SDavid du Colombier trytoclose(f); 5533e12c5d1SDavid du Colombier }else if(f==0 && readall) 5543e12c5d1SDavid du Colombier Fsetname(f = newfile(), t); 5553e12c5d1SDavid du Colombier } 5563e12c5d1SDavid du Colombier return f; 5573e12c5d1SDavid du Colombier } 5583e12c5d1SDavid du Colombier 5593e12c5d1SDavid du Colombier File * 5603e12c5d1SDavid du Colombier tofile(String *s) 5613e12c5d1SDavid du Colombier { 5623e12c5d1SDavid du Colombier File *f; 5633e12c5d1SDavid du Colombier 5643e12c5d1SDavid du Colombier if(s->s[0] != ' ') 5653e12c5d1SDavid du Colombier error(Eblank); 5663e12c5d1SDavid du Colombier if(loadflist(s) == 0){ 5673e12c5d1SDavid du Colombier f = lookfile(&genstr); /* empty string ==> nameless file */ 5683e12c5d1SDavid du Colombier if(f == 0) 5693e12c5d1SDavid du Colombier error_s(Emenu, genc); 5703e12c5d1SDavid du Colombier }else if((f=readflist(FALSE, FALSE)) == 0) 5713e12c5d1SDavid du Colombier error_s(Emenu, genc); 5723e12c5d1SDavid du Colombier return current(f); 5733e12c5d1SDavid du Colombier } 5743e12c5d1SDavid du Colombier 5753e12c5d1SDavid du Colombier File * 5763e12c5d1SDavid du Colombier getfile(String *s) 5773e12c5d1SDavid du Colombier { 5783e12c5d1SDavid du Colombier File *f; 5793e12c5d1SDavid du Colombier 5803e12c5d1SDavid du Colombier if(loadflist(s) == 0) 5813e12c5d1SDavid du Colombier Fsetname(f = newfile(), &genstr); 5823e12c5d1SDavid du Colombier else if((f=readflist(TRUE, FALSE)) == 0) 5833e12c5d1SDavid du Colombier error(Eblank); 5843e12c5d1SDavid du Colombier return current(f); 5853e12c5d1SDavid du Colombier } 5863e12c5d1SDavid du Colombier 5873e12c5d1SDavid du Colombier void 5883e12c5d1SDavid du Colombier closefiles(File *f, String *s) 5893e12c5d1SDavid du Colombier { 5903e12c5d1SDavid du Colombier if(s->s[0] == 0){ 5913e12c5d1SDavid du Colombier if(f == 0) 5923e12c5d1SDavid du Colombier error(Enofile); 5933e12c5d1SDavid du Colombier trytoclose(f); 5943e12c5d1SDavid du Colombier return; 5953e12c5d1SDavid du Colombier } 5963e12c5d1SDavid du Colombier if(s->s[0] != ' ') 5973e12c5d1SDavid du Colombier error(Eblank); 5983e12c5d1SDavid du Colombier if(loadflist(s) == 0) 5993e12c5d1SDavid du Colombier error(Enewline); 6003e12c5d1SDavid du Colombier readflist(FALSE, TRUE); 6013e12c5d1SDavid du Colombier } 6023e12c5d1SDavid du Colombier 6033e12c5d1SDavid du Colombier void 6043e12c5d1SDavid du Colombier copy(File *f, Address addr2) 6053e12c5d1SDavid du Colombier { 6063e12c5d1SDavid du Colombier Posn p; 6073e12c5d1SDavid du Colombier int ni; 6083e12c5d1SDavid du Colombier for(p=addr.r.p1; p<addr.r.p2; p+=ni){ 6093e12c5d1SDavid du Colombier ni = addr.r.p2-p; 6103e12c5d1SDavid du Colombier if(ni > BLOCKSIZE) 6113e12c5d1SDavid du Colombier ni = BLOCKSIZE; 6123e12c5d1SDavid du Colombier Fchars(f, genbuf, p, p+ni); 6133e12c5d1SDavid du Colombier Finsert(addr2.f, tmprstr(genbuf, ni), addr2.r.p2); 6143e12c5d1SDavid du Colombier } 6153e12c5d1SDavid du Colombier addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1); 6163e12c5d1SDavid du Colombier addr2.f->ndot.r.p1 = addr2.r.p2; 6173e12c5d1SDavid du Colombier } 6183e12c5d1SDavid du Colombier 6193e12c5d1SDavid du Colombier void 6203e12c5d1SDavid du Colombier move(File *f, Address addr2) 6213e12c5d1SDavid du Colombier { 6223e12c5d1SDavid du Colombier if(addr.r.p2 <= addr2.r.p2){ 6233e12c5d1SDavid du Colombier Fdelete(f, addr.r.p1, addr.r.p2); 6243e12c5d1SDavid du Colombier copy(f, addr2); 6253e12c5d1SDavid du Colombier }else if(addr.r.p1 >= addr2.r.p2){ 6263e12c5d1SDavid du Colombier copy(f, addr2); 6273e12c5d1SDavid du Colombier Fdelete(f, addr.r.p1, addr.r.p2); 6283e12c5d1SDavid du Colombier }else 6293e12c5d1SDavid du Colombier error(Eoverlap); 6303e12c5d1SDavid du Colombier } 6313e12c5d1SDavid du Colombier 6323e12c5d1SDavid du Colombier Posn 6333e12c5d1SDavid du Colombier nlcount(File *f, Posn p0, Posn p1) 6343e12c5d1SDavid du Colombier { 6353e12c5d1SDavid du Colombier Posn nl = 0; 6363e12c5d1SDavid du Colombier 6373e12c5d1SDavid du Colombier Fgetcset(f, p0); 6383e12c5d1SDavid du Colombier while(p0++<p1) 6393e12c5d1SDavid du Colombier if(Fgetc(f)=='\n') 6403e12c5d1SDavid du Colombier nl++; 6413e12c5d1SDavid du Colombier return nl; 6423e12c5d1SDavid du Colombier } 6433e12c5d1SDavid du Colombier 6443e12c5d1SDavid du Colombier void 6453e12c5d1SDavid du Colombier printposn(File *f, int charsonly) 6463e12c5d1SDavid du Colombier { 6473e12c5d1SDavid du Colombier Posn l1, l2; 6483e12c5d1SDavid du Colombier 6493e12c5d1SDavid du Colombier if(!charsonly){ 6503e12c5d1SDavid du Colombier l1 = 1+nlcount(f, (Posn)0, addr.r.p1); 6513e12c5d1SDavid du Colombier l2 = l1+nlcount(f, addr.r.p1, addr.r.p2); 6523e12c5d1SDavid du Colombier /* check if addr ends with '\n' */ 6533e12c5d1SDavid du Colombier if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && (Fgetcset(f, addr.r.p2-1),Fgetc(f)=='\n')) 6543e12c5d1SDavid du Colombier --l2; 6553e12c5d1SDavid du Colombier dprint("%lud", l1); 6563e12c5d1SDavid du Colombier if(l2 != l1) 6573e12c5d1SDavid du Colombier dprint(",%lud", l2); 6583e12c5d1SDavid du Colombier dprint("; "); 6593e12c5d1SDavid du Colombier } 6603e12c5d1SDavid du Colombier dprint("#%lud", addr.r.p1); 6613e12c5d1SDavid du Colombier if(addr.r.p2 != addr.r.p1) 6623e12c5d1SDavid du Colombier dprint(",#%lud", addr.r.p2); 6633e12c5d1SDavid du Colombier dprint("\n"); 6643e12c5d1SDavid du Colombier } 6653e12c5d1SDavid du Colombier 6663e12c5d1SDavid du Colombier void 6673e12c5d1SDavid du Colombier settempfile(void) 6683e12c5d1SDavid du Colombier { 6693e12c5d1SDavid du Colombier if(tempfile.nalloc < file.nused){ 6703e12c5d1SDavid du Colombier free(tempfile.listptr); 6713e12c5d1SDavid du Colombier tempfile.listptr = emalloc(sizeof(*tempfile.filepptr)*file.nused); 6723e12c5d1SDavid du Colombier tempfile.nalloc = file.nused; 6733e12c5d1SDavid du Colombier } 6743e12c5d1SDavid du Colombier tempfile.nused = file.nused; 6753e12c5d1SDavid du Colombier memmove(&tempfile.filepptr[0], &file.filepptr[0], file.nused*sizeof(File*)); 6763e12c5d1SDavid du Colombier } 677