13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <bio.h> 43e12c5d1SDavid du Colombier #include <ip.h> 53e12c5d1SDavid du Colombier #include <ndb.h> 63e12c5d1SDavid du Colombier 73e12c5d1SDavid du Colombier void fatal(int syserr, char *fmt, ...); 83e12c5d1SDavid du Colombier void openlisten(void); 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier int dbg; 11*219b2ee8SDavid du Colombier int restricted; 123e12c5d1SDavid du Colombier int tftpreq; 133e12c5d1SDavid du Colombier int tftpaddr; 143e12c5d1SDavid du Colombier int tftpctl; 153e12c5d1SDavid du Colombier void openlisten(void); 163e12c5d1SDavid du Colombier void sendfile(int, char*, char*); 173e12c5d1SDavid du Colombier void recvfile(int, char*, char*); 183e12c5d1SDavid du Colombier void nak(int, int, char*); 193e12c5d1SDavid du Colombier void ack(int, ushort); 203e12c5d1SDavid du Colombier void clrcon(void); 213e12c5d1SDavid du Colombier void setuser(void); 223e12c5d1SDavid du Colombier char* sunkernel(char*); 233e12c5d1SDavid du Colombier 243e12c5d1SDavid du Colombier char mbuf[32768]; 253e12c5d1SDavid du Colombier char raddr[32]; 263e12c5d1SDavid du Colombier 273e12c5d1SDavid du Colombier char *dir = "/lib/tftpd"; 28*219b2ee8SDavid du Colombier char *dirsl; 29*219b2ee8SDavid du Colombier int dirsllen; 303e12c5d1SDavid du Colombier char flog[] = "ipboot"; 313e12c5d1SDavid du Colombier 323e12c5d1SDavid du Colombier enum 333e12c5d1SDavid du Colombier { 343e12c5d1SDavid du Colombier Tftp_READ = 1, 353e12c5d1SDavid du Colombier Tftp_WRITE = 2, 363e12c5d1SDavid du Colombier Tftp_DATA = 3, 373e12c5d1SDavid du Colombier Tftp_ACK = 4, 383e12c5d1SDavid du Colombier Tftp_ERROR = 5, 393e12c5d1SDavid du Colombier Segsize = 512, 403e12c5d1SDavid du Colombier }; 413e12c5d1SDavid du Colombier 423e12c5d1SDavid du Colombier void 433e12c5d1SDavid du Colombier main(int argc, char **argv) 443e12c5d1SDavid du Colombier { 453e12c5d1SDavid du Colombier int n, dlen, clen; 463e12c5d1SDavid du Colombier char connect[64], buf[64], datadir[64]; 473e12c5d1SDavid du Colombier char *mode, *p; 483e12c5d1SDavid du Colombier short op; 493e12c5d1SDavid du Colombier int ctl, data; 503e12c5d1SDavid du Colombier 513e12c5d1SDavid du Colombier ARGBEGIN{ 523e12c5d1SDavid du Colombier case 'd': 533e12c5d1SDavid du Colombier dbg++; 543e12c5d1SDavid du Colombier break; 553e12c5d1SDavid du Colombier case 'h': 563e12c5d1SDavid du Colombier dir = ARGF(); 573e12c5d1SDavid du Colombier break; 58*219b2ee8SDavid du Colombier case 'r': 59*219b2ee8SDavid du Colombier restricted = 1; 60*219b2ee8SDavid du Colombier break; 613e12c5d1SDavid du Colombier default: 62*219b2ee8SDavid du Colombier fprint(2, "usage: tftpd [-dr] [-h homedir]\n"); 633e12c5d1SDavid du Colombier exits("usage"); 643e12c5d1SDavid du Colombier }ARGEND 653e12c5d1SDavid du Colombier USED(argc); USED(argv); 663e12c5d1SDavid du Colombier 67*219b2ee8SDavid du Colombier snprint(buf, sizeof buf, "%s/", dir); 68*219b2ee8SDavid du Colombier dirsl = strdup(buf); 69*219b2ee8SDavid du Colombier dirsllen = strlen(dirsl); 70*219b2ee8SDavid du Colombier 713e12c5d1SDavid du Colombier fmtinstall('E', eipconv); 723e12c5d1SDavid du Colombier fmtinstall('I', eipconv); 733e12c5d1SDavid du Colombier 743e12c5d1SDavid du Colombier if(chdir(dir) < 0) 753e12c5d1SDavid du Colombier fatal(1, "cant get to directory %s", dir); 763e12c5d1SDavid du Colombier 773e12c5d1SDavid du Colombier switch(rfork(RFNOTEG|RFPROC|RFFDG)) { 783e12c5d1SDavid du Colombier case -1: 793e12c5d1SDavid du Colombier fatal(1, "fork"); 803e12c5d1SDavid du Colombier case 0: 813e12c5d1SDavid du Colombier break; 823e12c5d1SDavid du Colombier default: 833e12c5d1SDavid du Colombier exits(0); 843e12c5d1SDavid du Colombier } 853e12c5d1SDavid du Colombier 863e12c5d1SDavid du Colombier syslog(dbg, flog, "started"); 873e12c5d1SDavid du Colombier 883e12c5d1SDavid du Colombier openlisten(); 893e12c5d1SDavid du Colombier setuser(); 903e12c5d1SDavid du Colombier for(;;) { 913e12c5d1SDavid du Colombier dlen = read(tftpreq, mbuf, sizeof(mbuf)); 923e12c5d1SDavid du Colombier if(dlen < 0) 933e12c5d1SDavid du Colombier fatal(1, "listen read"); 943e12c5d1SDavid du Colombier seek(tftpaddr, 0, 0); 953e12c5d1SDavid du Colombier clen = read(tftpaddr, raddr, sizeof(raddr)); 963e12c5d1SDavid du Colombier if(clen < 0) 973e12c5d1SDavid du Colombier fatal(1, "request address read"); 983e12c5d1SDavid du Colombier raddr[clen-1] = '\0'; 993e12c5d1SDavid du Colombier clrcon(); 1003e12c5d1SDavid du Colombier 1013e12c5d1SDavid du Colombier ctl = open("/net/udp/clone", ORDWR); 1023e12c5d1SDavid du Colombier if(ctl < 0) 1033e12c5d1SDavid du Colombier fatal(1, "open udp clone"); 1043e12c5d1SDavid du Colombier n = read(ctl, buf, sizeof(buf)); 1053e12c5d1SDavid du Colombier if(n < 0) 1063e12c5d1SDavid du Colombier fatal(1, "read udp ctl"); 1073e12c5d1SDavid du Colombier buf[n] = 0; 1083e12c5d1SDavid du Colombier 1093e12c5d1SDavid du Colombier clen = sprint(connect, "connect %s", raddr); 1103e12c5d1SDavid du Colombier n = write(ctl, connect, clen); 1113e12c5d1SDavid du Colombier if(n < 0) 1123e12c5d1SDavid du Colombier fatal(1, "udp %s", raddr); 1133e12c5d1SDavid du Colombier 1143e12c5d1SDavid du Colombier sprint(datadir, "/net/udp/%s/data", buf); 1153e12c5d1SDavid du Colombier data = open(datadir, ORDWR); 1163e12c5d1SDavid du Colombier if(data < 0) 1173e12c5d1SDavid du Colombier fatal(1, "open udp data"); 1183e12c5d1SDavid du Colombier 1193e12c5d1SDavid du Colombier close(ctl); 1203e12c5d1SDavid du Colombier 1213e12c5d1SDavid du Colombier dlen -= 2; 1223e12c5d1SDavid du Colombier mode = mbuf+2; 1233e12c5d1SDavid du Colombier while(*mode != '\0' && dlen--) 1243e12c5d1SDavid du Colombier mode++; 1253e12c5d1SDavid du Colombier mode++; 1263e12c5d1SDavid du Colombier p = mode; 1273e12c5d1SDavid du Colombier while(*p && dlen--) 1283e12c5d1SDavid du Colombier p++; 1293e12c5d1SDavid du Colombier if(dlen == 0) { 1303e12c5d1SDavid du Colombier nak(data, 0, "bad tftpmode"); 1313e12c5d1SDavid du Colombier close(data); 1323e12c5d1SDavid du Colombier syslog(dbg, flog, "bad mode %s", raddr); 1333e12c5d1SDavid du Colombier continue; 1343e12c5d1SDavid du Colombier } 1353e12c5d1SDavid du Colombier 1363e12c5d1SDavid du Colombier op = mbuf[0]<<8 | mbuf[1]; 1373e12c5d1SDavid du Colombier if(op != Tftp_READ && op != Tftp_WRITE) { 1383e12c5d1SDavid du Colombier nak(data, 4, "Illegal TFTP operation"); 1393e12c5d1SDavid du Colombier close(data); 1403e12c5d1SDavid du Colombier syslog(dbg, flog, "bad request %d %s", op, raddr); 1413e12c5d1SDavid du Colombier continue; 1423e12c5d1SDavid du Colombier } 143*219b2ee8SDavid du Colombier if(restricted){ 144*219b2ee8SDavid du Colombier if(strncmp(mbuf+2, "../", 3) || strstr(mbuf+2, "/../") || 145*219b2ee8SDavid du Colombier (mbuf[2] == '/' && strncmp(mbuf+2, dirsl, dirsllen)!=0)){ 146*219b2ee8SDavid du Colombier nak(data, 4, "Permission denied"); 147*219b2ee8SDavid du Colombier close(data); 148*219b2ee8SDavid du Colombier syslog(dbg, flog, "bad request %d %s", op, raddr); 149*219b2ee8SDavid du Colombier continue; 150*219b2ee8SDavid du Colombier } 151*219b2ee8SDavid du Colombier } 1523e12c5d1SDavid du Colombier switch(fork()) { 1533e12c5d1SDavid du Colombier case -1: 1543e12c5d1SDavid du Colombier fatal(1, "fork"); 1553e12c5d1SDavid du Colombier case 0: 1563e12c5d1SDavid du Colombier if(op == Tftp_READ) 1573e12c5d1SDavid du Colombier sendfile(data, mbuf+2, mode); 1583e12c5d1SDavid du Colombier else 1593e12c5d1SDavid du Colombier recvfile(data, mbuf+2, mode); 1603e12c5d1SDavid du Colombier exits("done"); 1613e12c5d1SDavid du Colombier default: 1623e12c5d1SDavid du Colombier close(data); 1633e12c5d1SDavid du Colombier } 1643e12c5d1SDavid du Colombier } 1653e12c5d1SDavid du Colombier } 1663e12c5d1SDavid du Colombier 1673e12c5d1SDavid du Colombier void 1683e12c5d1SDavid du Colombier catcher(void *junk, char *msg) 1693e12c5d1SDavid du Colombier { 1703e12c5d1SDavid du Colombier USED(junk); 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier if(strncmp(msg, "exit", 4) == 0) 1733e12c5d1SDavid du Colombier noted(NDFLT); 1743e12c5d1SDavid du Colombier noted(NCONT); 1753e12c5d1SDavid du Colombier } 1763e12c5d1SDavid du Colombier 1773e12c5d1SDavid du Colombier void 1783e12c5d1SDavid du Colombier sendfile(int fd, char *name, char *mode) 1793e12c5d1SDavid du Colombier { 1803e12c5d1SDavid du Colombier int file; 1813e12c5d1SDavid du Colombier uchar buf[Segsize+4]; 1823e12c5d1SDavid du Colombier uchar ack[1024]; 1833e12c5d1SDavid du Colombier char errbuf[ERRLEN]; 1843e12c5d1SDavid du Colombier int ackblock, block, ret; 1853e12c5d1SDavid du Colombier int rexmit, n, al, txtry, rxl; 1863e12c5d1SDavid du Colombier short op; 1873e12c5d1SDavid du Colombier 1883e12c5d1SDavid du Colombier syslog(dbg, flog, "send file '%s' %s to %s", name, mode, raddr); 1893e12c5d1SDavid du Colombier name = sunkernel(name); 1903e12c5d1SDavid du Colombier if(name == 0){ 1913e12c5d1SDavid du Colombier nak(fd, 0, "not in our database"); 1923e12c5d1SDavid du Colombier return; 1933e12c5d1SDavid du Colombier } 1943e12c5d1SDavid du Colombier 1953e12c5d1SDavid du Colombier notify(catcher); 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier file = open(name, OREAD); 1983e12c5d1SDavid du Colombier if(file < 0) { 1993e12c5d1SDavid du Colombier errstr(errbuf); 2003e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 2013e12c5d1SDavid du Colombier return; 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier block = 0; 2043e12c5d1SDavid du Colombier rexmit = 0; 2053e12c5d1SDavid du Colombier n = 0; 206*219b2ee8SDavid du Colombier for(txtry = 0; txtry < 5;) { 2073e12c5d1SDavid du Colombier if(rexmit == 0) { 2083e12c5d1SDavid du Colombier block++; 2093e12c5d1SDavid du Colombier buf[0] = 0; 2103e12c5d1SDavid du Colombier buf[1] = Tftp_DATA; 2113e12c5d1SDavid du Colombier buf[2] = block>>8; 2123e12c5d1SDavid du Colombier buf[3] = block; 2133e12c5d1SDavid du Colombier n = read(file, buf+4, Segsize); 2143e12c5d1SDavid du Colombier if(n < 0) { 2153e12c5d1SDavid du Colombier errstr(errbuf); 2163e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 2173e12c5d1SDavid du Colombier return; 2183e12c5d1SDavid du Colombier } 219*219b2ee8SDavid du Colombier txtry = 0; 2203e12c5d1SDavid du Colombier } 2213e12c5d1SDavid du Colombier else 2223e12c5d1SDavid du Colombier txtry++; 2233e12c5d1SDavid du Colombier ret = write(fd, buf, 4+n); 2243e12c5d1SDavid du Colombier if(ret < 0) 2253e12c5d1SDavid du Colombier fatal(1, "tftp: network write error"); 2263e12c5d1SDavid du Colombier 2273e12c5d1SDavid du Colombier for(rxl = 0; rxl < 10; rxl++) { 2283e12c5d1SDavid du Colombier rexmit = 0; 229*219b2ee8SDavid du Colombier alarm(500); 2303e12c5d1SDavid du Colombier al = read(fd, ack, sizeof(ack)); 2313e12c5d1SDavid du Colombier alarm(0); 2323e12c5d1SDavid du Colombier if(al < 0) { 2333e12c5d1SDavid du Colombier rexmit = 1; 2343e12c5d1SDavid du Colombier break; 2353e12c5d1SDavid du Colombier } 2363e12c5d1SDavid du Colombier op = ack[0]<<8|ack[1]; 2373e12c5d1SDavid du Colombier if(op == Tftp_ERROR) 2383e12c5d1SDavid du Colombier goto error; 2393e12c5d1SDavid du Colombier ackblock = ack[2]<<8|ack[3]; 2403e12c5d1SDavid du Colombier if(ackblock == block) 2413e12c5d1SDavid du Colombier break; 2423e12c5d1SDavid du Colombier if(ackblock == 0xffff) { 2433e12c5d1SDavid du Colombier rexmit = 1; 2443e12c5d1SDavid du Colombier break; 2453e12c5d1SDavid du Colombier } 2463e12c5d1SDavid du Colombier } 2473e12c5d1SDavid du Colombier if(ret != Segsize+4 && rexmit == 0) 2483e12c5d1SDavid du Colombier break; 2493e12c5d1SDavid du Colombier } 2503e12c5d1SDavid du Colombier error: 2513e12c5d1SDavid du Colombier close(fd); 2523e12c5d1SDavid du Colombier close(file); 2533e12c5d1SDavid du Colombier } 2543e12c5d1SDavid du Colombier 2553e12c5d1SDavid du Colombier void 2563e12c5d1SDavid du Colombier recvfile(int fd, char *name, char *mode) 2573e12c5d1SDavid du Colombier { 2583e12c5d1SDavid du Colombier ushort op, block, inblock; 2593e12c5d1SDavid du Colombier uchar buf[Segsize+8]; 2603e12c5d1SDavid du Colombier char errbuf[ERRLEN]; 2613e12c5d1SDavid du Colombier int n, ret, file; 2623e12c5d1SDavid du Colombier 2633e12c5d1SDavid du Colombier syslog(dbg, flog, "receive file '%s' %s from %s", name, mode, raddr); 2643e12c5d1SDavid du Colombier 2653e12c5d1SDavid du Colombier file = create(name, OWRITE, 0666); 2663e12c5d1SDavid du Colombier if(file < 0) { 2673e12c5d1SDavid du Colombier errstr(errbuf); 2683e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 2693e12c5d1SDavid du Colombier return; 2703e12c5d1SDavid du Colombier } 2713e12c5d1SDavid du Colombier 2723e12c5d1SDavid du Colombier block = 0; 2733e12c5d1SDavid du Colombier ack(fd, block); 2743e12c5d1SDavid du Colombier block++; 2753e12c5d1SDavid du Colombier 2763e12c5d1SDavid du Colombier for(;;) { 2773e12c5d1SDavid du Colombier alarm(15000); 2783e12c5d1SDavid du Colombier n = read(fd, buf, sizeof(buf)); 2793e12c5d1SDavid du Colombier alarm(0); 2803e12c5d1SDavid du Colombier if(n < 0) 2813e12c5d1SDavid du Colombier goto error; 2823e12c5d1SDavid du Colombier op = buf[0]<<8|buf[1]; 2833e12c5d1SDavid du Colombier if(op == Tftp_ERROR) 2843e12c5d1SDavid du Colombier goto error; 2853e12c5d1SDavid du Colombier 2863e12c5d1SDavid du Colombier n -= 4; 2873e12c5d1SDavid du Colombier inblock = buf[2]<<8|buf[3]; 2883e12c5d1SDavid du Colombier if(op == Tftp_DATA) { 2893e12c5d1SDavid du Colombier if(inblock == block) { 2903e12c5d1SDavid du Colombier ret = write(file, buf, n); 2913e12c5d1SDavid du Colombier if(ret < 0) { 2923e12c5d1SDavid du Colombier errstr(errbuf); 2933e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 2943e12c5d1SDavid du Colombier goto error; 2953e12c5d1SDavid du Colombier } 2963e12c5d1SDavid du Colombier ack(fd, block); 2973e12c5d1SDavid du Colombier block++; 2983e12c5d1SDavid du Colombier } 2993e12c5d1SDavid du Colombier ack(fd, 0xffff); 3003e12c5d1SDavid du Colombier } 3013e12c5d1SDavid du Colombier } 3023e12c5d1SDavid du Colombier error: 3033e12c5d1SDavid du Colombier close(file); 3043e12c5d1SDavid du Colombier } 3053e12c5d1SDavid du Colombier 3063e12c5d1SDavid du Colombier void 3073e12c5d1SDavid du Colombier ack(int fd, ushort block) 3083e12c5d1SDavid du Colombier { 3093e12c5d1SDavid du Colombier uchar ack[4]; 3103e12c5d1SDavid du Colombier int n; 3113e12c5d1SDavid du Colombier 3123e12c5d1SDavid du Colombier ack[0] = 0; 3133e12c5d1SDavid du Colombier ack[1] = Tftp_ACK; 3143e12c5d1SDavid du Colombier ack[2] = block>>8; 3153e12c5d1SDavid du Colombier ack[3] = block; 3163e12c5d1SDavid du Colombier 3173e12c5d1SDavid du Colombier n = write(fd, ack, 4); 3183e12c5d1SDavid du Colombier if(n < 0) 3193e12c5d1SDavid du Colombier fatal(1, "network write"); 3203e12c5d1SDavid du Colombier } 3213e12c5d1SDavid du Colombier 3223e12c5d1SDavid du Colombier void 3233e12c5d1SDavid du Colombier nak(int fd, int code, char *msg) 3243e12c5d1SDavid du Colombier { 3253e12c5d1SDavid du Colombier char buf[128]; 3263e12c5d1SDavid du Colombier int n; 3273e12c5d1SDavid du Colombier 3283e12c5d1SDavid du Colombier buf[0] = 0; 3293e12c5d1SDavid du Colombier buf[1] = Tftp_ERROR; 3303e12c5d1SDavid du Colombier buf[2] = 0; 3313e12c5d1SDavid du Colombier buf[3] = code; 3323e12c5d1SDavid du Colombier strcpy(buf+4, msg); 3333e12c5d1SDavid du Colombier n = strlen(msg) + 4 + 1; 3343e12c5d1SDavid du Colombier n = write(fd, buf, n); 3353e12c5d1SDavid du Colombier if(n < 0) 3363e12c5d1SDavid du Colombier fatal(1, "write nak"); 3373e12c5d1SDavid du Colombier } 3383e12c5d1SDavid du Colombier 3393e12c5d1SDavid du Colombier void 3403e12c5d1SDavid du Colombier fatal(int syserr, char *fmt, ...) 3413e12c5d1SDavid du Colombier { 3423e12c5d1SDavid du Colombier char buf[ERRLEN], sysbuf[ERRLEN]; 3433e12c5d1SDavid du Colombier 3443e12c5d1SDavid du Colombier doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); 3453e12c5d1SDavid du Colombier if(syserr) { 3463e12c5d1SDavid du Colombier errstr(sysbuf); 3473e12c5d1SDavid du Colombier fprint(2, "tftpd: %s: %s\n", buf, sysbuf); 3483e12c5d1SDavid du Colombier } 3493e12c5d1SDavid du Colombier else 3503e12c5d1SDavid du Colombier fprint(2, "tftpd: %s\n", buf); 3513e12c5d1SDavid du Colombier exits(buf); 3523e12c5d1SDavid du Colombier } 3533e12c5d1SDavid du Colombier 3543e12c5d1SDavid du Colombier void 3553e12c5d1SDavid du Colombier openlisten(void) 3563e12c5d1SDavid du Colombier { 3573e12c5d1SDavid du Colombier char buf[128], data[128]; 3583e12c5d1SDavid du Colombier int n; 3593e12c5d1SDavid du Colombier 3603e12c5d1SDavid du Colombier tftpctl = open("/net/udp/clone", ORDWR); 3613e12c5d1SDavid du Colombier if(tftpctl < 0) 3623e12c5d1SDavid du Colombier fatal(1, "open udp clone"); 3633e12c5d1SDavid du Colombier 3643e12c5d1SDavid du Colombier n = read(tftpctl, buf, sizeof(buf)); 3653e12c5d1SDavid du Colombier if(n < 0) 3663e12c5d1SDavid du Colombier fatal(1, "read clone"); 3673e12c5d1SDavid du Colombier buf[n] = 0; 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier n = write(tftpctl, "announce 69", sizeof("announce 69")); 3703e12c5d1SDavid du Colombier if(n < 0) 3713e12c5d1SDavid du Colombier fatal(1, "can't announce"); 3723e12c5d1SDavid du Colombier 3733e12c5d1SDavid du Colombier sprint(data, "/net/udp/%s/data", buf); 3743e12c5d1SDavid du Colombier 3753e12c5d1SDavid du Colombier tftpreq = open(data, ORDWR); 3763e12c5d1SDavid du Colombier if(tftpreq < 0) 3773e12c5d1SDavid du Colombier fatal(1, "open udp/data"); 3783e12c5d1SDavid du Colombier 3793e12c5d1SDavid du Colombier sprint(data, "/net/udp/%s/remote", buf); 3803e12c5d1SDavid du Colombier tftpaddr = open(data, OREAD); 3813e12c5d1SDavid du Colombier if(tftpaddr < 0) 3823e12c5d1SDavid du Colombier fatal(1, "open udp/remote"); 3833e12c5d1SDavid du Colombier 3843e12c5d1SDavid du Colombier } 3853e12c5d1SDavid du Colombier 3863e12c5d1SDavid du Colombier void 3873e12c5d1SDavid du Colombier clrcon(void) 3883e12c5d1SDavid du Colombier { 3893e12c5d1SDavid du Colombier int n; 3903e12c5d1SDavid du Colombier 3913e12c5d1SDavid du Colombier n = write(tftpctl, "connect 0.0.0.0!0!r", sizeof("connect 0.0.0.0!0!r")); 3923e12c5d1SDavid du Colombier if(n < 0) 3933e12c5d1SDavid du Colombier fatal(1, "clear connect"); 3943e12c5d1SDavid du Colombier } 3953e12c5d1SDavid du Colombier 3963e12c5d1SDavid du Colombier void 3973e12c5d1SDavid du Colombier setuser(void) 3983e12c5d1SDavid du Colombier { 3993e12c5d1SDavid du Colombier int f; 4003e12c5d1SDavid du Colombier 4013e12c5d1SDavid du Colombier f = open("/dev/user", OWRITE); 4023e12c5d1SDavid du Colombier if(f < 0) 4033e12c5d1SDavid du Colombier return; 4043e12c5d1SDavid du Colombier write(f, "none", sizeof("none")); 4053e12c5d1SDavid du Colombier close(f); 4063e12c5d1SDavid du Colombier } 4073e12c5d1SDavid du Colombier 4083e12c5d1SDavid du Colombier /* 4093e12c5d1SDavid du Colombier * for sun kernel boots, replace the requested file name with 4103e12c5d1SDavid du Colombier * a one from our database. If the database doesn't specify a file, 4113e12c5d1SDavid du Colombier * don't answer. 4123e12c5d1SDavid du Colombier */ 4133e12c5d1SDavid du Colombier char* 4143e12c5d1SDavid du Colombier sunkernel(char *name) 4153e12c5d1SDavid du Colombier { 4163e12c5d1SDavid du Colombier ulong addr; 4173e12c5d1SDavid du Colombier uchar ipaddr[4]; 4183e12c5d1SDavid du Colombier char buf[32]; 4193e12c5d1SDavid du Colombier static Ipinfo info; 4203e12c5d1SDavid du Colombier static Ndb *db; 4213e12c5d1SDavid du Colombier 422*219b2ee8SDavid du Colombier if(strlen(name) != 14 || strncmp(name + 8, ".SUN", 4) != 0) 4233e12c5d1SDavid du Colombier return name; 4243e12c5d1SDavid du Colombier 4253e12c5d1SDavid du Colombier addr = strtoul(name, 0, 16); 4263e12c5d1SDavid du Colombier ipaddr[0] = addr>>24; 4273e12c5d1SDavid du Colombier ipaddr[1] = addr>>16; 4283e12c5d1SDavid du Colombier ipaddr[2] = addr>>8; 4293e12c5d1SDavid du Colombier ipaddr[3] = addr; 4303e12c5d1SDavid du Colombier sprint(buf, "%I", ipaddr); 4313e12c5d1SDavid du Colombier if(db == 0) 4323e12c5d1SDavid du Colombier db = ndbopen(0); 4333e12c5d1SDavid du Colombier if(db == 0) 4343e12c5d1SDavid du Colombier return 0; 4353e12c5d1SDavid du Colombier if(ipinfo(db, 0, buf, 0, &info) < 0) 4363e12c5d1SDavid du Colombier return 0; 4373e12c5d1SDavid du Colombier if(info.bootf[0]) 4383e12c5d1SDavid du Colombier return info.bootf; 4393e12c5d1SDavid du Colombier return 0; 4403e12c5d1SDavid du Colombier } 441