static int readln(Fd *fd, char *expect) { char *p; if((p = rdln(fd)) == nil) return -1; if(strcmp(p, expect) != 0) return -1; return 0; }
F rdlnd(){F r;S s=rdln();r=strtod(s,0);DL(s);R r;} //read number(should this error on wrong input?)
V rdq(ST s,I u){S e,i=rdln();F d=strtod(i,&e);if(*e)psh(s,newoskz(i));else{DL(i);psh(s,newod(d));}if(u)v['Q']=dup(top(s));} //q,Q
/* * Assumes pipe is buffered at least 257 characters, * so both sides can send and then receive. */ int banner(Replica *r, char *name) { int i; char c, *p; char buf[257]; dbg(DbgRpc, "sending tracmd\n"); qlock(&r->rlock); qlock(&r->wlock); /* both sides send tracmd */ if(twrite(r->wfd, tracmd, sizeof tracmd-1) < 0 || twflush(r->wfd) == -1){ werrstr("writing banner: %r"); err: qunlock(&r->wlock); qunlock(&r->rlock); return -1; } dbg(DbgRpc, "waiting for tracmd\n"); while((p = rdln(r->rfd)) != nil){ if(strcmp(tracmd, p) == 0) break; if(name) fprint(2, "%s# %s", name, p); } if(p == nil){ werrstr("did not receive initial banner"); goto err; } dbg(DbgRpc, "sending antissh\n"); /* both sides send \n~?\n~.\n */ if(twrite(r->wfd, antissh, sizeof antissh-1) < 0 || twflush(r->wfd) == -1){ werrstr("writing antissh: %r"); goto err; } dbg(DbgRpc, "waiting for antissh\n"); if(readln(r->rfd, "\n")<0 || readln(r->rfd, "~?\n")<0 || readln(r->rfd, "~.\n") < 0){ werrstr("corrupt anti-ssh banner"); goto err; } dbg(DbgRpc, "sending byte map\n"); /* both sides send 0x00, 0x01, ..., 0xFF, 0x00 */ /* the second 0x00 gives us a way to notice 0xFF being dropped */ for(i=0; i<257; i++) buf[i] = i; if(twrite(r->wfd, buf, sizeof buf) < 0 || twflush(r->wfd) == -1){ werrstr("short channel test write: %r"); goto err; } dbg(DbgRpc, "receiving byte map\n"); /* could be more efficient but doesn't matter */ for(i=0; i < sizeof buf; i++){ if(tread(r->rfd, &c, 1) != 1){ werrstr("8-bit test: expected 0x%x, got eof", buf[i]); goto err; } if(c != buf[i]){ werrstr("8-bit test: expected 0x%x, got 0x%x", buf[i], c); goto err; } } //fprint(2, "%s: pass\n", argv0); qunlock(&r->wlock); qunlock(&r->rlock); return 0; }