#include <assert.h>
#include <errno.h>
#include <acess/devices/pty.h>
+#include <stdbool.h>
// === TYPES ===
enum eTelnetMode
MODE_WILL,
MODE_WONT,
MODE_DO,
- MODE_DONT
+ MODE_DONT,
+ MODE_SUBNEG_OPTION,
+ MODE_SUBNEG_DATA,
+ MODE_SUBNEG_IAC,
};
typedef struct sClient
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 ---
}
// 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) )
}
// - Initialise
{
- _SysIOCtl(clt->pty, PTY_IOCTL_SETID, "telnetd0");
+ _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);
// TODO: Arguments and envp
{
- int clientfd = _SysOpen("/Devices/pts/telnetd0", 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);
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);
}
}
{
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)
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;
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;
_SysWrite(Client->Socket, buf, len);
}
+void HandleOptionRequest(tClient *Client, int Option, bool Value, bool IsRequest)
+{
+ switch(Option)
+ {
+ default:
+ _SysDebug("Unknown option %i", Option);
+ break;
+ }
+}
+