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

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