void tty_setlinemode(int on) { set_termbuf(); (void) ioctl(pty, TIOCEXT, (char *)&on); init_termbuf(); }
void _termstat() { needtermstat = 0; init_termbuf(); localstat(); rcv_ioctl(); }
/* * clientstat * * Process linemode related requests from the client. * Client can request a change to only one of linemode, editmode or slc's * at a time, and if using kludge linemode, then only linemode may be * affected. */ void clientstat(int code, int parm1, int parm2) { /* * Get a copy of terminal characteristics. */ init_termbuf(); /* * Process request from client. code tells what it is. */ switch (code) { case TELOPT_NAWS: #ifdef TIOCSWINSZ { struct winsize ws; def_col = parm1; def_row = parm2; /* * Change window size as requested by client. */ ws.ws_col = parm1; ws.ws_row = parm2; ioctl(ourpty, TIOCSWINSZ, (char *)&ws); } #endif /* TIOCSWINSZ */ break; case TELOPT_TSPEED: { def_tspeed = parm1; def_rspeed = parm2; /* * Change terminal speed as requested by client. * We set the receive speed first, so that if we can't * store seperate receive and transmit speeds, the transmit * speed will take precedence. */ tty_rspeed(parm2); tty_tspeed(parm1); set_termbuf(); break; } /* end of case TELOPT_TSPEED */ default: /* What? */ break; } /* end of switch */ netflush(); }
/* * start_slc * * Get ready to process incoming slc's and respond to them. * * The parameter getit is non-zero if it is necessary to grab a copy * of the terminal control structures. */ void start_slc(int getit) { slcchange = 0; if (getit) init_termbuf(); snprintf(slcbuf, sizeof(slcbuf), "%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC); slcoff = 4; }
/* * get_slc_defaults * * Initialize the slc mapping table. */ void get_slc_defaults(void) { int i; init_termbuf(); for (i = 1; i <= NSLC; i++) { slctab[i].defset.flag = spcset(i, &slctab[i].defset.val, &slctab[i].sptr); slctab[i].current.flag = SLC_NOSUPPORT; slctab[i].current.val = 0; } }
/* * start_slc * * Get ready to process incoming slc's and respond to them. * * The parameter getit is non-zero if it is necessary to grab a copy * of the terminal control structures. */ void start_slc (register int getit) { slcchange = 0; if (getit) init_termbuf (); sprintf ((char *) slcbuf, "%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC); slcptr = slcbuf + 4; } /* end of start_slc */
void tty_setlinemode(int on) { #ifdef TIOCEXT set_termbuf(); ioctl(pty, TIOCEXT, (char *)&on); init_termbuf(); #else /* !TIOCEXT */ # ifdef EXTPROC if (on) termbuf.c_lflag |= EXTPROC; else termbuf.c_lflag &= ~EXTPROC; # endif #endif /* TIOCEXT */ }
void telrcv() { register int c; static int state = TS_DATA; #if defined(CRAY2) && defined(UNICOS5) char *opfrontp = pfrontp; #endif while (ncc > 0) { if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) break; c = *netip++ & 0377, ncc--; switch (state) { case TS_CR: state = TS_DATA; /* Strip off \n or \0 after a \r */ if ((c == 0) || (c == '\n')) { break; } /* FALL THROUGH */ case TS_DATA: if (c == IAC) { state = TS_IAC; break; } /* * We now map \r\n ==> \r for pragmatic reasons. * Many client implementations send \r\n when * the user hits the CarriageReturn key. * * We USED to map \r\n ==> \n, since \r\n says * that we want to be in column 1 of the next * printable line, and \n is the standard * unix way of saying that (\r is only good * if CRMOD is set, which it normally is). */ if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { int nc = *netip; #ifdef LINEMODE /* * If we are operating in linemode, * convert to local end-of-line. */ if (linemode && (ncc > 0) && (('\n' == nc) || ((0 == nc) && tty_iscrnl())) ) { netip++; ncc--; c = '\n'; } else #endif { state = TS_CR; } } *pfrontp++ = c; break; case TS_IAC: gotiac: switch (c) { /* * Send the process on the pty side an * interrupt. Do this with a NULL or * interrupt char; depending on the tty mode. */ case IP: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); interrupt(); break; case BREAK: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); sendbrk(); break; /* * Are You There? */ case AYT: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); recv_ayt(); break; /* * Abort Output */ case AO: { DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (slctab[SLC_AO].sptr && *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { *pfrontp++ = (unsigned char)*slctab[SLC_AO].sptr; } netclear(); /* clear buffer back */ *nfrontp++ = IAC; *nfrontp++ = DM; neturg = nfrontp-1; /* off by one XXX */ DIAG(TD_OPTIONS, printoption("td: send IAC", DM)); break; } /* * Erase Character and * Erase Line */ case EC: case EL: { cc_t ch; DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); ptyflush(); /* half-hearted */ init_termbuf(); if (c == EC) ch = *slctab[SLC_EC].sptr; else ch = *slctab[SLC_EL].sptr; if (ch != (cc_t)(_POSIX_VDISABLE)) *pfrontp++ = (unsigned char)ch; break; } /* * Check for urgent data... */ case DM: DIAG(TD_OPTIONS, printoption("td: recv IAC", c)); SYNCHing = stilloob(net); settimer(gotDM); break; /* * Begin option subnegotiation... */ case SB: state = TS_SB; SB_CLEAR(); continue; case WILL: state = TS_WILL; continue; case WONT: state = TS_WONT; continue; case DO: state = TS_DO; continue; case DONT: state = TS_DONT; continue; case EOR: if (his_state_is_will(TELOPT_EOR)) doeof(); break; /* * Handle RFC 10xx Telnet linemode option additions * to command stream (EOF, SUSP, ABORT). */ case xEOF: doeof(); break; case SUSP: sendsusp(); break; case ABORT: sendbrk(); break; case IAC: *pfrontp++ = c; break; } state = TS_DATA; break; case TS_SB: if (c == IAC) { state = TS_SE; } else { SB_ACCUM(c); } break; case TS_SE: if (c != SE) { if (c != IAC) { /* * bad form of suboption negotiation. * handle it in such a way as to avoid * damage to local state. Parse * suboption buffer found so far, * then treat remaining stream as * another command sequence. */ /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(c); subpointer -= 2; SB_TERM(); suboption(); state = TS_IAC; goto gotiac; } SB_ACCUM(c); state = TS_SB; } else { /* for DIAGNOSTICS */ SB_ACCUM(IAC); SB_ACCUM(SE); subpointer -= 2; SB_TERM(); suboption(); /* handle sub-option */ state = TS_DATA; } break; case TS_WILL: willoption(c); state = TS_DATA; continue; case TS_WONT: wontoption(c); state = TS_DATA; continue; case TS_DO: dooption(c); state = TS_DATA; continue; case TS_DONT: dontoption(c); state = TS_DATA; continue; default: syslog(LOG_ERR, "telnetd: panic state=%d\n", state); printf("telnetd: panic state=%d\n", state); exit(1); } } #if defined(CRAY2) && defined(UNICOS5) if (!linemode) { char xptyobuf[BUFSIZ+NETSLOP]; char xbuf2[BUFSIZ]; register char *cp; int n = pfrontp - opfrontp, oc; memmove(xptyobuf, opfrontp, n); pfrontp = opfrontp; pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP, xbuf2, &oc, BUFSIZ); for (cp = xbuf2; oc > 0; --oc) if ((*nfrontp++ = *cp++) == IAC) *nfrontp++ = IAC; } #endif /* defined(CRAY2) && defined(UNICOS5) */ } /* end of telrcv */
/* * clientstat * * Process linemode related requests from the client. * Client can request a change to only one of linemode, editmode or slc's * at a time, and if using kludge linemode, then only linemode may be * affected. */ void clientstat(int code, int parm1, int parm2) { /* * Get a copy of terminal characteristics. */ init_termbuf(); /* * Process request from client. code tells what it is. */ switch (code) { #ifdef LINEMODE case TELOPT_LINEMODE: /* * Don't do anything unless client is asking us to change * modes. */ uselinemode = (parm1 == WILL); if (uselinemode != linemode) { # ifdef KLUDGELINEMODE /* * If using kludge linemode, make sure that * we can do what the client asks. * We can not turn off linemode if alwayslinemode * and the ICANON bit is set. */ if (lmodetype == KLUDGE_LINEMODE) { if (alwayslinemode && tty_isediting()) { uselinemode = 1; } } /* * Quit now if we can't do it. */ if (uselinemode == linemode) return; /* * If using real linemode and linemode is being * turned on, send along the edit mode mask. */ if (lmodetype == REAL_LINEMODE && uselinemode) # else /* KLUDGELINEMODE */ if (uselinemode) # endif /* KLUDGELINEMODE */ { useeditmode = 0; if (tty_isediting()) useeditmode |= MODE_EDIT; if (tty_istrapsig()) useeditmode |= MODE_TRAPSIG; if (tty_issofttab()) useeditmode |= MODE_SOFT_TAB; if (tty_islitecho()) useeditmode |= MODE_LIT_ECHO; output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode, IAC, SE); editmode = useeditmode; } tty_setlinemode(uselinemode); linemode = uselinemode; if (!linemode) send_will(TELOPT_ECHO, 1); } break; case LM_MODE: { int ack, changed; /* * Client has sent along a mode mask. If it agrees with * what we are currently doing, ignore it; if not, it could * be viewed as a request to change. Note that the server * will change to the modes in an ack if it is different from * what we currently have, but we will not ack the ack. */ useeditmode &= MODE_MASK; ack = (useeditmode & MODE_ACK); useeditmode &= ~MODE_ACK; if ((changed = (useeditmode ^ editmode))) { /* * This check is for a timing problem. If the * state of the tty has changed (due to the user * application) we need to process that info * before we write in the state contained in the * ack!!! This gets out the new MODE request, * and when the ack to that command comes back * we'll set it and be in the right mode. */ if (ack) localstat(); if (changed & MODE_EDIT) tty_setedit(useeditmode & MODE_EDIT); if (changed & MODE_TRAPSIG) tty_setsig(useeditmode & MODE_TRAPSIG); if (changed & MODE_SOFT_TAB) tty_setsofttab(useeditmode & MODE_SOFT_TAB); if (changed & MODE_LIT_ECHO) tty_setlitecho(useeditmode & MODE_LIT_ECHO); set_termbuf(); if (!ack) { output_data("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE, useeditmode|MODE_ACK, IAC, SE); } editmode = useeditmode; } break; } /* end of case LM_MODE */ #endif /* LINEMODE */ case TELOPT_NAWS: #ifdef TIOCSWINSZ { struct winsize ws; def_col = parm1; def_row = parm2; #ifdef LINEMODE /* * Defer changing window size until after terminal is * initialized. */ if (terminit() == 0) return; #endif /* LINEMODE */ /* * Change window size as requested by client. */ ws.ws_col = parm1; ws.ws_row = parm2; (void) ioctl(spty, TIOCSWINSZ, (char *)&ws); } #endif /* TIOCSWINSZ */ break; case TELOPT_TSPEED: { def_tspeed = parm1; def_rspeed = parm2; #ifdef LINEMODE /* * Defer changing the terminal speed. */ if (terminit() == 0) return; #endif /* LINEMODE */ /* * Change terminal speed as requested by client. * We set the receive speed first, so that if we can't * store separate receive and transmit speeds, the transmit * speed will take precedence. */ tty_rspeed(parm2); tty_tspeed(parm1); set_termbuf(); break; } /* end of case TELOPT_TSPEED */ default: /* What? */ break; } /* end of switch */ netflush(); } /* end of clientstat */
void dooption(int option) { int changeok = 0; /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv do", option)); if (will_wont_resp[option]) { will_wont_resp[option]--; if (will_wont_resp[option] && my_state_is_will(option)) will_wont_resp[option]--; } if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { switch (option) { case TELOPT_ECHO: #ifdef LINEMODE #ifdef KLUDGELINEMODE if (lmodetype == NO_LINEMODE) #else if (his_state_is_wont(TELOPT_LINEMODE)) #endif #endif { init_termbuf(); tty_setecho(1); set_termbuf(); } changeok++; break; case TELOPT_BINARY: init_termbuf(); tty_binaryout(1); set_termbuf(); changeok++; break; case TELOPT_SGA: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * If kludge linemode is in use, then we must * process an incoming do SGA for linemode * purposes. */ if (lmodetype == KLUDGE_LINEMODE) { /* * Receipt of "do SGA" in kludge * linemode is the peer asking us to * turn off linemode. Make note of * the request. */ clientstat(TELOPT_LINEMODE, WONT, 0); /* * If linemode did not get turned off * then don't tell peer that we did. * Breaking here forces a wont SGA to * be returned. */ if (linemode) break; } #else turn_on_sga = 0; #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ changeok++; break; case TELOPT_STATUS: changeok++; break; case TELOPT_TM: /* * Special case for TM. We send a WILL, but * pretend we sent a WONT. */ send_will(option, 0); set_my_want_state_wont(option); set_my_state_wont(option); return; case TELOPT_LOGOUT: /* * When we get a LOGOUT option, respond * with a WILL LOGOUT, make sure that * it gets written out to the network, * and then just go away... */ set_my_want_state_will(TELOPT_LOGOUT); send_will(TELOPT_LOGOUT, 0); set_my_state_will(TELOPT_LOGOUT); (void)netflush(); cleanup(0); /* NOT REACHED */ break; #if defined(ENCRYPT) case TELOPT_ENCRYPT: changeok++; break; #endif case TELOPT_LINEMODE: case TELOPT_TTYPE: case TELOPT_NAWS: case TELOPT_TSPEED: case TELOPT_LFLOW: case TELOPT_XDISPLOC: case TELOPT_ENVIRON: default: break; } if (changeok) { set_my_want_state_will(option); send_will(option, 0); } else { will_wont_resp[option]++; send_wont(option, 0); } } set_my_state_will(option); }
void dontoption(int option) { /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv dont", option)); if (will_wont_resp[option]) { will_wont_resp[option]--; if (will_wont_resp[option] && my_state_is_wont(option)) will_wont_resp[option]--; } if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { switch (option) { case TELOPT_BINARY: init_termbuf(); tty_binaryout(0); set_termbuf(); break; case TELOPT_ECHO: /* we should stop echoing */ #ifdef LINEMODE #ifdef KLUDGELINEMODE if (lmodetype == NO_LINEMODE) #else if (his_state_is_wont(TELOPT_LINEMODE)) #endif #endif { init_termbuf(); tty_setecho(0); set_termbuf(); } break; case TELOPT_SGA: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * If kludge linemode is in use, then we * must process an incoming do SGA for * linemode purposes. */ if (lmodetype == KLUDGE_LINEMODE) { /* * The client is asking us to turn * linemode on. */ clientstat(TELOPT_LINEMODE, WILL, 0); /* * If we did not turn line mode on, * then what do we say? Will SGA? * This violates design of telnet. * Gross. Very Gross. */ } break; #else set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); set_my_state_wont(option); if (turn_on_sga ^= 1) send_will(option,1); return; #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ default: break; } set_my_want_state_wont(option); if (my_state_is_will(option)) send_wont(option, 0); } set_my_state_wont(option); }
void willoption(int option) { int changeok = 0; void (*func)(void) = 0; /* * process input from peer. */ DIAG(TD_OPTIONS, printoption("td: recv will", option)); if (do_dont_resp[option]) { do_dont_resp[option]--; if (do_dont_resp[option] && his_state_is_will(option)) do_dont_resp[option]--; } if (do_dont_resp[option] == 0) { if (his_want_state_is_wont(option)) { switch (option) { case TELOPT_BINARY: init_termbuf(); tty_binaryin(1); set_termbuf(); changeok++; break; case TELOPT_ECHO: /* * See comments below for more info. */ not42 = 0; /* looks like a 4.2 system */ break; case TELOPT_TM: #if defined(LINEMODE) && defined(KLUDGELINEMODE) /* * This telnetd implementation does not really * support timing marks, it just uses them to * support the kludge linemode stuff. If we * receive a will or wont TM in response to our * do TM request that may have been sent to * determine kludge linemode support, process * it, otherwise TM should get a negative * response back. */ /* * Handle the linemode kludge stuff. * If we are not currently supporting any * linemode at all, then we assume that this * is the client telling us to use kludge * linemode in response to our query. Set the * linemode type that is to be supported, note * that the client wishes to use linemode, and * eat the will TM as though it never arrived. */ if (lmodetype < KLUDGE_LINEMODE) { lmodetype = KLUDGE_LINEMODE; clientstat(TELOPT_LINEMODE, WILL, 0); send_wont(TELOPT_SGA, 1); } #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ /* * We never respond to a WILL TM, and * we leave the state WONT. */ return; case TELOPT_LFLOW: /* * If we are going to support flow control * option, then don't worry peer that we can't * change the flow control characters. */ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XON].defset.flag |= SLC_DEFAULT; slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; case TELOPT_TTYPE: case TELOPT_SGA: case TELOPT_NAWS: case TELOPT_TSPEED: case TELOPT_XDISPLOC: case TELOPT_ENVIRON: changeok++; break; #ifdef LINEMODE case TELOPT_LINEMODE: #ifdef KLUDGELINEMODE /* * Note client's desire to use linemode. */ lmodetype = REAL_LINEMODE; #endif /* KLUDGELINEMODE */ func = doclientstat; changeok++; break; #endif /* LINEMODE */ #ifdef AUTHENTICATE case TELOPT_AUTHENTICATION: func = auth_request; changeok++; break; #endif #ifdef ENCRYPT case TELOPT_ENCRYPT: func = encrypt_send_support; changeok++; break; #endif default: break; } if (changeok) { set_his_want_state_will(option); send_do(option, 0); } else { do_dont_resp[option]++; send_dont(option, 0); } } else { /* * Option processing that should happen when * we receive conformation of a change in * state that we had requested. */ switch (option) { case TELOPT_ECHO: not42 = 0; /* looks like a 4.2 system */ /* * Egads, he responded "WILL ECHO". Turn * it off right now! */ send_dont(option, 1); /* * "WILL ECHO". Kludge upon kludge! * A 4.2 client is now echoing user input at * the tty. This is probably undesireable and * it should be stopped. The client will * respond WONT TM to the DO TM that we send to * check for kludge linemode. When the WONT TM * arrives, linemode will be turned off and a * change propogated to the pty. This change * will cause us to process the new pty state * in localstat(), which will notice that * linemode is off and send a WILL ECHO * so that we are properly in character mode and * all is well. */ break; #ifdef LINEMODE case TELOPT_LINEMODE: # ifdef KLUDGELINEMODE /* * Note client's desire to use linemode. */ lmodetype = REAL_LINEMODE; # endif /* KLUDGELINEMODE */ func = doclientstat; break; #endif /* LINEMODE */ #ifdef AUTHENTICATE case TELOPT_AUTHENTICATION: func = auth_request; break; #endif #ifdef ENCRYPT case TELOPT_ENCRYPT: func = encrypt_send_support; break; #endif } } } set_his_state_will(option); if (func) (*func)(); }
void wontoption(int option) { /* * Process client input. */ DIAG(TD_OPTIONS, printoption("td: recv wont", option)); if (do_dont_resp[option]) { do_dont_resp[option]--; if (do_dont_resp[option] && his_state_is_wont(option)) do_dont_resp[option]--; } if (do_dont_resp[option] == 0) { if (his_want_state_is_will(option)) { /* it is always ok to change to negative state */ switch (option) { case TELOPT_ECHO: not42 = 1; /* doesn't seem to be a 4.2 system */ break; case TELOPT_BINARY: init_termbuf(); tty_binaryin(0); set_termbuf(); break; #ifdef LINEMODE case TELOPT_LINEMODE: #ifdef KLUDGELINEMODE /* * If real linemode is supported, then client is * asking to turn linemode off. */ if (lmodetype != REAL_LINEMODE) break; lmodetype = KLUDGE_LINEMODE; # endif /* KLUDGELINEMODE */ clientstat(TELOPT_LINEMODE, WONT, 0); break; #endif /* LINEMODE */ case TELOPT_TM: /* * If we get a WONT TM, and had sent a DO TM, * don't respond with a DONT TM, just leave it * as is. Short circut the state machine to * achive this. */ set_his_want_state_wont(TELOPT_TM); return; case TELOPT_LFLOW: /* * If we are not going to support flow control * option, then let peer know that we can't * change the flow control characters. */ slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; break; #if defined(AUTHENTICATE) case TELOPT_AUTHENTICATION: auth_finished(0, AUTH_REJECT); break; #endif /* * For options that we might spin waiting for * sub-negotiation, if the client turns off the * option rather than responding to the request, * we have to treat it here as if we got a response * to the sub-negotiation, (by updating the timers) * so that we'll break out of the loop. */ case TELOPT_TTYPE: settimer(ttypesubopt); break; case TELOPT_TSPEED: settimer(tspeedsubopt); break; case TELOPT_XDISPLOC: settimer(xdisplocsubopt); break; case TELOPT_ENVIRON: settimer(environsubopt); break; default: break; } set_his_want_state_wont(option); if (his_state_is_will(option)) send_dont(option, 0); } else { switch (option) { case TELOPT_TM: #if defined(LINEMODE) && defined(KLUDGELINEMODE) if (lmodetype < REAL_LINEMODE) { lmodetype = NO_LINEMODE; clientstat(TELOPT_LINEMODE, WONT, 0); send_will(TELOPT_SGA, 1); send_will(TELOPT_ECHO, 1); } #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ break; #if defined(AUTHENTICATE) case TELOPT_AUTHENTICATION: auth_finished(0, AUTH_REJECT); break; #endif default: break; } } } } /* end of wontoption */
/** * Main Program */ int main(int argc, char **argv) { TelnetDaemon daemon; std::string loginpath; std::string user; std::string login; std::string cdw = get_working_path(); int num = 0; for (int i = 0; ; i++) { if (cdw[i] == '\0') break; if (cdw[i] == '/') num = i; } if (num != 0) { for (int i = 0; i < num+1; i++) { PATH[i] = cdw[i]; } } else { strcpy(PATH,cdw.c_str()); } // If Config Exists Run if (configdataexists()) { parseconfig(); } // Unique filename to pass to BBS for // Reading in Detected Client Terminal. daemon.make_uuid(ENTHRAL_TEMP_PATH); // Lookup info for the passed socket descriptor daemon.get_host_info(); // Parameter for Login Program and User Login ID. int c = '\0'; for (;;) { c = getopt( argc, argv, "l:u:"); if (c == EOF) break; switch (c) { case 'u': user = strdup(optarg); break; case 'l': login = strdup(optarg); break; default: printf("%c\n", c); show_usage(); exit(1); } } if(login.size() > 0) { loginpath = login; login.erase(); } else { loginpath = "/bin/login"; } argv_init[0] = strdup(loginpath.c_str()); argv_init[1] = (char *)daemon.m_hostaddr_string.c_str(); argv_init[2] = (char *)daemon.m_hostname_string.c_str(); // Pass Login user for External Process if(user.size() > 0) { argv_init[3] = strdup("-f"); argv_init[4] = strdup(user.c_str()); } // Filename for passing the TERM to the external program. if(daemon.m_term_passing.size() > 0) { argv_init[5] = strdup(daemon.m_term_passing.c_str()); } // Startup Syslogd. openlog("telnet_daemon", LOG_PID, LOG_SYSLOG); syslog(LOG_INFO, "telnet_daemon in.telnetd PATH: %s", PATH); daemon.errlog((char *)"telnet_daemon in.telnetd PATH: %s", PATH); // Log Connection syslog(LOG_INFO, "telnet_daemon in.telnetd [%s] [Server Path]", loginpath.c_str()); daemon.errlog((char *)"telnet_daemon in.telnetd [%s] [Server Path]", (char *)loginpath.c_str()); syslog(LOG_INFO, "telnet_daemon in.telnetd [IP %s] [Host %s] [Connection Logged]", daemon.m_hostaddr_string.c_str(), daemon.m_hostname_string.c_str() ); daemon.errlog((char *)"telnet_daemon in.telnetd [IP %s] [Host %s] [Connection Logged]", (char *)daemon.m_hostaddr_string.c_str(), (char *)daemon.m_hostname_string.c_str() ); // Send Startup Telnet Sequences to connecting client. // Ready for Terminal / NAWS Detection and setting defaults. daemon.errlog((char *)"send_startup_iac"); daemon.send_startup_iac(); // Look intitial TELOPT codes with (2) second pause then (2) second detection loop // To Catch Terminal Type and NAWS. daemon.errlog((char *)"loop_detection"); daemon.loop_detection(); daemon.errlog((char *)"loop_detection completed."); // Display Detected Term, Rows, Cols. daemon.errlog((char *)"Term Type: %s", (char *)daemon.getTermType().c_str()); daemon.errlog((char *)"Term Cols: %i", daemon.getTermCols()); daemon.errlog((char *)"Term Rows: %i", daemon.getTermRows()); if (daemon.getTermType() == "undetected" || daemon.getTermType() == "VT220" || daemon.getTermType() == "") { daemon.errlog((char *)"No Term Detected, Disconnecting."); closelog(); exit(1); } // Terminal Type Detection completed, write out to file for extrnal program // So the Forked process can read it in. std::ofstream out; out.open(daemon.m_term_passing.c_str(),ios::trunc); if (out.is_open()) { out << daemon.getTermType() << endl; out.close(); } daemon.errlog((char *)"Starting BBS Server forkpty()"); // If the Connection is good, fork and start the BBS pid = forkpty(&ptyfd, NULL, NULL, NULL); daemon.errlog((char *)"ptyfd: %i", ptyfd); // Pid 0 Start Child Process. if (pid == 0) { setsid(); tcsetpgrp(0, getpid()); // exec shell, with correct argv and env execv(loginpath.c_str(), argv_init); syslog(LOG_INFO, "child process created for [IP %s] pid == 0", daemon.m_hostaddr_string.c_str()); daemon.errlog((char *)"child process created for [IP %s] pid == 0", (char*)daemon.m_hostaddr_string.c_str()); exit(1); } // Pid -1 is an error else if(pid == -1) { syslog(LOG_INFO, "fork() Error, exiting [IP %s] pid == -1", daemon.m_hostaddr_string.c_str()); daemon.errlog((char *)"fork() Error, exiting [IP %s] pid == -1", (char*)daemon.m_hostaddr_string.c_str()); closelog(); exit(1); } else if(pid > 0) { // Parent process. syslog(LOG_INFO, "parent process for [IP %s] pid > 0", daemon.m_hostaddr_string.c_str()); daemon.errlog((char *)"parent process for [IP %s] pid > 0", (char*)daemon.m_hostaddr_string.c_str()); } // Setup Detected Screen Size. struct winsize ws; // setup Term init_termbuf(); #ifdef TIOCSWINSZ if (daemon.getTermCols() || daemon.getTermRows()) { memset(&ws, 0, sizeof(ws)); ws.ws_col = daemon.getTermCols(); ws.ws_row = daemon.getTermRows(); ioctl(ptyfd, TIOCSWINSZ, (char *)&ws); } #endif // Start Main Parent Loop for communication with child (BBS) daemon.errlog((char *)"Starting Parent Loop"); daemon.loop_parent_process(ptyfd); daemon.errlog((char *)"Closing Parent Loop"); raise(SIGHUP); syslog(LOG_INFO, "in.telnetd [IP %s] [Closed Connection]", daemon.m_hostaddr_string.c_str()); daemon.errlog((char *)"in.telnetd [IP %s] [Closed Connection]", (char*)daemon.m_hostaddr_string.c_str()); closelog(); remove(daemon.m_term_passing.c_str()); _exit(0); }
static int getptyslave(void) { #if 0 register int t = -1; # ifdef LINEMODE int waslm; # endif # ifdef TIOCGWINSZ struct winsize ws; # endif /* * Opening the slave side may cause initilization of the * kernel tty structure. We need remember the state of * if linemode was turned on * terminal window size * terminal speed * so that we can re-set them if we need to. */ # ifdef LINEMODE waslm = tty_linemode(); # endif /* * Make sure that we don't have a controlling tty, and * that we are the session (process group) leader. */ t = open(_PATH_TTY, O_RDWR); if (t >= 0) { ioctl(t, TIOCNOTTY, (char *)0); close(t); } t = cleanopen(line); if (t < 0) fatalperror(net, line); #endif /* 0 */ struct winsize ws; int t = ptyslavefd; /* * set up the tty modes as we like them to be. */ init_termbuf(); # ifdef TIOCGWINSZ if (def_row || def_col) { bzero((char *)&ws, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; ioctl(t, TIOCSWINSZ, (char *)&ws); } # endif /* * Settings for all other termios/termio based * systems, other than 4.4BSD. In 4.4BSD the * kernel does the initial terminal setup. * * XXX what about linux? */ # ifndef OXTABS # define OXTABS 0 # endif termbuf.c_lflag |= ECHO; termbuf.c_oflag |= OPOST|ONLCR|OXTABS; termbuf.c_iflag |= ICRNL; termbuf.c_iflag &= ~IXOFF; tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); # ifdef LINEMODE if (waslm) tty_setlinemode(1); # endif /* LINEMODE */ /* * Set the tty modes, and make this our controlling tty. */ set_termbuf(); if (login_tty(t) == -1) fatalperror(net, "login_tty"); if (net > 2) close(net); if (pty > 2) close(pty); return t; }
/* * getptyslave() * * Open the slave side of the pty, and do any initialization * that is necessary. The return value is a file descriptor * for the slave side. */ void getptyslave(void) { int t = -1; struct winsize ws; /* * Opening the slave side may cause initilization of the * kernel tty structure. We need remember the state of * if linemode was turned on * terminal window size * terminal speed * so that we can re-set them if we need to. */ /* * Make sure that we don't have a controlling tty, and * that we are the session (process group) leader. */ #ifdef HAVE_SETSID if(setsid()<0) fatalperror(net, "setsid()"); #else # ifdef TIOCNOTTY t = open(_PATH_TTY, O_RDWR); if (t >= 0) { ioctl(t, TIOCNOTTY, (char *)0); close(t); } # endif #endif # ifdef PARENT_DOES_UTMP /* * Wait for our parent to get the utmp stuff to get done. */ utmp_sig_wait(); # endif t = cleanopen(line); if (t < 0) fatalperror(net, line); #ifdef STREAMSPTY ttyfd = t; /* * Not all systems have (or need) modules ttcompat and pckt so * don't flag it as a fatal error if they don't exist. */ if (really_stream) { /* these are the streams modules that we want pushed. note that they are in reverse order, ptem will be pushed first. maybe_push_modules() will try to push all modules before the first one that isn't already pushed. i.e if ldterm is pushed, only ttcompat will be attempted. all this is because we don't know which modules are available, and we don't know which modules are already pushed (via autopush, for instance). */ char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; char *ptymodules[] = { "pckt", NULL }; maybe_push_modules(t, ttymodules); maybe_push_modules(ourpty, ptymodules); } #endif /* * set up the tty modes as we like them to be. */ init_termbuf(); # ifdef TIOCSWINSZ if (def_row || def_col) { memset(&ws, 0, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; ioctl(t, TIOCSWINSZ, (char *)&ws); } # endif /* * Settings for sgtty based systems */ /* * Settings for UNICOS (and HPUX) */ # if defined(_CRAY) || defined(__hpux) termbuf.c_oflag = OPOST|ONLCR|TAB3; termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; termbuf.c_cflag = EXTB|HUPCL|CS8; # endif /* * Settings for all other termios/termio based * systems, other than 4.4BSD. In 4.4BSD the * kernel does the initial terminal setup. */ # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) # ifndef OXTABS # define OXTABS 0 # endif termbuf.c_lflag |= ECHO; termbuf.c_oflag |= ONLCR|OXTABS; termbuf.c_iflag |= ICRNL; termbuf.c_iflag &= ~IXOFF; # endif tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); /* * Set the tty modes, and make this our controlling tty. */ set_termbuf(); if (login_tty(t) == -1) fatalperror(net, "login_tty"); if (net > 2) close(net); if (ourpty > 2) { close(ourpty); ourpty = -1; } }
/* * start_slc * * Get ready to process incoming slc's and respond to them. * * The parameter getit is non-zero if it is necessary to grab a copy * of the terminal control structures. */ void start_slc(int getit) { slcchange = 0; if (getit) init_termbuf(); sprintf(slcbuf, "%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_SLC); slcptr = slcbuf + 4; }
void getptyslave(void) { int t = -1; #ifdef LINEMODE int waslm; #endif struct winsize ws; /* * Opening the slave side may cause initilization of the * kernel tty structure. We need remember the state of * if linemode was turned on * terminal window size * terminal speed * so that we can re-set them if we need to. */ #ifdef LINEMODE waslm = tty_linemode(); #endif /* * Make sure that we don't have a controlling tty, and * that we are the session (process group) leader. */ t = open(_PATH_TTY, O_RDWR); if (t >= 0) { (void) ioctl(t, TIOCNOTTY, (char *)0); (void) close(t); } t = cleanopen(line); if (t < 0) fatalperror(net, line); /* * set up the tty modes as we like them to be. */ init_termbuf(); if (def_row || def_col) { memset((char *)&ws, 0, sizeof(ws)); ws.ws_col = def_col; ws.ws_row = def_row; (void)ioctl(t, TIOCSWINSZ, (char *)&ws); } /* * Settings for sgtty based systems */ /* * Settings for all other termios/termio based * systems, other than 4.4BSD. In 4.4BSD the * kernel does the initial terminal setup. */ tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); #ifdef LINEMODE if (waslm) tty_setlinemode(1); #endif /* LINEMODE */ /* * Set the tty modes, and make this our controlling tty. */ set_termbuf(); if (login_tty(t) == -1) fatalperror(net, "login_tty"); if (net > 2) (void) close(net); if (pty > 2) { (void) close(pty); pty = -1; } }