Usermode/libaxwin4 - Handle demarshal failure
[tpg/acess2.git] / Usermode / Applications / telnetd_src / main.c
index 7fac367..fa85250 100644 (file)
@@ -11,6 +11,9 @@
 #include <stdlib.h>
 #include <acess/sys.h>
 #include <assert.h>
+#include <errno.h>
+#include <acess/devices/pty.h>
+#include <stdbool.h>
 
 // === TYPES ===
 enum eTelnetMode
@@ -20,7 +23,10 @@ enum eTelnetMode
        MODE_WILL,
        MODE_WONT,
        MODE_DO,
-       MODE_DONT
+       MODE_DONT,
+       MODE_SUBNEG_OPTION,
+       MODE_SUBNEG_DATA,
+       MODE_SUBNEG_IAC,
 };
 
 typedef struct sClient
@@ -28,8 +34,6 @@ typedef struct sClient
        enum eTelnetMode        Mode;
         int    Socket;
         int    pty;
-        int    stdin;
-        int    stdout;
 } tClient;
 
 // === PROTOTYPES ===
@@ -37,6 +41,7 @@ void  EventLoop(void);
 void   Server_NewClient(int FD);
 void   HandleServerBoundData(tClient *Client);
 void   HandleClientBoundData(tClient *Client);
+void   HandleOptionRequest(tClient *Client, int Option, bool Value, bool IsRequest);
 
 // === GLOBALS ===
 // --- Configuration ---
@@ -89,14 +94,13 @@ void EventLoop(void)
                for( int i = 0; i < giConfig_MaxClients; i ++ )
                {
                        if( gaClients[i].Socket == 0 )  continue ;
-                       _SysDebug("Socket = %i, pty = %i",
-                               gaClients[i].Socket, gaClients[i].pty);
                        FD_SET_MAX(&fds, gaClients[i].Socket, &maxfd);
                        FD_SET_MAX(&fds, gaClients[i].pty,  &maxfd);
                }
                
                // Select!
-               _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 );
+               int rv = _SysSelect( maxfd+1, &fds, NULL, NULL, NULL, 0 );
+               _SysDebug("Select return %i", rv);
                
                // Check events
                if( FD_ISSET(giServerFD, &fds) )
@@ -144,14 +148,30 @@ void Server_NewClient(int FD)
        clt->Socket = _SysOpenChild(FD, "", OPENFLAG_READ|OPENFLAG_WRITE);
        giNumClients ++;
        
-       // Create stdin/stdout
+       // Create PTY
        // TODO: Use PTYs
-       clt->stdin = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
-       clt->stdout = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+       clt->pty = _SysOpen("/Devices/pts/ptmx", OPENFLAG_READ|OPENFLAG_WRITE);
+       if( clt->pty < 0 ) {
+               perror("Unable to create/open PTY");
+               _SysDebug("Unable to create/open PTY: %s", strerror(errno));
+               _SysClose(clt->Socket);
+               clt->Socket = 0;
+               return ;
+       }
+       // - Initialise
+       {
+               _SysIOCtl(clt->pty, PTY_IOCTL_SETID, "telnetd#");
+               struct ptymode  mode = {.InputMode = 0, .OutputMode=0};
+               struct ptydims  dims = {.W = 80, .H = 25};
+               _SysIOCtl(clt->pty, PTY_IOCTL_SETMODE, &mode);
+               _SysIOCtl(clt->pty, PTY_IOCTL_SETDIMS, &dims);
+       }
        
        // TODO: Arguments and envp
        {
-                int    clientfd = _SysOpen("/Devices/pts/telnetd0c", OPENFLAG_READ|OPENFLAG_WRITE);
+               char pty_path[] = "/Devices/pts/telnetd000";
+               _SysIOCtl(clt->pty, PTY_IOCTL_GETID, pty_path+13);
+                int    clientfd = _SysOpen(pty_path, OPENFLAG_READ|OPENFLAG_WRITE);
                if(clientfd < 0) {
                        perror("Unable to open login PTY");
                        _SysClose(clt->Socket);
@@ -159,9 +179,11 @@ void Server_NewClient(int FD)
                        clt->Socket = 0;
                        return ;
                }
+               _SysDebug("Using client PTY %s", pty_path);
                int fds[3] = {clientfd, clientfd, clientfd};
                const char      *argv[] = {"login", NULL};
                _SysSpawn("/Acess/SBin/login", argv, argv, 3, fds, NULL);
+               _SysClose(clientfd);
        }
 }
 
@@ -169,14 +191,16 @@ void HandleServerBoundData(tClient *Client)
 {
        uint8_t buf[BUFSIZ];
        size_t  len;
-       
+
+       _SysDebug("Client %p", Client); 
        len = _SysRead(Client->Socket, buf, BUFSIZ);
+       _SysDebug("%i bytes for %p", len, Client);
        if( len == 0 )  return ;
        if( len == -1 ) {
                return ;
        }
        // handle options
-        int    last_flush = 0;
+       // int  last_flush = 0;
        for( int i = 0; i < len; i ++ )
        {
                switch(Client->Mode)
@@ -186,6 +210,8 @@ void HandleServerBoundData(tClient *Client)
                        switch(buf[i])
                        {
                        case 240:       // End of subnegotiation parameters
+                               _SysDebug("End Subnegotiation");
+                               break;
                        case 241:       // Nop
                                break;
                        case 242:       // SYNCH
@@ -198,42 +224,76 @@ void HandleServerBoundData(tClient *Client)
                        case 247:       // Function 'EC'
                        case 248:       // Function 'EL'
                        case 249:       // GA Signal
+                               break;
                        case 250:       // Subnegotation
+                               _SysDebug("Subnegotiation");
+                               // TODO: Get option ID, and then cache until 'END SB' (240)
+                               Client->Mode = MODE_SUBNEG_OPTION;
                                break;
                        case 251:       // WILL
                                Client->Mode = MODE_WILL;
                                break;
                        case 252:       // WONT
-                               Client->Mode = MODE_WILL;
+                               Client->Mode = MODE_WONT;
                                break;
                        case 253:       // DO
-                               Client->Mode = MODE_WILL;
+                               Client->Mode = MODE_DO;
                                break;
                        case 254:       // DONT
-                               Client->Mode = MODE_WILL;
+                               Client->Mode = MODE_DONT;
                                break;
                        case 255:       // Literal 255
-                               Client->Mode = MODE_DATA;
-                               i --;   // hacky!
+                               _SysWrite(Client->pty, buf+i, 1);
                                break;
                        }
                        break;
                case MODE_WILL:
                        _SysDebug("Option %i WILL", buf[i]);
+                       HandleOptionRequest(Client, buf[i], true, false);
                        Client->Mode = MODE_DATA;
                        break;
                case MODE_WONT:
                        _SysDebug("Option %i WONT", buf[i]);
+                       HandleOptionRequest(Client, buf[i], false, false);
                        Client->Mode = MODE_DATA;
                        break;
                case MODE_DO:
                        _SysDebug("Option %i DO", buf[i]);
+                       HandleOptionRequest(Client, buf[i], true, true);
                        Client->Mode = MODE_DATA;
                        break;
                case MODE_DONT:
                        _SysDebug("Option %i DONT", buf[i]);
+                       HandleOptionRequest(Client, buf[i], false, true);
                        Client->Mode = MODE_DATA;
                        break;
+               case MODE_SUBNEG_OPTION:
+                       _SysDebug("Option %i subnegotation", buf[i]);
+                       Client->Mode = MODE_SUBNEG_DATA;
+                       break;
+               case MODE_SUBNEG_IAC:
+                       switch(buf[i])
+                       {
+                       case 240:       // End subnegotation
+                               // TODO: Handle subnegotation data
+                               Client->Mode = MODE_DATA;
+                               break;
+                       case 255:
+                               // TODO: Literal 255
+                               Client->Mode = MODE_SUBNEG_DATA;
+                               break;
+                       default:
+                               _SysDebug("Unexpected %i in SUBNEG IAC", buf[i]);
+                               Client->Mode = MODE_SUBNEG_DATA;
+                               break;
+                       }
+               case MODE_SUBNEG_DATA:
+                       if( buf[i] == 255 )
+                               Client->Mode = MODE_SUBNEG_IAC;
+                       else
+                               ;//_SysWrite(Client->pty, buf+i, 1);
+                       break;
+               
                case MODE_DATA:
                        if( buf[i] == 255 )
                                Client->Mode = MODE_IAC;
@@ -254,3 +314,13 @@ void HandleClientBoundData(tClient *Client)
        _SysWrite(Client->Socket, buf, len);
 }
 
+void HandleOptionRequest(tClient *Client, int Option, bool Value, bool IsRequest)
+{
+       switch(Option)
+       {
+       default:
+               _SysDebug("Unknown option %i", Option);
+               break;
+       }
+}
+

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