2 * Acess2 Telnet Server (TCP server test case)
3 * - By John Hodge (thePowersGang)
12 #include <acess/sys.h>
15 #include <acess/devices/pty.h>
28 typedef struct sClient
30 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 FD_SET_MAX(&fds, gaClients[i].Socket, &maxfd);
93 FD_SET_MAX(&fds, gaClients[i].pty, &maxfd);
97 _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 );
100 if( FD_ISSET(giServerFD, &fds) )
102 Server_NewClient(giServerFD);
104 for( int i = 0; i < giConfig_MaxClients; i ++ )
106 if( FD_ISSET(gaClients[i].Socket, &fds) )
108 // Handle client data
109 HandleServerBoundData(&gaClients[i]);
111 if( FD_ISSET(gaClients[i].pty, &fds) )
113 // Handle output from terminal
114 HandleClientBoundData(&gaClients[i]);
120 void Server_NewClient(int FD)
124 // TODO: Is this done in the IPStack?
125 if( giNumClients == giConfig_MaxClients )
128 _SysClose( _SysOpenChild(FD, "", OPENFLAG_READ) );
132 // Allocate client structure and open socket
133 for( int i = 0; i < giConfig_MaxClients; i ++ )
135 if( gaClients[i].Socket == 0 ) {
141 // Accept the connection
142 clt->Socket = _SysOpenChild(FD, "", OPENFLAG_READ|OPENFLAG_WRITE);
147 clt->pty = _SysOpen("/Devices/pts/ptmx", OPENFLAG_READ|OPENFLAG_WRITE);
149 perror("Unable to create/open PTY");
150 _SysDebug("Unable to create/open PTY: %s", strerror(errno));
151 _SysClose(clt->Socket);
157 _SysIOCtl(clt->pty, PTY_IOCTL_SETID, "telnetd0");
158 struct ptymode mode = {.InputMode = 0, .OutputMode=0};
159 struct ptydims dims = {.W = 80, .H = 25};
160 _SysIOCtl(clt->pty, PTY_IOCTL_SETMODE, &mode);
161 _SysIOCtl(clt->pty, PTY_IOCTL_SETDIMS, &dims);
164 // TODO: Arguments and envp
166 int clientfd = _SysOpen("/Devices/pts/telnetd0", OPENFLAG_READ|OPENFLAG_WRITE);
168 perror("Unable to open login PTY");
169 _SysClose(clt->Socket);
174 int fds[3] = {clientfd, clientfd, clientfd};
175 const char *argv[] = {"login", NULL};
176 _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds, NULL);
180 void HandleServerBoundData(tClient *Client)
185 len = _SysRead(Client->Socket, buf, BUFSIZ);
186 if( len == 0 ) return ;
192 for( int i = 0; i < len; i ++ )
197 Client->Mode = MODE_DATA;
200 case 240: // End of subnegotiation parameters
201 _SysDebug("End Subnegotiation");
206 case 243: // NVT Break
207 case 244: // Function 'IP' (Ctrl-C)
210 case 245: // Function 'AO'
211 case 246: // Function 'AYT'
212 case 247: // Function 'EC'
213 case 248: // Function 'EL'
214 case 249: // GA Signal
216 case 250: // Subnegotation
217 _SysDebug("Subnegotiation");
220 Client->Mode = MODE_WILL;
223 Client->Mode = MODE_WONT;
226 Client->Mode = MODE_DO;
229 Client->Mode = MODE_DONT;
231 case 255: // Literal 255
232 Client->Mode = MODE_DATA;
238 _SysDebug("Option %i WILL", buf[i]);
239 Client->Mode = MODE_DATA;
242 _SysDebug("Option %i WONT", buf[i]);
243 Client->Mode = MODE_DATA;
246 _SysDebug("Option %i DO", buf[i]);
247 Client->Mode = MODE_DATA;
250 _SysDebug("Option %i DONT", buf[i]);
251 Client->Mode = MODE_DATA;
255 Client->Mode = MODE_IAC;
257 _SysWrite(Client->pty, buf+i, 1);
263 void HandleClientBoundData(tClient *Client)
268 len = _SysRead(Client->pty, buf, BUFSIZ);
269 if( len <= 0 ) return ;
270 _SysWrite(Client->Socket, buf, len);