/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "sam.h" #define NSYSFILE 3#define NOFILE 128 voidcheckqid(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); }} voidwritef(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->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); } }} Posnreadio(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;} Posnwriteio(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;}voidcloseio(Posn p){ close(io); io = 0; if(p >= 0) dprint("#%lud\n", p);} int remotefd0 = 0;int remotefd1 = 1; voidbootterm(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]);} voidconnectto(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]);} voidstartup(char *machine, int Rflag, char **argv, char **files){ if(machine) connectto(machine, files); if(!Rflag) bootterm(machine, argv); downloaded = 1; outTs(Hversion, VERSION);}
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#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->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);
}