+static char *connid(void)
+{
+ static struct charbuf cur;
+ int i;
+ char *ret;
+
+ for(i = 0; i < cur.d; i++) {
+ if((++cur.b[i]) > 'Z')
+ cur.b[i] = 'A';
+ else
+ goto done;
+ }
+ bufadd(cur, 'A');
+done:
+ ret = memcpy(smalloc(cur.d + 1), cur.b, cur.d);
+ ret[cur.d] = 0;
+ return(ret);
+}
+
+static void passduplex(struct bufio *a, int afd, struct bufio *b, int bfd)
+{
+ struct selected pfd[4], sel;
+ struct bufio *sio;
+ int n, ev;
+
+ while(!bioeof(a) && !bioeof(b)) {
+ biocopybuf(b, a);
+ biocopybuf(a, b);
+ n = 0;
+ if(!a->eof) {
+ ev = 0;
+ if(biorspace(a))
+ ev |= EV_READ;
+ if(biowdata(a))
+ ev |= EV_WRITE;
+ if(ev)
+ pfd[n++] = (struct selected){.fd = afd, .ev = ev};
+ }
+ if(!b->eof) {
+ ev = 0;
+ if(!b->eof && biorspace(b))
+ ev |= EV_READ;
+ if(biowdata(b))
+ ev |= EV_WRITE;
+ if(ev)
+ pfd[n++] = (struct selected){.fd = bfd, .ev = ev};
+ }
+ if((sel = mblock(600, n, pfd)).ev == 0)
+ break;
+ if(sel.fd == afd)
+ sio = a;
+ else if(sel.fd == bfd)
+ sio = b;
+ else
+ break;
+ if((sel.ev & EV_READ) && (biofillsome(sio) < 0))
+ break;
+ if((sel.ev & EV_WRITE) && (bioflushsome(sio) < 0))
+ break;
+ }
+}
+
+void serve(struct bufio *in, int infd, struct conn *conn)