summaryrefslogtreecommitdiff
path: root/vchat-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'vchat-client.c')
-rwxr-xr-xvchat-client.c586
1 files changed, 303 insertions, 283 deletions
diff --git a/vchat-client.c b/vchat-client.c
index e1fb8fc..c094376 100755
--- a/vchat-client.c
+++ b/vchat-client.c
@@ -15,25 +15,27 @@
15 */ 15 */
16 16
17/* general includes */ 17/* general includes */
18#include <sys/types.h> 18#include <errno.h>
19#include <sys/time.h> 19#include <locale.h>
20#include <signal.h>
20#include <stdint.h> 21#include <stdint.h>
21#include <time.h>
22#include <string.h>
23#include <unistd.h>
24#include <stdio.h> 22#include <stdio.h>
25#include <stdlib.h> 23#include <stdlib.h>
26#include <errno.h> 24#include <string.h>
27#include <signal.h> 25#include <sys/time.h>
26#include <sys/types.h>
27#include <time.h>
28#include <unistd.h>
29
28#include <readline/readline.h> 30#include <readline/readline.h>
29#include <locale.h>
30 31
31#include "vchat.h"
32#include "vchat-connection.h" 32#include "vchat-connection.h"
33#include "vchat-user.h" 33#include "vchat-user.h"
34#include "vchat.h"
34 35
35/* version of this module */ 36/* version of this module */
36const char *vchat_cl_version = "vchat-client.c $Id$"; 37const char *vchat_cl_version =
38 "vchat-client.c $Id$";
37 39
38/* externally used variables */ 40/* externally used variables */
39/* we're logged in */ 41/* we're logged in */
@@ -54,139 +56,149 @@ char errstr[ERRSTRSIZE] = "\0";
54/* declaration of configuration array */ 56/* declaration of configuration array */
55#include "vchat-config.h" 57#include "vchat-config.h"
56 58
57void setnoption (const char *, char *); 59void setnoption(const char *, char *);
58 60
59static void parsecfg(char *line) { 61static void parsecfg(char *line) {
60 int bytes; 62 int bytes;
61 char *param=line; 63 char *param = line;
62 char *value=NULL; 64 char *value = NULL;
63 65
64 /* handle quotes value is empty, so we can use it */ 66 /* handle quotes value is empty, so we can use it */
65 value = strchr(line,'#'); 67 value = strchr(line, '#');
66 if (value) { /* the line contains a cute little quote */ 68 if (value) { /* the line contains a cute little quote */
67 value[0]='\0'; /* ignore the rest of the line */ 69 value[0] = '\0'; /* ignore the rest of the line */
68 } 70 }
69 71
70 /* now split the line into two parts */ 72 /* now split the line into two parts */
71 value = strchr(line,'='); 73 value = strchr(line, '=');
72 if (!value) return; /* exit if strchr fails */ 74 if (!value)
73 value[0]='\0'; 75 return; /* exit if strchr fails */
76 value[0] = '\0';
74 value++; 77 value++;
75 78
76 /* "trim" values */ 79 /* "trim" values */
77 while ((value[0] == ' ')||(value[0] == '\t')) 80 while ((value[0] == ' ') || (value[0] == '\t'))
78 value++; 81 value++;
79 bytes = strlen(value); 82 bytes = strlen(value);
80 while ((value[bytes-1] == ' ')||(value[bytes-1] == '\t')) { 83 while ((value[bytes - 1] == ' ') || (value[bytes - 1] == '\t')) {
81 value[bytes-1] = '\0'; 84 value[bytes - 1] = '\0';
82 bytes=strlen(value); 85 bytes = strlen(value);
83 } 86 }
84 /* bytes should be strlen(value) */ 87 /* bytes should be strlen(value) */
85 if ( value[bytes-1] == '"' ) value[bytes-1] = '\0'; 88 if (value[bytes - 1] == '"')
86 if ( value[0] == '"' ) value++; 89 value[bytes - 1] = '\0';
90 if (value[0] == '"')
91 value++;
87 92
88 /* "trim" param */ 93 /* "trim" param */
89 while ((param[0] == ' ')||(param[0] == '\t')) 94 while ((param[0] == ' ') || (param[0] == '\t'))
90 param++; 95 param++;
91 bytes = strlen(param); 96 bytes = strlen(param);
92 while ((param[bytes-1] == ' ')||(param[bytes-1] == '\t')) { 97 while ((param[bytes - 1] == ' ') || (param[bytes - 1] == '\t')) {
93 param[bytes-1] = '\0'; 98 param[bytes - 1] = '\0';
94 bytes=strlen(param); 99 bytes = strlen(param);
95 } 100 }
96 /* bytes should be strlen(param) */ 101 /* bytes should be strlen(param) */
97 if ( param[bytes-1] == '\"' ) param[bytes-1] = '\0'; 102 if (param[bytes - 1] == '\"')
98 if ( param[0] == '\"' ) param++; 103 param[bytes - 1] = '\0';
104 if (param[0] == '\"')
105 param++;
99 106
100 if ((!param)||(!value)) return; /* failsave */ 107 if ((!param) || (!value))
108 return; /* failsave */
101 109
102 //fprintf(stderr,"\"%s\" -> \"%s\"\n",param,value); 110 // fprintf(stderr,"\"%s\" -> \"%s\"\n",param,value);
103 setnoption(param,value); 111 setnoption(param, value);
104} 112}
105 113
106static void parseformats(char *line) { 114static void parseformats(char *line) {
107 int i; 115 int i;
108 char *tmp = NULL; 116 char *tmp = NULL;
109 117
110 /* read a format line from file, syntax is 118 /* read a format line from file, syntax is
111 FS_XXX = "formatstring" 119 FS_XXX = "formatstring"
112 */ 120 */
113 121
114 while( *line == ' ') line++; 122 while (*line == ' ')
115 123 line++;
116 if( strlen( line ) > TMPSTRSIZE ) return; 124
117 125 if (strlen(line) > TMPSTRSIZE)
118 if( *line != '#') /* allow to comment out the line */ 126 return;
119 for (i = 0; formatstrings[i].formatstr; i++) 127
120 if (!strncasecmp(formatstrings[i].idstring, line, strlen( formatstrings[i].idstring) )) 128 if (*line != '#') /* allow to comment out the line */
121 { 129 for (i = 0; formatstrings[i].formatstr; i++)
122 char *tail = line + strlen( formatstrings[i].idstring); 130 if (!strncasecmp(formatstrings[i].idstring, line,
123 while( *tail==' ' || *tail=='\t') tail++; /* and skip whitespaces */ 131 strlen(formatstrings[i].idstring))) {
124 132 char *tail = line + strlen(formatstrings[i].idstring);
125 if( *tail++ == '=' ) 133 while (*tail == ' ' || *tail == '\t')
126 { 134 tail++; /* and skip whitespaces */
127 while( *tail==' ' || *tail=='\t') tail++; 135
128 if( *(tail++)=='\"' ) 136 if (*tail++ == '=') {
129 { 137 while (*tail == ' ' || *tail == '\t')
130 int j, k = 0, stringends = 0, backslash=0; 138 tail++;
131 for ( j = 0; tail[j] && !stringends; j++) 139 if (*(tail++) == '\"') {
132 { 140 int j, k = 0, stringends = 0, backslash = 0;
133 switch( tail[j] ) { 141 for (j = 0; tail[j] && !stringends; j++) {
134 case '^': 142 switch (tail[j]) {
135 if ( tail[j+1] != '^' ) 143 case '^':
136 tmpstr[k++] = 1; 144 if (tail[j + 1] != '^')
137 break; 145 tmpstr[k++] = 1;
138 case '\\': 146 break;
139 backslash=1-backslash; 147 case '\\':
140 tmpstr[k++] = '\\'; 148 backslash = 1 - backslash;
141 break; 149 tmpstr[k++] = '\\';
142 case '\"': 150 break;
143 if (backslash) k--; else stringends = 1; 151 case '\"':
144 default: 152 if (backslash)
145 tmpstr[k++] = tail[j]; 153 k--;
146 backslash = 0; 154 else
147 } 155 stringends = 1;
148 } 156 default:
149 157 tmpstr[k++] = tail[j];
150 if ( stringends && ( (tmp = (char *)malloc( 1 + j )) != NULL ) ) 158 backslash = 0;
151 {
152 memcpy( tmp, tmpstr, k);
153 tmp[k-1]=0;
154 formatstrings[i].formatstr = tmp;
155 }
156 }
157 } 159 }
158 } 160 }
159 161
162 if (stringends && ((tmp = (char *)malloc(1 + j)) != NULL)) {
163 memcpy(tmp, tmpstr, k);
164 tmp[k - 1] = 0;
165 formatstrings[i].formatstr = tmp;
166 }
167 }
168 }
169 }
160} 170}
161 171
162/* UNUSED uncomment if needed 172/* UNUSED uncomment if needed
163static void parseknownhosts(char *line) { 173static void parseknownhosts(char *line) {
164} 174}
165*/ 175*/
166 176
167/* load config file */ 177/* load config file */
168void 178void loadcfg(char *file, int complain, void (*lineparser)(char *)) {
169loadcfg (char *file,int complain, void (*lineparser) (char *))
170{
171 FILE *fh; 179 FILE *fh;
172#define BUFSIZE 4096 180#define BUFSIZE 4096
173 char buf[BUFSIZE]; /* data buffer */ 181 char buf[BUFSIZE]; /* data buffer */
174 char *tildex = NULL, *t; 182 char *tildex = NULL, *t;
175 183
176 /* Check and expand filename then open file */ 184 /* Check and expand filename then open file */
177 if (!file) return; 185 if (!file)
178 tildex = tilde_expand( file ); 186 return;
179 if (!tildex) return; 187 tildex = tilde_expand(file);
180 fh = fopen( tildex, "r" ); 188 if (!tildex)
181 free( tildex ); 189 return;
190 fh = fopen(tildex, "r");
191 free(tildex);
182 192
183 if (!fh) { 193 if (!fh) {
184 if( complain ) snprintf (errstr, TMPSTRSIZE, "Can't open config-file \"%s\": %s.", file, strerror(errno)); 194 if (complain)
195 snprintf(errstr, TMPSTRSIZE, "Can't open config-file \"%s\": %s.", file,
196 strerror(errno));
185 return; 197 return;
186 } 198 }
187 199
188 while ( fgets( buf, sizeof(buf), fh ) ) { 200 while (fgets(buf, sizeof(buf), fh)) {
189 if( ( t = strchr( buf, '\n' ) ) ) 201 if ((t = strchr(buf, '\n')))
190 *t = 0; 202 *t = 0;
191 lineparser(buf); 203 lineparser(buf);
192 } 204 }
@@ -194,77 +206,62 @@ loadcfg (char *file,int complain, void (*lineparser) (char *))
194 fclose(fh); 206 fclose(fh);
195} 207}
196 208
197void 209void loadconfig(char *file) { loadcfg(file, 1, parsecfg); }
198loadconfig (char *file)
199{
200 loadcfg(file,1,parsecfg);
201}
202 210
203void 211void loadformats(char *file) { loadcfg(file, 0, parseformats); }
204loadformats (char *file)
205{
206 loadcfg(file,0,parseformats);
207}
208 212
209/* get-format-string */ 213/* get-format-string */
210char * 214char *getformatstr(formtstr id) {
211getformatstr (formtstr id)
212{
213 int i; 215 int i;
214 for (i = 0; formatstrings[i].formatstr; i++) 216 for (i = 0; formatstrings[i].formatstr; i++)
215 if (formatstrings[i].id == id) return formatstrings[i].formatstr; 217 if (formatstrings[i].id == id)
218 return formatstrings[i].formatstr;
216 return NULL; 219 return NULL;
217} 220}
218 221
219/* get-string-option, fetches *char-value of variable named by option */ 222/* get-string-option, fetches *char-value of variable named by option */
220char * 223char *getstroption(confopt option) {
221getstroption (confopt option)
222{
223 int i; 224 int i;
224#ifdef DEBUG 225#ifdef DEBUG
225 fprintf(stderr,"getstroption: %d\n",option); 226 fprintf(stderr, "getstroption: %d\n", option);
226#endif 227#endif
227 for (i = 0; configoptions[i].type != CO_NIL; i++) 228 for (i = 0; configoptions[i].type != CO_NIL; i++)
228 if ((configoptions[i].id == option) && (configoptions[i].type == CO_STR)) { 229 if ((configoptions[i].id == option) && (configoptions[i].type == CO_STR)) {
229 if (!configoptions[i].value) 230 if (!configoptions[i].value)
230 return configoptions[i].defaultvalue; 231 return configoptions[i].defaultvalue;
231 else 232 else
232 return configoptions[i].value; 233 return configoptions[i].value;
233 } 234 }
234 return NULL; 235 return NULL;
235} 236}
236 237
237/* set-string-option, puts *char-value to variable named by option */ 238/* set-string-option, puts *char-value to variable named by option */
238void 239void setstroption(confopt option, char *string) {
239setstroption (confopt option, char *string)
240{
241 int i; 240 int i;
242#ifdef DEBUG 241#ifdef DEBUG
243 fprintf(stderr,"setstroption: %d to %s\n",option,string); 242 fprintf(stderr, "setstroption: %d to %s\n", option, string);
244#endif 243#endif
245 for (i = 0; configoptions[i].type != CO_NIL; i++) 244 for (i = 0; configoptions[i].type != CO_NIL; i++)
246 if ((configoptions[i].id == option) && (configoptions[i].type == CO_STR)) { 245 if ((configoptions[i].id == option) && (configoptions[i].type == CO_STR)) {
247 if (configoptions[i].value) 246 if (configoptions[i].value)
248 free(configoptions[i].value); 247 free(configoptions[i].value);
249 if (string) 248 if (string)
250 configoptions[i].value = strdup(string); 249 configoptions[i].value = strdup(string);
251 else 250 else
252 configoptions[i].value = NULL; 251 configoptions[i].value = NULL;
253 if (configoptions[i].localvar.pstr) 252 if (configoptions[i].localvar.pstr)
254 *configoptions[i].localvar.pstr = configoptions[i].value; 253 *configoptions[i].localvar.pstr = configoptions[i].value;
255 } 254 }
256} 255}
257 256
258/* set-named-option, puts string to variable named by name */ 257/* set-named-option, puts string to variable named by name */
259void 258void setnoption(const char *name, char *string) {
260setnoption (const char *name, char *string)
261{
262 int i; 259 int i;
263#ifdef DEBUG 260#ifdef DEBUG
264 fprintf(stderr,"setstrnoption: %s to %s\n",name,string); 261 fprintf(stderr, "setstrnoption: %s to %s\n", name, string);
265#endif 262#endif
266 for (i = 0; configoptions[i].type != CO_NIL; i++) 263 for (i = 0; configoptions[i].type != CO_NIL; i++)
267 if (!strcmp(configoptions[i].varname,name)) { 264 if (!strcmp(configoptions[i].varname, name)) {
268 if (configoptions[i].type == CO_STR) { 265 if (configoptions[i].type == CO_STR) {
269 if (configoptions[i].value) 266 if (configoptions[i].value)
270 free(configoptions[i].value); 267 free(configoptions[i].value);
@@ -273,265 +270,288 @@ setnoption (const char *name, char *string)
273 else 270 else
274 configoptions[i].value = NULL; 271 configoptions[i].value = NULL;
275 if (configoptions[i].localvar.pstr) 272 if (configoptions[i].localvar.pstr)
276 *configoptions[i].localvar.pstr = configoptions[i].value; 273 *configoptions[i].localvar.pstr = configoptions[i].value;
277 } else if (configoptions[i].type == CO_INT) { 274 } else if (configoptions[i].type == CO_INT) {
278 configoptions[i].value = (char *)(uintptr_t)atoi(string); 275 configoptions[i].value = (char *)(uintptr_t)atoi(string);
279 if (configoptions[i].localvar.pint) 276 if (configoptions[i].localvar.pint)
280 *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value; 277 *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value;
281 } 278 }
282 } 279 }
283} 280}
284 281
285/* get-integer-option, fetches int-value of variable named by option */ 282/* get-integer-option, fetches int-value of variable named by option */
286int 283int getintoption(confopt option) {
287getintoption (confopt option)
288{
289 int i; 284 int i;
290#ifdef DEBUG 285#ifdef DEBUG
291 fprintf(stderr,"getintoption: %d\n",option); 286 fprintf(stderr, "getintoption: %d\n", option);
292#endif 287#endif
293 for (i = 0; configoptions[i].type != CO_NIL; i++) 288 for (i = 0; configoptions[i].type != CO_NIL; i++)
294 if ((configoptions[i].id == option) && (configoptions[i].type == CO_INT)) { 289 if ((configoptions[i].id == option) && (configoptions[i].type == CO_INT)) {
295 if ((intptr_t)configoptions[i].value == -1) 290 if ((intptr_t)configoptions[i].value == -1)
296 return (intptr_t) configoptions[i].defaultvalue; 291 return (intptr_t)configoptions[i].defaultvalue;
297 else 292 else
298 return (intptr_t) configoptions[i].value; 293 return (intptr_t)configoptions[i].value;
299 } 294 }
300 return 0; 295 return 0;
301} 296}
302 297
303/* set-integer-option, puts int-value to variable named by option */ 298/* set-integer-option, puts int-value to variable named by option */
304void 299void setintoption(confopt option, int value) {
305setintoption (confopt option, int value)
306{
307 int i; 300 int i;
308#ifdef DEBUG 301#ifdef DEBUG
309 fprintf(stderr,"setintoption: %d to %d\n",option,value); 302 fprintf(stderr, "setintoption: %d to %d\n", option, value);
310#endif 303#endif
311 for (i = 0; configoptions[i].type != CO_NIL; i++) 304 for (i = 0; configoptions[i].type != CO_NIL; i++)
312 if ((configoptions[i].id == option) && (configoptions[i].type == CO_INT)) { 305 if ((configoptions[i].id == option) && (configoptions[i].type == CO_INT)) {
313 configoptions[i].value = (char *)(uintptr_t)value; 306 configoptions[i].value = (char *)(uintptr_t)value;
314 if (configoptions[i].localvar.pint) 307 if (configoptions[i].localvar.pint)
315 *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value; 308 *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value;
316 } 309 }
317} 310}
318 311
319int quitrequest = 0; 312int quitrequest = 0;
320 313
321/* cleanup-hook, for SIGINT */ 314/* cleanup-hook, for SIGINT */
322void 315void cleanup(int signal) {
323cleanup (int signal) 316 if (signal == SIGINT) {
324{ 317 switch (quitrequest >> 2) {
325 if( signal == SIGINT ) { 318 case 0:
326 switch( quitrequest >> 2 ) { 319 flushout();
327 case 0: 320 writeout(" Press Ctrl+C twice now to confirm ");
328 flushout( ); 321 showout();
329 writeout( " Press Ctrl+C twice now to confirm "); 322 quitrequest += 4;
330 showout( ); 323 return;
331 quitrequest+=4; 324 break;
332 return; 325 case 1:
333 break; 326 flushout();
334 case 1: 327 writeout(" Press Ctrl+C twice now to confirm ");
335 flushout( ); 328 writeout(" Press Ctrl+C once now to confirm ");
336 writeout( " Press Ctrl+C twice now to confirm "); 329 showout();
337 writeout( " Press Ctrl+C once now to confirm "); 330 quitrequest += 4;
338 showout( ); 331 return;
339 quitrequest+=4; 332 break;
340 return; 333 default:
341 break; 334 break;
342 default: 335 }
343 break;
344 }
345 } 336 }
346 /* restore terminal state */ 337 /* restore terminal state */
347 exitui (); 338 exitui();
348 /* clear userlist */ 339 /* clear userlist */
349 ul_clear (); 340 ul_clear();
350 vc_disconnect(); 341 vc_disconnect();
351 342
352 /* inform user if we where killed by signal */ 343 /* inform user if we where killed by signal */
353 if (signal > 1) 344 if (signal > 1) {
354 { 345 fprintf(stderr, "vchat-client: terminated with signal %d.\n", signal);
355 fprintf (stderr, "vchat-client: terminated with signal %d.\n", signal); 346 } else if (errstr[0])
356 } else if (errstr[0]) 347 fputs(errstr, stderr);
357 fputs (errstr, stderr);
358 /* end of story */ 348 /* end of story */
359 exit (0); 349 exit(0);
360} 350}
361 351
362static int oldseconds = 0; 352static int oldseconds = 0;
363 353
364void calleverysecond( void ) { 354void calleverysecond(void) {
365 /* timetriggered execution, don't rely on being called every 1000us */ 355 /* timetriggered execution, don't rely on being called every 1000us */
366 /* rather see it as a chance for being called 9 times in 10 seconds */ 356 /* rather see it as a chance for being called 9 times in 10 seconds */
367 /* so check time() */ 357 /* so check time() */
368 time_t now = time( NULL ); 358 time_t now = time(NULL);
369 struct tm *mytime = localtime( &now ); 359 struct tm *mytime = localtime(&now);
370 if( mytime->tm_sec < oldseconds ) { 360 if (mytime->tm_sec < oldseconds) {
371 consoleline( NULL ); 361 consoleline(NULL);
372 } 362 }
373 oldseconds = mytime->tm_sec; 363 oldseconds = mytime->tm_sec;
374 364
375 if(quitrequest) 365 if (quitrequest)
376 quitrequest--; 366 quitrequest--;
377 if(outputcountdown && !--outputcountdown) 367 if (outputcountdown && !--outputcountdown)
378 hideout( ); 368 hideout();
379 if( reconnect_time && ( time( NULL ) > reconnect_time ) ) 369 if (reconnect_time && (time(NULL) > reconnect_time))
380 status = 0; 370 status = 0;
381} 371}
382 372
383/* this function is called in the master loop */ 373/* this function is called in the master loop */
384void 374void eventloop(void) {
385eventloop (void) 375 int poll_result = vc_poll(1 /* second timeout */);
386{
387 int poll_result = vc_poll( 1 /* second timeout */ );
388 376
389 switch (poll_result) { 377 switch (poll_result) {
390 case -1: 378 case -1:
391 /* EINTR is most likely a SIGWINCH - ignore for now */ 379 /* EINTR is most likely a SIGWINCH - ignore for now */
392 if (errno != EINTR) 380 if (errno != EINTR) {
393 { 381 snprintf(tmpstr, TMPSTRSIZE, "Select fails, %s.", strerror(errno));
394 snprintf (tmpstr, TMPSTRSIZE, "Select fails, %s.", strerror(errno)); 382 strncpy(errstr, tmpstr, TMPSTRSIZE - 2);
395 strncpy(errstr,tmpstr,TMPSTRSIZE-2); 383 errstr[TMPSTRSIZE - 2] = '\0';
396 errstr[TMPSTRSIZE-2] = '\0'; 384 strcat(errstr, "\n");
397 strcat(errstr,"\n"); 385 writecf(FS_ERR, tmpstr);
398 writecf (FS_ERR,tmpstr); 386 /* see this as an error condition and bail out */
399 /* see this as an error condition and bail out */ 387 status = 0;
400 status = 0; 388 }
401 } 389 break;
402 break;
403 case 0: 390 case 0:
404 /* time out reached */ 391 /* time out reached */
405 calleverysecond(); 392 calleverysecond();
406 break; 393 break;
407 default: 394 default:
408 /* something to read from user & we're logged in or have a cert? */ 395 /* something to read from user & we're logged in or have a cert? */
409 if (poll_result & 1) 396 if (poll_result & 1)
410 userinput (); 397 userinput();
411 398
412 /* something to read from server? */ 399 /* something to read from server? */
413 if (poll_result & 2) 400 if (poll_result & 2)
414 vc_receive (); 401 vc_receive();
415 break; 402 break;
416 } 403 }
417} 404}
418 405
419void usage( char *name) { 406void usage(char *name) {
420 printf ("usage: %s [-C config-file] [-F formats] [-l] [-z] [-s host] [-p port] [-c channel] [-n nickname]\n",name); 407 printf("usage: %s [-C config-file] [-F formats] [-l] [-z] [-s host] [-p "
421 puts (" -C load a second config-file, overriding the first one"); 408 "port] [-c channel] [-n nickname]\n",
422 puts (" -F load format strings (skins) from this file"); 409 name);
423 puts (" -l local connect (no SSL)"); 410 puts(" -C load a second config-file, overriding the first one");
424 puts (" -z don't use certificate files"); 411 puts(" -F load format strings (skins) from this file");
425 printf (" -s set server (default \"%s\")\n",getstroption(CF_SERVERHOST)); 412 puts(" -l local connect (no SSL)");
426 printf (" -p set port (default %s)\n",getstroption(CF_SERVERPORT)); 413 puts(" -z don't use certificate files");
427 printf (" -c set channel (default %d)\n",getintoption(CF_CHANNEL)); 414 printf(" -s set server (default \"%s\")\n", getstroption(CF_SERVERHOST));
428 if (own_nick_get()) 415 printf(" -p set port (default %s)\n", getstroption(CF_SERVERPORT));
429 printf(" -n set nickname (default \"%s\")\n",own_nick_get()); 416 printf(" -c set channel (default %d)\n", getintoption(CF_CHANNEL));
430 else 417 if (own_nick_get())
431 puts (" -n set nickname"); 418 printf(" -n set nickname (default \"%s\")\n", own_nick_get());
432 printf (" -f set from (default \"%s\")\n",getstroption(CF_FROM)); 419 else
433 puts (" -h gives this help"); 420 puts(" -n set nickname");
434 puts (" -v show module versions"); 421 printf(" -f set from (default \"%s\")\n", getstroption(CF_FROM));
422 puts(" -h gives this help");
423 puts(" -v show module versions");
435} 424}
436 425
437void versions() { 426void versions() {
438 puts (vchat_cl_version); 427 puts(vchat_cl_version);
439 puts (vchat_ui_version); 428 puts(vchat_ui_version);
440 puts (vchat_io_version); 429 puts(vchat_io_version);
441 puts (vchat_us_version); 430 puts(vchat_us_version);
442 puts (vchat_cm_version); 431 puts(vchat_cm_version);
443 puts (vchat_tls_version); 432 puts(vchat_tls_version);
444 puts (vchat_tls_version_external); 433 puts(vchat_tls_version_external);
445} 434}
446 435
447/* main - d'oh */ 436/* main - d'oh */
448int 437int main(int argc, char **argv) {
449main (int argc, char **argv)
450{
451 int pchar; 438 int pchar;
452 int cmdsunparsed = 1; 439 int cmdsunparsed = 1;
453 440
454 setlocale(LC_ALL,""); 441 setlocale(LC_ALL, "");
455 442
456 loadconfig (GLOBAL_CONFIG_FILE); 443 loadconfig(GLOBAL_CONFIG_FILE);
457 loadconfig (getstroption (CF_CONFIGFILE)); 444 loadconfig(getstroption(CF_CONFIGFILE));
458 445
459 /* make SSL version used visible */ 446 /* make SSL version used visible */
460 vchat_tls_get_version_external(); 447 vchat_tls_get_version_external();
461 448
462 /* parse commandline */ 449 /* parse commandline */
463 while (cmdsunparsed) { 450 while (cmdsunparsed) {
464 pchar = getopt(argc,argv,"C:F:lzs:p:c:n:f:kKL:hv"); 451 pchar = getopt(argc, argv, "C:F:lzs:p:c:n:f:kKL:hv");
465#ifdef DEBUG 452#ifdef DEBUG
466 fprintf(stderr,"parse commandline: %d ('%c'): %s\n",pchar,pchar,optarg); 453 fprintf(stderr, "parse commandline: %d ('%c'): %s\n", pchar, pchar, optarg);
467#endif 454#endif
468 455
469 switch (pchar) { 456 switch (pchar) {
470 case -1 : cmdsunparsed = 0; break; 457 case -1:
471 case 'C': loadconfig(optarg); break; 458 cmdsunparsed = 0;
472 case 'F': setstroption(CF_FORMFILE,optarg); break; 459 break;
473 case 'l': setintoption(CF_USESSL,0); break; 460 case 'C':
474 case 'z': setintoption(CF_USECERT,0); break; 461 loadconfig(optarg);
475 case 's': setstroption(CF_SERVERHOST,optarg); break; 462 break;
476 case 'p': setstroption(CF_SERVERPORT,optarg); break; 463 case 'F':
477 case 'c': setintoption(CF_CHANNEL,strtol(optarg,NULL,10)); break; 464 setstroption(CF_FORMFILE, optarg);
478 case 'n': own_nick_set(optarg); break; 465 break;
479 case 'f': setstroption(CF_FROM,optarg); break; 466 case 'l':
480 case 'h': usage(argv[0]); exit(0); break; 467 setintoption(CF_USESSL, 0);
481 case 'v': versions(); exit(0); break; 468 break;
482 default : usage(argv[0]); exit(1); 469 case 'z':
483 } 470 setintoption(CF_USECERT, 0);
471 break;
472 case 's':
473 setstroption(CF_SERVERHOST, optarg);
474 break;
475 case 'p':
476 setstroption(CF_SERVERPORT, optarg);
477 break;
478 case 'c':
479 setintoption(CF_CHANNEL, strtol(optarg, NULL, 10));
480 break;
481 case 'n':
482 own_nick_set(optarg);
483 break;
484 case 'f':
485 setstroption(CF_FROM, optarg);
486 break;
487 case 'h':
488 usage(argv[0]);
489 exit(0);
490 break;
491 case 'v':
492 versions();
493 exit(0);
494 break;
495 default:
496 usage(argv[0]);
497 exit(1);
498 }
484 } 499 }
485 500
486 if (optind < argc) { usage(argv[0]); exit(1); } 501 if (optind < argc) {
502 usage(argv[0]);
503 exit(1);
504 }
487 505
488 loadformats(GLOBAL_FORMAT_FILE); 506 loadformats(GLOBAL_FORMAT_FILE);
489 loadformats(getstroption (CF_FORMFILE)); 507 loadformats(getstroption(CF_FORMFILE));
490 508
491 /* install signal handler */ 509 /* install signal handler */
492 signal (SIGINT, cleanup); 510 signal(SIGINT, cleanup);
493 signal (SIGHUP, cleanup); 511 signal(SIGHUP, cleanup);
494 signal (SIGTERM, cleanup); 512 signal(SIGTERM, cleanup);
495 signal (SIGQUIT, SIG_IGN); 513 signal(SIGQUIT, SIG_IGN);
496 514
497 /* initialize userinterface */ 515 /* initialize userinterface */
498 initui (); 516 initui();
499 517
500 while( status ) { 518 while (status) {
501 /* attempt connection */ 519 /* attempt connection */
502 if (vc_connect (getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) { 520 if (vc_connect(getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) {
503 snprintf (tmpstr, TMPSTRSIZE, "Could not connect to server, %s.", strerror(errno)); 521 snprintf(tmpstr, TMPSTRSIZE, "Could not connect to server, %s.",
504 strncpy(errstr,tmpstr,TMPSTRSIZE-2); 522 strerror(errno));
505 errstr[TMPSTRSIZE-2] = '\0'; 523 strncpy(errstr, tmpstr, TMPSTRSIZE - 2);
506 strcat(errstr,"\n"); 524 errstr[TMPSTRSIZE - 2] = '\0';
507 writecf (FS_ERR,tmpstr); 525 strcat(errstr, "\n");
508 526 writecf(FS_ERR, tmpstr);
509 if( getintoption( CF_AUTORECONN ) ) { 527
510 snprintf (tmpstr, TMPSTRSIZE, "reconnecting in %d seconds", reconnect_delay ); 528 if (getintoption(CF_AUTORECONN)) {
511 writecf (FS_ERR, tmpstr); 529 snprintf(tmpstr, TMPSTRSIZE, "reconnecting in %d seconds",
512 reconnect_delay = ( reconnect_delay * 15 ) / 10; 530 reconnect_delay);
513 reconnect_time = time( NULL ) + reconnect_delay; 531 writecf(FS_ERR, tmpstr);
532 reconnect_delay = (reconnect_delay * 15) / 10;
533 reconnect_time = time(NULL) + reconnect_delay;
514 } else 534 } else
515 status = 0; 535 status = 0;
516 } else { 536 } else {
517 /* reset reconnect delay */ 537 /* reset reconnect delay */
518 reconnect_delay = 6; 538 reconnect_delay = 6;
519 reconnect_time = 0; 539 reconnect_time = 0;
520 } 540 }
521 541
522 while (status) 542 while (status)
523 eventloop (); 543 eventloop();
524 544
525 /* sanely close connection to server */ 545 /* sanely close connection to server */
526 vc_disconnect (); 546 vc_disconnect();
527 547
528 if( !ownquit && ( getintoption( CF_AUTORECONN ) || wantreconnect ) ) 548 if (!ownquit && (getintoption(CF_AUTORECONN) || wantreconnect))
529 status = 1; 549 status = 1;
530 550
531 wantreconnect = 0; 551 wantreconnect = 0;
532 } 552 }
533 553
534 /* call cleanup-hook without signal */ 554 /* call cleanup-hook without signal */
535 cleanup (0); 555 cleanup(0);
536 return 0; 556 return 0;
537} 557}