1*3e12c5d1SDavid du Colombier #include "sam.h" 2*3e12c5d1SDavid du Colombier 3*3e12c5d1SDavid du Colombier Rune genbuf[BLOCKSIZE]; 4*3e12c5d1SDavid du Colombier int io; 5*3e12c5d1SDavid du Colombier int panicking; 6*3e12c5d1SDavid du Colombier int rescuing; 7*3e12c5d1SDavid du Colombier Mod modnum; 8*3e12c5d1SDavid du Colombier String genstr; 9*3e12c5d1SDavid du Colombier String rhs; 10*3e12c5d1SDavid du Colombier String wd; 11*3e12c5d1SDavid du Colombier String cmdstr; 12*3e12c5d1SDavid du Colombier Rune empty[] = { 0 }; 13*3e12c5d1SDavid du Colombier char *genc; 14*3e12c5d1SDavid du Colombier File *curfile; 15*3e12c5d1SDavid du Colombier File *flist; 16*3e12c5d1SDavid du Colombier File *cmd; 17*3e12c5d1SDavid du Colombier jmp_buf mainloop; 18*3e12c5d1SDavid du Colombier List tempfile; 19*3e12c5d1SDavid du Colombier int quitok = TRUE; 20*3e12c5d1SDavid du Colombier int downloaded; 21*3e12c5d1SDavid du Colombier int dflag; 22*3e12c5d1SDavid du Colombier int Rflag; 23*3e12c5d1SDavid du Colombier char *machine; 24*3e12c5d1SDavid du Colombier char *home; 25*3e12c5d1SDavid du Colombier int bpipeok; 26*3e12c5d1SDavid du Colombier int termlocked; 27*3e12c5d1SDavid du Colombier char *samterm = SAMTERM; 28*3e12c5d1SDavid du Colombier char *rsamname = RSAM; 29*3e12c5d1SDavid du Colombier 30*3e12c5d1SDavid du Colombier void usage(void); 31*3e12c5d1SDavid du Colombier 32*3e12c5d1SDavid du Colombier void 33*3e12c5d1SDavid du Colombier main(int argc, char *argv[]) 34*3e12c5d1SDavid du Colombier { 35*3e12c5d1SDavid du Colombier int i; 36*3e12c5d1SDavid du Colombier String *t; 37*3e12c5d1SDavid du Colombier char **ap, **arg; 38*3e12c5d1SDavid du Colombier 39*3e12c5d1SDavid du Colombier arg = argv++; 40*3e12c5d1SDavid du Colombier ap = argv; 41*3e12c5d1SDavid du Colombier while(argc>1 && argv[0] && argv[0][0]=='-'){ 42*3e12c5d1SDavid du Colombier switch(argv[0][1]){ 43*3e12c5d1SDavid du Colombier case 'd': 44*3e12c5d1SDavid du Colombier dflag++; 45*3e12c5d1SDavid du Colombier break; 46*3e12c5d1SDavid du Colombier 47*3e12c5d1SDavid du Colombier case 'r': 48*3e12c5d1SDavid du Colombier --argc, argv++; 49*3e12c5d1SDavid du Colombier if(argc == 1) 50*3e12c5d1SDavid du Colombier usage(); 51*3e12c5d1SDavid du Colombier machine = *argv; 52*3e12c5d1SDavid du Colombier break; 53*3e12c5d1SDavid du Colombier 54*3e12c5d1SDavid du Colombier case 'R': 55*3e12c5d1SDavid du Colombier Rflag++; 56*3e12c5d1SDavid du Colombier break; 57*3e12c5d1SDavid du Colombier 58*3e12c5d1SDavid du Colombier case 't': 59*3e12c5d1SDavid du Colombier --argc, argv++; 60*3e12c5d1SDavid du Colombier if(argc == 1) 61*3e12c5d1SDavid du Colombier usage(); 62*3e12c5d1SDavid du Colombier samterm = *argv; 63*3e12c5d1SDavid du Colombier break; 64*3e12c5d1SDavid du Colombier 65*3e12c5d1SDavid du Colombier case 's': 66*3e12c5d1SDavid du Colombier --argc, argv++; 67*3e12c5d1SDavid du Colombier if(argc == 1) 68*3e12c5d1SDavid du Colombier usage(); 69*3e12c5d1SDavid du Colombier rsamname = *argv; 70*3e12c5d1SDavid du Colombier break; 71*3e12c5d1SDavid du Colombier 72*3e12c5d1SDavid du Colombier case 'g': /* -geom -> pass to samterm */ 73*3e12c5d1SDavid du Colombier *ap++ = *argv++; 74*3e12c5d1SDavid du Colombier *ap++ = *argv; 75*3e12c5d1SDavid du Colombier argc--; 76*3e12c5d1SDavid du Colombier break; 77*3e12c5d1SDavid du Colombier 78*3e12c5d1SDavid du Colombier default: 79*3e12c5d1SDavid du Colombier dprint("sam: unknown flag %c\n", argv[1][1]); 80*3e12c5d1SDavid du Colombier exits("usage"); 81*3e12c5d1SDavid du Colombier } 82*3e12c5d1SDavid du Colombier --argc, argv++; 83*3e12c5d1SDavid du Colombier } 84*3e12c5d1SDavid du Colombier Strinit(&cmdstr); 85*3e12c5d1SDavid du Colombier Strinit0(&lastpat); 86*3e12c5d1SDavid du Colombier Strinit0(&lastregexp); 87*3e12c5d1SDavid du Colombier Strinit0(&genstr); 88*3e12c5d1SDavid du Colombier Strinit0(&rhs); 89*3e12c5d1SDavid du Colombier Strinit0(&wd); 90*3e12c5d1SDavid du Colombier tempfile.listptr = emalloc(0); 91*3e12c5d1SDavid du Colombier Strinit0(&plan9cmd); 92*3e12c5d1SDavid du Colombier home = getenv(HOME); 93*3e12c5d1SDavid du Colombier if(home == 0) 94*3e12c5d1SDavid du Colombier home = "/"; 95*3e12c5d1SDavid du Colombier if(!dflag) 96*3e12c5d1SDavid du Colombier startup(machine, Rflag, arg, ap); 97*3e12c5d1SDavid du Colombier Fstart(); 98*3e12c5d1SDavid du Colombier notify(notifyf); 99*3e12c5d1SDavid du Colombier if(argc>1){ 100*3e12c5d1SDavid du Colombier for(i=0; i<argc-1; i++) 101*3e12c5d1SDavid du Colombier if(!setjmp(mainloop)){ 102*3e12c5d1SDavid du Colombier t = tmpcstr(argv[i]); 103*3e12c5d1SDavid du Colombier Straddc(t, '\0'); 104*3e12c5d1SDavid du Colombier Strduplstr(&genstr, t); 105*3e12c5d1SDavid du Colombier freetmpstr(t); 106*3e12c5d1SDavid du Colombier Fsetname(newfile(), &genstr); 107*3e12c5d1SDavid du Colombier } 108*3e12c5d1SDavid du Colombier }else if(!downloaded) 109*3e12c5d1SDavid du Colombier newfile()->state = Clean; 110*3e12c5d1SDavid du Colombier modnum++; 111*3e12c5d1SDavid du Colombier if(file.nused) 112*3e12c5d1SDavid du Colombier current(file.filepptr[0]); 113*3e12c5d1SDavid du Colombier setjmp(mainloop); 114*3e12c5d1SDavid du Colombier cmdloop(); 115*3e12c5d1SDavid du Colombier trytoquit(); /* if we already q'ed, quitok will be TRUE */ 116*3e12c5d1SDavid du Colombier exits(0); 117*3e12c5d1SDavid du Colombier } 118*3e12c5d1SDavid du Colombier 119*3e12c5d1SDavid du Colombier void 120*3e12c5d1SDavid du Colombier usage(void) 121*3e12c5d1SDavid du Colombier { 122*3e12c5d1SDavid du Colombier dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n"); 123*3e12c5d1SDavid du Colombier exits("usage"); 124*3e12c5d1SDavid du Colombier } 125*3e12c5d1SDavid du Colombier 126*3e12c5d1SDavid du Colombier void 127*3e12c5d1SDavid du Colombier rescue(void) 128*3e12c5d1SDavid du Colombier { 129*3e12c5d1SDavid du Colombier int i, nblank = 0; 130*3e12c5d1SDavid du Colombier File *f; 131*3e12c5d1SDavid du Colombier char *c; 132*3e12c5d1SDavid du Colombier char buf[256]; 133*3e12c5d1SDavid du Colombier 134*3e12c5d1SDavid du Colombier if(rescuing++) 135*3e12c5d1SDavid du Colombier return; 136*3e12c5d1SDavid du Colombier io = -1; 137*3e12c5d1SDavid du Colombier for(i=0; i<file.nused; i++){ 138*3e12c5d1SDavid du Colombier f = file.filepptr[i]; 139*3e12c5d1SDavid du Colombier if(f==cmd || f->nrunes==0 || f->state!=Dirty) 140*3e12c5d1SDavid du Colombier continue; 141*3e12c5d1SDavid du Colombier if(io == -1){ 142*3e12c5d1SDavid du Colombier sprint(buf, "%s/sam.save", home); 143*3e12c5d1SDavid du Colombier io = create(buf, 1, 0777); 144*3e12c5d1SDavid du Colombier if(io<0) 145*3e12c5d1SDavid du Colombier return; 146*3e12c5d1SDavid du Colombier } 147*3e12c5d1SDavid du Colombier if(f->name.s[0]){ 148*3e12c5d1SDavid du Colombier c = Strtoc(&f->name); 149*3e12c5d1SDavid du Colombier strncpy(buf, c, sizeof buf-1); 150*3e12c5d1SDavid du Colombier buf[sizeof buf-1] = 0; 151*3e12c5d1SDavid du Colombier free(c); 152*3e12c5d1SDavid du Colombier }else 153*3e12c5d1SDavid du Colombier sprint(buf, "nameless.%d", nblank++); 154*3e12c5d1SDavid du Colombier fprint(io, "#!/bin/rc\n/sys/lib/samsave '%s' $* <<'---%s'\n", buf, buf); 155*3e12c5d1SDavid du Colombier addr.r.p1 = 0, addr.r.p2 = f->nrunes; 156*3e12c5d1SDavid du Colombier writeio(f); 157*3e12c5d1SDavid du Colombier fprint(io, "\n---%s\n", (char *)buf); 158*3e12c5d1SDavid du Colombier } 159*3e12c5d1SDavid du Colombier } 160*3e12c5d1SDavid du Colombier 161*3e12c5d1SDavid du Colombier void 162*3e12c5d1SDavid du Colombier panic(char *s) 163*3e12c5d1SDavid du Colombier { 164*3e12c5d1SDavid du Colombier int wasd; 165*3e12c5d1SDavid du Colombier 166*3e12c5d1SDavid du Colombier if(!panicking++ && !setjmp(mainloop)){ 167*3e12c5d1SDavid du Colombier wasd = downloaded; 168*3e12c5d1SDavid du Colombier downloaded = 0; 169*3e12c5d1SDavid du Colombier dprint("sam: panic: %s: %r\n", s); 170*3e12c5d1SDavid du Colombier if(wasd) 171*3e12c5d1SDavid du Colombier fprint(2, "sam: panic: %s: %r\n", s); 172*3e12c5d1SDavid du Colombier rescue(); 173*3e12c5d1SDavid du Colombier abort(); 174*3e12c5d1SDavid du Colombier } 175*3e12c5d1SDavid du Colombier } 176*3e12c5d1SDavid du Colombier 177*3e12c5d1SDavid du Colombier void 178*3e12c5d1SDavid du Colombier hiccough(char *s) 179*3e12c5d1SDavid du Colombier { 180*3e12c5d1SDavid du Colombier if(rescuing) 181*3e12c5d1SDavid du Colombier exits("rescue"); 182*3e12c5d1SDavid du Colombier if(s) 183*3e12c5d1SDavid du Colombier dprint("%s\n", s); 184*3e12c5d1SDavid du Colombier resetcmd(); 185*3e12c5d1SDavid du Colombier resetxec(); 186*3e12c5d1SDavid du Colombier resetsys(); 187*3e12c5d1SDavid du Colombier if(io > 0) 188*3e12c5d1SDavid du Colombier close(io); 189*3e12c5d1SDavid du Colombier if(undobuf->nrunes) 190*3e12c5d1SDavid du Colombier Bdelete(undobuf, (Posn)0, undobuf->nrunes); 191*3e12c5d1SDavid du Colombier update(); 192*3e12c5d1SDavid du Colombier if(curfile && curfile->state==Unread) 193*3e12c5d1SDavid du Colombier curfile->state = Clean; 194*3e12c5d1SDavid du Colombier if(downloaded && curfile && curfile->state!=Unread) 195*3e12c5d1SDavid du Colombier outTs(Hcurrent, curfile->tag); 196*3e12c5d1SDavid du Colombier longjmp(mainloop, 1); 197*3e12c5d1SDavid du Colombier } 198*3e12c5d1SDavid du Colombier 199*3e12c5d1SDavid du Colombier void 200*3e12c5d1SDavid du Colombier intr(void) 201*3e12c5d1SDavid du Colombier { 202*3e12c5d1SDavid du Colombier error(Eintr); 203*3e12c5d1SDavid du Colombier } 204*3e12c5d1SDavid du Colombier 205*3e12c5d1SDavid du Colombier void 206*3e12c5d1SDavid du Colombier trytoclose(File *f) 207*3e12c5d1SDavid du Colombier { 208*3e12c5d1SDavid du Colombier char *t; 209*3e12c5d1SDavid du Colombier 210*3e12c5d1SDavid du Colombier if(f == cmd) /* possible? */ 211*3e12c5d1SDavid du Colombier return; 212*3e12c5d1SDavid du Colombier if(f->state==Dirty && !f->closeok){ 213*3e12c5d1SDavid du Colombier f->closeok = TRUE; 214*3e12c5d1SDavid du Colombier if(f->name.s[0]){ 215*3e12c5d1SDavid du Colombier t = Strtoc(&f->name); 216*3e12c5d1SDavid du Colombier error_s(Emodified, t); 217*3e12c5d1SDavid du Colombier free(t); 218*3e12c5d1SDavid du Colombier }else 219*3e12c5d1SDavid du Colombier error_s(Emodified, "nameless file"); 220*3e12c5d1SDavid du Colombier } 221*3e12c5d1SDavid du Colombier if(downloaded && f->rasp) 222*3e12c5d1SDavid du Colombier outTs(Hclose, f->tag); 223*3e12c5d1SDavid du Colombier delfile(f); 224*3e12c5d1SDavid du Colombier if(f == curfile) 225*3e12c5d1SDavid du Colombier current((File *)0); 226*3e12c5d1SDavid du Colombier } 227*3e12c5d1SDavid du Colombier 228*3e12c5d1SDavid du Colombier void 229*3e12c5d1SDavid du Colombier trytoquit(void) 230*3e12c5d1SDavid du Colombier { 231*3e12c5d1SDavid du Colombier int c; 232*3e12c5d1SDavid du Colombier File *f; 233*3e12c5d1SDavid du Colombier 234*3e12c5d1SDavid du Colombier if(!quitok) 235*3e12c5d1SDavid du Colombier for(c = 0; c<file.nused; c++){ 236*3e12c5d1SDavid du Colombier f = file.filepptr[c]; 237*3e12c5d1SDavid du Colombier if(f!=cmd && f->state==Dirty){ 238*3e12c5d1SDavid du Colombier quitok = TRUE; 239*3e12c5d1SDavid du Colombier eof = FALSE; 240*3e12c5d1SDavid du Colombier error(Echanges); 241*3e12c5d1SDavid du Colombier } 242*3e12c5d1SDavid du Colombier } 243*3e12c5d1SDavid du Colombier } 244*3e12c5d1SDavid du Colombier 245*3e12c5d1SDavid du Colombier void 246*3e12c5d1SDavid du Colombier load(File *f) 247*3e12c5d1SDavid du Colombier { 248*3e12c5d1SDavid du Colombier Address saveaddr; 249*3e12c5d1SDavid du Colombier 250*3e12c5d1SDavid du Colombier Strduplstr(&genstr, &f->name); 251*3e12c5d1SDavid du Colombier filename(f); 252*3e12c5d1SDavid du Colombier if(f->name.s[0]){ 253*3e12c5d1SDavid du Colombier saveaddr = addr; 254*3e12c5d1SDavid du Colombier edit(f, 'I'); 255*3e12c5d1SDavid du Colombier addr = saveaddr; 256*3e12c5d1SDavid du Colombier }else 257*3e12c5d1SDavid du Colombier f->state = Clean; 258*3e12c5d1SDavid du Colombier Fupdate(f, TRUE, TRUE); 259*3e12c5d1SDavid du Colombier } 260*3e12c5d1SDavid du Colombier 261*3e12c5d1SDavid du Colombier void 262*3e12c5d1SDavid du Colombier cmdupdate(void) 263*3e12c5d1SDavid du Colombier { 264*3e12c5d1SDavid du Colombier if(cmd && cmd->mod!=0){ 265*3e12c5d1SDavid du Colombier Fupdate(cmd, FALSE, downloaded); 266*3e12c5d1SDavid du Colombier cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nrunes; 267*3e12c5d1SDavid du Colombier telldot(cmd); 268*3e12c5d1SDavid du Colombier } 269*3e12c5d1SDavid du Colombier } 270*3e12c5d1SDavid du Colombier 271*3e12c5d1SDavid du Colombier void 272*3e12c5d1SDavid du Colombier update(void) 273*3e12c5d1SDavid du Colombier { 274*3e12c5d1SDavid du Colombier int i, anymod; 275*3e12c5d1SDavid du Colombier File *f; 276*3e12c5d1SDavid du Colombier 277*3e12c5d1SDavid du Colombier settempfile(); 278*3e12c5d1SDavid du Colombier for(anymod = i=0; i<tempfile.nused; i++){ 279*3e12c5d1SDavid du Colombier f = tempfile.filepptr[i]; 280*3e12c5d1SDavid du Colombier if(f==cmd) /* cmd gets done in main() */ 281*3e12c5d1SDavid du Colombier continue; 282*3e12c5d1SDavid du Colombier if(f->mod==modnum && Fupdate(f, FALSE, downloaded)) 283*3e12c5d1SDavid du Colombier anymod++; 284*3e12c5d1SDavid du Colombier if(f->rasp) 285*3e12c5d1SDavid du Colombier telldot(f); 286*3e12c5d1SDavid du Colombier } 287*3e12c5d1SDavid du Colombier if(anymod) 288*3e12c5d1SDavid du Colombier modnum++; 289*3e12c5d1SDavid du Colombier } 290*3e12c5d1SDavid du Colombier 291*3e12c5d1SDavid du Colombier File * 292*3e12c5d1SDavid du Colombier current(File *f) 293*3e12c5d1SDavid du Colombier { 294*3e12c5d1SDavid du Colombier return curfile = f; 295*3e12c5d1SDavid du Colombier } 296*3e12c5d1SDavid du Colombier 297*3e12c5d1SDavid du Colombier void 298*3e12c5d1SDavid du Colombier edit(File *f, int cmd) 299*3e12c5d1SDavid du Colombier { 300*3e12c5d1SDavid du Colombier int empty = TRUE; 301*3e12c5d1SDavid du Colombier Posn p; 302*3e12c5d1SDavid du Colombier int nulls; 303*3e12c5d1SDavid du Colombier 304*3e12c5d1SDavid du Colombier if(cmd == 'r') 305*3e12c5d1SDavid du Colombier Fdelete(f, addr.r.p1, addr.r.p2); 306*3e12c5d1SDavid du Colombier if(cmd=='e' || cmd=='I'){ 307*3e12c5d1SDavid du Colombier Fdelete(f, (Posn)0, f->nrunes); 308*3e12c5d1SDavid du Colombier addr.r.p2 = f->nrunes; 309*3e12c5d1SDavid du Colombier }else if(f->nrunes!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0)) 310*3e12c5d1SDavid du Colombier empty = FALSE; 311*3e12c5d1SDavid du Colombier if((io = open(genc, OREAD))<0) 312*3e12c5d1SDavid du Colombier error_s(Eopen, genc); 313*3e12c5d1SDavid du Colombier p = readio(f, &nulls, empty); 314*3e12c5d1SDavid du Colombier closeio((cmd=='e' || cmd=='I')? -1 : p); 315*3e12c5d1SDavid du Colombier if(cmd == 'r') 316*3e12c5d1SDavid du Colombier f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p; 317*3e12c5d1SDavid du Colombier else 318*3e12c5d1SDavid du Colombier f->ndot.r.p1 = f->ndot.r.p2 = 0; 319*3e12c5d1SDavid du Colombier quitok = f->closeok = empty; 320*3e12c5d1SDavid du Colombier state(f, empty && !nulls? Clean : Dirty); 321*3e12c5d1SDavid du Colombier if(cmd == 'e') 322*3e12c5d1SDavid du Colombier filename(f); 323*3e12c5d1SDavid du Colombier } 324*3e12c5d1SDavid du Colombier 325*3e12c5d1SDavid du Colombier int 326*3e12c5d1SDavid du Colombier getname(File *f, String *s, int save) 327*3e12c5d1SDavid du Colombier { 328*3e12c5d1SDavid du Colombier int c, i; 329*3e12c5d1SDavid du Colombier 330*3e12c5d1SDavid du Colombier Strzero(&genstr); 331*3e12c5d1SDavid du Colombier if(genc){ 332*3e12c5d1SDavid du Colombier free(genc); 333*3e12c5d1SDavid du Colombier genc = 0; 334*3e12c5d1SDavid du Colombier } 335*3e12c5d1SDavid du Colombier if(s==0 || (c = s->s[0])==0){ /* no name provided */ 336*3e12c5d1SDavid du Colombier if(f) 337*3e12c5d1SDavid du Colombier Strduplstr(&genstr, &f->name); 338*3e12c5d1SDavid du Colombier else 339*3e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 340*3e12c5d1SDavid du Colombier goto Return; 341*3e12c5d1SDavid du Colombier } 342*3e12c5d1SDavid du Colombier if(c!=' ' && c!='\t') 343*3e12c5d1SDavid du Colombier error(Eblank); 344*3e12c5d1SDavid du Colombier for(i=0; (c=s->s[i])==' ' || c=='\t'; i++) 345*3e12c5d1SDavid du Colombier ; 346*3e12c5d1SDavid du Colombier while(s->s[i] > ' ') 347*3e12c5d1SDavid du Colombier Straddc(&genstr, s->s[i++]); 348*3e12c5d1SDavid du Colombier if(s->s[i]) 349*3e12c5d1SDavid du Colombier error(Enewline); 350*3e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 351*3e12c5d1SDavid du Colombier if(f && (save || f->name.s[0]==0)){ 352*3e12c5d1SDavid du Colombier Fsetname(f, &genstr); 353*3e12c5d1SDavid du Colombier if(Strcmp(&f->name, &genstr)){ 354*3e12c5d1SDavid du Colombier quitok = f->closeok = FALSE; 355*3e12c5d1SDavid du Colombier f->inumber = 0; 356*3e12c5d1SDavid du Colombier f->date = 0; 357*3e12c5d1SDavid du Colombier state(f, Dirty); /* if it's 'e', fix later */ 358*3e12c5d1SDavid du Colombier } 359*3e12c5d1SDavid du Colombier } 360*3e12c5d1SDavid du Colombier Return: 361*3e12c5d1SDavid du Colombier genc = Strtoc(&genstr); 362*3e12c5d1SDavid du Colombier return genstr.n-1; /* strlen(name) */ 363*3e12c5d1SDavid du Colombier } 364*3e12c5d1SDavid du Colombier 365*3e12c5d1SDavid du Colombier void 366*3e12c5d1SDavid du Colombier filename(File *f) 367*3e12c5d1SDavid du Colombier { 368*3e12c5d1SDavid du Colombier if(genc) 369*3e12c5d1SDavid du Colombier free(genc); 370*3e12c5d1SDavid du Colombier genc = Strtoc(&genstr); 371*3e12c5d1SDavid du Colombier dprint("%c%c%c %s\n", " '"[f->state==Dirty], 372*3e12c5d1SDavid du Colombier "-+"[f->rasp!=0], " ."[f==curfile], genc); 373*3e12c5d1SDavid du Colombier } 374*3e12c5d1SDavid du Colombier 375*3e12c5d1SDavid du Colombier void 376*3e12c5d1SDavid du Colombier undostep(File *f) 377*3e12c5d1SDavid du Colombier { 378*3e12c5d1SDavid du Colombier Buffer *t; 379*3e12c5d1SDavid du Colombier int changes; 380*3e12c5d1SDavid du Colombier Mark mark; 381*3e12c5d1SDavid du Colombier 382*3e12c5d1SDavid du Colombier t = f->transcript; 383*3e12c5d1SDavid du Colombier changes = Fupdate(f, TRUE, TRUE); 384*3e12c5d1SDavid du Colombier Bread(t, (Rune*)&mark, (sizeof mark)/RUNESIZE, f->markp); 385*3e12c5d1SDavid du Colombier Bdelete(t, f->markp, t->nrunes); 386*3e12c5d1SDavid du Colombier f->markp = mark.p; 387*3e12c5d1SDavid du Colombier f->dot.r = mark.dot; 388*3e12c5d1SDavid du Colombier f->ndot.r = mark.dot; 389*3e12c5d1SDavid du Colombier f->mark = mark.mark; 390*3e12c5d1SDavid du Colombier f->mod = mark.m; 391*3e12c5d1SDavid du Colombier f->closeok = mark.s1!=Dirty; 392*3e12c5d1SDavid du Colombier if(mark.s1==Dirty) 393*3e12c5d1SDavid du Colombier quitok = FALSE; 394*3e12c5d1SDavid du Colombier if(f->state==Clean && mark.s1==Clean && changes) 395*3e12c5d1SDavid du Colombier state(f, Dirty); 396*3e12c5d1SDavid du Colombier else 397*3e12c5d1SDavid du Colombier state(f, mark.s1); 398*3e12c5d1SDavid du Colombier } 399*3e12c5d1SDavid du Colombier 400*3e12c5d1SDavid du Colombier void 401*3e12c5d1SDavid du Colombier undo(void) 402*3e12c5d1SDavid du Colombier { 403*3e12c5d1SDavid du Colombier File *f; 404*3e12c5d1SDavid du Colombier int i; 405*3e12c5d1SDavid du Colombier Mod max; 406*3e12c5d1SDavid du Colombier 407*3e12c5d1SDavid du Colombier if((max = curfile->mod)==0) 408*3e12c5d1SDavid du Colombier return; 409*3e12c5d1SDavid du Colombier settempfile(); 410*3e12c5d1SDavid du Colombier for(i = 0; i<tempfile.nused; i++){ 411*3e12c5d1SDavid du Colombier f = tempfile.filepptr[i]; 412*3e12c5d1SDavid du Colombier if(f!=cmd && f->mod==max) 413*3e12c5d1SDavid du Colombier undostep(f); 414*3e12c5d1SDavid du Colombier } 415*3e12c5d1SDavid du Colombier } 416*3e12c5d1SDavid du Colombier 417*3e12c5d1SDavid du Colombier void 418*3e12c5d1SDavid du Colombier readcmd(String *s) 419*3e12c5d1SDavid du Colombier { 420*3e12c5d1SDavid du Colombier if(flist == 0) 421*3e12c5d1SDavid du Colombier (flist = Fopen())->state = Clean; 422*3e12c5d1SDavid du Colombier addr.r.p1 = 0, addr.r.p2 = flist->nrunes; 423*3e12c5d1SDavid du Colombier plan9(flist, '<', s, FALSE); 424*3e12c5d1SDavid du Colombier Fupdate(flist, FALSE, FALSE); 425*3e12c5d1SDavid du Colombier flist->mod = 0; 426*3e12c5d1SDavid du Colombier Strzero(&genstr); 427*3e12c5d1SDavid du Colombier Strinsure(&genstr, flist->nrunes); 428*3e12c5d1SDavid du Colombier Fchars(flist, genbuf, (Posn)0, flist->nrunes); 429*3e12c5d1SDavid du Colombier memmove(genstr.s, genbuf, flist->nrunes*RUNESIZE); 430*3e12c5d1SDavid du Colombier genstr.n = flist->nrunes; 431*3e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 432*3e12c5d1SDavid du Colombier } 433*3e12c5d1SDavid du Colombier 434*3e12c5d1SDavid du Colombier void 435*3e12c5d1SDavid du Colombier cd(String *str) 436*3e12c5d1SDavid du Colombier { 437*3e12c5d1SDavid du Colombier int i; 438*3e12c5d1SDavid du Colombier File *f; 439*3e12c5d1SDavid du Colombier String *t; 440*3e12c5d1SDavid du Colombier 441*3e12c5d1SDavid du Colombier t = tmpcstr("/bin/pwd"); 442*3e12c5d1SDavid du Colombier Straddc(t, '\0'); 443*3e12c5d1SDavid du Colombier readcmd(t); 444*3e12c5d1SDavid du Colombier freetmpstr(t); 445*3e12c5d1SDavid du Colombier Strduplstr(&wd, &genstr); 446*3e12c5d1SDavid du Colombier if(wd.s[0] == 0){ 447*3e12c5d1SDavid du Colombier wd.n = 0; 448*3e12c5d1SDavid du Colombier warn(Wpwd); 449*3e12c5d1SDavid du Colombier }else if(wd.s[wd.n-2] == '\n'){ 450*3e12c5d1SDavid du Colombier --wd.n; 451*3e12c5d1SDavid du Colombier wd.s[wd.n-1]='/'; 452*3e12c5d1SDavid du Colombier } 453*3e12c5d1SDavid du Colombier if(chdir(getname((File *)0, str, FALSE)? genc : home)) 454*3e12c5d1SDavid du Colombier syserror("chdir"); 455*3e12c5d1SDavid du Colombier settempfile(); 456*3e12c5d1SDavid du Colombier for(i=0; i<tempfile.nused; i++){ 457*3e12c5d1SDavid du Colombier f = tempfile.filepptr[i]; 458*3e12c5d1SDavid du Colombier if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){ 459*3e12c5d1SDavid du Colombier Strinsert(&f->name, &wd, (Posn)0); 460*3e12c5d1SDavid du Colombier sortname(f); 461*3e12c5d1SDavid du Colombier } 462*3e12c5d1SDavid du Colombier } 463*3e12c5d1SDavid du Colombier } 464*3e12c5d1SDavid du Colombier 465*3e12c5d1SDavid du Colombier int 466*3e12c5d1SDavid du Colombier loadflist(String *s) 467*3e12c5d1SDavid du Colombier { 468*3e12c5d1SDavid du Colombier int c, i; 469*3e12c5d1SDavid du Colombier 470*3e12c5d1SDavid du Colombier c = s->s[0]; 471*3e12c5d1SDavid du Colombier for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++) 472*3e12c5d1SDavid du Colombier ; 473*3e12c5d1SDavid du Colombier if((c==' ' || c=='\t') && s->s[i]!='\n'){ 474*3e12c5d1SDavid du Colombier if(s->s[i]=='<'){ 475*3e12c5d1SDavid du Colombier Strdelete(s, 0L, (long)i+1); 476*3e12c5d1SDavid du Colombier readcmd(s); 477*3e12c5d1SDavid du Colombier }else{ 478*3e12c5d1SDavid du Colombier Strzero(&genstr); 479*3e12c5d1SDavid du Colombier while((c = s->s[i++]) && c!='\n') 480*3e12c5d1SDavid du Colombier Straddc(&genstr, c); 481*3e12c5d1SDavid du Colombier Straddc(&genstr, '\0'); 482*3e12c5d1SDavid du Colombier } 483*3e12c5d1SDavid du Colombier }else{ 484*3e12c5d1SDavid du Colombier if(c != '\n') 485*3e12c5d1SDavid du Colombier error(Eblank); 486*3e12c5d1SDavid du Colombier Strdupl(&genstr, empty); 487*3e12c5d1SDavid du Colombier } 488*3e12c5d1SDavid du Colombier if(genc) 489*3e12c5d1SDavid du Colombier free(genc); 490*3e12c5d1SDavid du Colombier genc = Strtoc(&genstr); 491*3e12c5d1SDavid du Colombier return genstr.s[0]; 492*3e12c5d1SDavid du Colombier } 493*3e12c5d1SDavid du Colombier 494*3e12c5d1SDavid du Colombier File * 495*3e12c5d1SDavid du Colombier readflist(int readall, int delete) 496*3e12c5d1SDavid du Colombier { 497*3e12c5d1SDavid du Colombier Posn i; 498*3e12c5d1SDavid du Colombier int c; 499*3e12c5d1SDavid du Colombier File *f; 500*3e12c5d1SDavid du Colombier String *t; 501*3e12c5d1SDavid du Colombier 502*3e12c5d1SDavid du Colombier for(i=0,f=0; f==0 || readall || delete; i++){ /* ++ skips blank */ 503*3e12c5d1SDavid du Colombier Strdelete(&genstr, (Posn)0, i); 504*3e12c5d1SDavid du Colombier for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++) 505*3e12c5d1SDavid du Colombier ; 506*3e12c5d1SDavid du Colombier if(i >= genstr.n) 507*3e12c5d1SDavid du Colombier break; 508*3e12c5d1SDavid du Colombier Strdelete(&genstr, (Posn)0, i); 509*3e12c5d1SDavid du Colombier for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++) 510*3e12c5d1SDavid du Colombier ; 511*3e12c5d1SDavid du Colombier 512*3e12c5d1SDavid du Colombier if(i == 0) 513*3e12c5d1SDavid du Colombier break; 514*3e12c5d1SDavid du Colombier genstr.s[i] = 0; 515*3e12c5d1SDavid du Colombier t = tmprstr(genstr.s, i+1); 516*3e12c5d1SDavid du Colombier f = lookfile(t); 517*3e12c5d1SDavid du Colombier if(delete){ 518*3e12c5d1SDavid du Colombier if(f == 0) 519*3e12c5d1SDavid du Colombier warn_S(Wfile, t); 520*3e12c5d1SDavid du Colombier else 521*3e12c5d1SDavid du Colombier trytoclose(f); 522*3e12c5d1SDavid du Colombier }else if(f==0 && readall) 523*3e12c5d1SDavid du Colombier Fsetname(f = newfile(), t); 524*3e12c5d1SDavid du Colombier } 525*3e12c5d1SDavid du Colombier return f; 526*3e12c5d1SDavid du Colombier } 527*3e12c5d1SDavid du Colombier 528*3e12c5d1SDavid du Colombier File * 529*3e12c5d1SDavid du Colombier tofile(String *s) 530*3e12c5d1SDavid du Colombier { 531*3e12c5d1SDavid du Colombier File *f; 532*3e12c5d1SDavid du Colombier 533*3e12c5d1SDavid du Colombier if(s->s[0] != ' ') 534*3e12c5d1SDavid du Colombier error(Eblank); 535*3e12c5d1SDavid du Colombier if(loadflist(s) == 0){ 536*3e12c5d1SDavid du Colombier f = lookfile(&genstr); /* empty string ==> nameless file */ 537*3e12c5d1SDavid du Colombier if(f == 0) 538*3e12c5d1SDavid du Colombier error_s(Emenu, genc); 539*3e12c5d1SDavid du Colombier }else if((f=readflist(FALSE, FALSE)) == 0) 540*3e12c5d1SDavid du Colombier error_s(Emenu, genc); 541*3e12c5d1SDavid du Colombier return current(f); 542*3e12c5d1SDavid du Colombier } 543*3e12c5d1SDavid du Colombier 544*3e12c5d1SDavid du Colombier File * 545*3e12c5d1SDavid du Colombier getfile(String *s) 546*3e12c5d1SDavid du Colombier { 547*3e12c5d1SDavid du Colombier File *f; 548*3e12c5d1SDavid du Colombier 549*3e12c5d1SDavid du Colombier if(loadflist(s) == 0) 550*3e12c5d1SDavid du Colombier Fsetname(f = newfile(), &genstr); 551*3e12c5d1SDavid du Colombier else if((f=readflist(TRUE, FALSE)) == 0) 552*3e12c5d1SDavid du Colombier error(Eblank); 553*3e12c5d1SDavid du Colombier return current(f); 554*3e12c5d1SDavid du Colombier } 555*3e12c5d1SDavid du Colombier 556*3e12c5d1SDavid du Colombier void 557*3e12c5d1SDavid du Colombier closefiles(File *f, String *s) 558*3e12c5d1SDavid du Colombier { 559*3e12c5d1SDavid du Colombier if(s->s[0] == 0){ 560*3e12c5d1SDavid du Colombier if(f == 0) 561*3e12c5d1SDavid du Colombier error(Enofile); 562*3e12c5d1SDavid du Colombier trytoclose(f); 563*3e12c5d1SDavid du Colombier return; 564*3e12c5d1SDavid du Colombier } 565*3e12c5d1SDavid du Colombier if(s->s[0] != ' ') 566*3e12c5d1SDavid du Colombier error(Eblank); 567*3e12c5d1SDavid du Colombier if(loadflist(s) == 0) 568*3e12c5d1SDavid du Colombier error(Enewline); 569*3e12c5d1SDavid du Colombier readflist(FALSE, TRUE); 570*3e12c5d1SDavid du Colombier } 571*3e12c5d1SDavid du Colombier 572*3e12c5d1SDavid du Colombier void 573*3e12c5d1SDavid du Colombier copy(File *f, Address addr2) 574*3e12c5d1SDavid du Colombier { 575*3e12c5d1SDavid du Colombier Posn p; 576*3e12c5d1SDavid du Colombier int ni; 577*3e12c5d1SDavid du Colombier for(p=addr.r.p1; p<addr.r.p2; p+=ni){ 578*3e12c5d1SDavid du Colombier ni = addr.r.p2-p; 579*3e12c5d1SDavid du Colombier if(ni > BLOCKSIZE) 580*3e12c5d1SDavid du Colombier ni = BLOCKSIZE; 581*3e12c5d1SDavid du Colombier Fchars(f, genbuf, p, p+ni); 582*3e12c5d1SDavid du Colombier Finsert(addr2.f, tmprstr(genbuf, ni), addr2.r.p2); 583*3e12c5d1SDavid du Colombier } 584*3e12c5d1SDavid du Colombier addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1); 585*3e12c5d1SDavid du Colombier addr2.f->ndot.r.p1 = addr2.r.p2; 586*3e12c5d1SDavid du Colombier } 587*3e12c5d1SDavid du Colombier 588*3e12c5d1SDavid du Colombier void 589*3e12c5d1SDavid du Colombier move(File *f, Address addr2) 590*3e12c5d1SDavid du Colombier { 591*3e12c5d1SDavid du Colombier if(addr.r.p2 <= addr2.r.p2){ 592*3e12c5d1SDavid du Colombier Fdelete(f, addr.r.p1, addr.r.p2); 593*3e12c5d1SDavid du Colombier copy(f, addr2); 594*3e12c5d1SDavid du Colombier }else if(addr.r.p1 >= addr2.r.p2){ 595*3e12c5d1SDavid du Colombier copy(f, addr2); 596*3e12c5d1SDavid du Colombier Fdelete(f, addr.r.p1, addr.r.p2); 597*3e12c5d1SDavid du Colombier }else 598*3e12c5d1SDavid du Colombier error(Eoverlap); 599*3e12c5d1SDavid du Colombier } 600*3e12c5d1SDavid du Colombier 601*3e12c5d1SDavid du Colombier Posn 602*3e12c5d1SDavid du Colombier nlcount(File *f, Posn p0, Posn p1) 603*3e12c5d1SDavid du Colombier { 604*3e12c5d1SDavid du Colombier Posn nl = 0; 605*3e12c5d1SDavid du Colombier 606*3e12c5d1SDavid du Colombier Fgetcset(f, p0); 607*3e12c5d1SDavid du Colombier while(p0++<p1) 608*3e12c5d1SDavid du Colombier if(Fgetc(f)=='\n') 609*3e12c5d1SDavid du Colombier nl++; 610*3e12c5d1SDavid du Colombier return nl; 611*3e12c5d1SDavid du Colombier } 612*3e12c5d1SDavid du Colombier 613*3e12c5d1SDavid du Colombier void 614*3e12c5d1SDavid du Colombier printposn(File *f, int charsonly) 615*3e12c5d1SDavid du Colombier { 616*3e12c5d1SDavid du Colombier Posn l1, l2; 617*3e12c5d1SDavid du Colombier 618*3e12c5d1SDavid du Colombier if(!charsonly){ 619*3e12c5d1SDavid du Colombier l1 = 1+nlcount(f, (Posn)0, addr.r.p1); 620*3e12c5d1SDavid du Colombier l2 = l1+nlcount(f, addr.r.p1, addr.r.p2); 621*3e12c5d1SDavid du Colombier /* check if addr ends with '\n' */ 622*3e12c5d1SDavid du Colombier if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && (Fgetcset(f, addr.r.p2-1),Fgetc(f)=='\n')) 623*3e12c5d1SDavid du Colombier --l2; 624*3e12c5d1SDavid du Colombier dprint("%lud", l1); 625*3e12c5d1SDavid du Colombier if(l2 != l1) 626*3e12c5d1SDavid du Colombier dprint(",%lud", l2); 627*3e12c5d1SDavid du Colombier dprint("; "); 628*3e12c5d1SDavid du Colombier } 629*3e12c5d1SDavid du Colombier dprint("#%lud", addr.r.p1); 630*3e12c5d1SDavid du Colombier if(addr.r.p2 != addr.r.p1) 631*3e12c5d1SDavid du Colombier dprint(",#%lud", addr.r.p2); 632*3e12c5d1SDavid du Colombier dprint("\n"); 633*3e12c5d1SDavid du Colombier } 634*3e12c5d1SDavid du Colombier 635*3e12c5d1SDavid du Colombier void 636*3e12c5d1SDavid du Colombier settempfile(void) 637*3e12c5d1SDavid du Colombier { 638*3e12c5d1SDavid du Colombier if(tempfile.nalloc < file.nused){ 639*3e12c5d1SDavid du Colombier free(tempfile.listptr); 640*3e12c5d1SDavid du Colombier tempfile.listptr = emalloc(sizeof(*tempfile.filepptr)*file.nused); 641*3e12c5d1SDavid du Colombier tempfile.nalloc = file.nused; 642*3e12c5d1SDavid du Colombier } 643*3e12c5d1SDavid du Colombier tempfile.nused = file.nused; 644*3e12c5d1SDavid du Colombier memmove(&tempfile.filepptr[0], &file.filepptr[0], file.nused*sizeof(File*)); 645*3e12c5d1SDavid du Colombier } 646