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

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