052680115e4a243df458b11c9e0538aca6ba03a3
[tpg/acess2.git] / Usermode / Applications / telnetd_src / main.c
1 /*
2  * Acess2 Telnet Server (TCP server test case)
3  * - By John Hodge (thePowersGang)
4  *
5  * main.c
6  * - All
7  */
8 #include <stddef.h>
9 #include <net.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <acess/sys.h>
13 #include <assert.h>
14
15 // === TYPES ===
16 typedef struct sClient
17 {
18          int    Socket;
19          int    stdout;
20          int    stdin;
21 } tClient;
22
23 // === PROTOTYPES ===
24 void    EventLoop(void);
25 void    Server_NewClient(int FD);
26 void    HandleServerBoundData(tClient *Client);
27 void    HandleClientBoundData(tClient *Client);
28
29 // === GLOBALS ===
30 // --- Configuration ---
31  int    giConfig_MaxClients = 5;
32 // --- State ---
33  int    giServerFD;
34 tClient *gaClients;
35  int    giNumClients;
36
37 // === CODE ===
38 int main(int argc, char *argv[])
39 {
40         // TODO: Configure
41
42         // Initialise
43         gaClients = calloc(giConfig_MaxClients, sizeof(tClient));
44
45         // Open server
46         {
47                 uint8_t data[16];
48                  int    addrtype = Net_ParseAddress("10.0.2.10", data);
49                  int    port = 23;
50                 giServerFD = Net_OpenSocket(addrtype, data, "tcps");
51                 _SysIOCtl(giServerFD, 4, &port);        // Set port and start listening
52         }
53
54         // Event loop
55         EventLoop();
56         
57         return 0;
58 }
59
60 static void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
61 {
62         FD_SET(fd, set);
63         if(*maxfd < fd) *maxfd = fd;
64 }
65
66 void EventLoop(void)
67 {
68         fd_set  fds;
69          int    maxfd;
70
71         for( ;; )
72         {
73                 FD_ZERO(&fds);
74                 maxfd = 0;
75                 // Fill select
76                 FD_SET_MAX(&fds, giServerFD, &maxfd);
77                 for( int i = 0; i < giConfig_MaxClients; i ++ )
78                 {
79                         if( gaClients[i].Socket == 0 )  continue ;
80                         _SysDebug("Socket = %i, stdout = %i",
81                                 gaClients[i].Socket, gaClients[i].stdout);
82                         FD_SET_MAX(&fds, gaClients[i].Socket, &maxfd);
83                         FD_SET_MAX(&fds, gaClients[i].stdout,  &maxfd);
84                 }
85                 
86                 // Select!
87                 _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 );
88                 
89                 // Check events
90                 if( FD_ISSET(giServerFD, &fds) )
91                 {
92                         Server_NewClient(giServerFD);
93                 }
94                 for( int i = 0; i < giConfig_MaxClients; i ++ )
95                 {
96                         if( FD_ISSET(gaClients[i].Socket, &fds) )
97                         {
98                                 // Handle client data
99                                 HandleServerBoundData(&gaClients[i]);
100                         }
101                         if( FD_ISSET(gaClients[i].stdout, &fds) )
102                         {
103                                 // Handle output from terminal
104                                 HandleClientBoundData(&gaClients[i]);
105                         }
106                 }
107         }
108 }
109
110 void Server_NewClient(int FD)
111 {
112         tClient *clt = NULL;
113         
114         // TODO: Is this done in the IPStack?
115         if( giNumClients == giConfig_MaxClients )
116         {
117                 // Open, reject
118                 _SysClose( _SysOpenChild(FD, "", OPENFLAG_READ) );
119                 return ;
120         }
121         
122         // Allocate client structure and open socket
123         for( int i = 0; i < giConfig_MaxClients; i ++ )
124         {
125                 if( gaClients[i].Socket == 0 ) {
126                         clt = &gaClients[i];
127                         break;
128                 }
129         }
130         assert(clt);
131         // Accept the connection
132         clt->Socket = _SysOpenChild(FD, "", OPENFLAG_READ|OPENFLAG_WRITE);
133         giNumClients ++;
134         
135         // Create stdin/stdout
136         // TODO: Use PTYs
137         clt->stdin = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
138         clt->stdout = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
139         
140         // TODO: Arguments and envp
141         {
142                 int fds[3] = {clt->stdin, clt->stdout, clt->stdout};
143                 const char      *argv[] = {NULL};
144                 _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds, NULL);
145         }
146 }
147
148 void HandleServerBoundData(tClient *Client)
149 {
150         char    buf[BUFSIZ];
151          int    len;
152         
153         len = _SysRead(Client->Socket, buf, BUFSIZ);
154         if( len <= 0 )  return ;
155         _SysWrite(Client->stdin, buf, len);
156 }
157
158 void HandleClientBoundData(tClient *Client)
159 {
160         char    buf[BUFSIZ];
161          int    len;
162         
163         len = _SysRead(Client->stdout, buf, BUFSIZ);
164         if( len <= 0 )  return ;
165         _SysWrite(Client->Socket, buf, len);
166 }
167

UCC git Repository :: git.ucc.asn.au