| io.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| io.c (4703B) | |
| --- | |
| 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->qidpath==g->qidpath) | |
| 18 warn_SS(Wdupfile, &f->name, &g->name); | |
| 19 } | |
| 20 } | |
| 21 | |
| 22 void | |
| 23 writef(File *f) | |
| 24 { | |
| 25 Posn n; | |
| 26 char *name; | |
| 27 int i, samename, newfile; | |
| 28 ulong dev; | |
| 29 uvlong 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->qidpath!=qid || f->mtime<mtime)){ | |
| 40 f->dev = dev; | |
| 41 f->qidpath = qid; | |
| 42 f->mtime = 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_r(Ecreate, genc); | |
| 51 dprint("%s: ", genc); | |
| 52 if(statfd(io, 0, 0, 0, &length, &appendonly) > 0 && appendonly &… | |
| 53 error(Eappend); | |
| 54 n = writeio(f); | |
| 55 if(f->name.s[0]==0 || samename){ | |
| 56 if(addr.r.p1==0 && addr.r.p2==f->b.nc) | |
| 57 f->cleanseq = f->seq; | |
| 58 state(f, f->cleanseq==f->seq? Clean : Dirty); | |
| 59 } | |
| 60 if(newfile) | |
| 61 dprint("(new file) "); | |
| 62 if(addr.r.p2>0 && filereadc(f, addr.r.p2-1)!='\n') | |
| 63 warn(Wnotnewline); | |
| 64 closeio(n); | |
| 65 if(f->name.s[0]==0 || samename){ | |
| 66 if(statfile(name, &dev, &qid, &mtime, 0, 0) > 0){ | |
| 67 f->dev = dev; | |
| 68 f->qidpath = qid; | |
| 69 f->mtime = mtime; | |
| 70 checkqid(f); | |
| 71 } | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 Posn | |
| 76 readio(File *f, int *nulls, int setdate, int toterm) | |
| 77 { | |
| 78 int n, b, w; | |
| 79 Rune *r; | |
| 80 Posn nt; | |
| 81 Posn p = addr.r.p2; | |
| 82 ulong dev; | |
| 83 uvlong qid; | |
| 84 long mtime; | |
| 85 char buf[BLOCKSIZE+1], *s; | |
| 86 | |
| 87 *nulls = FALSE; | |
| 88 b = 0; | |
| 89 if(f->unread){ | |
| 90 nt = bufload(&f->b, 0, io, nulls); | |
| 91 if(toterm) | |
| 92 raspload(f); | |
| 93 }else | |
| 94 for(nt = 0; (n = read(io, buf+b, BLOCKSIZE-b))>0; nt+=(r… | |
| 95 n += b; | |
| 96 b = 0; | |
| 97 r = genbuf; | |
| 98 s = buf; | |
| 99 while(n > 0){ | |
| 100 if((*r = *(uchar*)s) < Runeself){ | |
| 101 if(*r) | |
| 102 r++; | |
| 103 else | |
| 104 *nulls = TRUE; | |
| 105 --n; | |
| 106 s++; | |
| 107 continue; | |
| 108 } | |
| 109 if(fullrune(s, n)){ | |
| 110 w = chartorune(r, s); | |
| 111 if(*r) | |
| 112 r++; | |
| 113 else | |
| 114 *nulls = TRUE; | |
| 115 n -= w; | |
| 116 s += w; | |
| 117 continue; | |
| 118 } | |
| 119 b = n; | |
| 120 memmove(buf, s, b); | |
| 121 break; | |
| 122 } | |
| 123 loginsert(f, p, genbuf, r-genbuf); | |
| 124 } | |
| 125 if(b) | |
| 126 *nulls = TRUE; | |
| 127 if(*nulls) | |
| 128 warn(Wnulls); | |
| 129 if(setdate){ | |
| 130 if(statfd(io, &dev, &qid, &mtime, 0, 0) > 0){ | |
| 131 f->dev = dev; | |
| 132 f->qidpath = qid; | |
| 133 f->mtime = mtime; | |
| 134 checkqid(f); | |
| 135 } | |
| 136 } | |
| 137 return nt; | |
| 138 } | |
| 139 | |
| 140 Posn | |
| 141 writeio(File *f) | |
| 142 { | |
| 143 int m, n; | |
| 144 Posn p = addr.r.p1; | |
| 145 char *c; | |
| 146 | |
| 147 while(p < addr.r.p2){ | |
| 148 if(addr.r.p2-p>BLOCKSIZE) | |
| 149 n = BLOCKSIZE; | |
| 150 else | |
| 151 n = addr.r.p2-p; | |
| 152 bufread(&f->b, p, genbuf, n); | |
| 153 c = Strtoc(tmprstr(genbuf, n)); | |
| 154 m = strlen(c); | |
| 155 if(Write(io, c, m) != m){ | |
| 156 free(c); | |
| 157 if(p > 0) | |
| 158 p += n; | |
| 159 break; | |
| 160 } | |
| 161 free(c); | |
| 162 p += n; | |
| 163 } | |
| 164 return p-addr.r.p1; | |
| 165 } | |
| 166 void | |
| 167 closeio(Posn p) | |
| 168 { | |
| 169 close(io); | |
| 170 io = 0; | |
| 171 if(p >= 0) | |
| 172 dprint("#%lud\n", p); | |
| 173 } | |
| 174 | |
| 175 int remotefd0 = 0; | |
| 176 int remotefd1 = 1; | |
| 177 | |
| 178 void | |
| 179 bootterm(char *machine, char **argv) | |
| 180 { | |
| 181 int ph2t[2], pt2h[2]; | |
| 182 | |
| 183 if(machine){ | |
| 184 dup(remotefd0, 0); | |
| 185 dup(remotefd1, 1); | |
| 186 close(remotefd0); | |
| 187 close(remotefd1); | |
| 188 argv[0] = "samterm"; | |
| 189 execvp(samterm, argv); | |
| 190 fprint(2, "can't exec %s: %r\n", samterm); | |
| 191 _exits("damn"); | |
| 192 } | |
| 193 if(pipe(ph2t)==-1 || pipe(pt2h)==-1) | |
| 194 panic("pipe"); | |
| 195 switch(fork()){ | |
| 196 case 0: | |
| 197 dup(ph2t[0], 0); | |
| 198 dup(pt2h[1], 1); | |
| 199 close(ph2t[0]); | |
| 200 close(ph2t[1]); | |
| 201 close(pt2h[0]); | |
| 202 close(pt2h[1]); | |
| 203 argv[0] = "samterm"; | |
| 204 execvp(samterm, argv); | |
| 205 fprint(2, "can't exec: "); | |
| 206 perror(samterm); | |
| 207 _exits("damn"); | |
| 208 case -1: | |
| 209 panic("can't fork samterm"); | |
| 210 } | |
| 211 dup(pt2h[0], 0); | |
| 212 dup(ph2t[1], 1); | |
| 213 close(ph2t[0]); | |
| 214 close(ph2t[1]); | |
| 215 close(pt2h[0]); | |
| 216 close(pt2h[1]); | |
| 217 } | |
| 218 | |
| 219 void | |
| 220 connectto(char *machine, char **argv) | |
| 221 { | |
| 222 int p1[2], p2[2]; | |
| 223 char **av; | |
| 224 int ac; | |
| 225 | |
| 226 /* count args */ | |
| 227 for(av = argv; *av; av++) | |
| 228 ; | |
| 229 av = malloc(sizeof(char*)*((av-argv) + 5)); | |
| 230 if(av == nil){ | |
| 231 dprint("out of memory\n"); | |
| 232 exits("fork/exec"); | |
| 233 } | |
| 234 ac = 0; | |
| 235 av[ac++] = RX; | |
| 236 av[ac++] = machine; | |
| 237 av[ac++] = rsamname; | |
| 238 av[ac++] = "-R"; | |
| 239 while(*argv) | |
| 240 av[ac++] = *argv++; | |
| 241 av[ac] = 0; | |
| 242 if(pipe(p1)<0 || pipe(p2)<0){ | |
| 243 dprint("can't pipe\n"); | |
| 244 exits("pipe"); | |
| 245 } | |
| 246 remotefd0 = p1[0]; | |
| 247 remotefd1 = p2[1]; | |
| 248 switch(fork()){ | |
| 249 case 0: | |
| 250 dup(p2[0], 0); | |
| 251 dup(p1[1], 1); | |
| 252 close(p1[0]); | |
| 253 close(p1[1]); | |
| 254 close(p2[0]); | |
| 255 close(p2[1]); | |
| 256 execvp(RXPATH, av); | |
| 257 dprint("can't exec %s\n", RXPATH); | |
| 258 exits("exec"); | |
| 259 | |
| 260 case -1: | |
| 261 dprint("can't fork\n"); | |
| 262 exits("fork"); | |
| 263 } | |
| 264 free(av); | |
| 265 close(p1[1]); | |
| 266 close(p2[0]); | |
| 267 } | |
| 268 | |
| 269 void | |
| 270 startup(char *machine, int Rflag, char **argv, char **files) | |
| 271 { | |
| 272 if(machine) | |
| 273 connectto(machine, files); | |
| 274 if(!Rflag) | |
| 275 bootterm(machine, argv); | |
| 276 downloaded = 1; | |
| 277 outTs(Hversion, VERSION); | |
| 278 } |