Usermode/irc - Rework into multiple files
[tpg/acess2.git] / Usermode / Applications / irc_src / main.c
old mode 100644 (file)
new mode 100755 (executable)
index 119e025..e3e2af4
-/*\r
- * Acess2 IRC Client\r
- */\r
-#include <acess/sys.h>\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <net.h>\r
-\r
-#define BUFSIZ 1023\r
-\r
-// === TYPES ===\r
-typedef struct sServer {\r
-        int    FD;\r
-       char    InBuf[BUFSIZ+1];\r
-        int    ReadPos;\r
-} tServer;\r
-\r
-// === PROTOTYPES ===\r
- int   ParseArguments(int argc, const char *argv[]);\r
-void   ProcessIncoming(tServer *Server);\r
- int   writef(int FD, const char *Format, ...);\r
- int   OpenTCP(const char *AddressString, short PortNumber);\r
-\r
-// === GLOBALS ===\r
-char   *gsUsername = "root";\r
-char   *gsHostname = "acess";\r
-char   *gsRemoteAddress = NULL;\r
-char   *gsRealName = "Acess2 IRC Client";\r
-char   *gsNickname = "acess";\r
-short  giRemotePort = 6667;\r
-\r
-// ==== CODE ====\r
-int main(int argc, const char *argv[], const char *envp[])\r
-{\r
-        int    tmp;\r
-       tServer srv;\r
-       \r
-       memset(&srv, 0, sizeof(srv));\r
-       \r
-       if( (tmp = ParseArguments(argc, argv)) ) {\r
-               return tmp;\r
-       }\r
-       \r
-       srv.FD = OpenTCP( gsRemoteAddress, giRemotePort );\r
-       if( srv.FD == -1 ) {\r
-               fprintf(stderr, "Unable to create socket\n");\r
-               return -1;\r
-       }\r
-       \r
-       writef(srv.FD, "USER %s %s %s : %s\n", gsUsername, gsHostname, gsRemoteAddress, gsRealName);\r
-       writef(srv.FD, "NICK %s", gsNickname);\r
-       \r
-       ProcessIncoming(&srv);\r
-       \r
-       close(srv.FD);\r
-       return 0;\r
-}\r
-\r
-/**\r
- * \todo Actually implement correctly :)\r
- */\r
-int ParseArguments(int argc, const char *argv[])\r
-{\r
-       gsRemoteAddress = "130.95.13.18";       // irc.ucc.asn.au\r
-       \r
-       return 0;\r
-}\r
-\r
-void Cmd_PRIVMSG(tServer *Server, const char *Dest, const char *Src, const char *Message)\r
-{\r
-       printf("%p: %s => %s\t%s\n", Server, Src, Dest, Message);\r
-}\r
-\r
-/**\r
- * \brief Read a space-separated value from a string\r
- */\r
-char *GetValue(char *Src, int *Ofs)\r
-{\r
-        int    pos = *Ofs;\r
-       char    *ret = Src + pos;\r
-       char    *end;\r
-       \r
-       while( *ret == ' ' )    ret ++;\r
-       \r
-       end = strchr(ret, ' ');\r
-       if( end ) {\r
-               *end = '\0';\r
-       }\r
-       else {\r
-               end = ret + strlen(ret) - 1;\r
-       }\r
-       *Ofs = end - Src + 1;\r
-       \r
-       return ret;\r
-}\r
-\r
-/**\r
- */\r
-void ParseServerLine(tServer *Server, char *Line)\r
-{\r
-        int    pos;\r
-       char    *ident, *cmd;\r
-       if( *Line == ':' ) {\r
-               // Message\r
-               ident = GetValue(Line, &pos);\r
-               pos ++; // Space\r
-               cmd = GetValue(Line, &pos);\r
-               \r
-               if( strcmp(cmd, "PRIVMSG") == 0 ) {\r
-                       char    *dest, *message;\r
-                       pos ++;\r
-                       dest = GetValue(Line, &pos);\r
-                       pos ++;\r
-                       if( Line[pos] == ':' ) {\r
-                               message = Line + pos + 1;\r
-                       }\r
-                       else {\r
-                               message = GetValue(Line, &pos);\r
-                       }\r
-                       Cmd_PRIVMSG(Server, dest, ident, message);\r
-               }\r
-       }\r
-       else {\r
-               // Command to client\r
-       }\r
-}\r
-\r
-/**\r
- * \brief Process incoming lines from the server\r
- */\r
-void ProcessIncoming(tServer *Server)\r
-{      \r
-       char    *ptr, *newline;\r
-        int    len;\r
-       \r
-       // While there is data in the buffer, read it into user memory and \r
-       // process it line by line\r
-       // ioctl#8 on a TCP client gets the number of bytes in the recieve buffer\r
-       // - Used to avoid blocking\r
-       while( ioctl(Server->FD, 8, NULL) )\r
-       {\r
-               // Read data\r
-               len = read(Server->FD, BUFSIZ - Server->ReadPos, Server->InBuf + Server->ReadPos);\r
-               Server->InBuf[Server->ReadPos + len] = '\0';\r
-               \r
-               // Break into lines\r
-               ptr = Server->InBuf;\r
-               while( (newline = strchr(ptr, '\n')) )\r
-               {\r
-                       *newline = '\0';\r
-                       printf("%s\n", ptr);\r
-                       ParseServerLine(Server, ptr);\r
-                       ptr = newline + 1;\r
-               }\r
-               \r
-               // Handle incomplete lines\r
-               if( ptr - Server->InBuf < len + Server->ReadPos ) {\r
-                       Server->ReadPos = ptr - Server->InBuf;\r
-                       memcpy(Server->InBuf, ptr, Server->ReadPos);\r
-               }\r
-               else {\r
-                       Server->ReadPos = 0;\r
-               }\r
-       }\r
-}\r
-\r
-/**\r
- * \brief Write a formatted string to a file descriptor\r
- * \r
- */\r
-int writef(int FD, const char *Format, ...)\r
-{\r
-       va_list args;\r
-        int    len;\r
-       \r
-       va_start(args, Format);\r
-       len = vsnprintf(NULL, 1000, Format, args);\r
-       va_end(args);\r
-       \r
-       {\r
-               char    buf[len+1];\r
-               va_start(args, Format);\r
-               vsnprintf(buf, len+1, Format, args);\r
-               va_end(args);\r
-               \r
-               return write(FD, len, buf);\r
-       }\r
-}\r
-\r
-/**\r
- * \brief Initialise a TCP connection to \a AddressString on port \a PortNumber\r
- */\r
-int OpenTCP(const char *AddressString, short PortNumber)\r
-{\r
-        int    fd, addrType;\r
-       char    *iface;\r
-       char    addrBuffer[8];\r
-       \r
-       // Parse IP Address\r
-       addrType = Net_ParseAddress(AddressString, addrBuffer);\r
-       if( addrType == 0 ) {\r
-               fprintf(stderr, "Unable to parse '%s' as an IP address\n", AddressString);\r
-               return -1;\r
-       }\r
-       \r
-       // Finds the interface for the destination address\r
-       iface = Net_GetInterface(addrType, addrBuffer);\r
-       if( iface == NULL ) {\r
-               fprintf(stderr, "Unable to find a route to '%s'\n", AddressString);\r
-               return -1;\r
-       }\r
-       \r
-       // Open client socket\r
-       // TODO: Move this out to libnet?\r
-       {\r
-                int    len = snprintf(NULL, 100, "/Devices/ip/%s/tcpc", iface);\r
-               char    path[len+1];\r
-               snprintf(path, 100, "/Devices/ip/%s/tcpc", iface);\r
-               fd = open(path, OPENFLAG_READ|OPENFLAG_WRITE);\r
-       }\r
-       \r
-       free(iface);\r
-       \r
-       if( fd == -1 ) {\r
-               return -1;\r
-       }\r
-\r
-       // Set remote port and address\r
-       ioctl(fd, 5, &PortNumber);\r
-       ioctl(fd, 6, addrBuffer);\r
-       \r
-       // Connect\r
-       if( ioctl(fd, 7, NULL) == 0 ) {\r
-               // Shouldn't happen :(\r
-               return -1;\r
-       }\r
-       \r
-       // Return descriptor\r
-       return fd;\r
-}\r
+/*
+ * Acess2 IRC Client
+ */
+#include <acess/sys.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <net.h>
+#include <stdarg.h>
+
+#include "common.h"
+#include "input.h"
+#include "window.h"
+#include "server.h"
+
+// === TYPES ===
+
+// === PROTOTYPES ===
+ int   main(int argc, const char *argv[], const char *envp[]);
+ int   MainLoop(void);
+ int   ParseArguments(int argc, const char *argv[]);
+// --- 
+void   Redraw_Screen(void);
+// --- Helpers
+void   Exit(const char *Reason);
+ int   writef(int FD, const char *Format, ...);
+ int   OpenTCP(const char *AddressString, short PortNumber);
+char   *GetValue(char *Str, int *Ofs);
+
+// === GLOBALS ===
+const char     *gsExitReason = "No reason [BUG]";
+
+// ==== CODE ====
+void ExitHandler(void)
+{
+       printf("\x1B[?1047l");
+       printf("Quit: %s\n", gsExitReason);
+}
+
+void Exit(const char *Reason)
+{
+       gsExitReason = (Reason ? Reason : "User Requested");
+       exit( (Reason ? 1 : 0) );
+}
+
+int main(int argc, const char *argv[], const char *envp[])
+{
+        int    tmp;
+       
+       // Parse Command line
+       if( (tmp = ParseArguments(argc, argv)) )        return tmp;
+       
+       atexit(ExitHandler);
+       
+       ACurses_Init();
+       
+       printf("\x1B[?1047h");
+       printf("\x1B[%i;%ir", 1, giTerminal_Height-1);
+       
+       SetCursorPos(giTerminal_Height-1, 1);
+       printf("[(status)] ");
+       
+       // HACK: Static server entry
+       // UCC (University [of Western Australia] Computer Club) IRC Server
+       tServer *starting_server = Server_Connect( "UCC", "130.95.13.18", 6667 );
+       // Freenode (#osdev)
+//     gWindow_Status.Server = Server_Connect( "Freenode", "89.16.176.16", 6667 );
+       // Local servers
+//     gWindow_Status.Server = Server_Connect( "VMHost", "10.0.2.2", 6667 );
+//     gWindow_Status.Server = Server_Connect( "BitlBee", "192.168.1.39", 6667 );
+       
+       if( !starting_server )
+               return -1;
+       
+       Windows_SetStatusServer(starting_server);
+       
+       MainLoop();
+
+       Servers_CloseAll("Client closing");
+       
+       return 0;
+}
+
+int MainLoop(void)
+{
+       SetCursorPos(giTerminal_Height-1, 1);
+       printf("[(status)] ");
+       fflush(stdout);
+       
+       for( ;; )
+       {
+               fd_set  readfds, errorfds;
+                int    nfds = 1;
+               
+               FD_ZERO(&readfds);
+               FD_ZERO(&errorfds);
+               
+               Input_FillSelect(&nfds, &readfds);
+               Servers_FillSelect(&nfds, &readfds, &errorfds);
+               
+               int rv = _SysSelect(nfds, &readfds, 0, &errorfds, NULL, 0);
+               if( rv < 0 )    break;
+               
+               // user input
+               Input_HandleSelect(nfds, &readfds);
+               
+               // Server response
+               Servers_HandleSelect(nfds, &readfds, &errorfds);
+       }
+       return 0;
+}
+
+/**
+ * \todo Actually implement correctly :)
+ */
+int ParseArguments(int argc, const char *argv[])
+{
+       return 0;
+}
+
+void Redraw_Screen(void)
+{
+       printf("\x1B[2J");      // Clear screen
+       printf("\x1B[0;0H");    // Reset cursor
+
+       Windows_RepaintCurrent();
+}
+
+/**
+ * \brief Write a formatted string to a file descriptor
+ * 
+ */
+int writef(int FD, const char *Format, ...)
+{
+       va_list args;
+        int    len;
+       
+       va_start(args, Format);
+       len = vsnprintf(NULL, 0, Format, args);
+       va_end(args);
+       
+       {
+               char    buf[len+1];
+               va_start(args, Format);
+               vsnprintf(buf, len+1, Format, args);
+               va_end(args);
+               
+               return _SysWrite(FD, buf, len);
+       }
+}
+
+/**
+ * \brief Initialise a TCP connection to \a AddressString on port \a PortNumber
+ */
+int OpenTCP(const char *AddressString, short PortNumber)
+{
+        int    fd, addrType;
+       char    addrBuffer[8];
+       
+       // Parse IP Address
+       addrType = Net_ParseAddress(AddressString, addrBuffer);
+       if( addrType == 0 ) {
+               fprintf(stderr, "Unable to parse '%s' as an IP address\n", AddressString);
+               _SysDebug("Unable to parse '%s' as an IP address\n", AddressString);
+               return -1;
+       }
+       
+       // Finds the interface for the destination address
+       fd = Net_OpenSocket(addrType, addrBuffer, "tcpc");
+       if( fd == -1 ) {
+               fprintf(stderr, "Unable to open TCP Client to '%s'\n", AddressString);
+               _SysDebug("Unable to open TCP client to '%s'\n", AddressString);
+               return -1;
+       }
+       
+       // Set remote port and address
+//     printf("Setting port and remote address\n");
+       _SysIOCtl(fd, 5, &PortNumber);
+       _SysIOCtl(fd, 6, addrBuffer);
+       
+       // Connect
+//     printf("Initiating connection\n");
+       if( _SysIOCtl(fd, 7, NULL) == 0 ) {
+               // Shouldn't happen :(
+               fprintf(stderr, "Unable to start connection\n");
+               return -1;
+       }
+       
+       // Return descriptor
+       return fd;
+}
+
+/**
+ * \brief Read a space-separated value from a string
+ */
+char *GetValue(char *Src, int *Ofs)
+{
+        int    pos = *Ofs;
+       char    *ret = Src + pos;
+       char    *end;
+       
+       if( !Src )      return NULL;
+       
+       while( *ret == ' ' )    ret ++;
+       
+       end = strchr(ret, ' ');
+       if( end ) {
+               *end = '\0';
+       }
+       else {
+               end = ret + strlen(ret) - 1;
+       }
+       
+       end ++ ;
+       while( *ret == ' ' )    end ++;
+       *Ofs = end - Src;
+       
+       return ret;
+}
+

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