|  | #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); | 
|  | } |