Mercurial > hg > nnchat
annotate nnchat.c @ 27:da721f94c60f
Use ANSI colours.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 02 Aug 2008 04:04:58 +0300 |
parents | b84fc46c6035 |
children | 512775f6b081 |
rev | line source |
---|---|
0 | 1 #ifdef __WIN32 |
2 #include <winsock2.h> | |
3 #else | |
4 #include <sys/socket.h> | |
5 #include <sys/types.h> | |
6 #include <arpa/inet.h> | |
7 #include <sys/time.h> | |
8 #include <netdb.h> | |
9 #endif | |
10 | |
11 #include <unistd.h> | |
12 #include <stdlib.h> | |
13 #include <stdio.h> | |
14 #include "th_args.h" | |
15 #include "th_string.h" | |
16 #include <string.h> | |
17 #include <errno.h> | |
18 #include <time.h> | |
19 | |
20 | |
21 #define SET_ALLOC_SIZE (128) | |
22 #define SET_SELECT_USEC (100000) | |
23 | |
27 | 24 #define ANSI_BLACK "\x1b[0;30m" |
25 #define ANSI_RED "\x1b[0;31m" | |
26 #define ANSI_GREEN "\x1b[0;32m" | |
27 #define ANSI_YELLOW "\x1b[0;33m" | |
28 #define ANSI_BLUE "\x1b[0;34m" | |
29 #define ANSI_MAGENTA "\x1b[0;35m" | |
30 #define ANSI_CYAN "\x1b[0;36m" | |
31 #define ANSI_WHITE "\x1b[0;37m" | |
32 | |
33 #define ANSI_L_BLACK "\x1b[0;1;30m" | |
34 #define ANSI_L_RED "\x1b[0;1;31m" | |
35 #define ANSI_L_GREEN "\x1b[0;1;32m" | |
36 #define ANSI_L_YELLOW "\x1b[0;1;33m" | |
37 #define ANSI_L_BLUE "\x1b[0;1;34m" | |
38 #define ANSI_L_MAGENTA "\x1b[0;1;35m" | |
39 #define ANSI_L_CYAN "\x1b[0;1;36m" | |
40 #define ANSI_L_WHITE "\x1b[0;1;37m" | |
41 | |
42 #define ANSI_END "\x1b[0m" | |
43 | |
0 | 44 |
45 /* Options | |
46 */ | |
27 | 47 int optPort = 8005; |
48 int optUserColor = 0x408060; | |
49 char *optServer = "www11.servemedata.com", | |
50 *optUserName = NULL, | |
51 *optUserName2 = NULL, | |
52 *optPassword = NULL, | |
53 *optLogFilename = NULL, | |
54 *setTarget = NULL; | |
21 | 55 BOOL optDaemon = FALSE; |
0 | 56 FILE *optLogFile = NULL; |
57 | |
58 | |
59 /* Arguments | |
60 */ | |
61 optarg_t optList[] = { | |
27 | 62 { 0, '?', "help", "Show this help", OPT_NONE }, |
63 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, | |
64 { 2, 'p', "port", "Connect to port", OPT_ARGREQ }, | |
65 { 3, 's', "server", "Server to connect to", OPT_ARGREQ }, | |
66 { 4, 'C', "color", "Initial color in RGB hex 000000", OPT_ARGREQ }, | |
67 { 5, 'l', "logfile", "Log filename", OPT_ARGREQ }, | |
68 { 6, 'D', "daemon", "A pseudo-daemon mode for logging", OPT_NONE }, | |
0 | 69 }; |
70 | |
71 const int optListN = (sizeof(optList) / sizeof(optarg_t)); | |
72 | |
73 | |
74 void argShowHelp() | |
75 { | |
76 th_args_help(stdout, optList, optListN, th_prog_name, | |
77 "[options] <username> <password>"); | |
78 } | |
79 | |
80 | |
81 #ifdef __WIN32 | |
1 | 82 /* Just a bogus stub |
83 */ | |
0 | 84 const char *hstrerror(int err) |
85 { | |
1 | 86 (void) err; |
87 | |
0 | 88 return "???"; |
89 } | |
90 #endif | |
91 | |
27 | 92 |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
93 int getColor(char *str) |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
94 { |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
95 char *p = str; |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
96 int len, val = 0; |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
97 |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
98 for (len = 0; *p && len < 6; p++, len++) { |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
99 if (*p >= '0' && *p <= '9') { |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
100 val *= 16; val += (*p - '0'); |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
101 } else if (*p >= 'A' && *p <= 'F') { |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
102 val *= 16; val += (*p - 'A') + 10; |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
103 } else if (*p >= 'a' && *p <= 'f') { |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
104 val *= 16; val += (*p - 'a') + 10; |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
105 } else |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
106 return -1; |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
107 } |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
108 |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
109 return (len == 6) ? val : -1; |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
110 } |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
111 |
0 | 112 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) |
113 { | |
114 switch (optN) { | |
115 case 0: | |
116 argShowHelp(); | |
117 exit(0); | |
118 break; | |
119 | |
120 case 1: | |
121 th_verbosityLevel++; | |
122 break; | |
123 | |
124 case 2: | |
125 optPort = atoi(optArg); | |
126 break; | |
127 | |
128 case 3: | |
129 optServer = optArg; | |
130 break; | |
131 | |
132 case 4: | |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
133 if ((optUserColor = getColor(optArg)) < 0) { |
0 | 134 THERR("Invalid color argument '%s', should be a RGB hex triplet '000000'.\n", |
135 optArg); | |
136 return FALSE; | |
137 } | |
138 THMSG(1, "Using color #%06x\n", optUserColor); | |
139 break; | |
140 | |
141 case 5: | |
142 optLogFilename = optArg; | |
143 break; | |
144 | |
21 | 145 case 6: |
146 optDaemon = TRUE; | |
147 THMSG(1, "Running in pseudo-daemon mode.\n"); | |
148 break; | |
149 | |
0 | 150 default: |
151 THERR("Unknown option '%s'.\n", currArg); | |
152 return FALSE; | |
153 } | |
154 | |
155 return TRUE; | |
156 } | |
157 | |
158 | |
159 BOOL argHandleFile(char *currArg) | |
160 { | |
161 if (!optUserName) | |
162 optUserName = currArg; | |
163 else if (!optPassword) | |
164 optPassword = currArg; | |
165 else { | |
166 THERR("Username '%s' already specified on commandline!\n", optUserName); | |
167 return FALSE; | |
168 } | |
169 | |
170 return TRUE; | |
171 } | |
172 | |
173 | |
15 | 174 int openConnection(struct in_addr *addr, int port) |
175 { | |
176 struct sockaddr_in tmpAddr; | |
177 int sock = -1; | |
178 | |
179 tmpAddr.sin_family = AF_INET; | |
180 tmpAddr.sin_port = htons(port); | |
181 tmpAddr.sin_addr = *addr; | |
182 | |
183 THMSG(1, "Connecting to %s:%d ...\n", | |
184 inet_ntoa(tmpAddr.sin_addr), port); | |
185 | |
186 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { | |
187 THERR("Could not open socket: %s\n", strerror(errno)); | |
188 return -2; | |
189 } | |
190 | |
191 THMSG(2, "Using socket %d.\n", sock); | |
192 | |
193 if (connect(sock, (struct sockaddr *) &tmpAddr, sizeof(tmpAddr)) == -1) { | |
194 THERR("Could not connect: %s\n", strerror(errno)); | |
195 return -5; | |
196 } | |
197 | |
198 return sock; | |
199 } | |
200 | |
201 | |
202 void closeConnection(int sock) | |
203 { | |
204 if (sock >= 0) { | |
205 #ifdef __WIN32 | |
206 closesocket(sock); | |
207 #else | |
208 close(sock); | |
209 #endif | |
210 } | |
211 } | |
212 | |
213 | |
0 | 214 BOOL sendToSocket(int sock, char *buf, const size_t bufLen) |
215 { | |
216 size_t bufLeft = bufLen; | |
217 char *bufPtr = buf; | |
218 | |
219 while (bufLeft > 0) { | |
220 ssize_t bufSent; | |
221 bufSent = send(sock, bufPtr, bufLeft, 0); | |
222 if (bufSent < 0) return FALSE; | |
223 bufLeft -= bufSent; | |
224 bufPtr += bufSent; | |
225 } | |
226 return TRUE; | |
227 } | |
228 | |
229 | |
27 | 230 void printMsg(char *fmt, char *fmt2, ...) |
0 | 231 { |
232 char tmpStr[64] = ""; | |
233 va_list ap; | |
234 time_t timeStamp; | |
235 struct tm *tmpTime;; | |
236 | |
237 timeStamp = time(NULL); | |
238 if ((tmpTime = localtime(&timeStamp)) != NULL) { | |
27 | 239 strftime(tmpStr, sizeof(tmpStr), "%H:%M:%S", tmpTime); |
0 | 240 } |
241 | |
242 if (optLogFile) { | |
27 | 243 fprintf(optLogFile, "[%s] ", tmpStr); |
244 va_start(ap, fmt2); | |
0 | 245 vfprintf(optLogFile, fmt, ap); |
246 va_end(ap); | |
247 fflush(optLogFile); | |
248 } | |
249 | |
21 | 250 if (!optDaemon) { |
27 | 251 fprintf(stdout, ANSI_L_BLACK "[" ANSI_L_GREEN "%s" ANSI_L_BLACK "]" ANSI_END " ", tmpStr); |
252 va_start(ap, fmt2); | |
253 vfprintf(stdout, fmt2, ap); | |
21 | 254 va_end(ap); |
255 fflush(stdout); | |
256 } | |
0 | 257 } |
258 | |
259 | |
260 BOOL bufRealloc(char **buf, size_t *size, size_t add) | |
261 { | |
262 return ((*buf = th_realloc(*buf, *size + add)) != NULL); | |
263 } | |
264 | |
12 | 265 #define PUSHCHAR(x) bufPushChar(&result, &resSize, &resPos, x) |
0 | 266 BOOL bufPushChar(char **buf, size_t *size, size_t *pos, char ch) |
267 { | |
268 if (*pos >= *size && !bufRealloc(buf, size, SET_ALLOC_SIZE)) | |
269 return FALSE; | |
270 | |
271 (*buf)[*pos] = ch; | |
272 (*pos)++; | |
273 return TRUE; | |
274 } | |
275 | |
12 | 276 #define PUSHSTR(x) bufPushStr(&result, &resSize, &resPos, x) |
0 | 277 BOOL bufPushStr(char **buf, size_t *size, size_t *pos, char *str) |
278 { | |
279 size_t tmpLen; | |
280 | |
281 if (!str) return FALSE; | |
282 tmpLen = strlen(str); | |
283 | |
284 if ((*pos + tmpLen) >= *size && !bufRealloc(buf, size, tmpLen + SET_ALLOC_SIZE)) | |
285 return FALSE; | |
286 | |
287 strcpy(*buf + *pos, str); | |
288 (*pos) += tmpLen; | |
289 return TRUE; | |
290 } | |
291 | |
292 | |
293 char *encodeStr1(char *str) | |
294 { | |
295 char *result, *s = str; | |
296 size_t resSize, resPos = 0; | |
297 | |
298 if (!str) return NULL; | |
299 | |
300 resSize = strlen(str) + SET_ALLOC_SIZE; | |
301 if ((result = th_malloc(resSize)) == NULL) | |
302 return NULL; | |
303 | |
304 while (*s) { | |
305 switch (*s) { | |
306 case 32: | |
12 | 307 PUSHCHAR('+'); |
0 | 308 break; |
309 | |
310 default: | |
311 if (th_isalnum(*s)) | |
12 | 312 PUSHCHAR(*s); |
0 | 313 else { |
314 char tmpStr[4]; | |
315 sprintf(tmpStr, "%2X", (unsigned char) *s); | |
12 | 316 PUSHCHAR('%'); |
317 PUSHSTR(tmpStr); | |
0 | 318 } |
319 break; | |
320 } | |
321 s++; | |
322 } | |
12 | 323 PUSHCHAR(0); |
0 | 324 |
325 return result; | |
326 } | |
327 | |
15 | 328 |
0 | 329 int getxdigit(int c, int shift) |
330 { | |
331 int i; | |
332 | |
333 if (c >= 'A' && c <= 'F') | |
334 i = c - 'A' + 10; | |
335 else if (c >= 'a' && c <= 'f') | |
336 i = c - 'a' + 10; | |
337 else if (c >= '0' && c <= '9') | |
338 i = c - '0'; | |
339 else | |
340 return -1; | |
341 | |
342 return i << shift; | |
343 } | |
344 | |
15 | 345 |
0 | 346 char *decodeStr1(char *str) |
347 { | |
348 char *result, *s = str; | |
349 size_t resSize, resPos = 0; | |
350 int c; | |
351 | |
352 if (!str) return NULL; | |
353 | |
354 resSize = strlen(str) + SET_ALLOC_SIZE; | |
355 if ((result = th_malloc(resSize)) == NULL) | |
356 return NULL; | |
357 | |
358 while (*s) { | |
359 switch (*s) { | |
360 case '+': | |
12 | 361 PUSHCHAR(' '); |
0 | 362 s++; |
363 break; | |
364 | |
27 | 365 case '\r': |
366 PUSHCHAR(' '); | |
367 s++; | |
368 break; | |
369 | |
0 | 370 case '%': |
371 s++; | |
372 if (*s == '%') | |
12 | 373 PUSHCHAR('%'); |
0 | 374 else if ((c = getxdigit(*s, 4)) >= 0) { |
375 int i = getxdigit(*(++s), 0); | |
376 if (i >= 0) { | |
12 | 377 PUSHCHAR(c | i); |
0 | 378 } else { |
12 | 379 PUSHCHAR('§'); |
380 PUSHCHAR(*s); | |
0 | 381 } |
382 } else { | |
12 | 383 PUSHCHAR('§'); |
384 PUSHCHAR(*s); | |
0 | 385 } |
386 s++; | |
387 break; | |
388 | |
389 default: | |
12 | 390 PUSHCHAR(*s); |
0 | 391 s++; |
392 } | |
393 } | |
12 | 394 PUSHCHAR(0); |
0 | 395 |
396 return result; | |
397 } | |
398 | |
399 | |
400 char *stripTags(char *str) | |
401 { | |
402 char *result, *s = str; | |
403 size_t resSize, resPos = 0; | |
404 | |
405 if (!str) return NULL; | |
406 | |
407 resSize = strlen(str) + SET_ALLOC_SIZE; | |
408 if ((result = th_malloc(resSize)) == NULL) | |
409 return NULL; | |
410 | |
411 while (*s) { | |
412 if (*s == '<') { | |
413 while (*s && *s != '>') s++; | |
414 if (*s == '>') s++; | |
415 } else | |
12 | 416 PUSHCHAR(*s++); |
0 | 417 } |
12 | 418 PUSHCHAR(0); |
0 | 419 |
420 return result; | |
421 } | |
422 | |
423 | |
424 typedef struct { | |
425 char c; | |
426 char *ent; | |
427 } html_entity_t; | |
428 | |
429 | |
430 html_entity_t HTMLEntities[] = { | |
431 { '<', "<" }, | |
432 { '>', ">" }, | |
433 }; | |
434 | |
435 const int numHTMLEntities = (sizeof(HTMLEntities) / sizeof(html_entity_t)); | |
436 | |
437 | |
438 char *encodeStr2(char *str) | |
439 { | |
440 char *result, *s = str; | |
441 size_t resSize, resPos = 0; | |
442 | |
443 if (!str) return NULL; | |
444 | |
445 resSize = strlen(str) + SET_ALLOC_SIZE; | |
446 if ((result = th_malloc(resSize)) == NULL) | |
447 return NULL; | |
448 | |
449 while (*s) { | |
450 int i; | |
451 BOOL found = FALSE; | |
452 for (i = 0; i < numHTMLEntities; i++) | |
453 if (HTMLEntities[i].c == *s) { | |
12 | 454 PUSHSTR(HTMLEntities[i].ent); |
0 | 455 found = TRUE; |
456 break; | |
457 } | |
12 | 458 if (!found) PUSHCHAR(*s); |
0 | 459 |
460 s++; | |
461 } | |
12 | 462 PUSHCHAR(0); |
0 | 463 |
464 return result; | |
465 } | |
466 | |
467 | |
468 char *decodeStr2(char *str) | |
469 { | |
470 char *result, *s = str; | |
471 size_t resSize, resPos = 0; | |
472 | |
473 if (!str) return NULL; | |
474 | |
475 resSize = strlen(str); | |
476 if ((result = th_malloc(resSize)) == NULL) | |
477 return NULL; | |
478 | |
479 while (*s) { | |
480 if (*s == '&') { | |
481 int i; | |
482 BOOL found = FALSE; | |
483 for (i = 0; i < numHTMLEntities; i++) { | |
484 html_entity_t *ent = &HTMLEntities[i]; | |
485 int len = strlen(ent->ent); | |
486 if (!strncmp(s, ent->ent, len)) { | |
12 | 487 PUSHCHAR(ent->c); |
0 | 488 s += len; |
489 found = TRUE; | |
490 break; | |
491 } | |
492 } | |
12 | 493 if (!found) PUSHCHAR(*s++); |
0 | 494 } else |
12 | 495 PUSHCHAR(*s++); |
0 | 496 } |
12 | 497 PUSHCHAR(0); |
0 | 498 |
499 return result; | |
500 } | |
501 | |
502 | |
503 BOOL sendUserMsg(int sock, char *user, char *fmt, ...) | |
504 { | |
505 char tmpBuf[4096], tmpBuf2[4096+256]; | |
506 int n; | |
507 va_list ap; | |
508 | |
509 va_start(ap, fmt); | |
510 n = vsnprintf(tmpBuf, sizeof(tmpBuf), fmt, ap); | |
511 va_end(ap); | |
512 | |
513 if (n < 0) return FALSE; | |
514 | |
515 snprintf(tmpBuf2, sizeof(tmpBuf2), | |
516 "<USER>%s</USER><MESSAGE>%s</MESSAGE>", | |
517 user, tmpBuf); | |
518 | |
519 return sendToSocket(sock, tmpBuf2, strlen(tmpBuf2) + 1); | |
520 } | |
521 | |
522 | |
523 int handleUser(int sock, char *str) | |
524 { | |
525 const char *msg = "</USER><MESSAGE>"; | |
22 | 526 char *p = str, *q, *s, *t, *h; |
0 | 527 |
528 (void) sock; | |
529 | |
530 s = strstr(str, msg); | |
531 if (!s) return 1; | |
532 *s = 0; | |
533 s += strlen(msg); | |
534 | |
535 q = strstr(s, "</MESSAGE>"); | |
536 if (!q) return 3; | |
537 *q = 0; | |
538 | |
539 s = decodeStr1(s); | |
540 if (!s) return -1; | |
541 | |
542 p = decodeStr1(p); | |
543 if (!p) { | |
544 th_free(s); | |
545 return -2; | |
546 } | |
547 | |
548 | |
549 if (*s == '/') { | |
19 | 550 if (!strncmp(s, "/BPRV", 5)) { |
551 t = stripTags(s + 2); | |
22 | 552 h = decodeStr2(t); |
27 | 553 printMsg("%s\n", ANSI_YELLOW "%s" ANSI_END "\n", h); |
19 | 554 } else { |
555 t = stripTags(s + 1); | |
22 | 556 h = decodeStr2(t); |
27 | 557 printMsg("* %s\n", ANSI_L_YELLOW "* %s" ANSI_END "\n", h); |
19 | 558 } |
22 | 559 th_free(h); |
0 | 560 th_free(t); |
561 } else { | |
22 | 562 t = stripTags(s); |
563 h = decodeStr2(t); | |
27 | 564 printMsg("<%s> %s\n", ANSI_MAGENTA "<" ANSI_L_CYAN "%s" ANSI_MAGENTA ">" ANSI_END " %s\n", p, h); |
22 | 565 th_free(h); |
0 | 566 th_free(t); |
567 } | |
568 | |
569 th_free(s); | |
570 th_free(p); | |
571 return 0; | |
572 } | |
573 | |
574 | |
575 int handleLogin(int sock, char *str) | |
576 { | |
19 | 577 char tmpStr[256] = ""; |
578 time_t timeStamp; | |
579 struct tm *tmpTime;; | |
580 | |
581 timeStamp = time(NULL); | |
582 if ((tmpTime = localtime(&timeStamp)) != NULL) { | |
583 strftime(tmpStr, sizeof(tmpStr), "%c", tmpTime); | |
584 } | |
585 | |
0 | 586 if (!strncmp(str, "FAILURE", 7)) { |
27 | 587 printMsg("Login failure - %s\n", "Login failure - %s\n", tmpStr); |
0 | 588 return -2; |
589 } else if (!strncmp(str, "SUCCESS", 7)) { | |
27 | 590 printMsg("Login success - %s\n", "Login success - %s\n", tmpStr); |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
591 sendUserMsg(sock, optUserName2, "%%2FRequestUserList"); |
0 | 592 return 0; |
593 } else | |
594 return 1; | |
595 } | |
596 | |
597 | |
598 int handleAddUser(int sock, char *str) | |
599 { | |
9 | 600 char *p, *s = strstr(str, "</ADD_USER>"); |
0 | 601 |
602 (void) sock; | |
603 | |
604 if (!s) return 1; | |
605 *s = 0; | |
9 | 606 |
607 p = decodeStr1(str); | |
608 if (!p) return -1; | |
609 | |
27 | 610 printMsg("! %s ADDED.\n", "! " ANSI_GREEN "%s" ANSI_END " ADDED.\n", p); |
9 | 611 th_free(p); |
0 | 612 return 0; |
613 } | |
614 | |
615 | |
616 int handleDeleteUser(int sock, char *str) | |
617 { | |
9 | 618 char *p, *s = strstr(str, "</DELETE_USER>"); |
0 | 619 |
620 (void) sock; | |
621 | |
622 if (!s) return 1; | |
623 *s = 0; | |
9 | 624 |
625 p = decodeStr1(str); | |
626 if (!p) return -1; | |
627 | |
27 | 628 printMsg("! %s DELETED.\n", "! " ANSI_RED "%s" ANSI_END " DELETED.\n", p); |
9 | 629 th_free(p); |
0 | 630 return 0; |
631 } | |
632 | |
633 | |
634 int handleFoo(int sock, char *str) | |
635 { | |
636 (void) sock; (void) str; | |
637 | |
638 return 0; | |
639 } | |
640 | |
641 | |
642 typedef struct { | |
643 char *cmd; | |
644 int (*handler)(int, char *); | |
645 } protocmd_t; | |
646 | |
647 | |
648 protocmd_t protoCmds[] = { | |
649 { "<USER>", handleUser }, | |
650 { "<LOGIN_", handleLogin }, | |
651 { "<DELETE_USER>", handleDeleteUser }, | |
652 { "<ADD_USER>", handleAddUser }, | |
653 { "<NUMCLIENTS>", handleFoo }, | |
654 }; | |
655 | |
656 const int nprotoCmds = (sizeof(protoCmds) / sizeof(protocmd_t)); | |
657 | |
658 | |
659 int handleProtocol(int sock, char *buf, size_t bufLen) | |
660 { | |
661 int i; | |
662 | |
663 for (i = 0; i < nprotoCmds; i++) { | |
664 size_t cmdLen = strlen(protoCmds[i].cmd); | |
665 if (cmdLen < bufLen && !strncmp(buf, protoCmds[i].cmd, cmdLen)) { | |
666 return protoCmds[i].handler(sock, buf + cmdLen); | |
667 } | |
668 } | |
669 | |
670 return 1; | |
671 } | |
672 | |
673 | |
15 | 674 int handleUserInput(int sock, char *buf, size_t bufLen) |
0 | 675 { |
25
3b67a9a806a7
Added /color command to change colour.
Matti Hamalainen <ccr@tnsp.org>
parents:
24
diff
changeset
|
676 char *tmpStr, *tmpStr2, tmpBuf[4096]; |
0 | 677 BOOL result; |
678 | |
679 /* Trim right */ | |
680 buf[--bufLen] = 0; | |
681 while (bufLen > 0 && (buf[bufLen] == '\n' || buf[bufLen] == '\r' || th_isspace(buf[bufLen]))) | |
682 buf[bufLen--] = 0; | |
683 | |
684 //fprintf(stderr, "'%s'\n", buf); fflush(stderr); | |
685 | |
686 /* Check command */ | |
687 if (*buf == 0) { | |
688 return 1; | |
25
3b67a9a806a7
Added /color command to change colour.
Matti Hamalainen <ccr@tnsp.org>
parents:
24
diff
changeset
|
689 } else if (!strncmp(buf, "/color ", 7)) { |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
690 if ((optUserColor = getColor(buf+7)) < 0) { |
27 | 691 printMsg("Invalid color value '%s'\n", "Invalid color value '%s'\n", buf+7); |
25
3b67a9a806a7
Added /color command to change colour.
Matti Hamalainen <ccr@tnsp.org>
parents:
24
diff
changeset
|
692 return 1; |
3b67a9a806a7
Added /color command to change colour.
Matti Hamalainen <ccr@tnsp.org>
parents:
24
diff
changeset
|
693 } |
27 | 694 printMsg("Setting color to #%06x\n", "Setting color to #%06x\n", optUserColor); |
25
3b67a9a806a7
Added /color command to change colour.
Matti Hamalainen <ccr@tnsp.org>
parents:
24
diff
changeset
|
695 sendUserMsg(sock, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); |
3b67a9a806a7
Added /color command to change colour.
Matti Hamalainen <ccr@tnsp.org>
parents:
24
diff
changeset
|
696 return 0; |
27 | 697 } else if (!strncmp(buf, "/fake ", 6)) { |
698 printMsg("Sending /%s\n", "Sending /%s\n", buf+6); | |
699 tmpStr = encodeStr2(tmpBuf); | |
700 if (!tmpStr) return -2; | |
701 tmpStr2 = encodeStr1(tmpStr); | |
702 if (!tmpStr2) { | |
703 th_free(tmpStr); | |
704 return -3; | |
705 } | |
706 sendUserMsg(sock ,optUserName2, "%%2F%s", tmpStr2); | |
707 | |
708 th_free(tmpStr); | |
709 th_free(tmpStr2); | |
710 return 0; | |
711 } else if (!strncmp(buf, "/flood ", 7)) { | |
712 int i; | |
713 | |
714 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg . .", | |
715 buf+7); | |
716 | |
717 tmpStr = encodeStr2(tmpBuf); | |
718 if (!tmpStr) return -2; | |
719 tmpStr2 = encodeStr1(tmpStr); | |
720 if (!tmpStr2) { | |
721 th_free(tmpStr); | |
722 return -3; | |
723 } | |
724 | |
725 result = TRUE; | |
726 for (i = 0; i < 50 && result; i++) { | |
727 result = sendUserMsg(sock, optUserName2, "%s", tmpStr2); | |
728 usleep(250); | |
729 } | |
730 | |
731 th_free(tmpStr); | |
732 th_free(tmpStr2); | |
733 return 0; | |
24
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
734 } else if (!strncmp(buf, "/msg ", 5)) { |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
735 if (setTarget) { |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
736 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg %s", setTarget, buf+5); |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
737 buf = tmpBuf; |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
738 } else { |
27 | 739 printMsg("No target set!\n", ANSI_L_RED "No target set!" ANSI_END "\n"); |
24
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
740 return 1; |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
741 } |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
742 } else if (!strncmp(buf, "/to ", 4)) { |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
743 buf += 4; |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
744 th_free(setTarget); |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
745 setTarget = th_strdup(buf); |
27 | 746 printMsg("Set prv target to '%s'\n", |
747 "Set prv target to '" ANSI_L_GREEN "%s" ANSI_END "'\n", setTarget); | |
24
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
748 return 0; |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
749 } |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
750 |
78d260256450
Added two simple commands to simplify private chatting, "/to" and "/msg".
Matti Hamalainen <ccr@tnsp.org>
parents:
23
diff
changeset
|
751 { |
0 | 752 /* Send double-encoded */ |
22 | 753 //printf("ENC>%s\n", buf); |
754 //fflush(stdout); | |
0 | 755 |
756 tmpStr = encodeStr2(buf); | |
757 if (!tmpStr) return -2; | |
758 tmpStr2 = encodeStr1(tmpStr); | |
759 if (!tmpStr2) { | |
760 th_free(tmpStr); | |
761 return -3; | |
762 } | |
763 | |
764 result = sendUserMsg(sock, optUserName2, "%s", tmpStr2); | |
765 th_free(tmpStr); | |
766 th_free(tmpStr2); | |
767 if (result) | |
768 return 0; | |
769 else | |
770 return -1; | |
771 } | |
772 } | |
773 | |
774 | |
775 int main(int argc, char *argv[]) | |
776 { | |
777 int tmpSocket; | |
778 struct hostent *tmpHost; | |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
779 BOOL argsOK, exitProg = FALSE, colorSet = FALSE; |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
780 struct timeval tv; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
781 fd_set sockfds; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
782 fd_set inputfds; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
783 char *tmpStr; |
0 | 784 |
785 /* Initialize */ | |
21 | 786 th_init("NNChat", "Newbie Nudes chat client", "0.4", |
6
526ba3b578d7
Changed copyright etc. again.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
787 "Written and designed by Anonymous Finnish Guy (C) 2008", |
526ba3b578d7
Changed copyright etc. again.
Matti Hamalainen <ccr@tnsp.org>
parents:
4
diff
changeset
|
788 "This software is freeware, use and distribute as you wish."); |
0 | 789 th_verbosityLevel = 0; |
790 | |
791 /* Parse arguments */ | |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
792 argsOK = th_args_process(argc, argv, optList, optListN, |
0 | 793 argHandleOpt, argHandleFile, FALSE); |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
794 |
0 | 795 /* Check the mode and arguments */ |
796 if (optUserName == NULL || optPassword == NULL) { | |
797 THERR("User/pass not specified, get some --help\n"); | |
798 return -1; | |
799 } | |
800 | |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
801 if (!argsOK) |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
802 return -2; |
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
803 |
0 | 804 /* Open logfile */ |
805 if (optLogFilename) { | |
806 THMSG(1, "Opening logfile '%s'\n", optLogFilename); | |
807 | |
808 if ((optLogFile = fopen(optLogFilename, "a")) == NULL) { | |
809 THERR("Could not open logfile for appending!\n"); | |
810 return -9; | |
811 } | |
812 } | |
813 | |
10 | 814 #ifdef __WIN32 |
815 { | |
816 WSADATA wsaData; | |
817 if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { | |
818 THERR("WinSock API v2.0 not supported.\n"); | |
819 return -20; | |
820 } | |
821 } | |
822 #endif | |
823 | |
0 | 824 /* Okay ... */ |
825 THMSG(1, "Trying to resolve host '%s' ...\n", optServer); | |
826 tmpHost = gethostbyname(optServer); | |
827 if (tmpHost == NULL) { | |
828 THERR("Could not resolve hostname: %s.\n", | |
829 hstrerror(h_errno)); | |
830 return -3; | |
831 } | |
832 THMSG(2, "True hostname: %s\n", tmpHost->h_name); | |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
833 |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
834 /* To emulate the official client, we first make a fake connection ... */ |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
835 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
836 THERR("Fakeprobe connection setup failed!\n"); |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
837 goto err_exit; |
0 | 838 } |
839 | |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
840 tmpStr = "<policy-file-request/>"; |
23
40fecbab1dc1
Check for error condition properly.
Matti Hamalainen <ccr@tnsp.org>
parents:
22
diff
changeset
|
841 if (sendToSocket(tmpSocket, tmpStr, strlen(tmpStr) + 1) == FALSE) { |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
842 THERR("Failed to send fakeprobe.\n"); |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
843 goto err_exit; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
844 } else { |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
845 ssize_t gotBuf; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
846 char tmpBuf[4096]; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
847 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
848 tmpBuf[gotBuf-1] = 0; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
849 THMSG(2, "Probe got: %s\n", tmpBuf); |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
850 closeConnection(tmpSocket); |
0 | 851 } |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
852 |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
853 /* Okay, now do the proper connection ... */ |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
854 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
855 THERR("Main connection setup failed!\n"); |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
856 goto err_exit; |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
857 } |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
858 |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
859 |
0 | 860 THMSG(1, "Connected, logging in as '%s'.\n", optUserName); |
861 optUserName2 = encodeStr1(optUserName); | |
862 | |
863 sendUserMsg(tmpSocket, optUserName2, "%%2Flogin%%20%%2Dsite%%20NN%%20%%2Dpassword%%20%s", optPassword); | |
864 | |
865 FD_ZERO(&inputfds); | |
866 FD_SET(0, &inputfds); | |
867 FD_ZERO(&sockfds); | |
868 FD_SET(tmpSocket, &sockfds); | |
869 | |
870 while (!exitProg) { | |
871 ssize_t gotBuf; | |
872 int result; | |
873 char tmpBuf[4096]; | |
874 fd_set tmpfds; | |
875 | |
876 /* Check for incoming data from the server */ | |
877 tv.tv_sec = 0; | |
878 tv.tv_usec = SET_SELECT_USEC; | |
879 tmpfds = sockfds; | |
880 if ((result = select(tmpSocket+1, &tmpfds, NULL, NULL, &tv)) == -1) { | |
27 | 881 printMsg("Error occured in select(sockfds): %s\n", |
882 "Error occured in select(sockfds): %s\n", | |
883 strerror(errno)); | |
0 | 884 exitProg = TRUE; |
885 } else if (FD_ISSET(tmpSocket, &tmpfds)) { | |
886 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); | |
887 | |
888 if (gotBuf < 0) { | |
9 | 889 printMsg("Error in recv: %s\n", strerror(errno)); |
0 | 890 exitProg = TRUE; |
891 } else if (gotBuf == 0) { | |
27 | 892 printMsg("Server closed connection.\n", "Server closed connection.\n"); |
0 | 893 exitProg = TRUE; |
894 } else { | |
895 /* Handle protocol data */ | |
896 tmpBuf[gotBuf] = 0; | |
897 result = handleProtocol(tmpSocket, tmpBuf, gotBuf); | |
898 | |
899 if (result > 0) { | |
900 /* Couldn't handle the message for some reason */ | |
27 | 901 printMsg("Could not handle: %s\n", "Could not handle: %s\n", tmpBuf); |
0 | 902 } else if (result < 0) { |
903 /* Fatal error, quit */ | |
9 | 904 printMsg("Fatal error with message: %s\n", tmpBuf); |
0 | 905 exitProg = TRUE; |
906 } | |
907 } | |
908 } | |
909 | |
910 /* Check for user input */ | |
21 | 911 if (!optDaemon) { |
0 | 912 tv.tv_sec = 0; |
913 tv.tv_usec = SET_SELECT_USEC; | |
914 tmpfds = inputfds; | |
915 if ((result = select(1, &tmpfds, NULL, NULL, &tv)) == -1) { | |
9 | 916 printMsg("Error occured in select(inputfds): %s\n", strerror(errno)); |
0 | 917 exitProg = TRUE; |
918 } else if (FD_ISSET(0, &tmpfds)) { | |
919 gotBuf = read(0, tmpBuf, sizeof(tmpBuf)); | |
920 | |
921 if (gotBuf < 0) { | |
27 | 922 printMsg("Error in reading stdio.\n", "Error in reading stdio.\n"); |
0 | 923 exitProg = TRUE; |
924 } else { | |
925 /* Call the user input handler */ | |
15 | 926 result = handleUserInput(tmpSocket, tmpBuf, gotBuf); |
0 | 927 if (result < 0) { |
9 | 928 printMsg("Fatal error handling user input: %s\n", |
0 | 929 tmpBuf); |
930 exitProg = TRUE; | |
931 } | |
932 } | |
933 } | |
21 | 934 } /* !optDaemon */ |
0 | 935 |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
936 if (!colorSet) { |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
937 colorSet = TRUE; |
27 | 938 sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
939 } |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
940 |
0 | 941 fflush(stdout); |
942 fflush(stderr); | |
943 } | |
944 | |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
945 /* Shotdiwn */ |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
946 err_exit: |
26
b84fc46c6035
Improved color hex triplet parsing.
Matti Hamalainen <ccr@tnsp.org>
parents:
25
diff
changeset
|
947 THMSG(1, "Error exit.\n"); |
0 | 948 th_free(optUserName2); |
10 | 949 |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
950 closeConnection(tmpSocket); |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
951 |
10 | 952 #ifdef __WIN32 |
953 WSACleanup(); | |
954 #endif | |
13
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
955 |
86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
Matti Hamalainen <ccr@tnsp.org>
parents:
12
diff
changeset
|
956 THMSG(1, "Connection terminated.\n"); |
0 | 957 |
958 if (optLogFile) { | |
959 THMSG(1, "Closing logfile.\n"); | |
960 fclose(optLogFile); | |
961 } | |
962 | |
963 | |
964 return 0; | |
965 } |