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

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