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

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