+/*\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, 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 == -1 ) {\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/%i/tcpc", iface);\r
+ char path[len+1];\r
+ snprintf(path, 100, "/Devices/ip/%i/tcpc", iface);\r
+ fd = open(path, OPENFLAG_READ|OPENFLAG_WRITE);\r
+ }\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