Slight bugfixes and output cleanups
[tpg/acess2.git] / Usermode / Applications / irc_src / main.c
1 /*\r
2  * Acess2 IRC Client\r
3  */\r
4 #include <acess/sys.h>\r
5 #include <stdlib.h>\r
6 #include <stdio.h>\r
7 #include <string.h>\r
8 #include <net.h>\r
9 \r
10 #define BUFSIZ  1023\r
11 \r
12 // === TYPES ===\r
13 typedef struct sServer {\r
14          int    FD;\r
15         char    InBuf[BUFSIZ+1];\r
16          int    ReadPos;\r
17 } tServer;\r
18 \r
19 // === PROTOTYPES ===\r
20  int    ParseArguments(int argc, const char *argv[]);\r
21 void    ProcessIncoming(tServer *Server);\r
22  int    writef(int FD, const char *Format, ...);\r
23  int    OpenTCP(const char *AddressString, short PortNumber);\r
24 \r
25 // === GLOBALS ===\r
26 char    *gsUsername = "root";\r
27 char    *gsHostname = "acess";\r
28 char    *gsRemoteAddress = NULL;\r
29 char    *gsRealName = "Acess2 IRC Client";\r
30 char    *gsNickname = "acess";\r
31 short   giRemotePort = 6667;\r
32 \r
33 // ==== CODE ====\r
34 int main(int argc, const char *argv[], const char *envp[])\r
35 {\r
36          int    tmp;\r
37         tServer srv;\r
38         \r
39         memset(&srv, 0, sizeof(srv));\r
40         \r
41         // Parse Command line\r
42         // - Sets the server configuration globals\r
43         if( (tmp = ParseArguments(argc, argv)) ) {\r
44                 return tmp;\r
45         }\r
46         \r
47         // Connect to the remove server\r
48         srv.FD = OpenTCP( gsRemoteAddress, giRemotePort );\r
49         if( srv.FD == -1 ) {\r
50                 fprintf(stderr, "Unable to create socket\n");\r
51                 return -1;\r
52         }\r
53         \r
54         printf("Connection opened\n");\r
55         \r
56         writef(srv.FD, "USER %s %s %s : %s\n", gsUsername, gsHostname, gsRemoteAddress, gsRealName);\r
57         writef(srv.FD, "NICK %s", gsNickname);\r
58         \r
59         ProcessIncoming(&srv);\r
60         \r
61         close(srv.FD);\r
62         return 0;\r
63 }\r
64 \r
65 /**\r
66  * \todo Actually implement correctly :)\r
67  */\r
68 int ParseArguments(int argc, const char *argv[])\r
69 {\r
70         gsRemoteAddress = "130.95.13.18";       // irc.ucc.asn.au\r
71         \r
72         return 0;\r
73 }\r
74 \r
75 void Cmd_PRIVMSG(tServer *Server, const char *Dest, const char *Src, const char *Message)\r
76 {\r
77         printf("%p: %s => %s\t%s\n", Server, Src, Dest, Message);\r
78 }\r
79 \r
80 /**\r
81  * \brief Read a space-separated value from a string\r
82  */\r
83 char *GetValue(char *Src, int *Ofs)\r
84 {\r
85          int    pos = *Ofs;\r
86         char    *ret = Src + pos;\r
87         char    *end;\r
88         \r
89         while( *ret == ' ' )    ret ++;\r
90         \r
91         end = strchr(ret, ' ');\r
92         if( end ) {\r
93                 *end = '\0';\r
94         }\r
95         else {\r
96                 end = ret + strlen(ret) - 1;\r
97         }\r
98         *Ofs = end - Src + 1;\r
99         \r
100         return ret;\r
101 }\r
102 \r
103 /**\r
104  */\r
105 void ParseServerLine(tServer *Server, char *Line)\r
106 {\r
107          int    pos;\r
108         char    *ident, *cmd;\r
109         if( *Line == ':' ) {\r
110                 // Message\r
111                 ident = GetValue(Line, &pos);\r
112                 pos ++; // Space\r
113                 cmd = GetValue(Line, &pos);\r
114                 \r
115                 if( strcmp(cmd, "PRIVMSG") == 0 ) {\r
116                         char    *dest, *message;\r
117                         pos ++;\r
118                         dest = GetValue(Line, &pos);\r
119                         pos ++;\r
120                         if( Line[pos] == ':' ) {\r
121                                 message = Line + pos + 1;\r
122                         }\r
123                         else {\r
124                                 message = GetValue(Line, &pos);\r
125                         }\r
126                         Cmd_PRIVMSG(Server, dest, ident, message);\r
127                 }\r
128         }\r
129         else {\r
130                 // Command to client\r
131         }\r
132 }\r
133 \r
134 /**\r
135  * \brief Process incoming lines from the server\r
136  */\r
137 void ProcessIncoming(tServer *Server)\r
138 {       \r
139         char    *ptr, *newline;\r
140          int    len;\r
141         \r
142         // While there is data in the buffer, read it into user memory and \r
143         // process it line by line\r
144         // ioctl#8 on a TCP client gets the number of bytes in the recieve buffer\r
145         // - Used to avoid blocking\r
146         while( ioctl(Server->FD, 8, NULL) )\r
147         {\r
148                 // Read data\r
149                 len = read(Server->FD, BUFSIZ - Server->ReadPos, Server->InBuf + Server->ReadPos);\r
150                 Server->InBuf[Server->ReadPos + len] = '\0';\r
151                 \r
152                 // Break into lines\r
153                 ptr = Server->InBuf;\r
154                 while( (newline = strchr(ptr, '\n')) )\r
155                 {\r
156                         *newline = '\0';\r
157                         printf("%s\n", ptr);\r
158                         ParseServerLine(Server, ptr);\r
159                         ptr = newline + 1;\r
160                 }\r
161                 \r
162                 // Handle incomplete lines\r
163                 if( ptr - Server->InBuf < len + Server->ReadPos ) {\r
164                         Server->ReadPos = ptr - Server->InBuf;\r
165                         memcpy(Server->InBuf, ptr, Server->ReadPos);\r
166                 }\r
167                 else {\r
168                         Server->ReadPos = 0;\r
169                 }\r
170         }\r
171 }\r
172 \r
173 /**\r
174  * \brief Write a formatted string to a file descriptor\r
175  * \r
176  */\r
177 int writef(int FD, const char *Format, ...)\r
178 {\r
179         va_list args;\r
180          int    len;\r
181         \r
182         va_start(args, Format);\r
183         len = vsnprintf(NULL, 1000, Format, args);\r
184         va_end(args);\r
185         \r
186         {\r
187                 char    buf[len+1];\r
188                 va_start(args, Format);\r
189                 vsnprintf(buf, len+1, Format, args);\r
190                 va_end(args);\r
191                 \r
192                 return write(FD, len, buf);\r
193         }\r
194 }\r
195 \r
196 /**\r
197  * \brief Initialise a TCP connection to \a AddressString on port \a PortNumber\r
198  */\r
199 int OpenTCP(const char *AddressString, short PortNumber)\r
200 {\r
201          int    fd, addrType;\r
202         char    *iface;\r
203         char    addrBuffer[8];\r
204         \r
205         // Parse IP Address\r
206         addrType = Net_ParseAddress(AddressString, addrBuffer);\r
207         if( addrType == 0 ) {\r
208                 fprintf(stderr, "Unable to parse '%s' as an IP address\n", AddressString);\r
209                 return -1;\r
210         }\r
211         \r
212         // Finds the interface for the destination address\r
213         iface = Net_GetInterface(addrType, addrBuffer);\r
214         if( iface == NULL ) {\r
215                 fprintf(stderr, "Unable to find a route to '%s'\n", AddressString);\r
216                 return -1;\r
217         }\r
218         \r
219         printf("iface = '%s'\n", iface);\r
220         \r
221         // Open client socket\r
222         // TODO: Move this out to libnet?\r
223         {\r
224                  int    len = snprintf(NULL, 100, "/Devices/ip/%s/tcpc", iface);\r
225                 char    path[len+1];\r
226                 snprintf(path, 100, "/Devices/ip/%s/tcpc", iface);\r
227                 fd = open(path, OPENFLAG_READ|OPENFLAG_WRITE);\r
228         }\r
229         \r
230         free(iface);\r
231         \r
232         if( fd == -1 ) {\r
233                 fprintf(stderr, "Unable to open TCP Client for reading\n");\r
234                 return -1;\r
235         }\r
236         \r
237         // Set remote port and address\r
238         printf("Setting port and remote address\n");\r
239         ioctl(fd, 5, &PortNumber);\r
240         ioctl(fd, 6, addrBuffer);\r
241         \r
242         // Connect\r
243         printf("Initiating connection\n");\r
244         if( ioctl(fd, 7, NULL) == 0 ) {\r
245                 // Shouldn't happen :(\r
246                 fprintf(stderr, "Unable to start connection\n");\r
247                 return -1;\r
248         }\r
249         \r
250         // Return descriptor\r
251         return fd;\r
252 }\r

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