| #include "sam.h" |
| |
| #define NSYSFILE 3 |
| #define NOFILE 128 |
| |
| void |
| checkqid(File *f) |
| { |
| int i, w; |
| File *g; |
| |
| w = whichmenu(f); |
| for(i=1; i<file.nused; i++){ |
| g = file.filepptr[i]; |
| if(w == i) |
| continue; |
| if(f->dev==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->mtime<mtime)){ |
| f->dev = 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->b.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->b, 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->b, 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"; |
| execvp(samterm, argv); |
| fprint(2, "can't exec %s: %r\n", 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"; |
| execvp(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]); |
| execvp(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); |
| } |