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