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 String genstr;
83e12c5d1SDavid du Colombier String rhs;
97dd7cddfSDavid du Colombier String curwd;
103e12c5d1SDavid du Colombier String cmdstr;
113e12c5d1SDavid du Colombier Rune empty[] = { 0 };
123e12c5d1SDavid du Colombier char *genc;
133e12c5d1SDavid du Colombier File *curfile;
143e12c5d1SDavid du Colombier File *flist;
153e12c5d1SDavid du Colombier File *cmd;
163e12c5d1SDavid du Colombier jmp_buf mainloop;
17*73e742d7SDavid du Colombier List tempfile = { 'p' };
183e12c5d1SDavid du Colombier int quitok = TRUE;
193e12c5d1SDavid du Colombier int downloaded;
203e12c5d1SDavid du Colombier int dflag;
213e12c5d1SDavid du Colombier int Rflag;
223e12c5d1SDavid du Colombier char *machine;
233e12c5d1SDavid du Colombier char *home;
243e12c5d1SDavid du Colombier int bpipeok;
253e12c5d1SDavid du Colombier int termlocked;
263e12c5d1SDavid du Colombier char *samterm = SAMTERM;
273e12c5d1SDavid du Colombier char *rsamname = RSAM;
287dd7cddfSDavid du Colombier File *lastfile;
297dd7cddfSDavid du Colombier Disk *disk;
307dd7cddfSDavid du Colombier long seq;
313e12c5d1SDavid du Colombier
32219b2ee8SDavid du Colombier Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'};
33219b2ee8SDavid du Colombier
343e12c5d1SDavid du Colombier void usage(void);
353e12c5d1SDavid du Colombier
main(int argc,char * argv[])367dd7cddfSDavid du Colombier void main(int argc, char *argv[])
373e12c5d1SDavid du Colombier {
383e12c5d1SDavid du Colombier int i;
393e12c5d1SDavid du Colombier String *t;
40e7d29567SDavid du Colombier char *termargs[10], **ap;
413e12c5d1SDavid du Colombier
42e7d29567SDavid du Colombier ap = termargs;
43e7d29567SDavid du Colombier *ap++ = "samterm";
44e7d29567SDavid du Colombier ARGBEGIN{
453e12c5d1SDavid du Colombier case 'd':
463e12c5d1SDavid du Colombier dflag++;
473e12c5d1SDavid du Colombier break;
483e12c5d1SDavid du Colombier case 'r':
49e7d29567SDavid du Colombier machine = EARGF(usage());
503e12c5d1SDavid du Colombier break;
513e12c5d1SDavid du Colombier case 'R':
523e12c5d1SDavid du Colombier Rflag++;
533e12c5d1SDavid du Colombier break;
543e12c5d1SDavid du Colombier case 't':
55e7d29567SDavid du Colombier samterm = EARGF(usage());
563e12c5d1SDavid du Colombier break;
573e12c5d1SDavid du Colombier case 's':
58e7d29567SDavid du Colombier rsamname = EARGF(usage());
593e12c5d1SDavid du Colombier break;
603e12c5d1SDavid du Colombier default:
61e7d29567SDavid du Colombier dprint("sam: unknown flag %c\n", ARGC());
62e7d29567SDavid du Colombier usage();
63e7d29567SDavid du Colombier /* options for samterm */
64e7d29567SDavid du Colombier case 'a':
65e7d29567SDavid du Colombier *ap++ = "-a";
66e7d29567SDavid du Colombier break;
67e7d29567SDavid du Colombier }ARGEND
68e7d29567SDavid du Colombier *ap = nil;
69e7d29567SDavid du Colombier
703e12c5d1SDavid du Colombier Strinit(&cmdstr);
713e12c5d1SDavid du Colombier Strinit0(&lastpat);
723e12c5d1SDavid du Colombier Strinit0(&lastregexp);
733e12c5d1SDavid du Colombier Strinit0(&genstr);
743e12c5d1SDavid du Colombier Strinit0(&rhs);
757dd7cddfSDavid du Colombier Strinit0(&curwd);
763e12c5d1SDavid du Colombier Strinit0(&plan9cmd);
773e12c5d1SDavid du Colombier home = getenv(HOME);
787dd7cddfSDavid du Colombier disk = diskinit();
793e12c5d1SDavid du Colombier if(home == 0)
803e12c5d1SDavid du Colombier home = "/";
813e12c5d1SDavid du Colombier if(!dflag)
82e7d29567SDavid du Colombier startup(machine, Rflag, termargs, argv);
833e12c5d1SDavid du Colombier notify(notifyf);
847dd7cddfSDavid du Colombier getcurwd();
85e7d29567SDavid du Colombier if(argc>0){
86e7d29567SDavid du Colombier for(i=0; i<argc; i++){
873e12c5d1SDavid du Colombier if(!setjmp(mainloop)){
883e12c5d1SDavid du Colombier t = tmpcstr(argv[i]);
893e12c5d1SDavid du Colombier Straddc(t, '\0');
903e12c5d1SDavid du Colombier Strduplstr(&genstr, t);
913e12c5d1SDavid du Colombier freetmpstr(t);
927dd7cddfSDavid du Colombier fixname(&genstr);
937dd7cddfSDavid du Colombier logsetname(newfile(), &genstr);
947dd7cddfSDavid du Colombier }
953e12c5d1SDavid du Colombier }
963e12c5d1SDavid du Colombier }else if(!downloaded)
977dd7cddfSDavid du Colombier newfile();
987dd7cddfSDavid du Colombier seq++;
993e12c5d1SDavid du Colombier if(file.nused)
1003e12c5d1SDavid du Colombier current(file.filepptr[0]);
1013e12c5d1SDavid du Colombier setjmp(mainloop);
1023e12c5d1SDavid du Colombier cmdloop();
1033e12c5d1SDavid du Colombier trytoquit(); /* if we already q'ed, quitok will be TRUE */
1043e12c5d1SDavid du Colombier exits(0);
1053e12c5d1SDavid du Colombier }
1063e12c5d1SDavid du Colombier
1073e12c5d1SDavid du Colombier void
usage(void)1083e12c5d1SDavid du Colombier usage(void)
1093e12c5d1SDavid du Colombier {
1103e12c5d1SDavid du Colombier dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n");
1113e12c5d1SDavid du Colombier exits("usage");
1123e12c5d1SDavid du Colombier }
1133e12c5d1SDavid du Colombier
1143e12c5d1SDavid du Colombier void
rescue(void)1153e12c5d1SDavid du Colombier rescue(void)
1163e12c5d1SDavid du Colombier {
1173e12c5d1SDavid du Colombier int i, nblank = 0;
1183e12c5d1SDavid du Colombier File *f;
1193e12c5d1SDavid du Colombier char *c;
1203e12c5d1SDavid du Colombier char buf[256];
1213e12c5d1SDavid du Colombier
1223e12c5d1SDavid du Colombier if(rescuing++)
1233e12c5d1SDavid du Colombier return;
1243e12c5d1SDavid du Colombier io = -1;
1253e12c5d1SDavid du Colombier for(i=0; i<file.nused; i++){
1263e12c5d1SDavid du Colombier f = file.filepptr[i];
1277dd7cddfSDavid du Colombier if(f==cmd || f->nc==0 || !fileisdirty(f))
1283e12c5d1SDavid du Colombier continue;
1293e12c5d1SDavid du Colombier if(io == -1){
1303e12c5d1SDavid du Colombier sprint(buf, "%s/sam.save", home);
1313e12c5d1SDavid du Colombier io = create(buf, 1, 0777);
1323e12c5d1SDavid du Colombier if(io<0)
1333e12c5d1SDavid du Colombier return;
1343e12c5d1SDavid du Colombier }
1353e12c5d1SDavid du Colombier if(f->name.s[0]){
1363e12c5d1SDavid du Colombier c = Strtoc(&f->name);
1373e12c5d1SDavid du Colombier strncpy(buf, c, sizeof buf-1);
1383e12c5d1SDavid du Colombier buf[sizeof buf-1] = 0;
1393e12c5d1SDavid du Colombier free(c);
1403e12c5d1SDavid du Colombier }else
1413e12c5d1SDavid du Colombier sprint(buf, "nameless.%d", nblank++);
142bd389b36SDavid du Colombier fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf);
1437dd7cddfSDavid du Colombier addr.r.p1 = 0, addr.r.p2 = f->nc;
1443e12c5d1SDavid du Colombier writeio(f);
1453e12c5d1SDavid du Colombier fprint(io, "\n---%s\n", (char *)buf);
1463e12c5d1SDavid du Colombier }
1473e12c5d1SDavid du Colombier }
1483e12c5d1SDavid du Colombier
1493e12c5d1SDavid du Colombier void
panic(char * s)1503e12c5d1SDavid du Colombier panic(char *s)
1513e12c5d1SDavid du Colombier {
1523e12c5d1SDavid du Colombier int wasd;
1533e12c5d1SDavid du Colombier
1543e12c5d1SDavid du Colombier if(!panicking++ && !setjmp(mainloop)){
1553e12c5d1SDavid du Colombier wasd = downloaded;
1563e12c5d1SDavid du Colombier downloaded = 0;
1573e12c5d1SDavid du Colombier dprint("sam: panic: %s: %r\n", s);
1583e12c5d1SDavid du Colombier if(wasd)
1593e12c5d1SDavid du Colombier fprint(2, "sam: panic: %s: %r\n", s);
1603e12c5d1SDavid du Colombier rescue();
1613e12c5d1SDavid du Colombier abort();
1623e12c5d1SDavid du Colombier }
1633e12c5d1SDavid du Colombier }
1643e12c5d1SDavid du Colombier
1653e12c5d1SDavid du Colombier void
hiccough(char * s)1663e12c5d1SDavid du Colombier hiccough(char *s)
1673e12c5d1SDavid du Colombier {
1687dd7cddfSDavid du Colombier File *f;
1697dd7cddfSDavid du Colombier int i;
1707dd7cddfSDavid du Colombier
1713e12c5d1SDavid du Colombier if(rescuing)
1723e12c5d1SDavid du Colombier exits("rescue");
1733e12c5d1SDavid du Colombier if(s)
1743e12c5d1SDavid du Colombier dprint("%s\n", s);
1753e12c5d1SDavid du Colombier resetcmd();
1763e12c5d1SDavid du Colombier resetxec();
1773e12c5d1SDavid du Colombier resetsys();
1783e12c5d1SDavid du Colombier if(io > 0)
1793e12c5d1SDavid du Colombier close(io);
1807dd7cddfSDavid du Colombier
1817dd7cddfSDavid du Colombier /*
1827dd7cddfSDavid du Colombier * back out any logged changes & restore old sequences
1837dd7cddfSDavid du Colombier */
1847dd7cddfSDavid du Colombier for(i=0; i<file.nused; i++){
1857dd7cddfSDavid du Colombier f = file.filepptr[i];
1867dd7cddfSDavid du Colombier if(f==cmd)
1877dd7cddfSDavid du Colombier continue;
1887dd7cddfSDavid du Colombier if(f->seq==seq){
1897dd7cddfSDavid du Colombier bufdelete(&f->epsilon, 0, f->epsilon.nc);
1907dd7cddfSDavid du Colombier f->seq = f->prevseq;
1917dd7cddfSDavid du Colombier f->dot.r = f->prevdot;
1927dd7cddfSDavid du Colombier f->mark = f->prevmark;
1937dd7cddfSDavid du Colombier state(f, f->prevmod ? Dirty: Clean);
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier
1973e12c5d1SDavid du Colombier update();
198219b2ee8SDavid du Colombier if (curfile) {
1997dd7cddfSDavid du Colombier if (curfile->unread)
2007dd7cddfSDavid du Colombier curfile->unread = FALSE;
201219b2ee8SDavid du Colombier else if (downloaded)
2023e12c5d1SDavid du Colombier outTs(Hcurrent, curfile->tag);
203219b2ee8SDavid du Colombier }
2043e12c5d1SDavid du Colombier longjmp(mainloop, 1);
2053e12c5d1SDavid du Colombier }
2063e12c5d1SDavid du Colombier
2073e12c5d1SDavid du Colombier void
intr(void)2083e12c5d1SDavid du Colombier intr(void)
2093e12c5d1SDavid du Colombier {
2103e12c5d1SDavid du Colombier error(Eintr);
2113e12c5d1SDavid du Colombier }
2123e12c5d1SDavid du Colombier
2133e12c5d1SDavid du Colombier void
trytoclose(File * f)2143e12c5d1SDavid du Colombier trytoclose(File *f)
2153e12c5d1SDavid du Colombier {
2163e12c5d1SDavid du Colombier char *t;
217219b2ee8SDavid du Colombier char buf[256];
2183e12c5d1SDavid du Colombier
2193e12c5d1SDavid du Colombier if(f == cmd) /* possible? */
2203e12c5d1SDavid du Colombier return;
221219b2ee8SDavid du Colombier if(f->deleted)
222219b2ee8SDavid du Colombier return;
2237dd7cddfSDavid du Colombier if(fileisdirty(f) && !f->closeok){
2243e12c5d1SDavid du Colombier f->closeok = TRUE;
2253e12c5d1SDavid du Colombier if(f->name.s[0]){
2263e12c5d1SDavid du Colombier t = Strtoc(&f->name);
227219b2ee8SDavid du Colombier strncpy(buf, t, sizeof buf-1);
2283e12c5d1SDavid du Colombier free(t);
2293e12c5d1SDavid du Colombier }else
230219b2ee8SDavid du Colombier strcpy(buf, "nameless file");
231219b2ee8SDavid du Colombier error_s(Emodified, buf);
2323e12c5d1SDavid du Colombier }
233219b2ee8SDavid du Colombier f->deleted = TRUE;
2343e12c5d1SDavid du Colombier }
2353e12c5d1SDavid du Colombier
2363e12c5d1SDavid du Colombier void
trytoquit(void)2373e12c5d1SDavid du Colombier trytoquit(void)
2383e12c5d1SDavid du Colombier {
2393e12c5d1SDavid du Colombier int c;
2403e12c5d1SDavid du Colombier File *f;
2413e12c5d1SDavid du Colombier
2427dd7cddfSDavid du Colombier if(!quitok){
2433e12c5d1SDavid du Colombier for(c = 0; c<file.nused; c++){
2443e12c5d1SDavid du Colombier f = file.filepptr[c];
2457dd7cddfSDavid du Colombier if(f!=cmd && fileisdirty(f)){
2463e12c5d1SDavid du Colombier quitok = TRUE;
2473e12c5d1SDavid du Colombier eof = FALSE;
2483e12c5d1SDavid du Colombier error(Echanges);
2493e12c5d1SDavid du Colombier }
2503e12c5d1SDavid du Colombier }
2513e12c5d1SDavid du Colombier }
252219b2ee8SDavid du Colombier }
2533e12c5d1SDavid du Colombier
2543e12c5d1SDavid du Colombier void
load(File * f)2553e12c5d1SDavid du Colombier load(File *f)
2563e12c5d1SDavid du Colombier {
2573e12c5d1SDavid du Colombier Address saveaddr;
2583e12c5d1SDavid du Colombier
2593e12c5d1SDavid du Colombier Strduplstr(&genstr, &f->name);
2603e12c5d1SDavid du Colombier filename(f);
2613e12c5d1SDavid du Colombier if(f->name.s[0]){
2623e12c5d1SDavid du Colombier saveaddr = addr;
2633e12c5d1SDavid du Colombier edit(f, 'I');
2643e12c5d1SDavid du Colombier addr = saveaddr;
2657dd7cddfSDavid du Colombier }else{
2667dd7cddfSDavid du Colombier f->unread = 0;
2677dd7cddfSDavid du Colombier f->cleanseq = f->seq;
2687dd7cddfSDavid du Colombier }
2697dd7cddfSDavid du Colombier
2707dd7cddfSDavid du Colombier fileupdate(f, TRUE, TRUE);
2713e12c5d1SDavid du Colombier }
2723e12c5d1SDavid du Colombier
2733e12c5d1SDavid du Colombier void
cmdupdate(void)2743e12c5d1SDavid du Colombier cmdupdate(void)
2753e12c5d1SDavid du Colombier {
2767dd7cddfSDavid du Colombier if(cmd && cmd->seq!=0){
2777dd7cddfSDavid du Colombier fileupdate(cmd, FALSE, downloaded);
2787dd7cddfSDavid du Colombier cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc;
2793e12c5d1SDavid du Colombier telldot(cmd);
2803e12c5d1SDavid du Colombier }
2813e12c5d1SDavid du Colombier }
2823e12c5d1SDavid du Colombier
2833e12c5d1SDavid du Colombier void
delete(File * f)284219b2ee8SDavid du Colombier delete(File *f)
285219b2ee8SDavid du Colombier {
286219b2ee8SDavid du Colombier if(downloaded && f->rasp)
287219b2ee8SDavid du Colombier outTs(Hclose, f->tag);
288219b2ee8SDavid du Colombier delfile(f);
289219b2ee8SDavid du Colombier if(f == curfile)
290219b2ee8SDavid du Colombier current(0);
291219b2ee8SDavid du Colombier }
292219b2ee8SDavid du Colombier
293219b2ee8SDavid du Colombier void
update(void)2943e12c5d1SDavid du Colombier update(void)
2953e12c5d1SDavid du Colombier {
2963e12c5d1SDavid du Colombier int i, anymod;
2973e12c5d1SDavid du Colombier File *f;
2983e12c5d1SDavid du Colombier
2993e12c5d1SDavid du Colombier settempfile();
3003e12c5d1SDavid du Colombier for(anymod = i=0; i<tempfile.nused; i++){
3013e12c5d1SDavid du Colombier f = tempfile.filepptr[i];
3023e12c5d1SDavid du Colombier if(f==cmd) /* cmd gets done in main() */
3033e12c5d1SDavid du Colombier continue;
3047dd7cddfSDavid du Colombier if(f->deleted) {
305219b2ee8SDavid du Colombier delete(f);
3067dd7cddfSDavid du Colombier continue;
3077dd7cddfSDavid du Colombier }
3087dd7cddfSDavid du Colombier if(f->seq==seq && fileupdate(f, FALSE, downloaded))
3093e12c5d1SDavid du Colombier anymod++;
3103e12c5d1SDavid du Colombier if(f->rasp)
3113e12c5d1SDavid du Colombier telldot(f);
3123e12c5d1SDavid du Colombier }
3133e12c5d1SDavid du Colombier if(anymod)
3147dd7cddfSDavid du Colombier seq++;
3153e12c5d1SDavid du Colombier }
3163e12c5d1SDavid du Colombier
3173e12c5d1SDavid du Colombier File *
current(File * f)3183e12c5d1SDavid du Colombier current(File *f)
3193e12c5d1SDavid du Colombier {
3203e12c5d1SDavid du Colombier return curfile = f;
3213e12c5d1SDavid du Colombier }
3223e12c5d1SDavid du Colombier
3233e12c5d1SDavid du Colombier void
edit(File * f,int cmd)3243e12c5d1SDavid du Colombier edit(File *f, int cmd)
3253e12c5d1SDavid du Colombier {
3263e12c5d1SDavid du Colombier int empty = TRUE;
3273e12c5d1SDavid du Colombier Posn p;
3283e12c5d1SDavid du Colombier int nulls;
3293e12c5d1SDavid du Colombier
3303e12c5d1SDavid du Colombier if(cmd == 'r')
3317dd7cddfSDavid du Colombier logdelete(f, addr.r.p1, addr.r.p2);
3323e12c5d1SDavid du Colombier if(cmd=='e' || cmd=='I'){
3337dd7cddfSDavid du Colombier logdelete(f, (Posn)0, f->nc);
3347dd7cddfSDavid du Colombier addr.r.p2 = f->nc;
3357dd7cddfSDavid du Colombier }else if(f->nc!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0))
3363e12c5d1SDavid du Colombier empty = FALSE;
337219b2ee8SDavid du Colombier if((io = open(genc, OREAD))<0) {
3387dd7cddfSDavid du Colombier if (curfile && curfile->unread)
3397dd7cddfSDavid du Colombier curfile->unread = FALSE;
3409a747e4fSDavid du Colombier error_r(Eopen, genc);
341219b2ee8SDavid du Colombier }
3427dd7cddfSDavid du Colombier p = readio(f, &nulls, empty, TRUE);
3433e12c5d1SDavid du Colombier closeio((cmd=='e' || cmd=='I')? -1 : p);
3443e12c5d1SDavid du Colombier if(cmd == 'r')
3453e12c5d1SDavid du Colombier f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p;
3463e12c5d1SDavid du Colombier else
3473e12c5d1SDavid du Colombier f->ndot.r.p1 = f->ndot.r.p2 = 0;
348219b2ee8SDavid du Colombier f->closeok = empty;
349219b2ee8SDavid du Colombier if (quitok)
350219b2ee8SDavid du Colombier quitok = empty;
351219b2ee8SDavid du Colombier else
352219b2ee8SDavid du Colombier quitok = FALSE;
3533e12c5d1SDavid du Colombier state(f, empty && !nulls? Clean : Dirty);
3547dd7cddfSDavid du Colombier if(empty && !nulls)
3557dd7cddfSDavid du Colombier f->cleanseq = f->seq;
3563e12c5d1SDavid du Colombier if(cmd == 'e')
3573e12c5d1SDavid du Colombier filename(f);
3583e12c5d1SDavid du Colombier }
3593e12c5d1SDavid du Colombier
3603e12c5d1SDavid du Colombier int
getname(File * f,String * s,int save)3613e12c5d1SDavid du Colombier getname(File *f, String *s, int save)
3623e12c5d1SDavid du Colombier {
3633e12c5d1SDavid du Colombier int c, i;
3643e12c5d1SDavid du Colombier
3653e12c5d1SDavid du Colombier Strzero(&genstr);
3663e12c5d1SDavid du Colombier if(genc){
3673e12c5d1SDavid du Colombier free(genc);
3683e12c5d1SDavid du Colombier genc = 0;
3693e12c5d1SDavid du Colombier }
3703e12c5d1SDavid du Colombier if(s==0 || (c = s->s[0])==0){ /* no name provided */
3713e12c5d1SDavid du Colombier if(f)
3723e12c5d1SDavid du Colombier Strduplstr(&genstr, &f->name);
3733e12c5d1SDavid du Colombier goto Return;
3743e12c5d1SDavid du Colombier }
3753e12c5d1SDavid du Colombier if(c!=' ' && c!='\t')
3763e12c5d1SDavid du Colombier error(Eblank);
3773e12c5d1SDavid du Colombier for(i=0; (c=s->s[i])==' ' || c=='\t'; i++)
3783e12c5d1SDavid du Colombier ;
3793e12c5d1SDavid du Colombier while(s->s[i] > ' ')
3803e12c5d1SDavid du Colombier Straddc(&genstr, s->s[i++]);
3813e12c5d1SDavid du Colombier if(s->s[i])
3823e12c5d1SDavid du Colombier error(Enewline);
3837dd7cddfSDavid du Colombier fixname(&genstr);
3843e12c5d1SDavid du Colombier if(f && (save || f->name.s[0]==0)){
3857dd7cddfSDavid du Colombier logsetname(f, &genstr);
3863e12c5d1SDavid du Colombier if(Strcmp(&f->name, &genstr)){
3873e12c5d1SDavid du Colombier quitok = f->closeok = FALSE;
3887dd7cddfSDavid du Colombier f->qidpath = 0;
3897dd7cddfSDavid du Colombier f->mtime = 0;
3903e12c5d1SDavid du Colombier state(f, Dirty); /* if it's 'e', fix later */
3913e12c5d1SDavid du Colombier }
3923e12c5d1SDavid du Colombier }
3933e12c5d1SDavid du Colombier Return:
3943e12c5d1SDavid du Colombier genc = Strtoc(&genstr);
3957dd7cddfSDavid du Colombier i = genstr.n;
3967dd7cddfSDavid du Colombier if(i && genstr.s[i-1]==0)
3977dd7cddfSDavid du Colombier i--;
3987dd7cddfSDavid du Colombier return i; /* strlen(name) */
3993e12c5d1SDavid du Colombier }
4003e12c5d1SDavid du Colombier
4013e12c5d1SDavid du Colombier void
filename(File * f)4023e12c5d1SDavid du Colombier filename(File *f)
4033e12c5d1SDavid du Colombier {
4043e12c5d1SDavid du Colombier if(genc)
4053e12c5d1SDavid du Colombier free(genc);
4063e12c5d1SDavid du Colombier genc = Strtoc(&genstr);
4077dd7cddfSDavid du Colombier dprint("%c%c%c %s\n", " '"[f->mod],
4083e12c5d1SDavid du Colombier "-+"[f->rasp!=0], " ."[f==curfile], genc);
4093e12c5d1SDavid du Colombier }
4103e12c5d1SDavid du Colombier
4113e12c5d1SDavid du Colombier void
undostep(File * f,int isundo)4127dd7cddfSDavid du Colombier undostep(File *f, int isundo)
4133e12c5d1SDavid du Colombier {
4147dd7cddfSDavid du Colombier uint p1, p2;
4157dd7cddfSDavid du Colombier int mod;
4163e12c5d1SDavid du Colombier
4177dd7cddfSDavid du Colombier mod = f->mod;
4187dd7cddfSDavid du Colombier fileundo(f, isundo, 1, &p1, &p2, TRUE);
4197dd7cddfSDavid du Colombier f->ndot = f->dot;
4207dd7cddfSDavid du Colombier if(f->mod){
4217dd7cddfSDavid du Colombier f->closeok = 0;
4227dd7cddfSDavid du Colombier quitok = 0;
4237dd7cddfSDavid du Colombier }else
4247dd7cddfSDavid du Colombier f->closeok = 1;
4257dd7cddfSDavid du Colombier
4267dd7cddfSDavid du Colombier if(f->mod != mod){
4277dd7cddfSDavid du Colombier f->mod = mod;
4287dd7cddfSDavid du Colombier if(mod)
4297dd7cddfSDavid du Colombier mod = Clean;
4303e12c5d1SDavid du Colombier else
4317dd7cddfSDavid du Colombier mod = Dirty;
4327dd7cddfSDavid du Colombier state(f, mod);
4337dd7cddfSDavid du Colombier }
4343e12c5d1SDavid du Colombier }
4353e12c5d1SDavid du Colombier
436bd389b36SDavid du Colombier int
undo(int isundo)4377dd7cddfSDavid du Colombier undo(int isundo)
4383e12c5d1SDavid du Colombier {
4393e12c5d1SDavid du Colombier File *f;
4403e12c5d1SDavid du Colombier int i;
4413e12c5d1SDavid du Colombier Mod max;
4427dd7cddfSDavid du Colombier
4437dd7cddfSDavid du Colombier max = undoseq(curfile, isundo);
4447dd7cddfSDavid du Colombier if(max == 0)
445bd389b36SDavid du Colombier return 0;
4463e12c5d1SDavid du Colombier settempfile();
4473e12c5d1SDavid du Colombier for(i = 0; i<tempfile.nused; i++){
4483e12c5d1SDavid du Colombier f = tempfile.filepptr[i];
4497dd7cddfSDavid du Colombier if(f!=cmd && undoseq(f, isundo)==max)
4507dd7cddfSDavid du Colombier undostep(f, isundo);
4513e12c5d1SDavid du Colombier }
452bd389b36SDavid du Colombier return 1;
4533e12c5d1SDavid du Colombier }
4543e12c5d1SDavid du Colombier
455219b2ee8SDavid du Colombier int
readcmd(String * s)4563e12c5d1SDavid du Colombier readcmd(String *s)
4573e12c5d1SDavid du Colombier {
458219b2ee8SDavid du Colombier int retcode;
459219b2ee8SDavid du Colombier
4607dd7cddfSDavid du Colombier if(flist != 0)
4617dd7cddfSDavid du Colombier fileclose(flist);
4627dd7cddfSDavid du Colombier flist = fileopen();
4637dd7cddfSDavid du Colombier
4647dd7cddfSDavid du Colombier addr.r.p1 = 0, addr.r.p2 = flist->nc;
465219b2ee8SDavid du Colombier retcode = plan9(flist, '<', s, FALSE);
4667dd7cddfSDavid du Colombier fileupdate(flist, FALSE, FALSE);
4677dd7cddfSDavid du Colombier flist->seq = 0;
4687dd7cddfSDavid du Colombier if (flist->nc > BLOCKSIZE)
469bd389b36SDavid du Colombier error(Etoolong);
4703e12c5d1SDavid du Colombier Strzero(&genstr);
4717dd7cddfSDavid du Colombier Strinsure(&genstr, flist->nc);
4727dd7cddfSDavid du Colombier bufread(flist, (Posn)0, genbuf, flist->nc);
4737dd7cddfSDavid du Colombier memmove(genstr.s, genbuf, flist->nc*RUNESIZE);
4747dd7cddfSDavid du Colombier genstr.n = flist->nc;
4753e12c5d1SDavid du Colombier Straddc(&genstr, '\0');
476219b2ee8SDavid du Colombier return retcode;
4773e12c5d1SDavid du Colombier }
4783e12c5d1SDavid du Colombier
4793e12c5d1SDavid du Colombier void
getcurwd(void)4807dd7cddfSDavid du Colombier getcurwd(void)
4817dd7cddfSDavid du Colombier {
4827dd7cddfSDavid du Colombier String *t;
4837dd7cddfSDavid du Colombier char buf[256];
4847dd7cddfSDavid du Colombier
4857dd7cddfSDavid du Colombier buf[0] = 0;
4867dd7cddfSDavid du Colombier getwd(buf, sizeof(buf));
4877dd7cddfSDavid du Colombier t = tmpcstr(buf);
4887dd7cddfSDavid du Colombier Strduplstr(&curwd, t);
4897dd7cddfSDavid du Colombier freetmpstr(t);
4907dd7cddfSDavid du Colombier if(curwd.n == 0)
4917dd7cddfSDavid du Colombier warn(Wpwd);
4927dd7cddfSDavid du Colombier else if(curwd.s[curwd.n-1] != '/')
4937dd7cddfSDavid du Colombier Straddc(&curwd, '/');
4947dd7cddfSDavid du Colombier }
4957dd7cddfSDavid du Colombier
4967dd7cddfSDavid du Colombier void
cd(String * str)4973e12c5d1SDavid du Colombier cd(String *str)
4983e12c5d1SDavid du Colombier {
4997dd7cddfSDavid du Colombier int i, fd;
5007dd7cddfSDavid du Colombier char *s;
5013e12c5d1SDavid du Colombier File *f;
5027dd7cddfSDavid du Colombier String owd;
5033e12c5d1SDavid du Colombier
5047dd7cddfSDavid du Colombier getcurwd();
5057dd7cddfSDavid du Colombier if(getname((File *)0, str, FALSE))
5067dd7cddfSDavid du Colombier s = genc;
5077dd7cddfSDavid du Colombier else
5087dd7cddfSDavid du Colombier s = home;
5097dd7cddfSDavid du Colombier if(chdir(s))
5103e12c5d1SDavid du Colombier syserror("chdir");
5117dd7cddfSDavid du Colombier fd = open("/dev/wdir", OWRITE);
5127dd7cddfSDavid du Colombier if(fd > 0)
5137dd7cddfSDavid du Colombier write(fd, s, strlen(s));
5147dd7cddfSDavid du Colombier dprint("!\n");
5157dd7cddfSDavid du Colombier Strinit(&owd);
5167dd7cddfSDavid du Colombier Strduplstr(&owd, &curwd);
5177dd7cddfSDavid du Colombier getcurwd();
5183e12c5d1SDavid du Colombier settempfile();
5193e12c5d1SDavid du Colombier for(i=0; i<tempfile.nused; i++){
5203e12c5d1SDavid du Colombier f = tempfile.filepptr[i];
5213e12c5d1SDavid du Colombier if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){
5227dd7cddfSDavid du Colombier Strinsert(&f->name, &owd, (Posn)0);
5237dd7cddfSDavid du Colombier fixname(&f->name);
5247dd7cddfSDavid du Colombier sortname(f);
5257dd7cddfSDavid du Colombier }else if(f != cmd && Strispre(&curwd, &f->name)){
5267dd7cddfSDavid du Colombier fixname(&f->name);
5273e12c5d1SDavid du Colombier sortname(f);
5283e12c5d1SDavid du Colombier }
5293e12c5d1SDavid du Colombier }
5307dd7cddfSDavid du Colombier Strclose(&owd);
5313e12c5d1SDavid du Colombier }
5323e12c5d1SDavid du Colombier
5333e12c5d1SDavid du Colombier int
loadflist(String * s)5343e12c5d1SDavid du Colombier loadflist(String *s)
5353e12c5d1SDavid du Colombier {
5363e12c5d1SDavid du Colombier int c, i;
5373e12c5d1SDavid du Colombier
5383e12c5d1SDavid du Colombier c = s->s[0];
5393e12c5d1SDavid du Colombier for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++)
5403e12c5d1SDavid du Colombier ;
5413e12c5d1SDavid du Colombier if((c==' ' || c=='\t') && s->s[i]!='\n'){
5423e12c5d1SDavid du Colombier if(s->s[i]=='<'){
5433e12c5d1SDavid du Colombier Strdelete(s, 0L, (long)i+1);
5443e12c5d1SDavid du Colombier readcmd(s);
5453e12c5d1SDavid du Colombier }else{
5463e12c5d1SDavid du Colombier Strzero(&genstr);
5473e12c5d1SDavid du Colombier while((c = s->s[i++]) && c!='\n')
5483e12c5d1SDavid du Colombier Straddc(&genstr, c);
5493e12c5d1SDavid du Colombier Straddc(&genstr, '\0');
5503e12c5d1SDavid du Colombier }
5513e12c5d1SDavid du Colombier }else{
5523e12c5d1SDavid du Colombier if(c != '\n')
5533e12c5d1SDavid du Colombier error(Eblank);
5543e12c5d1SDavid du Colombier Strdupl(&genstr, empty);
5553e12c5d1SDavid du Colombier }
5563e12c5d1SDavid du Colombier if(genc)
5573e12c5d1SDavid du Colombier free(genc);
5583e12c5d1SDavid du Colombier genc = Strtoc(&genstr);
5593e12c5d1SDavid du Colombier return genstr.s[0];
5603e12c5d1SDavid du Colombier }
5613e12c5d1SDavid du Colombier
5623e12c5d1SDavid du Colombier File *
readflist(int readall,int delete)5633e12c5d1SDavid du Colombier readflist(int readall, int delete)
5643e12c5d1SDavid du Colombier {
5653e12c5d1SDavid du Colombier Posn i;
5663e12c5d1SDavid du Colombier int c;
5673e12c5d1SDavid du Colombier File *f;
5687dd7cddfSDavid du Colombier String t;
5693e12c5d1SDavid du Colombier
5707dd7cddfSDavid du Colombier Strinit(&t);
5713e12c5d1SDavid du Colombier for(i=0,f=0; f==0 || readall || delete; i++){ /* ++ skips blank */
5723e12c5d1SDavid du Colombier Strdelete(&genstr, (Posn)0, i);
5733e12c5d1SDavid du Colombier for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++)
5743e12c5d1SDavid du Colombier ;
5753e12c5d1SDavid du Colombier if(i >= genstr.n)
5763e12c5d1SDavid du Colombier break;
5773e12c5d1SDavid du Colombier Strdelete(&genstr, (Posn)0, i);
5783e12c5d1SDavid du Colombier for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++)
5793e12c5d1SDavid du Colombier ;
5803e12c5d1SDavid du Colombier
5813e12c5d1SDavid du Colombier if(i == 0)
5823e12c5d1SDavid du Colombier break;
5833e12c5d1SDavid du Colombier genstr.s[i] = 0;
5847dd7cddfSDavid du Colombier Strduplstr(&t, tmprstr(genstr.s, i+1));
5857dd7cddfSDavid du Colombier fixname(&t);
5867dd7cddfSDavid du Colombier f = lookfile(&t);
5873e12c5d1SDavid du Colombier if(delete){
5883e12c5d1SDavid du Colombier if(f == 0)
5897dd7cddfSDavid du Colombier warn_S(Wfile, &t);
5903e12c5d1SDavid du Colombier else
5913e12c5d1SDavid du Colombier trytoclose(f);
5923e12c5d1SDavid du Colombier }else if(f==0 && readall)
5937dd7cddfSDavid du Colombier logsetname(f = newfile(), &t);
5943e12c5d1SDavid du Colombier }
5957dd7cddfSDavid du Colombier Strclose(&t);
5963e12c5d1SDavid du Colombier return f;
5973e12c5d1SDavid du Colombier }
5983e12c5d1SDavid du Colombier
5993e12c5d1SDavid du Colombier File *
tofile(String * s)6003e12c5d1SDavid du Colombier tofile(String *s)
6013e12c5d1SDavid du Colombier {
6023e12c5d1SDavid du Colombier File *f;
6033e12c5d1SDavid du Colombier
6043e12c5d1SDavid du Colombier if(s->s[0] != ' ')
6053e12c5d1SDavid du Colombier error(Eblank);
6063e12c5d1SDavid du Colombier if(loadflist(s) == 0){
6073e12c5d1SDavid du Colombier f = lookfile(&genstr); /* empty string ==> nameless file */
6083e12c5d1SDavid du Colombier if(f == 0)
6093e12c5d1SDavid du Colombier error_s(Emenu, genc);
6103e12c5d1SDavid du Colombier }else if((f=readflist(FALSE, FALSE)) == 0)
6113e12c5d1SDavid du Colombier error_s(Emenu, genc);
6123e12c5d1SDavid du Colombier return current(f);
6133e12c5d1SDavid du Colombier }
6143e12c5d1SDavid du Colombier
6153e12c5d1SDavid du Colombier File *
getfile(String * s)6163e12c5d1SDavid du Colombier getfile(String *s)
6173e12c5d1SDavid du Colombier {
6183e12c5d1SDavid du Colombier File *f;
6193e12c5d1SDavid du Colombier
6203e12c5d1SDavid du Colombier if(loadflist(s) == 0)
6217dd7cddfSDavid du Colombier logsetname(f = newfile(), &genstr);
6223e12c5d1SDavid du Colombier else if((f=readflist(TRUE, FALSE)) == 0)
6233e12c5d1SDavid du Colombier error(Eblank);
6243e12c5d1SDavid du Colombier return current(f);
6253e12c5d1SDavid du Colombier }
6263e12c5d1SDavid du Colombier
6273e12c5d1SDavid du Colombier void
closefiles(File * f,String * s)6283e12c5d1SDavid du Colombier closefiles(File *f, String *s)
6293e12c5d1SDavid du Colombier {
6303e12c5d1SDavid du Colombier if(s->s[0] == 0){
6313e12c5d1SDavid du Colombier if(f == 0)
6323e12c5d1SDavid du Colombier error(Enofile);
6333e12c5d1SDavid du Colombier trytoclose(f);
6343e12c5d1SDavid du Colombier return;
6353e12c5d1SDavid du Colombier }
6363e12c5d1SDavid du Colombier if(s->s[0] != ' ')
6373e12c5d1SDavid du Colombier error(Eblank);
6383e12c5d1SDavid du Colombier if(loadflist(s) == 0)
6393e12c5d1SDavid du Colombier error(Enewline);
6403e12c5d1SDavid du Colombier readflist(FALSE, TRUE);
6413e12c5d1SDavid du Colombier }
6423e12c5d1SDavid du Colombier
6433e12c5d1SDavid du Colombier void
copy(File * f,Address addr2)6443e12c5d1SDavid du Colombier copy(File *f, Address addr2)
6453e12c5d1SDavid du Colombier {
6463e12c5d1SDavid du Colombier Posn p;
6473e12c5d1SDavid du Colombier int ni;
6483e12c5d1SDavid du Colombier for(p=addr.r.p1; p<addr.r.p2; p+=ni){
6493e12c5d1SDavid du Colombier ni = addr.r.p2-p;
6503e12c5d1SDavid du Colombier if(ni > BLOCKSIZE)
6513e12c5d1SDavid du Colombier ni = BLOCKSIZE;
6527dd7cddfSDavid du Colombier bufread(f, p, genbuf, ni);
6537dd7cddfSDavid du Colombier loginsert(addr2.f, addr2.r.p2, tmprstr(genbuf, ni)->s, ni);
6543e12c5d1SDavid du Colombier }
6553e12c5d1SDavid du Colombier addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1);
6563e12c5d1SDavid du Colombier addr2.f->ndot.r.p1 = addr2.r.p2;
6573e12c5d1SDavid du Colombier }
6583e12c5d1SDavid du Colombier
6593e12c5d1SDavid du Colombier void
move(File * f,Address addr2)6603e12c5d1SDavid du Colombier move(File *f, Address addr2)
6613e12c5d1SDavid du Colombier {
6623e12c5d1SDavid du Colombier if(addr.r.p2 <= addr2.r.p2){
6637dd7cddfSDavid du Colombier logdelete(f, addr.r.p1, addr.r.p2);
6643e12c5d1SDavid du Colombier copy(f, addr2);
6653e12c5d1SDavid du Colombier }else if(addr.r.p1 >= addr2.r.p2){
6663e12c5d1SDavid du Colombier copy(f, addr2);
6677dd7cddfSDavid du Colombier logdelete(f, addr.r.p1, addr.r.p2);
6683e12c5d1SDavid du Colombier }else
6693e12c5d1SDavid du Colombier error(Eoverlap);
6703e12c5d1SDavid du Colombier }
6713e12c5d1SDavid du Colombier
6723e12c5d1SDavid du Colombier Posn
nlcount(File * f,Posn p0,Posn p1)6733e12c5d1SDavid du Colombier nlcount(File *f, Posn p0, Posn p1)
6743e12c5d1SDavid du Colombier {
6753e12c5d1SDavid du Colombier Posn nl = 0;
6763e12c5d1SDavid du Colombier
6777dd7cddfSDavid du Colombier while(p0 < p1)
6787dd7cddfSDavid du Colombier if(filereadc(f, p0++)=='\n')
6793e12c5d1SDavid du Colombier nl++;
6803e12c5d1SDavid du Colombier return nl;
6813e12c5d1SDavid du Colombier }
6823e12c5d1SDavid du Colombier
6833e12c5d1SDavid du Colombier void
printposn(File * f,int charsonly)6843e12c5d1SDavid du Colombier printposn(File *f, int charsonly)
6853e12c5d1SDavid du Colombier {
6863e12c5d1SDavid du Colombier Posn l1, l2;
6873e12c5d1SDavid du Colombier
6883e12c5d1SDavid du Colombier if(!charsonly){
6893e12c5d1SDavid du Colombier l1 = 1+nlcount(f, (Posn)0, addr.r.p1);
6903e12c5d1SDavid du Colombier l2 = l1+nlcount(f, addr.r.p1, addr.r.p2);
6913e12c5d1SDavid du Colombier /* check if addr ends with '\n' */
6927dd7cddfSDavid du Colombier if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && filereadc(f, addr.r.p2-1)=='\n')
6933e12c5d1SDavid du Colombier --l2;
6943e12c5d1SDavid du Colombier dprint("%lud", l1);
6953e12c5d1SDavid du Colombier if(l2 != l1)
6963e12c5d1SDavid du Colombier dprint(",%lud", l2);
6973e12c5d1SDavid du Colombier dprint("; ");
6983e12c5d1SDavid du Colombier }
6993e12c5d1SDavid du Colombier dprint("#%lud", addr.r.p1);
7003e12c5d1SDavid du Colombier if(addr.r.p2 != addr.r.p1)
7013e12c5d1SDavid du Colombier dprint(",#%lud", addr.r.p2);
7023e12c5d1SDavid du Colombier dprint("\n");
7033e12c5d1SDavid du Colombier }
7043e12c5d1SDavid du Colombier
7053e12c5d1SDavid du Colombier void
settempfile(void)7063e12c5d1SDavid du Colombier settempfile(void)
7073e12c5d1SDavid du Colombier {
7083e12c5d1SDavid du Colombier if(tempfile.nalloc < file.nused){
709*73e742d7SDavid du Colombier if(tempfile.filepptr)
710*73e742d7SDavid du Colombier free(tempfile.filepptr);
711*73e742d7SDavid du Colombier tempfile.filepptr = emalloc(sizeof(File*)*file.nused);
7123e12c5d1SDavid du Colombier tempfile.nalloc = file.nused;
7133e12c5d1SDavid du Colombier }
714*73e742d7SDavid du Colombier memmove(tempfile.filepptr, file.filepptr, sizeof(File*)*file.nused);
7153e12c5d1SDavid du Colombier tempfile.nused = file.nused;
7163e12c5d1SDavid du Colombier }
717