#include "sam.h" #define NSYSFILE 3 #define NOFILE 128 void checkqid(File *f) { int i, w; File *g; w = whichmenu(f); for(i=1; idev==g->dev && f->qidpath==g->qidpath) warn_SS(Wdupfile, &f->name, &g->name); } } void writef(File *f) { Posn n; char *name; int i, samename, newfile; ulong dev; uvlong qid; long mtime, appendonly, length; newfile = 0; samename = Strcmp(&genstr, &f->name) == 0; name = Strtoc(&f->name); i = statfile(name, &dev, &qid, &mtime, 0, 0); if(i == -1) newfile++; else if(samename && (f->dev!=dev || f->qidpath!=qid || f->mtimedev = dev; f->qidpath = qid; f->mtime = mtime; warn_S(Wdate, &genstr); return; } if(genc) free(genc); genc = Strtoc(&genstr); if((io=create(genc, 1, 0666L)) < 0) error_r(Ecreate, genc); dprint("%s: ", genc); if(statfd(io, 0, 0, 0, &length, &appendonly) > 0 && appendonly && length>0) error(Eappend); n = writeio(f); if(f->name.s[0]==0 || samename){ if(addr.r.p1==0 && addr.r.p2==f->nc) f->cleanseq = f->seq; state(f, f->cleanseq==f->seq? Clean : Dirty); } if(newfile) dprint("(new file) "); if(addr.r.p2>0 && filereadc(f, addr.r.p2-1)!='\n') warn(Wnotnewline); closeio(n); if(f->name.s[0]==0 || samename){ if(statfile(name, &dev, &qid, &mtime, 0, 0) > 0){ f->dev = dev; f->qidpath = qid; f->mtime = mtime; checkqid(f); } } } Posn readio(File *f, int *nulls, int setdate, int toterm) { int n, b, w; Rune *r; Posn nt; Posn p = addr.r.p2; ulong dev; uvlong qid; long mtime; char buf[BLOCKSIZE+1], *s; *nulls = FALSE; b = 0; if(f->unread){ nt = bufload(f, 0, io, nulls); if(toterm) raspload(f); }else for(nt = 0; (n = read(io, buf+b, BLOCKSIZE-b))>0; nt+=(r-genbuf)){ n += b; b = 0; r = genbuf; s = buf; while(n > 0){ if((*r = *(uchar*)s) < Runeself){ if(*r) r++; else *nulls = TRUE; --n; s++; continue; } if(fullrune(s, n)){ w = chartorune(r, s); if(*r) r++; else *nulls = TRUE; n -= w; s += w; continue; } b = n; memmove(buf, s, b); break; } loginsert(f, p, genbuf, r-genbuf); } if(b) *nulls = TRUE; if(*nulls) warn(Wnulls); if(setdate){ if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){ f->dev = dev; f->qidpath = qid; f->mtime = mtime; checkqid(f); } } return nt; } Posn writeio(File *f) { int m, n; Posn p = addr.r.p1; char *c; while(p < addr.r.p2){ if(addr.r.p2-p>BLOCKSIZE) n = BLOCKSIZE; else n = addr.r.p2-p; bufread(f, p, genbuf, n); c = Strtoc(tmprstr(genbuf, n)); m = strlen(c); if(Write(io, c, m) != m){ free(c); if(p > 0) p += n; break; } free(c); p += n; } return p-addr.r.p1; } void closeio(Posn p) { close(io); io = 0; if(p >= 0) dprint("#%lud\n", p); } int remotefd0 = 0; int remotefd1 = 1; void bootterm(char *machine, char **argv) { int ph2t[2], pt2h[2]; if(machine){ dup(remotefd0, 0); dup(remotefd1, 1); close(remotefd0); close(remotefd1); argv[0] = "samterm"; exec(samterm, argv); fprint(2, "can't exec: "); perror(samterm); _exits("damn"); } if(pipe(ph2t)==-1 || pipe(pt2h)==-1) panic("pipe"); switch(fork()){ case 0: dup(ph2t[0], 0); dup(pt2h[1], 1); close(ph2t[0]); close(ph2t[1]); close(pt2h[0]); close(pt2h[1]); argv[0] = "samterm"; exec(samterm, argv); fprint(2, "can't exec: "); perror(samterm); _exits("damn"); case -1: panic("can't fork samterm"); } dup(pt2h[0], 0); dup(ph2t[1], 1); close(ph2t[0]); close(ph2t[1]); close(pt2h[0]); close(pt2h[1]); } void connectto(char *machine, char **argv) { int p1[2], p2[2]; char **av; int ac; // count args for(av = argv; *av; av++) ; av = malloc(sizeof(char*)*((av-argv) + 5)); if(av == nil){ dprint("out of memory\n"); exits("fork/exec"); } ac = 0; av[ac++] = RX; av[ac++] = machine; av[ac++] = rsamname; av[ac++] = "-R"; while(*argv) av[ac++] = *argv++; av[ac] = 0; if(pipe(p1)<0 || pipe(p2)<0){ dprint("can't pipe\n"); exits("pipe"); } remotefd0 = p1[0]; remotefd1 = p2[1]; switch(fork()){ case 0: dup(p2[0], 0); dup(p1[1], 1); close(p1[0]); close(p1[1]); close(p2[0]); close(p2[1]); exec(RXPATH, av); dprint("can't exec %s\n", RXPATH); exits("exec"); case -1: dprint("can't fork\n"); exits("fork"); } free(av); close(p1[1]); close(p2[0]); } void startup(char *machine, int Rflag, char **argv, char **files) { if(machine) connectto(machine, files); if(!Rflag) bootterm(machine, argv); downloaded = 1; outTs(Hversion, VERSION); }