198ddaaf3db35568e810e317ce3ce5b8b3577b86
[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         giServerFD = Net_OpenSocket(0, NULL, "tcps");
40
41         // Event loop
42         EventLoop();
43         
44         return 0;
45 }
46
47 void EventLoop(void)
48 {
49         fd_set  fds;
50          int    maxfd;
51
52         void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
53         {
54                 FD_SET(fd, set);
55                 if(*maxfd < fd) *maxfd = fd;
56         }
57
58         for( ;; )
59         {
60                 maxfd = 0;
61                 // Fill select
62                 FD_SET_MAX(&fds, giServerFD, &maxfd);
63                 for( int i = 0; i < giConfig_MaxClients; i ++ )
64                 {
65                         FD_SET_MAX(&fds, gaClients[i].Socket, &maxfd);
66                         FD_SET_MAX(&fds, gaClients[i].stdout,  &maxfd);
67                 }
68                 
69                 // Select!
70                 select( maxfd+1, &fds, NULL, NULL, NULL );
71                 
72                 // Check events
73                 if( FD_ISSET(giServerFD, &fds) )
74                 {
75                         Server_NewClient(giServerFD);
76                 }
77                 for( int i = 0; i < giConfig_MaxClients; i ++ )
78                 {
79                         if( FD_ISSET(gaClients[i].Socket, &fds) )
80                         {
81                                 // Handle client data
82                                 HandleServerBoundData(&gaClients[i]);
83                         }
84                         if( FD_ISSET(gaClients[i].stdout, &fds) )
85                         {
86                                 // Handle output from terminal
87                                 HandleClientBoundData(&gaClients[i]);
88                         }
89                 }
90         }
91 }
92
93 void Server_NewClient(int FD)
94 {
95         tClient *clt;
96         
97         // TODO: Is this done in the IPStack?
98         if( giNumClients == giConfig_MaxClients )
99         {
100                 // Open, reject
101                 close( _SysOpenChild(FD, "", O_RDWR) );
102                 return ;
103         }
104         
105         // Allocate client structure and open socket
106         for( int i = 0; i < giConfig_MaxClients; i ++ )
107         {
108                 if( gaClients[i].Socket == 0 ) {
109                         clt = &gaClients[i];
110                         break;
111                 }
112         }
113         // Accept the connection
114         clt->Socket = _SysOpenChild(FD, "", O_RDWR);
115         giNumClients ++;        
116         
117         // Create stdin/stdout
118         clt->stdin = open("/Devices/fifo", O_RDWR);
119         clt->stdout = open("/Devices/fifo", O_RDWR);
120         
121         // TODO: Arguments and envp
122         {
123                 int fds[3] = {clt->stdin, clt->stdout, clt->stdout};
124                 _SysSpawn("/Acess/SBin/login", NULL, NULL, 3, fds);
125         }
126 }
127
128 void HandleServerBoundData(tClient *Client)
129 {
130         char    buf[BUFSIZ];
131          int    len;
132         
133         len = read(Client->Socket, buf, BUFSIZ);
134         write(Client->stdin, buf, len);
135 }
136
137 void HandleClientBoundData(tClient *Client)
138 {
139         char    buf[BUFSIZ];
140          int    len;
141         
142         len = read(Client->stdout, buf, BUFSIZ);
143         write(Client->Socket, buf, len);
144 }
145

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