📄 telnetdlib.c
字号:
* REMOTE_STOP if the connection is ever broken. */ pSlot->loggedIn = TRUE; } } }/********************************************************************************* telnetOutTask - relay output to remote user** This routine transfers data from the registered input/output task to* the remote user. It is the entry point for the output task which is* deleted when the client disconnects.** INTERNAL* * This routine blocks within the read() call until the command interpreter* sends a response. When the telnet server creates all input/output tasks* during startup (i.e. telnetdTaskFlag is TRUE), this routine cannot send* any data to the socket until the primary server task (telnetd) awakens * the input routine.** NOMANUAL* but not LOCAL for i()*/void telnetOutTask ( TELNETD_SESSION_DATA *pSlot /* pointer to the connection information */ ) { FAST int n; char buf [STDOUT_BUF_SIZE]; int sock; /* Socket for individual telnet session */ int outputFd; /* Output from command interpreter */ /* * Wait for a connection if the server creates this task in advance. */ if (telnetdTaskFlag) /* static task creation */ semTake (pSlot->startOutput, WAIT_FOREVER); sock = pSlot->socket; outputFd = pSlot->outputFd; /* * In the default configuration, the following read loop exits after * the connection between the client and server ends because closing * the socket to the remote client causes the input task to close the * output file descriptor. * * When the server creates the input and output tasks in advance, that * operation does not occur. To prevent writing to a non-existent * socket, the input task restarts the output task after using the * FIOFLUSH ioctl to prevent stale data from reaching the next session. */ while ((n = read (outputFd, buf, sizeof (buf))) > 0) { /* XXX should scan for IAC and double 'em to escape 'em */ write (sock, buf, n); } return; /* This point is never reached */ }/********************************************************************************* telnetInTask - relay input from remote user** This routine transfers data from the remote user to the registered* input/output task. It is deleted when the client disconnects. The* <slot> argument has two possible meanings. In the default setup,* it provides access to the session data which includes two file* descriptors: one for a socket (to the remote client) and another* provided by the command interpreter for the connection. That* information is not available when the server creates the input/output* tasks in advance. ** RETURNS: N/A.** NOMANUAL* but not LOCAL for i()*/void telnetInTask ( TELNETD_SESSION_DATA * pSlot ) { int n; int state = TS_DATA; char buf [STDIN_BUF_SIZE]; int sock; /* Socket for individual telnet session */ int inputFd; /* Input to command interpreter */ int slaveFd; /* Command interpreter stdin */ FOREVER { /* Wait for a connection if the server creates this task in advance. */ if (telnetdTaskFlag) /* static creation */ semTake (pSlot->startInput, WAIT_FOREVER); /* * Transfer data from the socket to the command interpreter, after * filtering out the telnet commands and options. */ sock = pSlot->socket; inputFd = pSlot->inputFd; slaveFd = pSlot->slaveFd; while ((n = read (sock, buf, sizeof (buf))) > 0) state = tnInput (state, slaveFd, sock, inputFd, buf, n); /* * Terminate the session. This is done as a seperate job because * the function telnetdSessionDisconnectFromRemote() deletes * the inTask before completion and that is our context (in this case)! */ excJobAdd (telnetdSessionDisconnectFromRemote, (int)pSlot, 0, 0, 0, 0, 0); taskSuspend (0); /* Wait to be deleted by telnetdSessionDisconnect */ } return; }/********************************************************************************* tnInput - process input from remote user** This routine transfers input data from a telnet client's <clientSock>* socket to the command interpreter through the <inputFd> file descriptor.* The <state> parameter triggers interpretation of the input as raw data or* as part of a command sequence or telnet option.** RETURNS: state value for next data bytes** NOMANUAL*/LOCAL int tnInput ( FAST int state, /* state of telnet session's input handler */ FAST int slaveFd, /* local fd, some options adjust it via ioctl */ FAST int clientSock, /* socket connected to telnet client */ FAST int inputFd, /* input to command interpreter */ FAST char *buf, /* buffer containing client data */ FAST int n /* amount of client data in buffer */ ) { char cc; int ci; while (--n >= 0) { cc = *buf++; /* get next character */ ci = (unsigned char) cc; /* convert to int since many values * are negative characters */ switch (state) { case TS_CR: /* doing crmod; ignore add'l linefeed */ state = TS_DATA; if ((cc != EOS) && (cc != '\n')) write (inputFd, &cc, 1); /* forward char */ break; case TS_DATA: /* just pass data */ if (ci == IAC) state = TS_IAC; else { write (inputFd, &cc, 1); /* forward char */ if (!myOpts [TELOPT_BINARY] && (cc == '\r')) state = TS_CR; } break; case TS_IAC: switch (ci) { case BREAK: /* interrupt from remote */ case IP: /* XXX interrupt (); */ state = TS_DATA; break; case AYT: /* Are You There? */ { static char aytAnswer [] = "\r\n[yes]\r\n"; write (clientSock, aytAnswer, sizeof (aytAnswer) - 1); state = TS_DATA; break; } case EC: /* erase character */ write (inputFd, "\b", 1); state = TS_DATA; break; case EL: /* erase line */ write (inputFd, "\025", 1); state = TS_DATA; break; case DM: /* data mark */ state = TS_DATA; break; case SB: /* sub-option negotiation begin */ state = TS_BEGINNEG; break; case WILL: state = TS_WILL; break; /* remote will do opt */ case WONT: state = TS_WONT; break; /* remote wont do opt */ case DO: state = TS_DO; break; /* req we do opt */ case DONT: state = TS_DONT; break; /* req we dont do opt */ case IAC: write (inputFd, &cc, 1); /* forward char */ state = TS_DATA; break; } break; case TS_BEGINNEG: /* ignore sub-option stuff for now */ if (ci == IAC) state = TS_ENDNEG; break; case TS_ENDNEG: state = (ci == SE) ? TS_DATA : TS_BEGINNEG; break; case TS_WILL: /* remote side said it will do opt */ (void)remDoOpt (slaveFd, ci, TRUE, clientSock, TRUE); state = TS_DATA; break; case TS_WONT: /* remote side said it wont do opt */ (void)remDoOpt (slaveFd, ci, FALSE, clientSock, TRUE); state = TS_DATA; break; case TS_DO: /* remote wants us to do opt */ (void)localDoOpt (slaveFd, ci, TRUE, clientSock, TRUE); state = TS_DATA; break; case TS_DONT: /* remote wants us to not do opt */ (void)localDoOpt (slaveFd, ci, FALSE, clientSock, TRUE); state = TS_DATA; break; default: TELNETD_DEBUG ("telnetd: invalid state = %d\n", state, 1, 2, 3, 4, 5); break; } } return (state); }/********************************************************************************* remDoOpt - request/acknowledge remote enable/disable of option** This routine will try to accept the remote's enable or disable,* as specified by "will", of the remote's support for the specified option.* If the request is to disable the option, the option will always be disabled.* If the request is to enable the option, the option will be enabled, IF we* are capable of supporting it. The remote is notified to DO/DONT support* the option.** RETURNS: OK or ERROR.*/LOCAL STATUS remDoOpt ( FAST int slaveFd,/* slave fd */ FAST int opt, /* option to be enabled/disabled */ BOOL enable, /* TRUE = enable option, FALSE = disable */ int clientSock, /* socket connection to telnet client */ BOOL remFlag /* TRUE = request is from remote */ ) { BOOL doOpt = enable; if (remOpts [opt] == enable) return (OK); switch (opt) { case TELOPT_BINARY: case TELOPT_ECHO: setMode (slaveFd, opt, enable); break; case TELOPT_SGA: break; default: doOpt = FALSE; break; } if ((remOpts [opt] != doOpt) || remFlag) { char msg[3]; msg[0] = IAC; msg[1] = doOpt ? DO : DONT; msg[2] = opt; write (clientSock, msg, 3); remOpts [opt] = doOpt; } return ((enable == doOpt) ? OK : ERROR); }/********************************************************************************* localDoOpt - offer/acknowledge local support of option** This routine will try to enable or disable local support for the specified* option. If local support of the option is already in the desired mode, no* action is taken. If the request is to disable the option, the option will* always be disabled. If the request is to enable the option, the option* will be enabled, IF we are capable of supporting it. The remote is* notified that we WILL/WONT support the option.** NOMANUAL** RETURNS: OK or ERROR.*/LOCAL STATUS localDoOpt ( FAST int slaveFd, /* slave fd */ FAST int opt, /* option to be enabled/disabled */ BOOL enable, /* TRUE = enable option, FALSE = disable */ int clientSock, /* socket connection to telnet client */ BOOL remFlag /* TRUE = request is from remote */ ) { BOOL will = enable; if (myOpts [opt] == enable) return (OK); switch (opt) { case TELOPT_BINARY: case TELOPT_ECHO: setMode (slaveFd, opt, enable); break; case TELOPT_SGA: break; default: will = FALSE; break; } if ((myOpts [opt] != will) || remFlag) { char msg[3]; msg[0] = IAC; msg[1] = will ? WILL : WONT; msg[2] = opt; write (clientSock, msg, 3); myOpts [opt] = will; } return ((will == enable) ? OK : ERROR); }/********************************************************************************* setMode - set telnet option** RETURNS: N/A.** NOMANUAL**/LOCAL void setMode ( int fd, int telnetOption, BOOL enable ) { FAST int ioOptions; switch (telnetOption) { case TELOPT_BINARY: raw = enable; break; case TELOPT_ECHO: echo = enable; break; } if (raw) ioOptions = 0; else { ioOptions = OPT_7_BIT | OPT_ABORT | OPT_TANDEM | OPT_LINE; if (echo) { ioOptions |= (OPT_ECHO | OPT_CRMOD); } } (void) ioctl (fd, FIOOPTIONS, ioOptions); }/********************************************************************************* telnetdStaticTaskInitializationGet - report whether tasks were pre-started by telnetd** This function is called by a custom shell parser library to determine if a shell * is to be spawned at the time a connection is requested.** RETURNS ** TRUE, if all tasks are pre-spawned; FALSE, if tasks are spawned at the * time a connection is requested.** SEE ALSO: telnetdInit(), telnetdParserSet()** INTERNAL* This routine is used by custom shells and is demonstrated in the * unsupported user shell echoShell.c**/BOOL telnetdStaticTaskInitializationGet() { return (telnetdTaskFlag); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -