2 * Acess2 Telnet Server (TCP server test case)
3 * - By John Hodge (thePowersGang)
12 #include <acess/sys.h>
26 typedef struct sClient
28 enum eTelnetMode Mode;
37 void Server_NewClient(int FD);
38 void HandleServerBoundData(tClient *Client);
39 void HandleClientBoundData(tClient *Client);
42 // --- Configuration ---
43 int giConfig_MaxClients = 5;
50 int main(int argc, char *argv[])
55 gaClients = calloc(giConfig_MaxClients, sizeof(tClient));
60 int addrtype = Net_ParseAddress("10.0.2.10", data);
62 giServerFD = Net_OpenSocket(addrtype, data, "tcps");
63 _SysIOCtl(giServerFD, 4, &port); // Set port and start listening
72 static void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
75 if(*maxfd < fd) *maxfd = fd;
88 FD_SET_MAX(&fds, giServerFD, &maxfd);
89 for( int i = 0; i < giConfig_MaxClients; i ++ )
91 if( gaClients[i].Socket == 0 ) continue ;
92 _SysDebug("Socket = %i, pty = %i",
93 gaClients[i].Socket, gaClients[i].pty);
94 FD_SET_MAX(&fds, gaClients[i].Socket, &maxfd);
95 FD_SET_MAX(&fds, gaClients[i].pty, &maxfd);
99 _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 );
102 if( FD_ISSET(giServerFD, &fds) )
104 Server_NewClient(giServerFD);
106 for( int i = 0; i < giConfig_MaxClients; i ++ )
108 if( FD_ISSET(gaClients[i].Socket, &fds) )
110 // Handle client data
111 HandleServerBoundData(&gaClients[i]);
113 if( FD_ISSET(gaClients[i].pty, &fds) )
115 // Handle output from terminal
116 HandleClientBoundData(&gaClients[i]);
122 void Server_NewClient(int FD)
126 // TODO: Is this done in the IPStack?
127 if( giNumClients == giConfig_MaxClients )
130 _SysClose( _SysOpenChild(FD, "", OPENFLAG_READ) );
134 // Allocate client structure and open socket
135 for( int i = 0; i < giConfig_MaxClients; i ++ )
137 if( gaClients[i].Socket == 0 ) {
143 // Accept the connection
144 clt->Socket = _SysOpenChild(FD, "", OPENFLAG_READ|OPENFLAG_WRITE);
147 // Create stdin/stdout
149 clt->stdin = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
150 clt->stdout = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
152 // TODO: Arguments and envp
154 int clientfd = _SysOpen("/Devices/pts/telnetd0c", OPENFLAG_READ|OPENFLAG_WRITE);
156 perror("Unable to open login PTY");
157 _SysClose(clt->Socket);
162 int fds[3] = {clientfd, clientfd, clientfd};
163 const char *argv[] = {"login", NULL};
164 _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds, NULL);
168 void HandleServerBoundData(tClient *Client)
173 len = _SysRead(Client->Socket, buf, BUFSIZ);
174 if( len == 0 ) return ;
180 for( int i = 0; i < len; i ++ )
185 Client->Mode = MODE_DATA;
188 case 240: // End of subnegotiation parameters
192 case 243: // NVT Break
193 case 244: // Function 'IP' (Ctrl-C)
196 case 245: // Function 'AO'
197 case 246: // Function 'AYT'
198 case 247: // Function 'EC'
199 case 248: // Function 'EL'
200 case 249: // GA Signal
201 case 250: // Subnegotation
204 Client->Mode = MODE_WILL;
207 Client->Mode = MODE_WILL;
210 Client->Mode = MODE_WILL;
213 Client->Mode = MODE_WILL;
215 case 255: // Literal 255
216 Client->Mode = MODE_DATA;
222 _SysDebug("Option %i WILL", buf[i]);
223 Client->Mode = MODE_DATA;
226 _SysDebug("Option %i WONT", buf[i]);
227 Client->Mode = MODE_DATA;
230 _SysDebug("Option %i DO", buf[i]);
231 Client->Mode = MODE_DATA;
234 _SysDebug("Option %i DONT", buf[i]);
235 Client->Mode = MODE_DATA;
239 Client->Mode = MODE_IAC;
241 _SysWrite(Client->pty, buf+i, 1);
247 void HandleClientBoundData(tClient *Client)
252 len = _SysRead(Client->pty, buf, BUFSIZ);
253 if( len <= 0 ) return ;
254 _SysWrite(Client->Socket, buf, len);