case 22:
case CTRL('V'):
static void term_send(char *buf, int len) {    while (len--) {	char c;        c = *buf++;	switch (term_quotenext ? ' ' : c) {	    /*	     * ^h/^?: delete one char and output one BSB	     * ^w: delete, and output BSBs, to return to last space/nonspace	     * boundary	     * ^u: delete, and output BSBs, to return to BOL	     * ^r: echo "^R\n" and redraw line	     * ^v: quote next char	     * ^d: if at BOL, end of file and close connection, else send line	     * and reset to BOL	     * ^m/^j: send line-plus-\r\n and reset to BOL	     */	  case 8: case 127:	       /* backspace/delete */	    if (term_buflen > 0) {		bsb(plen(term_buf[term_buflen-1]));		term_buflen--;	    }	    break;	  case 23:		       /* ^W delete word */	    while (term_buflen > 0) {		bsb(plen(term_buf[term_buflen-1]));		term_buflen--;		if (term_buflen > 0 &&		    isspace(term_buf[term_buflen-1]) &&		    !isspace(term_buf[term_buflen]))		    break;	    }	    break;	  case 21:		       /* ^U delete line */	    while (term_buflen > 0) {		bsb(plen(term_buf[term_buflen-1]));		term_buflen--;	    }            break;	  case 18:		       /* ^R redraw line */	    c_write("^R\r\n", 4);	    {		int i;		for (i = 0; i < term_buflen; i++)		    pwrite(term_buf[i]);	    }	    break;	  case 22:		       /* ^V quote next char */	    term_quotenext = TRUE;	    break;	  case 4:		       /* ^D logout or send */	    if (term_buflen == 0) {		/* FIXME: eof */;	    } else {		back->send(term_buf, term_buflen);		term_buflen = 0;	    }	    break;	  case 13: case 10:	       /* ^M/^J send with newline */	    back->send(term_buf, term_buflen);	    back->send("\r\n", 2);	    c_write("\r\n", 2);	    term_buflen = 0;	    break;	  default:                     /* get to this label from ^V handler */	    if (term_buflen >= term_bufsiz) {		term_bufsiz = term_buflen + 256;		term_buf = saferealloc(term_buf, term_bufsiz);	    }	    term_buf[term_buflen++] = c;	    pwrite(c);            term_quotenext = FALSE;	    break;	}    }}