1 #include "sam.h" 2 3 #define NSYSFILE 3 4 #define NOFILE 128 5 6 void 7 checkqid(File *f) 8 { 9 int i, w; 10 File *g; 11 12 w = whichmenu(f); 13 for(i=1; i<file.nused; i++){ 14 g = file.filepptr[i]; 15 if(w == i) 16 continue; 17 if(f->dev==g->dev && f->qid==g->qid) 18 warn_SS(Wdupfile, &f->name, &g->name); 19 } 20 } 21 22 void 23 writef(File *f) 24 { 25 Rune c; 26 Posn n; 27 char *name; 28 int i, samename, newfile; 29 ulong dev, qid; 30 long mtime, appendonly, length; 31 32 newfile = 0; 33 samename = Strcmp(&genstr, &f->name) == 0; 34 name = Strtoc(&f->name); 35 i = statfile(name, &dev, &qid, &mtime, 0, 0); 36 if(i == -1) 37 newfile++; 38 else if(samename && 39 (f->dev!=dev || f->qid!=qid || f->date<mtime)){ 40 f->dev = dev; 41 f->qid = qid; 42 f->date = mtime; 43 warn_S(Wdate, &genstr); 44 return; 45 } 46 if(genc) 47 free(genc); 48 genc = Strtoc(&genstr); 49 if((io=create(genc, 1, 0666L)) < 0) 50 error_s(Ecreate, genc); 51 dprint("%s: ", genc); 52 if(statfd(io, 0, 0, 0, &length, &appendonly) > 0 && appendonly && length>0) 53 error(Eappend); 54 n = writeio(f); 55 if(f->name.s[0]==0 || samename) 56 state(f, addr.r.p1==0 && addr.r.p2==f->nrunes? Clean : Dirty); 57 if(newfile) 58 dprint("(new file) "); 59 if(addr.r.p2>0 && Fchars(f, &c, addr.r.p2-1, addr.r.p2) && c!='\n') 60 warn(Wnotnewline); 61 if(f->name.s[0]==0 || samename){ 62 if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){ 63 f->dev = dev; 64 f->qid = qid; 65 f->date = mtime; 66 checkqid(f); 67 } 68 } 69 closeio(n); 70 } 71 72 Posn 73 readio(File *f, int *nulls, int setdate) 74 { 75 int n, b, w; 76 Rune *r; 77 Posn nt; 78 Posn p = addr.r.p2; 79 ulong dev, qid; 80 long mtime; 81 char buf[BLOCKSIZE+1], *s; 82 83 *nulls = FALSE; 84 b = 0; 85 for(nt = 0; (n = read(io, buf+b, BLOCKSIZE-b))>0; nt+=(r-genbuf)){ 86 n += b; 87 b = 0; 88 r = genbuf; 89 s = buf; 90 while(n > 0){ 91 if((*r = *(uchar*)s) < Runeself){ 92 if(*r) 93 r++; 94 else 95 *nulls = TRUE; 96 --n; 97 s++; 98 continue; 99 } 100 if(fullrune(s, n)){ 101 w = chartorune(r, s); 102 if(*r) 103 r++; 104 else 105 *nulls = TRUE; 106 n -= w; 107 s += w; 108 continue; 109 } 110 b = n; 111 memmove(buf, s, b); 112 break; 113 } 114 Finsert(f, tmprstr(genbuf, r-genbuf), p); 115 } 116 if(b) 117 *nulls = TRUE; 118 if(*nulls) 119 warn(Wnulls); 120 if(setdate){ 121 if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){ 122 f->dev = dev; 123 f->qid = qid; 124 f->date = mtime; 125 checkqid(f); 126 } 127 } 128 return nt; 129 } 130 131 Posn 132 writeio(File *f) 133 { 134 int m, n; 135 Posn p = addr.r.p1; 136 char *c; 137 138 while(p < addr.r.p2){ 139 if(addr.r.p2-p>BLOCKSIZE) 140 n = BLOCKSIZE; 141 else 142 n = addr.r.p2-p; 143 if(Fchars(f, genbuf, p, p+n)!=n) 144 panic("writef read"); 145 c = Strtoc(tmprstr(genbuf, n)); 146 m = strlen(c); 147 if(Write(io, c, m) != m){ 148 free(c); 149 if(p > 0) 150 p += n; 151 break; 152 } 153 free(c); 154 p += n; 155 } 156 return p-addr.r.p1; 157 } 158 void 159 closeio(Posn p) 160 { 161 close(io); 162 io = 0; 163 if(p >= 0) 164 dprint("#%lud\n", p); 165 } 166 167 int remotefd0 = 0; 168 int remotefd1 = 1; 169 170 void 171 bootterm(char *machine, char **argv, char **end) 172 { 173 int ph2t[2], pt2h[2]; 174 175 if(machine){ 176 dup(remotefd0, 0); 177 dup(remotefd1, 1); 178 close(remotefd0); 179 close(remotefd1); 180 argv[0] = "samterm"; 181 *end = 0; 182 exec(samterm, argv); 183 fprint(2, "can't exec: "); 184 perror(samterm); 185 _exits("damn"); 186 } 187 if(pipe(ph2t)==-1 || pipe(pt2h)==-1) 188 panic("pipe"); 189 switch(fork()){ 190 case 0: 191 dup(ph2t[0], 0); 192 dup(pt2h[1], 1); 193 close(ph2t[0]); 194 close(ph2t[1]); 195 close(pt2h[0]); 196 close(pt2h[1]); 197 argv[0] = "samterm"; 198 *end = 0; 199 exec(samterm, argv); 200 fprint(2, "can't exec: "); 201 perror(samterm); 202 _exits("damn"); 203 case -1: 204 panic("can't fork samterm"); 205 } 206 dup(pt2h[0], 0); 207 dup(ph2t[1], 1); 208 close(ph2t[0]); 209 close(ph2t[1]); 210 close(pt2h[0]); 211 close(pt2h[1]); 212 } 213 214 void 215 connectto(char *machine) 216 { 217 int p1[2], p2[2]; 218 219 if(pipe(p1)<0 || pipe(p2)<0){ 220 dprint("can't pipe\n"); 221 exits("pipe"); 222 } 223 remotefd0 = p1[0]; 224 remotefd1 = p2[1]; 225 switch(fork()){ 226 case 0: 227 dup(p2[0], 0); 228 dup(p1[1], 1); 229 close(p1[0]); 230 close(p1[1]); 231 close(p2[0]); 232 close(p2[1]); 233 execl(RXPATH, RX, machine, rsamname, "-R", (char*)0); 234 dprint("can't exec %s\n", RXPATH); 235 exits("exec"); 236 237 case -1: 238 dprint("can't fork\n"); 239 exits("fork"); 240 } 241 close(p1[1]); 242 close(p2[0]); 243 } 244 245 void 246 startup(char *machine, int Rflag, char **argv, char **end) 247 { 248 if(machine) 249 connectto(machine); 250 if(!Rflag) 251 bootterm(machine, argv, end); 252 downloaded = 1; 253 outTs(Hversion, VERSION); 254 } 255