int init() { int c_init(); user_list_fd=c_open("./user_list",O_RDWR|O_CREAT|0660); USER usr; memset(&usr,0,sizeof(USER)); c_lseek(user_list_fd,0,SEEK_SET); c_write(user_list_fd,(char *)&usr,USR_LEN); int on = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) perror("setsockopt error"); c_bind(sockfd,(struct sockaddr*)&server,ADDR_LEN); listen(sockfd,7);//两个队列之和为7 CHIS ch_his; bzero(&ch_his,HSTR_LEN); c_lseek(mainfd,0,SEEK_SET); c_write(mainfd,&ch_his,HSTR_LEN); c_lseek(mainfd,-HSTR_LEN,SEEK_END); c_read(mainfd,&ch_his,HSTR_LEN); count=ch_his.count;//initialize the value by the last count in the local file printf("initialization finished\n"); return 0; }
static void pwrite(unsigned char c) { if ((c >= 32 && c <= 126) || (c >= 160)) { c_write1(c); } else if (c < 128) { char cc[2]; cc[1] = (c == 127 ? '?' : c + 0x40); cc[0] = '^'; c_write(cc, 2); } else { char cc[5]; sprintf(cc, "<%02X>", c); c_write(cc, 4); } }
static int adb_receive(Plug plug, int urgent, char *data, int len) { Adb adb = (Adb) plug; if (adb->state == STATE_SENT_HELLO) { if (data[0]=='O') { // OKAY sk_write(adb->s,"0006shell:",10); adb->state = STATE_ASKED_FOR_SHELL; // wait for shell start response } else { if (data[0]=='F') { handle_fail(adb, data, len); } else { connection_fatal(adb->frontend, "Bad response after initial send"); } return 0; } } else if (adb->state == STATE_ASKED_FOR_SHELL) { if (data[0]=='O') { //OKAY adb->state = STATE_CONNECTED; // shell started, switch to terminal mode } else { if (data[0]=='F') { handle_fail(adb, data, len); } else { connection_fatal(adb->frontend, "Bad response waiting for shell start"); } return 0; } } else if (adb->state == STATE_WAITING_FOR_ERROR_MESSAGE) { do_fatal(adb, data, len); } else { c_write(adb, data, len); } return 1; }
int login()//return 1 success { USER usr; int i=usr.userid; printf("a login request\n"); c_lseek(user_list_fd,i*USR_LEN,SEEK_SET); c_read(user_list_fd,&usr,USR_LEN); int check; check= strcmp(usr.password,user_temp_p.password); if(check==0)//验证成功,将status置为1,写回文件。可以考虑建一个在线用户的数据结构; { usr.status=1; c_lseek(user_list_fd,-USR_LEN,SEEK_CUR); c_write(user_list_fd,&usr,USR_LEN); c_send(sockfd,(USER*)usr,USR_LEN,0); return 1; } else { printf("user:%d login error\n",usr.userid); usr.status=0; c_send(sockfd,(USER*)usr,USR_LEN,0); return 0; } }
int user_transations() { USER usr; memset(&usr,0,USR_LEN); int i=user_temp_p.userid; int is_exist; int is_match; //user结构体status最初被初始化为0,只有上线以后才会变为1 //所以首先检查status的状态 //如果为0,且用户名存在,则表示用户名密码错 //如果为0,且用户名不存在,则表示用户要注册 //如果为1,则表示用户想改密码 if(user_temp_p.status==0) { is_exist=check_exist(); if(is_exist==0) registration(); else login(); } else { c_lseek(user_list_fd,i*USR_LEN,SEEK_SET); c_read(user_list_fd,&usr,USR_LEN); memset(usr.password,0,15); strncpy(usr.password,user_temp_p.password,strlen(user_temp_p.password)); c_lseek(user_list_fd,i*USR_LEN,SEEK_SET); c_write(user_list_fd,&usr,USR_LEN); //modify password; } }
static int rlogin_receive(Plug plug, int urgent, char *data, int len) { Rlogin rlogin = (Rlogin) plug; if (urgent == 2) { char c; c = *data++; len--; if (c == '\x80') rlogin_size(rlogin, rlogin->term_width, rlogin->term_height); /* * We should flush everything (aka Telnet SYNCH) if we see * 0x02, and we should turn off and on _local_ flow control * on 0x10 and 0x20 respectively. I'm not convinced it's * worth it... */ } else { /* * Main rlogin protocol. This is really simple: the first * byte is expected to be NULL and is ignored, and the rest * is printed. */ if (rlogin->firstbyte) { if (data[0] == '\0') { data++; len--; } rlogin->firstbyte = 0; } if (len > 0) c_write(rlogin, data, len); } return 1; }
static void raw_receive(Plug plug, int urgent, char *data, int len) { Raw raw = (Raw) plug; c_write(raw, data, len); /* We count 'session start', for proxy logging purposes, as being * when data is received from the network and printed. */ raw->session_started = TRUE; }
static void pwrite(Ldisc ldisc, unsigned char c) { if ((c >= 32 && c <= 126) || (!in_utf(ldisc->term) && c >= 0xA0) || (in_utf(ldisc->term) && c >= 0x80)) { c_write(ldisc, (char *)&c, 1); } else if (c < 128) { char cc[2]; cc[1] = (c == 127 ? '?' : c + 0x40); cc[0] = '^'; c_write(ldisc, cc, 2); } else { char cc[5]; sprintf(cc, "<%02X>", c); c_write(ldisc, cc, 4); } }
void virtual_kb_paste(char *c) { // perform text paste uint8_t *text = paste_text(); if(text != 0) { c_write(text,strlen(text)); // free(text); } }
int32_t sys_write(context_t *c, uint32_t *args) { // use the console driver here int32_t file = args[0]; char *p = (char *) args[1]; int32_t len = args[2]; //c_printf("write(%d, 0x%x, %d) ", file, p, len); c_write(p, len); c->eax = len; }
void pipbin(C_FILE * cid, FILE * ufid) { char buf[128]; while (read(fileno(ufid), buf, 128) != 0) { if (c_write(cid, buf, 128) != 128) { fprintf(stderr, "pipbin: write error\n"); return; } } }
static int adb_receive(Plug plug, int urgent, char *data, int len) { Adb adb = (Adb) plug; if (adb->state==1) { if (data[0]=='O') { // OKAY sk_write(adb->s,"0006shell:",10); adb->state=2; // wait for shell start response } else { if (data[0]=='F') { char* d = (char*)smalloc(len+1); memcpy(d,data,len); d[len]='\0'; connection_fatal(adb->frontend, "%s", d+8); sfree(d); } else { connection_fatal(adb->frontend, "Bad response"); } return 0; } } else if (adb->state==2) { if (data[0]=='O') { //OKAY adb->state=3; // shell started, switch to terminal mode } else { if (data[0]=='F') { char* d = (char*)smalloc(len+1); memcpy(d,data,len); d[len]='\0'; connection_fatal(adb->frontend, "%s", d+8); sfree(d); } else { connection_fatal(adb->frontend, "Bad response"); } return 0; } } else { c_write((Raw)adb, data, len); } return 1; }
int registration() { USER usr; int id; c_lseek(user_list_fd,-USR_LEN,SEEK_END); c_read(user_list_fd,&usr,USR_LEN); id=usr.userid; const char *name; const char *password; memset(&usr,0,USR_LEN); name=&(user_temp_p.name); password=&(user_temp_p.password); strncpy(usr.name,name,10); strncpy(usr.password,password,15); usr.status=0; usr.userid= id+1; c_lseek(user_list_fd,0,SEEK_END); c_write(user_list_fd,&usr,USR_LEN); //返回一则成功信息。 //c_send(sockfd,....) }
static void bsb(Ldisc ldisc, int n) { while (n--) c_write(ldisc, "\010 \010", 3); }
static void bsb(int n) { while (n--) c_write("\010 \010", 3); }
static void ssh_protocol(unsigned char *in, int inlen, int ispkt) { int i, j, len; unsigned char session_id[16]; unsigned char *rsabuf, *keystr1, *keystr2; unsigned char cookie[8]; struct RSAKey servkey, hostkey; struct MD5Context md5c; unsigned long supported_ciphers_mask; int cipher_type; extern struct ssh_cipher ssh_3des; extern struct ssh_cipher ssh_blowfish; crBegin; random_init(); while (!ispkt) crReturnV; if (pktin.type != 2) fatalbox("Public key packet not received"); memcpy(cookie, pktin.body, 8); MD5Init(&md5c); i = makekey(pktin.body+8, &servkey, &keystr1); j = makekey(pktin.body+8+i, &hostkey, &keystr2); supported_ciphers_mask = (pktin.body[12+i+j] << 24) | (pktin.body[13+i+j] << 16) | (pktin.body[14+i+j] << 8) | (pktin.body[15+i+j]); MD5Update(&md5c, keystr2, hostkey.bytes); MD5Update(&md5c, keystr1, servkey.bytes); MD5Update(&md5c, pktin.body, 8); MD5Final(session_id, &md5c); for (i=0; i<32; i++) session_key[i] = random_byte(); len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes); rsabuf = malloc(len); if (!rsabuf) fatalbox("Out of memory"); verify_ssh_host_key(savedhost, &hostkey); for (i=0; i<32; i++) { rsabuf[i] = session_key[i]; if (i < 16) rsabuf[i] ^= session_id[i]; } if (hostkey.bytes > servkey.bytes) { rsaencrypt(rsabuf, 32, &servkey); rsaencrypt(rsabuf, servkey.bytes, &hostkey); } else { rsaencrypt(rsabuf, 32, &hostkey); rsaencrypt(rsabuf, hostkey.bytes, &servkey); } cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH : SSH_CIPHER_3DES; if ((supported_ciphers_mask & (1 << cipher_type)) == 0) { c_write("Selected cipher not supported, falling back to 3DES\r\n", 53); cipher_type = SSH_CIPHER_3DES; } s_wrpkt_start(3, len+15); pktout.body[0] = cipher_type; memcpy(pktout.body+1, cookie, 8); pktout.body[9] = (len*8) >> 8; pktout.body[10] = (len*8) & 0xFF; memcpy(pktout.body+11, rsabuf, len); pktout.body[len+11] = pktout.body[len+12] = 0; /* protocol flags */ pktout.body[len+13] = pktout.body[len+14] = 0; s_wrpkt(); free(rsabuf); cipher = cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish : &ssh_3des; cipher->sesskey(session_key); do { crReturnV; } while (!ispkt); if (pktin.type != 14) fatalbox("Encryption not successfully enabled"); fflush(stdout); { static char username[100]; static int pos = 0; static char c; if (!*cfg.username) { c_write("login as: ", 10); while (pos >= 0) { do { crReturnV; } while (ispkt); while (inlen--) switch (c = *in++) { case 10: case 13: username[pos] = 0; pos = -1; break; case 8: case 127: if (pos > 0) { c_write("\b \b", 3); pos--; } break; case 21: case 27: while (pos > 0) { c_write("\b \b", 3); pos--; } break; case 3: case 4: random_save_seed(); exit(0); break; default: if (c >= ' ' && c <= '~' && pos < 40) { username[pos++] = c; c_write(&c, 1); } break; } } c_write("\r\n", 2); username[strcspn(username, "\n\r")] = '\0'; } else { char stuff[200]; strncpy(username, cfg.username, 99); username[99] = '\0'; sprintf(stuff, "Sent username \"%s\".\r\n", username); c_write(stuff, strlen(stuff)); } s_wrpkt_start(4, 4+strlen(username)); pktout.body[0] = pktout.body[1] = pktout.body[2] = 0; pktout.body[3] = strlen(username); memcpy(pktout.body+4, username, strlen(username)); s_wrpkt(); } do { crReturnV; } while (!ispkt); while (pktin.type == 15) { static char password[100]; static int pos; static char c; c_write("password: "******"\r\n", 2); s_wrpkt_start(9, 4+strlen(password)); pktout.body[0] = pktout.body[1] = pktout.body[2] = 0; pktout.body[3] = strlen(password); memcpy(pktout.body+4, password, strlen(password)); s_wrpkt(); memset(password, 0, strlen(password)); do { crReturnV; } while (!ispkt); if (pktin.type == 15) { c_write("Access denied\r\n", 15); } else if (pktin.type != 14) { fatalbox("Strange packet received, type %d", pktin.type); } } if (!cfg.nopty) { i = strlen(cfg.termtype); s_wrpkt_start(10, i+5*4+1); pktout.body[0] = (i >> 24) & 0xFF; pktout.body[1] = (i >> 16) & 0xFF; pktout.body[2] = (i >> 8) & 0xFF; pktout.body[3] = i & 0xFF; memcpy(pktout.body+4, cfg.termtype, i); i += 4; pktout.body[i++] = (rows >> 24) & 0xFF; pktout.body[i++] = (rows >> 16) & 0xFF; pktout.body[i++] = (rows >> 8) & 0xFF; pktout.body[i++] = rows & 0xFF; pktout.body[i++] = (cols >> 24) & 0xFF; pktout.body[i++] = (cols >> 16) & 0xFF; pktout.body[i++] = (cols >> 8) & 0xFF; pktout.body[i++] = cols & 0xFF; memset(pktout.body+i, 0, 9); /* 0 pixwidth, 0 pixheight, 0.b endofopt */ s_wrpkt(); ssh_state = SSH_STATE_INTERMED; do { crReturnV; } while (!ispkt); if (pktin.type != 14 && pktin.type != 15) { fatalbox("Protocol confusion"); } else if (pktin.type == 15) { c_write("Server refused to allocate pty\r\n", 32); } }
static int raw_receive(Plug plug, int urgent, char *data, int len) { c_write(data, len); return 1; }
pass2() { int saved[12] ; int i ; char line[LINELEN] ; char *tail, *arg, *temp, *temp2, *temp3 ; /* start pass 3 */ switch_down(1) ; saved[0] = saved[1] = saved[2] = saved[3] = 0 ; saved[4] = saved[5] = saved[6] = saved[7] = saved[8] = 0 ; saved[9] = saved[10] = saved[11] = 0 ; ln1 = alloc(LINELEN) ; ln2 = alloc(LINELEN) ; ln3 = alloc(LINELEN) ; ln4 = alloc(LINELEN) ; ln5 = alloc(LINELEN) ; ln6 = alloc(LINELEN) ; p_read(ln1) ; p_read(ln2) ; p_read(ln3) ; p_read(ln4) ; p_read(ln5) ; while ( p_read(ln6) ) { /* inc or dec top or second on stack */ if ( strcmp(Ldhl0,ln1) == 0 || strcmp(Ldhl2,ln1) == 0 || strcmp(Ldhl4,ln1) == 0 || strcmp(Ldhl6,ln1) == 0 ) { if ( strcmp("\tADD HL,SP",ln2) == 0 && strcmp(Pushhl,ln3) == 0 && strcmp("\tCALL ccgint",ln4) == 0 && (strcmp(Inchl,ln5) == 0 || strcmp(Dechl,ln5) == 0) && strcmp("\tCALL ccpint",ln6) == 0 ) { if ( strcmp(Ldhl6,ln1) == 0 ) { c_write(Popix); c_write(Popde); c_write(Popbc); } else if ( strcmp(Ldhl4,ln1) == 0 ) { c_write(Popde); c_write(Popbc); } else if ( strcmp(Ldhl2,ln1) == 0 ) { c_write(Popbc); } c_write(Pophl); c_write(ln5); if ( strcmp(Ldhl6,ln1) == 0 ) { c_write(Pushhl); c_write(Pushbc); c_write(Pushde); strcpy(ln1,Pushix); ++saved[3]; } else if ( strcmp(Ldhl4,ln1) == 0 ) { c_write(Pushhl); c_write(Pushbc); strcpy(ln1,Pushde); ++saved[2]; } else if ( strcmp(Ldhl2,ln1) == 0 ) { c_write(Pushhl); strcpy(ln1,Pushbc); ++saved[1]; } else { strcpy(ln1,Pushhl); ++saved[0] ; } p_read(ln2); p_read(ln3); p_read(ln4); p_read(ln5); p_read(ln6); } } /* check for comparison against small constant and jump */ if ( strcmp(Exdehl, ln1) == 0 && (arg=match(Ldhl, ln2)) && (strcmp("\tCALL cceq",ln3) == 0 || strcmp("\tCALL ccne",ln3) == 0) ) if ( strcmp("\tLD A,H", ln4) == 0 && strcmp("\tOR L", ln5) == 0 && ((tail=match("\tJP NZ,",ln6)) || (tail=match("\tJP Z,",ln6)))) { if ( (i=chk_arg(arg)) != 0 ) { if ( strcmp("\tCALL cceq",ln3) == 0 ) { if ( match("\tJP NZ,",ln6 ) ) { strcpy(line, "\tJP Z,") ; } else { strcpy(line, "\tJP NZ,") ; } strcat(line, tail) ; strcpy(ln6, line) ; } temp = ln1 ; temp2 = ln2 ; temp3 = ln3 ; ln1 = ln4 ; ln2 = ln5 ; ln3 = ln6 ; ln4 = temp ; ln5 = temp2 ; ln6 = temp3 ; p_read(ln4) ; p_read(ln5) ; p_read(ln6) ; ++saved[3+i] ; } } /* lh hl,0 after test has ensured hl is zero */ if ( strcmp("\tLD A,H", ln1) == 0 ) { if ( strcmp("\tOR L", ln2) == 0 ) { if ( match("\tJP NZ,", ln3) ) { if ( strcmp(Ldhl0, ln4) == 0 ) { temp = ln4 ; ln4 = ln5 ; ln5 = ln6 ; ln6 = temp ; p_read(ln6) ; ++saved[9] ; } } } } /* return TOS, one item on stack */ if ( strcmp(Pophl, ln3) == 0 ) { if ( strcmp(Pushhl, ln4) == 0 ) { if ( strcmp(Popbc, ln5) == 0 ) { if ( strcmp(Ret, ln6) == 0 ) { strcpy(ln4, Ret) ; p_read(ln5) ; p_read(ln6) ; ++saved[10] ; } } } } /* return TOS, two items on stack */ if ( strcmp(Pophl, ln2) == 0 ) { if ( strcmp(Pushhl, ln3) == 0 ) { if ( strcmp(Popbc, ln4) == 0 ) { if ( strcmp(Popbc, ln5) == 0 ) { if ( strcmp(Ret, ln6) == 0 ) { strcpy(ln3, Popbc) ; strcpy(ln4, Ret) ; p_read(ln5) ; p_read(ln6) ; ++saved[11] ; } } } } } c_write(ln1); temp = ln1; ln1 = ln2; ln2 = ln3; ln3 = ln4; ln4 = ln5; ln5 = ln6; ln6 = temp; if (cpm(CONIN, 255) == CTRLC) exit() ; } c_write(ln1); c_write(ln2); c_write(ln3); c_write(ln4); c_write(ln5); puts("INC or DEC top of stack "); putdec(saved[0]) ; putchar('\n') ; puts("INC or DEC 2nd top of stack "); putdec(saved[1]) ; putchar('\n') ; puts("INC or DEC 3rd top of stack "); putdec(saved[2]) ; putchar('\n') ; puts("INC or DEC 4th top of stack "); putdec(saved[3]) ; putchar('\n') ; puts("Test for == or != zero "); putdec(saved[4]) ; putchar('\n') ; puts("Test for == or != +/-1 "); putdec(saved[5]) ; putchar('\n') ; puts("Test for == or != +/-2 "); putdec(saved[6]) ; putchar('\n') ; puts("Test for == or != +/-3 "); putdec(saved[7]) ; putchar('\n') ; puts("Test for == or != constant "); putdec(saved[8]) ; putchar('\n') ; puts("LD HL,0 when HL is zero "); putdec(saved[9]) ; putchar('\n') ; puts("Return TOS, one item on stack "); putdec(saved[10]) ; putchar('\n') ; puts("Return TOS, two on stack "); putdec(saved[11]) ; putchar('\n') ; putchar('\n') ; i = saved[0]*9 + saved[1]*7 + saved[2]*5 + saved[3] ; i += saved[4]*7 + saved[5]*6 + saved[6]*5 + saved[7]*4 ; i += saved[8]*3 + saved[9]*3 + saved[10]*2 + saved[11]*2 ; pr_total(i); Total += i ; }
static int raw_receive(Plug plug, int urgent, char *data, int len) { Raw raw = (Raw) plug; c_write(raw, data, len); return 1; }
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 * ^c: Do a ^u then send a telnet IP * ^z: Do a ^u then send a telnet SUSP * ^\: Do a ^u then send a telnet ABORT * ^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: send line-plus-\r\n and reset to BOL */ case CTRL('H'): case CTRL('?'): /* backspace/delete */ if (term_buflen > 0) { bsb(plen(term_buf[term_buflen-1])); term_buflen--; } break; case CTRL('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 CTRL('U'): /* delete line */ case CTRL('C'): /* Send IP */ case CTRL('\\'): /* Quit */ case CTRL('Z'): /* Suspend */ while (term_buflen > 0) { bsb(plen(term_buf[term_buflen-1])); term_buflen--; } back->special (TS_EL); if( c == CTRL('C') ) back->special (TS_IP); if( c == CTRL('Z') ) back->special (TS_SUSP); if( c == CTRL('\\') ) back->special (TS_ABORT); break; case CTRL('R'): /* redraw line */ c_write("^R\r\n", 4); { int i; for (i = 0; i < term_buflen; i++) pwrite(term_buf[i]); } break; case CTRL('V'): /* quote next char */ term_quotenext = TRUE; break; case CTRL('D'): /* logout or send */ if (term_buflen == 0) { back->special (TS_EOF); } else { back->send(term_buf, term_buflen); term_buflen = 0; } break; case CTRL('M'): /* send with newline */ if (term_buflen > 0) back->send(term_buf, term_buflen); if (cfg.protocol == PROT_RAW) back->send("\r\n", 2); else back->send("\r", 1); 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; } } }
static void do_telnet_read (char *buf, int len) { static enum { TOPLEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT, SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR } state = TOPLEVEL; char b[10]; while (len--) { int c = (unsigned char) *buf++; switch (state) { case TOPLEVEL: case SEENCR: if (c == 0 && state == SEENCR) state = TOPLEVEL; else if (c == IAC) state = SEENIAC; else { b[0] = c; if (!in_synch) c_write (b, 1); if (c == 13) state = SEENCR; else state = TOPLEVEL; } break; case SEENIAC: if (c == DO) state = SEENDO; else if (c == DONT) state = SEENDONT; else if (c == WILL) state = SEENWILL; else if (c == WONT) state = SEENWONT; else if (c == SB) state = SEENSB; else state = TOPLEVEL; /* we really ignore _everything_ else! */ break; case SEENWILL: proc_rec_opt (WILL, c); state = TOPLEVEL; break; case SEENWONT: proc_rec_opt (WONT, c); state = TOPLEVEL; break; case SEENDO: proc_rec_opt (DO, c); state = TOPLEVEL; break; case SEENDONT: proc_rec_opt (DONT, c); state = TOPLEVEL; break; case SEENSB: sb_opt = c; sb_len = 0; state = SUBNEGOT; break; case SUBNEGOT: if (c == IAC) state = SUBNEG_IAC; else { subneg_addchar: if (sb_len >= sb_size) { char *newbuf; sb_size += SB_DELTA; newbuf = (sb_buf ? realloc(sb_buf, sb_size) : malloc(sb_size)); if (newbuf) sb_buf = newbuf; else sb_size -= SB_DELTA; } if (sb_len < sb_size) sb_buf[sb_len++] = c; state = SUBNEGOT; /* in case we came here by goto */ } break; case SUBNEG_IAC: if (c != SE) goto subneg_addchar; /* yes, it's a hack, I know, but... */ else { process_subneg(); state = TOPLEVEL; } break; } } }
void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, bool interactive) { const char *buf = (const char *)vbuf; int keyflag = 0; assert(ldisc->term); assert(len); if (interactive) { /* * Interrupt a paste from the clipboard, if one was in * progress when the user pressed a key. This is easier than * buffering the current piece of data and saving it until the * terminal has finished pasting, and has the potential side * benefit of permitting a user to cancel an accidental huge * paste. */ term_nopaste(ldisc->term); } /* * Less than zero means null terminated special string. */ if (len < 0) { len = strlen(buf); keyflag = KCTRL('@'); } /* * Either perform local editing, or just send characters. */ if (EDITING) { while (len--) { int c; c = (unsigned char)(*buf++) + keyflag; if (!interactive && c == '\r') c += KCTRL('@'); switch (ldisc->quotenext ? ' ' : c) { /* * ^h/^?: delete, and output BSBs, to return to * last character boundary (in UTF-8 mode this may * be more than one byte) * ^w: delete, and output BSBs, to return to last * space/nonspace boundary * ^u: delete, and output BSBs, to return to BOL * ^c: Do a ^u then send a telnet IP * ^z: Do a ^u then send a telnet SUSP * ^\: Do a ^u then send a telnet ABORT * ^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: send line-plus-\r\n and reset to BOL */ case KCTRL('H'): case KCTRL('?'): /* backspace/delete */ if (ldisc->buflen > 0) { do { if (ECHOING) bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); ldisc->buflen--; } while (!char_start(ldisc, ldisc->buf[ldisc->buflen])); } break; case CTRL('W'): /* delete word */ while (ldisc->buflen > 0) { if (ECHOING) bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); ldisc->buflen--; if (ldisc->buflen > 0 && isspace((unsigned char)ldisc->buf[ldisc->buflen-1]) && !isspace((unsigned char)ldisc->buf[ldisc->buflen])) break; } break; case CTRL('U'): /* delete line */ case CTRL('C'): /* Send IP */ case CTRL('\\'): /* Quit */ case CTRL('Z'): /* Suspend */ while (ldisc->buflen > 0) { if (ECHOING) bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); ldisc->buflen--; } backend_special(ldisc->backend, SS_EL, 0); /* * We don't send IP, SUSP or ABORT if the user has * configured telnet specials off! This breaks * talkers otherwise. */ if (!ldisc->telnet_keyboard) goto default_case; if (c == CTRL('C')) backend_special(ldisc->backend, SS_IP, 0); if (c == CTRL('Z')) backend_special(ldisc->backend, SS_SUSP, 0); if (c == CTRL('\\')) backend_special(ldisc->backend, SS_ABORT, 0); break; case CTRL('R'): /* redraw line */ if (ECHOING) { int i; c_write(ldisc, "^R\r\n", 4); for (i = 0; i < ldisc->buflen; i++) pwrite(ldisc, ldisc->buf[i]); } break; case CTRL('V'): /* quote next char */ ldisc->quotenext = true; break; case CTRL('D'): /* logout or send */ if (ldisc->buflen == 0) { backend_special(ldisc->backend, SS_EOF, 0); } else { backend_send(ldisc->backend, ldisc->buf, ldisc->buflen); ldisc->buflen = 0; } break; /* * This particularly hideous bit of code from RDB * allows ordinary ^M^J to do the same thing as * magic-^M when in Raw protocol. The line `case * KCTRL('M'):' is _inside_ the if block. Thus: * * - receiving regular ^M goes straight to the * default clause and inserts as a literal ^M. * - receiving regular ^J _not_ directly after a * literal ^M (or not in Raw protocol) fails the * if condition, leaps to the bottom of the if, * and falls through into the default clause * again. * - receiving regular ^J just after a literal ^M * in Raw protocol passes the if condition, * deletes the literal ^M, and falls through * into the magic-^M code * - receiving a magic-^M empties the line buffer, * signals end-of-line in one of the various * entertaining ways, and _doesn't_ fall out of * the bottom of the if and through to the * default clause because of the break. */ case CTRL('J'): if (ldisc->protocol == PROT_RAW && ldisc->buflen > 0 && ldisc->buf[ldisc->buflen - 1] == '\r') { if (ECHOING) bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); ldisc->buflen--; /* FALLTHROUGH */ case KCTRL('M'): /* send with newline */ if (ldisc->buflen > 0) backend_send(ldisc->backend, ldisc->buf, ldisc->buflen); if (ldisc->protocol == PROT_RAW) backend_send(ldisc->backend, "\r\n", 2); else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline) backend_special(ldisc->backend, SS_EOL, 0); else backend_send(ldisc->backend, "\r", 1); if (ECHOING) c_write(ldisc, "\r\n", 2); ldisc->buflen = 0; break; } /* FALLTHROUGH */ default: /* get to this label from ^V handler */ default_case: sgrowarray(ldisc->buf, ldisc->bufsiz, ldisc->buflen); ldisc->buf[ldisc->buflen++] = c; if (ECHOING) pwrite(ldisc, (unsigned char) c); ldisc->quotenext = false; break; } } } else { if (ldisc->buflen != 0) { backend_send(ldisc->backend, ldisc->buf, ldisc->buflen); while (ldisc->buflen > 0) { bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1])); ldisc->buflen--; } } if (len > 0) { if (ECHOING) c_write(ldisc, buf, len); if (keyflag && ldisc->protocol == PROT_TELNET && len == 1) { switch (buf[0]) { case CTRL('M'): if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline) backend_special(ldisc->backend, SS_EOL, 0); else backend_send(ldisc->backend, "\r", 1); break; case CTRL('?'): case CTRL('H'): if (ldisc->telnet_keyboard) { backend_special(ldisc->backend, SS_EC, 0); break; } case CTRL('C'): if (ldisc->telnet_keyboard) { backend_special(ldisc->backend, SS_IP, 0); break; } case CTRL('Z'): if (ldisc->telnet_keyboard) { backend_special(ldisc->backend, SS_SUSP, 0); break; } default: backend_send(ldisc->backend, buf, len); break; } } else backend_send(ldisc->backend, buf, len); } } }