int lstat(const char *path, struct stat *buf) { int fd = _SysOpen(path, OPENFLAG_NOLINK); if( !fd ) { // errno is set by _SysOpen return -1; } int rv = fstat(fd, buf); _SysClose(fd); return rv; }
EXPORT int fclose(FILE *fp) { if( !(fp->Flags & FILE_FLAG_ALLOC) ) return 0; fflush(fp); if( fp->FD >= 0 ) { _SysClose(fp->FD); if( fp->Buffer && (fp->Flags & FILE_FLAG_OURBUFFER) ) { free(fp->Buffer); } fp->Buffer = NULL; } fp->Flags = 0; fp->FD = FD_NOTOPEN; return 0; }
int Net_OpenSocket_TCPC(int AddrType, const void *Addr, int Port) { int fd = Net_OpenSocket(AddrType, Addr, "tcpc"); if( fd == -1 ) return -1; if( _SysIOCtl(fd, 5, &Port) < 0 ) // Remote Port goto err; if( _SysIOCtl(fd, 6, (void*)Addr) < 0 ) // Remote address (kernel shouldn't modify) goto err; if( _SysIOCtl(fd, 7, NULL) < 0) // connect goto err; return fd; err: _SysClose(fd); return -1; }
int Net_OpenSocket_UDP(int AddrType, const void *Addr, int RPort, int LPort) { int fd = Net_OpenSocket(AddrType, Addr, "udp"); if( fd == -1 ) return -1; if( _SysIOCtl(fd, UDP_IOCTL_GETSETLPORT, &LPort) < 0 ) goto err; if( _SysIOCtl(fd, UDP_IOCTL_GETSETRPORT, &RPort) < 0 ) goto err; int maskbits = Net_GetAddressSize(AddrType) * 8; if( _SysIOCtl(fd, UDP_IOCTL_GETSETRMASK, &maskbits) < 0 ) goto err; if( _SysIOCtl(fd, UDP_IOCTL_SETRADDR, (void*)Addr) < 0 ) // Remote address (kernel shouldn't modify) goto err; return fd; err: _SysClose(fd); return -1; }
// === CODE === int main(int argc, char *argv[], const char **envp) { AxWin3_Connect(NULL); // --- Build up window gMainWindow = AxWin3_RichText_CreateWindow(NULL, AXWIN3_RICHTEXT_READONLY); AxWin3_SetWindowTitle(gMainWindow, "Terminal"); // TODO: Update title with other info gMenuWindow = AxWin3_Menu_Create(gMainWindow); AxWin3_Menu_AddItem(gMenuWindow, "Copy\tWin+C", NULL, NULL, 0, NULL); AxWin3_Menu_AddItem(gMenuWindow, "Paste\tWin+V", NULL, NULL, 0, NULL); // TODO: Populate menu // TODO: Tabs? AxWin3_RichText_SetKeyHandler (gMainWindow, Term_KeyHandler); AxWin3_RichText_SetMouseHandler (gMainWindow, Term_MouseHandler); AxWin3_RichText_SetDefaultColour(gMainWindow, 0xFFFFFF); AxWin3_RichText_SetBackground (gMainWindow, 0x000000); AxWin3_RichText_SetFont (gMainWindow, "#monospace", 10); AxWin3_RichText_SetCursorPos (gMainWindow, 0, 0); AxWin3_RichText_SetCursorType (gMainWindow, AXWIN3_RICHTEXT_CURSOR_INV); AxWin3_RichText_SetCursorBlink (gMainWindow, 1); tTerminal *term = Display_Init(80, 25, 100); AxWin3_ResizeWindow(gMainWindow, 80*8, 25*16); AxWin3_MoveWindow(gMainWindow, 20, 50); AxWin3_ShowWindow(gMainWindow, 1); AxWin3_FocusWindow(gMainWindow); // Create PTY giPTYHandle = _SysOpen("/Devices/pts/ptmx", OPENFLAG_READ|OPENFLAG_WRITE); if( giPTYHandle < 0 ) { perror("Unable to create/open PTY"); _SysDebug("Unable to create/open PTY: %s", strerror(errno)); return -1; } // - Initialise { _SysIOCtl(giPTYHandle, PTY_IOCTL_SETID, "gui0"); struct ptymode mode = {.InputMode = PTYIMODE_CANON|PTYIMODE_ECHO, .OutputMode=0}; struct ptydims dims = {.W = 80, .H = 25}; _SysIOCtl(giPTYHandle, PTY_IOCTL_SETMODE, &mode); _SysIOCtl(giPTYHandle, PTY_IOCTL_SETDIMS, &dims); } // Spawn shell { int fd = _SysOpen("/Devices/pts/gui0", OPENFLAG_READ|OPENFLAG_WRITE); int fds[] = {fd, fd, fd}; const char *argv[] = {"CLIShell", NULL}; int pid = _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL); if( pid < 0 ) _SysDebug("ERROR: Shell spawn failed: %s", strerror(errno)); _SysIOCtl(fd, PTY_IOCTL_SETPGRP, &pid); _SysClose(fd); } // Main loop for( ;; ) { fd_set fds; FD_ZERO(&fds); FD_SET(giPTYHandle, &fds); AxWin3_MessageSelect(giPTYHandle + 1, &fds); if( FD_ISSET(giPTYHandle, &fds) ) { _SysDebug("Activity on child stdout"); // Read and update screen char buf[512]; int len = _SysRead(giPTYHandle, buf, sizeof(buf)); if( len <= 0 ) break; Term_HandleOutput(term, len, buf); } } return 0; } int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated) { static int ctrl_state = 0; // Handle modifiers #define _bitset(var,bit,set) do{if(set)var|=1<<(bit);else var&=~(1<<(bit));}while(0) switch(KeySym) { case KEYSYM_LEFTCTRL: _bitset(ctrl_state, 0, bPress!=0); return 0; case KEYSYM_RIGHTCTRL: _bitset(ctrl_state, 1, bPress!=0); return 0; } #undef _bitset // Handle shortcuts // - Ctrl-A -- Ctrl-Z if( ctrl_state && KeySym >= KEYSYM_a && KeySym <= KEYSYM_z ) { Translated = KeySym - KEYSYM_a + 1; _SysDebug("Ctrl-%c: KS %x => Trans %x", 'A'+(KeySym-KEYSYM_a), KeySym, Translated); } // == 2 :: FIRE if( bPress == 2 ) { if( Translated ) { char buf[6]; int len; // Encode and send len = WriteUTF8(buf, Translated); _SysDebug("Keystroke %x:%x translated to '%.*s'", KeySym, Translated, len, buf); _SysWrite(giPTYHandle, buf, len); return 0; } // No translation, look for escape sequences to send const char *str = NULL; switch(KeySym) { case KEYSYM_LEFTARROW: str = "\x1b[D"; break; case KEYSYM_RIGHTARROW: str = "\x1b[C"; break; case KEYSYM_UPARROW: str = "\x1b[A"; break; case KEYSYM_DOWNARROW: str = "\x1b[B"; break; } if( str ) { _SysWrite(giPTYHandle, str, strlen(str)); } } return 0; } int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col) { return 0; } void Term_HandleOutput(tTerminal *Term, int Len, const char *Buf) { // TODO: Handle graphical / accelerated modes //_SysDebug("Term_HandleOutput: %i \"%.*s\"", Len, Len, Buf); int ofs = 0; int esc_len = 0; while( ofs < Len ) { esc_len = Term_HandleVT100(Term, Len - ofs, Buf + ofs); if( esc_len < 0 ) { Display_AddText(Term, -esc_len, Buf + ofs); esc_len = -esc_len; } ofs += esc_len; //_SysDebug("Len = %i, ofs = %i", Len, ofs); } Display_Flush(Term); }
void Server_NewClient(int FD) { tClient *clt = NULL; // TODO: Is this done in the IPStack? if( giNumClients == giConfig_MaxClients ) { // Open, reject _SysClose( _SysOpenChild(FD, "", OPENFLAG_READ) ); return ; } // Allocate client structure and open socket for( int i = 0; i < giConfig_MaxClients; i ++ ) { if( gaClients[i].Socket == 0 ) { clt = &gaClients[i]; break; } } assert(clt); // Accept the connection clt->Socket = _SysOpenChild(FD, "", OPENFLAG_READ|OPENFLAG_WRITE); giNumClients ++; // Create PTY // TODO: Use PTYs 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 { 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); _SysClose(clt->pty); 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); } } 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; for( int i = 0; i < len; i ++ ) { switch(Client->Mode) { case MODE_IAC: Client->Mode = MODE_DATA; switch(buf[i]) { case 240: // End of subnegotiation parameters _SysDebug("End Subnegotiation"); break; case 241: // Nop break; case 242: // SYNCH case 243: // NVT Break case 244: // Function 'IP' (Ctrl-C) break; case 245: // Function 'AO' case 246: // Function 'AYT' 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_WONT; break; case 253: // DO Client->Mode = MODE_DO; break; case 254: // DONT Client->Mode = MODE_DONT; break; case 255: // Literal 255 _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; else _SysWrite(Client->pty, buf+i, 1); break; } } } void HandleClientBoundData(tClient *Client) { char buf[BUFSIZ]; int len; len = _SysRead(Client->pty, buf, BUFSIZ); if( len <= 0 ) return ; _SysWrite(Client->Socket, buf, len); }