From 24effe857346411aa6b92c7d238441ce0e6cd861 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Sat, 21 May 2022 14:13:28 +0200 Subject: Reformatted using clang-format -format llvm --- vchat-client.c | 586 ++++++++-------- vchat-commands.c | 519 +++++++------- vchat-connection.c | 133 ++-- vchat-connection.h | 10 +- vchat-protocol.c | 556 +++++++-------- vchat-tls.c | 1036 ++++++++++++++-------------- vchat-tls.h | 16 +- vchat-ui.c | 1945 +++++++++++++++++++++++++++------------------------- vchat-user.c | 399 ++++++----- vchat.h | 217 ++++-- 10 files changed, 2816 insertions(+), 2601 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 @@ */ /* general includes */ -#include -#include +#include +#include +#include #include -#include -#include -#include #include #include -#include -#include +#include +#include +#include +#include +#include + #include -#include -#include "vchat.h" #include "vchat-connection.h" #include "vchat-user.h" +#include "vchat.h" /* version of this module */ -const char *vchat_cl_version = "vchat-client.c $Id$"; +const char *vchat_cl_version = + "vchat-client.c $Id$"; /* externally used variables */ /* we're logged in */ @@ -54,139 +56,149 @@ char errstr[ERRSTRSIZE] = "\0"; /* declaration of configuration array */ #include "vchat-config.h" -void setnoption (const char *, char *); +void setnoption(const char *, char *); static void parsecfg(char *line) { int bytes; - char *param=line; - char *value=NULL; + char *param = line; + char *value = NULL; /* handle quotes value is empty, so we can use it */ - value = strchr(line,'#'); - if (value) { /* the line contains a cute little quote */ - value[0]='\0'; /* ignore the rest of the line */ + value = strchr(line, '#'); + if (value) { /* the line contains a cute little quote */ + value[0] = '\0'; /* ignore the rest of the line */ } /* now split the line into two parts */ - value = strchr(line,'='); - if (!value) return; /* exit if strchr fails */ - value[0]='\0'; + value = strchr(line, '='); + if (!value) + return; /* exit if strchr fails */ + value[0] = '\0'; value++; /* "trim" values */ - while ((value[0] == ' ')||(value[0] == '\t')) + while ((value[0] == ' ') || (value[0] == '\t')) value++; bytes = strlen(value); - while ((value[bytes-1] == ' ')||(value[bytes-1] == '\t')) { - value[bytes-1] = '\0'; - bytes=strlen(value); + while ((value[bytes - 1] == ' ') || (value[bytes - 1] == '\t')) { + value[bytes - 1] = '\0'; + bytes = strlen(value); } /* bytes should be strlen(value) */ - if ( value[bytes-1] == '"' ) value[bytes-1] = '\0'; - if ( value[0] == '"' ) value++; + if (value[bytes - 1] == '"') + value[bytes - 1] = '\0'; + if (value[0] == '"') + value++; /* "trim" param */ - while ((param[0] == ' ')||(param[0] == '\t')) + while ((param[0] == ' ') || (param[0] == '\t')) param++; bytes = strlen(param); - while ((param[bytes-1] == ' ')||(param[bytes-1] == '\t')) { - param[bytes-1] = '\0'; - bytes=strlen(param); + while ((param[bytes - 1] == ' ') || (param[bytes - 1] == '\t')) { + param[bytes - 1] = '\0'; + bytes = strlen(param); } /* bytes should be strlen(param) */ - if ( param[bytes-1] == '\"' ) param[bytes-1] = '\0'; - if ( param[0] == '\"' ) param++; + if (param[bytes - 1] == '\"') + param[bytes - 1] = '\0'; + if (param[0] == '\"') + param++; - if ((!param)||(!value)) return; /* failsave */ + if ((!param) || (!value)) + return; /* failsave */ - //fprintf(stderr,"\"%s\" -> \"%s\"\n",param,value); - setnoption(param,value); + // fprintf(stderr,"\"%s\" -> \"%s\"\n",param,value); + setnoption(param, value); } static void parseformats(char *line) { int i; - char *tmp = NULL; + char *tmp = NULL; /* read a format line from file, syntax is FS_XXX = "formatstring" */ - while( *line == ' ') line++; - - if( strlen( line ) > TMPSTRSIZE ) return; - - if( *line != '#') /* allow to comment out the line */ - for (i = 0; formatstrings[i].formatstr; i++) - if (!strncasecmp(formatstrings[i].idstring, line, strlen( formatstrings[i].idstring) )) - { - char *tail = line + strlen( formatstrings[i].idstring); - while( *tail==' ' || *tail=='\t') tail++; /* and skip whitespaces */ - - if( *tail++ == '=' ) - { - while( *tail==' ' || *tail=='\t') tail++; - if( *(tail++)=='\"' ) - { - int j, k = 0, stringends = 0, backslash=0; - for ( j = 0; tail[j] && !stringends; j++) - { - switch( tail[j] ) { - case '^': - if ( tail[j+1] != '^' ) - tmpstr[k++] = 1; - break; - case '\\': - backslash=1-backslash; - tmpstr[k++] = '\\'; - break; - case '\"': - if (backslash) k--; else stringends = 1; - default: - tmpstr[k++] = tail[j]; - backslash = 0; - } - } - - if ( stringends && ( (tmp = (char *)malloc( 1 + j )) != NULL ) ) - { - memcpy( tmp, tmpstr, k); - tmp[k-1]=0; - formatstrings[i].formatstr = tmp; - } - } + while (*line == ' ') + line++; + + if (strlen(line) > TMPSTRSIZE) + return; + + if (*line != '#') /* allow to comment out the line */ + for (i = 0; formatstrings[i].formatstr; i++) + if (!strncasecmp(formatstrings[i].idstring, line, + strlen(formatstrings[i].idstring))) { + char *tail = line + strlen(formatstrings[i].idstring); + while (*tail == ' ' || *tail == '\t') + tail++; /* and skip whitespaces */ + + if (*tail++ == '=') { + while (*tail == ' ' || *tail == '\t') + tail++; + if (*(tail++) == '\"') { + int j, k = 0, stringends = 0, backslash = 0; + for (j = 0; tail[j] && !stringends; j++) { + switch (tail[j]) { + case '^': + if (tail[j + 1] != '^') + tmpstr[k++] = 1; + break; + case '\\': + backslash = 1 - backslash; + tmpstr[k++] = '\\'; + break; + case '\"': + if (backslash) + k--; + else + stringends = 1; + default: + tmpstr[k++] = tail[j]; + backslash = 0; } - } + } + if (stringends && ((tmp = (char *)malloc(1 + j)) != NULL)) { + memcpy(tmp, tmpstr, k); + tmp[k - 1] = 0; + formatstrings[i].formatstr = tmp; + } + } + } + } } -/* UNUSED uncomment if needed +/* UNUSED uncomment if needed static void parseknownhosts(char *line) { } */ /* load config file */ -void -loadcfg (char *file,int complain, void (*lineparser) (char *)) -{ +void loadcfg(char *file, int complain, void (*lineparser)(char *)) { FILE *fh; #define BUFSIZE 4096 - char buf[BUFSIZE]; /* data buffer */ + char buf[BUFSIZE]; /* data buffer */ char *tildex = NULL, *t; /* Check and expand filename then open file */ - if (!file) return; - tildex = tilde_expand( file ); - if (!tildex) return; - fh = fopen( tildex, "r" ); - free( tildex ); + if (!file) + return; + tildex = tilde_expand(file); + if (!tildex) + return; + fh = fopen(tildex, "r"); + free(tildex); if (!fh) { - if( complain ) snprintf (errstr, TMPSTRSIZE, "Can't open config-file \"%s\": %s.", file, strerror(errno)); + if (complain) + snprintf(errstr, TMPSTRSIZE, "Can't open config-file \"%s\": %s.", file, + strerror(errno)); return; } - while ( fgets( buf, sizeof(buf), fh ) ) { - if( ( t = strchr( buf, '\n' ) ) ) + while (fgets(buf, sizeof(buf), fh)) { + if ((t = strchr(buf, '\n'))) *t = 0; lineparser(buf); } @@ -194,77 +206,62 @@ loadcfg (char *file,int complain, void (*lineparser) (char *)) fclose(fh); } -void -loadconfig (char *file) -{ - loadcfg(file,1,parsecfg); -} +void loadconfig(char *file) { loadcfg(file, 1, parsecfg); } -void -loadformats (char *file) -{ - loadcfg(file,0,parseformats); -} +void loadformats(char *file) { loadcfg(file, 0, parseformats); } /* get-format-string */ -char * -getformatstr (formtstr id) -{ +char *getformatstr(formtstr id) { int i; for (i = 0; formatstrings[i].formatstr; i++) - if (formatstrings[i].id == id) return formatstrings[i].formatstr; + if (formatstrings[i].id == id) + return formatstrings[i].formatstr; return NULL; } /* get-string-option, fetches *char-value of variable named by option */ -char * -getstroption (confopt option) -{ +char *getstroption(confopt option) { int i; #ifdef DEBUG - fprintf(stderr,"getstroption: %d\n",option); + fprintf(stderr, "getstroption: %d\n", option); #endif for (i = 0; configoptions[i].type != CO_NIL; i++) if ((configoptions[i].id == option) && (configoptions[i].type == CO_STR)) { if (!configoptions[i].value) - return configoptions[i].defaultvalue; - else - return configoptions[i].value; + return configoptions[i].defaultvalue; + else + return configoptions[i].value; } return NULL; } /* set-string-option, puts *char-value to variable named by option */ -void -setstroption (confopt option, char *string) -{ +void setstroption(confopt option, char *string) { int i; #ifdef DEBUG - fprintf(stderr,"setstroption: %d to %s\n",option,string); + fprintf(stderr, "setstroption: %d to %s\n", option, string); #endif for (i = 0; configoptions[i].type != CO_NIL; i++) if ((configoptions[i].id == option) && (configoptions[i].type == CO_STR)) { if (configoptions[i].value) - free(configoptions[i].value); + free(configoptions[i].value); if (string) - configoptions[i].value = strdup(string); - else - configoptions[i].value = NULL; + configoptions[i].value = strdup(string); + else + configoptions[i].value = NULL; if (configoptions[i].localvar.pstr) - *configoptions[i].localvar.pstr = configoptions[i].value; + *configoptions[i].localvar.pstr = configoptions[i].value; } } /* set-named-option, puts string to variable named by name */ -void -setnoption (const char *name, char *string) -{ +void setnoption(const char *name, char *string) { int i; #ifdef DEBUG - fprintf(stderr,"setstrnoption: %s to %s\n",name,string); + fprintf(stderr, "setstrnoption: %s to %s\n", name, string); #endif for (i = 0; configoptions[i].type != CO_NIL; i++) - if (!strcmp(configoptions[i].varname,name)) { + if (!strcmp(configoptions[i].varname, name)) { if (configoptions[i].type == CO_STR) { if (configoptions[i].value) free(configoptions[i].value); @@ -273,265 +270,288 @@ setnoption (const char *name, char *string) else configoptions[i].value = NULL; if (configoptions[i].localvar.pstr) - *configoptions[i].localvar.pstr = configoptions[i].value; + *configoptions[i].localvar.pstr = configoptions[i].value; } else if (configoptions[i].type == CO_INT) { configoptions[i].value = (char *)(uintptr_t)atoi(string); if (configoptions[i].localvar.pint) - *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value; + *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value; } } } /* get-integer-option, fetches int-value of variable named by option */ -int -getintoption (confopt option) -{ +int getintoption(confopt option) { int i; #ifdef DEBUG - fprintf(stderr,"getintoption: %d\n",option); + fprintf(stderr, "getintoption: %d\n", option); #endif for (i = 0; configoptions[i].type != CO_NIL; i++) if ((configoptions[i].id == option) && (configoptions[i].type == CO_INT)) { if ((intptr_t)configoptions[i].value == -1) - return (intptr_t) configoptions[i].defaultvalue; - else - return (intptr_t) configoptions[i].value; + return (intptr_t)configoptions[i].defaultvalue; + else + return (intptr_t)configoptions[i].value; } return 0; } /* set-integer-option, puts int-value to variable named by option */ -void -setintoption (confopt option, int value) -{ +void setintoption(confopt option, int value) { int i; #ifdef DEBUG - fprintf(stderr,"setintoption: %d to %d\n",option,value); + fprintf(stderr, "setintoption: %d to %d\n", option, value); #endif for (i = 0; configoptions[i].type != CO_NIL; i++) if ((configoptions[i].id == option) && (configoptions[i].type == CO_INT)) { - configoptions[i].value = (char *)(uintptr_t)value; - if (configoptions[i].localvar.pint) - *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value; + configoptions[i].value = (char *)(uintptr_t)value; + if (configoptions[i].localvar.pint) + *configoptions[i].localvar.pint = (uintptr_t)configoptions[i].value; } } int quitrequest = 0; /* cleanup-hook, for SIGINT */ -void -cleanup (int signal) -{ - if( signal == SIGINT ) { - switch( quitrequest >> 2 ) { - case 0: - flushout( ); - writeout( " Press Ctrl+C twice now to confirm "); - showout( ); - quitrequest+=4; - return; - break; - case 1: - flushout( ); - writeout( " Press Ctrl+C twice now to confirm "); - writeout( " Press Ctrl+C once now to confirm "); - showout( ); - quitrequest+=4; - return; - break; - default: - break; - } +void cleanup(int signal) { + if (signal == SIGINT) { + switch (quitrequest >> 2) { + case 0: + flushout(); + writeout(" Press Ctrl+C twice now to confirm "); + showout(); + quitrequest += 4; + return; + break; + case 1: + flushout(); + writeout(" Press Ctrl+C twice now to confirm "); + writeout(" Press Ctrl+C once now to confirm "); + showout(); + quitrequest += 4; + return; + break; + default: + break; + } } /* restore terminal state */ - exitui (); + exitui(); /* clear userlist */ - ul_clear (); + ul_clear(); vc_disconnect(); /* inform user if we where killed by signal */ - if (signal > 1) - { - fprintf (stderr, "vchat-client: terminated with signal %d.\n", signal); - } else if (errstr[0]) - fputs (errstr, stderr); + if (signal > 1) { + fprintf(stderr, "vchat-client: terminated with signal %d.\n", signal); + } else if (errstr[0]) + fputs(errstr, stderr); /* end of story */ - exit (0); + exit(0); } static int oldseconds = 0; -void calleverysecond( void ) { +void calleverysecond(void) { /* timetriggered execution, don't rely on being called every 1000us */ /* rather see it as a chance for being called 9 times in 10 seconds */ /* so check time() */ - time_t now = time( NULL ); - struct tm *mytime = localtime( &now ); - if( mytime->tm_sec < oldseconds ) { - consoleline( NULL ); + time_t now = time(NULL); + struct tm *mytime = localtime(&now); + if (mytime->tm_sec < oldseconds) { + consoleline(NULL); } oldseconds = mytime->tm_sec; - if(quitrequest) - quitrequest--; - if(outputcountdown && !--outputcountdown) - hideout( ); - if( reconnect_time && ( time( NULL ) > reconnect_time ) ) - status = 0; + if (quitrequest) + quitrequest--; + if (outputcountdown && !--outputcountdown) + hideout(); + if (reconnect_time && (time(NULL) > reconnect_time)) + status = 0; } /* this function is called in the master loop */ -void -eventloop (void) -{ - int poll_result = vc_poll( 1 /* second timeout */ ); +void eventloop(void) { + int poll_result = vc_poll(1 /* second timeout */); switch (poll_result) { case -1: - /* EINTR is most likely a SIGWINCH - ignore for now */ - if (errno != EINTR) - { - snprintf (tmpstr, TMPSTRSIZE, "Select fails, %s.", strerror(errno)); - strncpy(errstr,tmpstr,TMPSTRSIZE-2); - errstr[TMPSTRSIZE-2] = '\0'; - strcat(errstr,"\n"); - writecf (FS_ERR,tmpstr); - /* see this as an error condition and bail out */ - status = 0; - } - break; + /* EINTR is most likely a SIGWINCH - ignore for now */ + if (errno != EINTR) { + snprintf(tmpstr, TMPSTRSIZE, "Select fails, %s.", strerror(errno)); + strncpy(errstr, tmpstr, TMPSTRSIZE - 2); + errstr[TMPSTRSIZE - 2] = '\0'; + strcat(errstr, "\n"); + writecf(FS_ERR, tmpstr); + /* see this as an error condition and bail out */ + status = 0; + } + break; case 0: - /* time out reached */ - calleverysecond(); - break; + /* time out reached */ + calleverysecond(); + break; default: - /* something to read from user & we're logged in or have a cert? */ - if (poll_result & 1) - userinput (); - - /* something to read from server? */ - if (poll_result & 2) - vc_receive (); - break; + /* something to read from user & we're logged in or have a cert? */ + if (poll_result & 1) + userinput(); + + /* something to read from server? */ + if (poll_result & 2) + vc_receive(); + break; } } -void usage( char *name) { - printf ("usage: %s [-C config-file] [-F formats] [-l] [-z] [-s host] [-p port] [-c channel] [-n nickname]\n",name); - puts (" -C load a second config-file, overriding the first one"); - puts (" -F load format strings (skins) from this file"); - puts (" -l local connect (no SSL)"); - puts (" -z don't use certificate files"); - printf (" -s set server (default \"%s\")\n",getstroption(CF_SERVERHOST)); - printf (" -p set port (default %s)\n",getstroption(CF_SERVERPORT)); - printf (" -c set channel (default %d)\n",getintoption(CF_CHANNEL)); - if (own_nick_get()) - printf(" -n set nickname (default \"%s\")\n",own_nick_get()); - else - puts (" -n set nickname"); - printf (" -f set from (default \"%s\")\n",getstroption(CF_FROM)); - puts (" -h gives this help"); - puts (" -v show module versions"); +void usage(char *name) { + printf("usage: %s [-C config-file] [-F formats] [-l] [-z] [-s host] [-p " + "port] [-c channel] [-n nickname]\n", + name); + puts(" -C load a second config-file, overriding the first one"); + puts(" -F load format strings (skins) from this file"); + puts(" -l local connect (no SSL)"); + puts(" -z don't use certificate files"); + printf(" -s set server (default \"%s\")\n", getstroption(CF_SERVERHOST)); + printf(" -p set port (default %s)\n", getstroption(CF_SERVERPORT)); + printf(" -c set channel (default %d)\n", getintoption(CF_CHANNEL)); + if (own_nick_get()) + printf(" -n set nickname (default \"%s\")\n", own_nick_get()); + else + puts(" -n set nickname"); + printf(" -f set from (default \"%s\")\n", getstroption(CF_FROM)); + puts(" -h gives this help"); + puts(" -v show module versions"); } void versions() { - puts (vchat_cl_version); - puts (vchat_ui_version); - puts (vchat_io_version); - puts (vchat_us_version); - puts (vchat_cm_version); - puts (vchat_tls_version); - puts (vchat_tls_version_external); + puts(vchat_cl_version); + puts(vchat_ui_version); + puts(vchat_io_version); + puts(vchat_us_version); + puts(vchat_cm_version); + puts(vchat_tls_version); + puts(vchat_tls_version_external); } /* main - d'oh */ -int -main (int argc, char **argv) -{ +int main(int argc, char **argv) { int pchar; int cmdsunparsed = 1; - setlocale(LC_ALL,""); + setlocale(LC_ALL, ""); - loadconfig (GLOBAL_CONFIG_FILE); - loadconfig (getstroption (CF_CONFIGFILE)); + loadconfig(GLOBAL_CONFIG_FILE); + loadconfig(getstroption(CF_CONFIGFILE)); /* make SSL version used visible */ vchat_tls_get_version_external(); /* parse commandline */ while (cmdsunparsed) { - pchar = getopt(argc,argv,"C:F:lzs:p:c:n:f:kKL:hv"); + pchar = getopt(argc, argv, "C:F:lzs:p:c:n:f:kKL:hv"); #ifdef DEBUG - fprintf(stderr,"parse commandline: %d ('%c'): %s\n",pchar,pchar,optarg); + fprintf(stderr, "parse commandline: %d ('%c'): %s\n", pchar, pchar, optarg); #endif - switch (pchar) { - case -1 : cmdsunparsed = 0; break; - case 'C': loadconfig(optarg); break; - case 'F': setstroption(CF_FORMFILE,optarg); break; - case 'l': setintoption(CF_USESSL,0); break; - case 'z': setintoption(CF_USECERT,0); break; - case 's': setstroption(CF_SERVERHOST,optarg); break; - case 'p': setstroption(CF_SERVERPORT,optarg); break; - case 'c': setintoption(CF_CHANNEL,strtol(optarg,NULL,10)); break; - case 'n': own_nick_set(optarg); break; - case 'f': setstroption(CF_FROM,optarg); break; - case 'h': usage(argv[0]); exit(0); break; - case 'v': versions(); exit(0); break; - default : usage(argv[0]); exit(1); - } + switch (pchar) { + case -1: + cmdsunparsed = 0; + break; + case 'C': + loadconfig(optarg); + break; + case 'F': + setstroption(CF_FORMFILE, optarg); + break; + case 'l': + setintoption(CF_USESSL, 0); + break; + case 'z': + setintoption(CF_USECERT, 0); + break; + case 's': + setstroption(CF_SERVERHOST, optarg); + break; + case 'p': + setstroption(CF_SERVERPORT, optarg); + break; + case 'c': + setintoption(CF_CHANNEL, strtol(optarg, NULL, 10)); + break; + case 'n': + own_nick_set(optarg); + break; + case 'f': + setstroption(CF_FROM, optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + break; + case 'v': + versions(); + exit(0); + break; + default: + usage(argv[0]); + exit(1); + } } - if (optind < argc) { usage(argv[0]); exit(1); } + if (optind < argc) { + usage(argv[0]); + exit(1); + } loadformats(GLOBAL_FORMAT_FILE); - loadformats(getstroption (CF_FORMFILE)); + loadformats(getstroption(CF_FORMFILE)); /* install signal handler */ - signal (SIGINT, cleanup); - signal (SIGHUP, cleanup); - signal (SIGTERM, cleanup); - signal (SIGQUIT, SIG_IGN); + signal(SIGINT, cleanup); + signal(SIGHUP, cleanup); + signal(SIGTERM, cleanup); + signal(SIGQUIT, SIG_IGN); /* initialize userinterface */ - initui (); + initui(); - while( status ) { + while (status) { /* attempt connection */ - if (vc_connect (getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) { - snprintf (tmpstr, TMPSTRSIZE, "Could not connect to server, %s.", strerror(errno)); - strncpy(errstr,tmpstr,TMPSTRSIZE-2); - errstr[TMPSTRSIZE-2] = '\0'; - strcat(errstr,"\n"); - writecf (FS_ERR,tmpstr); - - if( getintoption( CF_AUTORECONN ) ) { - snprintf (tmpstr, TMPSTRSIZE, "reconnecting in %d seconds", reconnect_delay ); - writecf (FS_ERR, tmpstr); - reconnect_delay = ( reconnect_delay * 15 ) / 10; - reconnect_time = time( NULL ) + reconnect_delay; + if (vc_connect(getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT))) { + snprintf(tmpstr, TMPSTRSIZE, "Could not connect to server, %s.", + strerror(errno)); + strncpy(errstr, tmpstr, TMPSTRSIZE - 2); + errstr[TMPSTRSIZE - 2] = '\0'; + strcat(errstr, "\n"); + writecf(FS_ERR, tmpstr); + + if (getintoption(CF_AUTORECONN)) { + snprintf(tmpstr, TMPSTRSIZE, "reconnecting in %d seconds", + reconnect_delay); + writecf(FS_ERR, tmpstr); + reconnect_delay = (reconnect_delay * 15) / 10; + reconnect_time = time(NULL) + reconnect_delay; } else status = 0; } else { /* reset reconnect delay */ reconnect_delay = 6; - reconnect_time = 0; + reconnect_time = 0; } while (status) - eventloop (); + eventloop(); /* sanely close connection to server */ - vc_disconnect (); + vc_disconnect(); - if( !ownquit && ( getintoption( CF_AUTORECONN ) || wantreconnect ) ) + if (!ownquit && (getintoption(CF_AUTORECONN) || wantreconnect)) status = 1; wantreconnect = 0; } /* call cleanup-hook without signal */ - cleanup (0); + cleanup(0); return 0; } diff --git a/vchat-commands.c b/vchat-commands.c index 8094a7c..9aa3abd 100755 --- a/vchat-commands.c +++ b/vchat-commands.c @@ -10,27 +10,29 @@ * without even the implied warranty of merchantability or fitness for a * particular purpose. In no event shall the copyright holder be liable for * any direct, indirect, incidental or special damages arising in any way out - * of the use of this software. + * of the use of this software. * */ /* general includes */ -#include -#include #include #include +#include #include #include +#include + #include /* local includes */ -#include "vchat.h" #include "vchat-connection.h" #include "vchat-help.h" #include "vchat-user.h" +#include "vchat.h" /* version of this module */ -const char *vchat_cm_version = "vchat-commands.c $Id$"; +const char *vchat_cm_version = + "vchat-commands.c $Id$"; /* from vchat-client.c */ extern int ownquit; @@ -39,45 +41,45 @@ extern int status; /* our "/command " table */ enum { -COMMAND_VERSION, -COMMAND_FILTERS, -COMMAND_LSFLT, -COMMAND_RMFLT, -COMMAND_CLFLT, -COMMAND_HELP, -COMMAND_FORMAT, -COMMAND_KEYS, -COMMAND_QUIT, -COMMAND_USER, -COMMAND_DICT, -COMMAND_FLT, -COMMAND_PM, -COMMAND_ACTION, -COMMAND_PMSHORT, -COMMAND_QUERY, -COMMAND_QUITSHORT, -COMMAND_PLAIN, -COMMAND_RECONNECT, -COMMAND_NONE + COMMAND_VERSION, + COMMAND_FILTERS, + COMMAND_LSFLT, + COMMAND_RMFLT, + COMMAND_CLFLT, + COMMAND_HELP, + COMMAND_FORMAT, + COMMAND_KEYS, + COMMAND_QUIT, + COMMAND_USER, + COMMAND_DICT, + COMMAND_FLT, + COMMAND_PM, + COMMAND_ACTION, + COMMAND_PMSHORT, + COMMAND_QUERY, + COMMAND_QUITSHORT, + COMMAND_PLAIN, + COMMAND_RECONNECT, + COMMAND_NONE }; -static void command_quit ( char *tail); -static void command_user ( char *tail); -static void command_pm ( char *tail); -static void command_action ( char *tail); -static void command_help ( char *tail); -static void command_format ( char *tail); -static void command_flt ( char *tail); -static void command_lsflt ( char *tail); -static void command_clflt ( char *tail); -static void command_rmflt ( char *tail); - void command_version ( char *tail); -static void command_none ( char *line); -static void command_query ( char *tail); -static void command_reconnect ( char *tail); -static void command_dict ( char *tail); - -static void output_default ( char *tail); +static void command_quit(char *tail); +static void command_user(char *tail); +static void command_pm(char *tail); +static void command_action(char *tail); +static void command_help(char *tail); +static void command_format(char *tail); +static void command_flt(char *tail); +static void command_lsflt(char *tail); +static void command_clflt(char *tail); +static void command_rmflt(char *tail); +void command_version(char *tail); +static void command_none(char *line); +static void command_query(char *tail); +static void command_reconnect(char *tail); +static void command_dict(char *tail); + +static void output_default(char *tail); /* commandentry defined in vchat.h */ @@ -106,9 +108,7 @@ commandtable[] = { }; /* parse "/command" */ -static int -translatecommand( char **cmd) -{ +static int translatecommand(char **cmd) { int result; int cut = 0; int maxcut = 0; @@ -116,214 +116,215 @@ translatecommand( char **cmd) /* We do only want to allow Command abbrevation to the next newline, so that /VRES won't expand to /V RES */ - while( (*cmd)[maxcut] && ((*cmd)[maxcut] != 0x20) && ((*cmd)[maxcut] != '\n')) maxcut++; - if( maxcut ) maxcut--; + while ((*cmd)[maxcut] && ((*cmd)[maxcut] != 0x20) && ((*cmd)[maxcut] != '\n')) + maxcut++; + if (maxcut) + maxcut--; - /* Repeatedly scan command table for command, with growing abbrevation cut off */ + /* Repeatedly scan command table for command, with growing abbrevation cut off + */ do { - /* Looks ugly, needs rewrite for better understanding */ - for( result = 0; - (result != COMMAND_NONE) && - (strncasecmp(*cmd, commandtable[result].name, commandtable[result].len - - ((commandtable[result].len - maxcut - cut > 0) ? cut : 0))); - result++); - } while ((cut < commandtable[0].len) && (commandtable[result].number == COMMAND_NONE) && (++cut)); + /* Looks ugly, needs rewrite for better understanding */ + for (result = 0; + (result != COMMAND_NONE) && + (strncasecmp( + *cmd, commandtable[result].name, + commandtable[result].len - + ((commandtable[result].len - maxcut - cut > 0) ? cut : 0))); + result++) + ; + } while ((cut < commandtable[0].len) && + (commandtable[result].number == COMMAND_NONE) && (++cut)); /* Just leave the tail... */ (*cmd) += commandtable[result].len; /* ... whose start may be affected by abbrevation */ - if( commandtable[result].number != COMMAND_NONE ) - (*cmd) -= cut; + if (commandtable[result].number != COMMAND_NONE) + (*cmd) -= cut; return result; } /* handle thought */ -static void -dothink(const char *tail, const char nice ) -{ - while( *tail == ' ' ) tail++; +static void dothink(const char *tail, const char nice) { + while (*tail == ' ') + tail++; /* send users message to server */ - snprintf (tmpstr, TMPSTRSIZE, ".%c %s", nice, tail); - vc_sendmessage (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, ".%c %s", nice, tail); + vc_sendmessage(tmpstr); /* show action in channel window */ - snprintf (tmpstr, TMPSTRSIZE, nice == 'O' ? getformatstr(FS_TXPUBNTHOUGHT) : getformatstr(FS_TXPUBTHOUGHT), tail); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, + nice == 'O' ? getformatstr(FS_TXPUBNTHOUGHT) + : getformatstr(FS_TXPUBTHOUGHT), + tail); + writechan(tmpstr); } - /* handle action */ -static void -doaction(const char *tail ) -{ - while( *tail == ' ' ) tail++; - - if( *tail ) { - /* send users message to server */ - snprintf (tmpstr, TMPSTRSIZE, ".a %s", tail); - vc_sendmessage (tmpstr); - - /* show action in channel window */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBACTION), own_nick_get(), tail); - writechan (tmpstr); +static void doaction(const char *tail) { + while (*tail == ' ') + tail++; + + if (*tail) { + /* send users message to server */ + snprintf(tmpstr, TMPSTRSIZE, ".a %s", tail); + vc_sendmessage(tmpstr); + + /* show action in channel window */ + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBACTION), own_nick_get(), + tail); + writechan(tmpstr); } else { - /* missing action */ - msgout( " You do nothing. " ); + /* missing action */ + msgout(" You do nothing. "); } } /* handle private message outgoing */ -static void -privatemessagetx (char *tail ) { +static void privatemessagetx(char *tail) { char *mesg; /* find nick */ - while( *tail==' ') tail++; + while (*tail == ' ') + tail++; /* find message */ mesg = tail; - while ( *mesg && *mesg!=' ') mesg++; + while (*mesg && *mesg != ' ') + mesg++; /* check for nick && message */ - if(*tail && *mesg) { + if (*tail && *mesg) { - /* terminate nick, move to rel start */ - *mesg++ = '\0'; + /* terminate nick, move to rel start */ + *mesg++ = '\0'; - /* form message and send to server */ - snprintf (tmpstr, TMPSTRSIZE, ".m %s %s", tail, mesg); - vc_sendmessage (tmpstr); + /* form message and send to server */ + snprintf(tmpstr, TMPSTRSIZE, ".m %s %s", tail, mesg); + vc_sendmessage(tmpstr); - /* show message in private window */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPRIVMSG), tail, mesg); - writepriv (tmpstr, 0); + /* show message in private window */ + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_TXPRIVMSG), tail, mesg); + writepriv(tmpstr, 0); - /* note we messaged someone */ - ul_private_action(tail); + /* note we messaged someone */ + ul_private_action(tail); } else { - /* Bump user to fill in missing parts */ - msgout( *tail ? " Won't send empty message. ":" Recipient missing. " ); + /* Bump user to fill in missing parts */ + msgout(*tail ? " Won't send empty message. " : " Recipient missing. "); } } /* handle line entered by user */ -void -handleline (char *line) -{ +void handleline(char *line) { #ifdef DEBUG /* debugging? log users input! */ - fprintf (stderr, "=| %s\n", line); + fprintf(stderr, "=| %s\n", line); #endif - switch ( line[0] ) - { + switch (line[0]) { case '.': - switch ( line[1] ) { - case 'm': /* sending a private message? */ - privatemessagetx( line+2 ); - break; - case 'a': /* Do an action */ - doaction( line+2 ); - break; - case '.': - /* .. on start of line is public */ - if( line[2] != 'm' ) { - output_default( line ); - } else { - /* oopsi, "..m " detected */ - /* dunno what to do */ - flushout( ); - writeout("? You probably misstyped ?"); - writeout(" "); - writeout(line ); - showout( ); - } - break; - case 'o': - case 'O': - dothink( line + 2, line[1] ); - break; - case 'x': - /* inform vchat-client, that the following connection - drop was intentional */ - ownquit = 1; /* fallthrough intended */ - default: - /* generic server command, send to server, show to user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_COMMAND), line); - writechan (tmpstr); - vc_sendmessage (line); - break; + switch (line[1]) { + case 'm': /* sending a private message? */ + privatemessagetx(line + 2); + break; + case 'a': /* Do an action */ + doaction(line + 2); + break; + case '.': + /* .. on start of line is public */ + if (line[2] != 'm') { + output_default(line); + } else { + /* oopsi, "..m " detected */ + /* dunno what to do */ + flushout(); + writeout("? You probably misstyped ?"); + writeout(" "); + writeout(line); + showout(); } break; - case '/': - line++; - commandtable[translatecommand(&line)].handler(line); + case 'o': + case 'O': + dothink(line + 2, line[1]); break; - default: - output_default( line ); + case 'x': + /* inform vchat-client, that the following connection + drop was intentional */ + ownquit = 1; /* fallthrough intended */ + default: + /* generic server command, send to server, show to user */ + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_COMMAND), line); + writechan(tmpstr); + vc_sendmessage(line); break; + } + break; + case '/': + line++; + commandtable[translatecommand(&line)].handler(line); + break; + default: + output_default(line); + break; } } -static void -output_default(char *line ) { - /* prepare for output on display */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBMSG), own_nick_get(), line); +static void output_default(char *line) { + /* prepare for output on display */ + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_TXPUBMSG), own_nick_get(), line); - /* send original line to server */ - vc_sendmessage (line); + /* send original line to server */ + vc_sendmessage(line); - /* output message to channel window */ - writechan (tmpstr); + /* output message to channel window */ + writechan(tmpstr); } /* handle a "/user " request */ -static void -command_user(char *tail) -{ - while( *tail == ' ') tail++; - if( *tail ) { - char * out = ul_match_user( tail); - if( *out ) { - snprintf( tmpstr, TMPSTRSIZE, getformatstr(FS_USMATCH), tail, out); - } else { - snprintf( tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), " No user matched that regex. "); - } +static void command_user(char *tail) { + while (*tail == ' ') + tail++; + if (*tail) { + char *out = ul_match_user(tail); + if (*out) { + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_USMATCH), tail, out); + } else { + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), + " No user matched that regex. "); + } } else { - snprintf( tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), " Which user? "); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), " Which user? "); } - msgout( tmpstr ); + msgout(tmpstr); } /* handle a "/msg " request */ -static void -command_pm (char *tail) -{ - privatemessagetx( tail ); -} +static void command_pm(char *tail) { privatemessagetx(tail); } -static void -command_format(char *line) { +static void command_format(char *line) { struct stat testexist; - char * tildex = NULL; + char *tildex = NULL; flushout(); - while( *line==' ') line++; - if(line) { - tildex = tilde_expand( line ); - if(tildex && !stat(tildex, &testexist )) + while (*line == ' ') + line++; + if (line) { + tildex = tilde_expand(line); + if (tildex && !stat(tildex, &testexist)) loadformats(tildex); else { #define BUFSIZE 4096 char buf[BUFSIZE]; - snprintf( buf, BUFSIZE, "~/.vchat/sample-%s.fmt", line ); + snprintf(buf, BUFSIZE, "~/.vchat/sample-%s.fmt", line); free(tildex); - tildex = tilde_expand( line ); - if(tildex && !stat(tildex, &testexist )) + tildex = tilde_expand(line); + if (tildex && !stat(tildex, &testexist)) loadformats(tildex); } writeout(" Sort of done. "); @@ -335,92 +336,87 @@ command_format(char *line) { } /* handle a help request */ -static void -command_help (char *line) { - flushout( ); - while( *line==' ') line++; - if( *line ) { /* Get help on command */ - int i; - if( ( i = translatecommand( &line ) ) != COMMAND_NONE ) { - snprintf( tmpstr, TMPSTRSIZE, "Help on command: %s", commandtable[i].name); - writeout( tmpstr ); - writeout(" "); - if( commandtable[i].short_help && !commandtable[i].help ) - writeout(commandtable[i].short_help ); - line = commandtable[i].help; - if( line ) { - while( *line ) { - char *tmp = tmpstr; - while( *line && (*line != '\n') ) - *tmp++ = *line++; - *tmp = '\0'; if( *line == '\n') line++; - writeout ( tmpstr ); - } - } - } else { - command_help( " " ); - } - } else { /* Get overall help */ - int i; - for( i = 0; commandtable[i].number != COMMAND_NONE; i++ ) { - if( commandtable[i].short_help ) - writeout( commandtable[i].short_help ); +static void command_help(char *line) { + flushout(); + while (*line == ' ') + line++; + if (*line) { /* Get help on command */ + int i; + if ((i = translatecommand(&line)) != COMMAND_NONE) { + snprintf(tmpstr, TMPSTRSIZE, "Help on command: %s", commandtable[i].name); + writeout(tmpstr); + writeout(" "); + if (commandtable[i].short_help && !commandtable[i].help) + writeout(commandtable[i].short_help); + line = commandtable[i].help; + if (line) { + while (*line) { + char *tmp = tmpstr; + while (*line && (*line != '\n')) + *tmp++ = *line++; + *tmp = '\0'; + if (*line == '\n') + line++; + writeout(tmpstr); + } } + } else { + command_help(" "); + } + } else { /* Get overall help */ + int i; + for (i = 0; commandtable[i].number != COMMAND_NONE; i++) { + if (commandtable[i].short_help) + writeout(commandtable[i].short_help); + } } showout(); } /* handle an unknown command */ -static void -command_none(char *line) { - snprintf(tmpstr, TMPSTRSIZE, " Unknown client command: %s ", line); - msgout(tmpstr); +static void command_none(char *line) { + snprintf(tmpstr, TMPSTRSIZE, " Unknown client command: %s ", line); + msgout(tmpstr); } /* handle a "/flt " request */ -static void -command_flt(char *tail){ +static void command_flt(char *tail) { char colour; - while(*tail==' ') tail++; + while (*tail == ' ') + tail++; colour = *tail++; - while( colour && *tail == ' ') tail++; - if( colour && *tail) { - addfilter( colour, tail); + while (colour && *tail == ' ') + tail++; + if (colour && *tail) { + addfilter(colour, tail); } } /* handle a "/clflt " request */ -static void -command_clflt (char *tail) { - while( *tail == ' ') tail++; - clearfilters( *tail ); +static void command_clflt(char *tail) { + while (*tail == ' ') + tail++; + clearfilters(*tail); } /* handle a "/rmflt " request */ -static void -command_rmflt (char *tail) { - while( *tail == ' ') tail++; - removefilter( tail ); +static void command_rmflt(char *tail) { + while (*tail == ' ') + tail++; + removefilter(tail); } /* list filters */ -static void -command_lsflt (char *tail) { +static void command_lsflt(char *tail) { (void)tail; listfilters(); } /* handle a "/me " action */ -static void -command_action(char *tail) -{ - doaction(tail); -} +static void command_action(char *tail) { doaction(tail); } /* handle a "/reconnect" request */ -static void -command_reconnect(char *tail) -{ +static void command_reconnect(char *tail) { (void)tail; status = 0; wantreconnect = 1; @@ -428,15 +424,13 @@ command_reconnect(char *tail) } /* handle a "/quit " exit */ -static void -command_quit(char *tail) -{ +static void command_quit(char *tail) { /* send users message to server */ - snprintf (tmpstr, TMPSTRSIZE, ".x %s", tail); - vc_sendmessage (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, ".x %s", tail); + vc_sendmessage(tmpstr); /* show action in channel window */ - writechan (tmpstr); + writechan(tmpstr); /* Inform vchat-client, that the closing connection following is intended */ @@ -445,42 +439,35 @@ command_quit(char *tail) } /* print out version */ -void -command_version(char *tail) -{ +void command_version(char *tail) { (void)tail; /* output internal versions of all modules */ flushout(); - writeout (vchat_cl_version); - writeout (vchat_ui_version); - writeout (vchat_io_version); - writeout (vchat_us_version); - writeout (vchat_cm_version); - writeout (vchat_tls_version); - writeout (vchat_tls_version_external); + writeout(vchat_cl_version); + writeout(vchat_ui_version); + writeout(vchat_io_version); + writeout(vchat_us_version); + writeout(vchat_cm_version); + writeout(vchat_tls_version); + writeout(vchat_tls_version_external); showout(); } /* start or end a query */ -void -command_query(char *tail) -{ +void command_query(char *tail) { char *msg; - while( *tail == ' ') tail++; + while (*tail == ' ') + tail++; // Check, if a message is to be sent in first query // Note: this is safe, since readline chops trailing spaces - if((msg = strchr(tail, ' '))) { - privatemessagetx( tail ); + if ((msg = strchr(tail, ' '))) { + privatemessagetx(tail); *msg = 0; } // Do the ui stuff for query - handlequery( tail ); + handlequery(tail); } -void -command_dict(char *tail) -{ - ul_add_to_dict(tail); -} +void command_dict(char *tail) { ul_add_to_dict(tail); } diff --git a/vchat-connection.c b/vchat-connection.c index 5ab4dd4..01cf2c2 100644 --- a/vchat-connection.c +++ b/vchat-connection.c @@ -10,27 +10,27 @@ * without even the implied warranty of merchantability or fitness for a * particular purpose. In no event shall the copyright holder be liable for * any direct, indirect, incidental or special damages arising in any way out - * of the use of this software. + * of the use of this software. * */ -#include +#include +#include +#include #include -#include #include -#include -#include -#include -#include +#include +#include #include -#include +#include +#include /* For tilde_expand */ #include -#include "vchat.h" #include "vchat-connection.h" #include "vchat-tls.h" +#include "vchat.h" static int serverfd = -1; unsigned int want_tcp_keepalive = 0; @@ -40,49 +40,49 @@ unsigned int want_tcp_keepalive = 0; extern int status; /* Generic tcp connector, blocking */ -static int connect_tcp_socket( const char *server, const char *port ) { +static int connect_tcp_socket(const char *server, const char *port) { struct addrinfo hints, *res, *res0; int s, error; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - error = getaddrinfo( server, port, &hints, &res0 ); - if (error) return -1; + error = getaddrinfo(server, port, &hints, &res0); + if (error) + return -1; s = -1; for (res = res0; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s < 0) continue; + if (s < 0) + continue; if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { close(s); s = -1; continue; } - break; /* okay we got one */ + break; /* okay we got one */ } freeaddrinfo(res0); if (want_tcp_keepalive) { - int one=1; - setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&one,sizeof(one)); + int one = 1; + setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)); } return s; } /* Return a tilde expanded path in a malloced buffer or NULL */ static char *get_tilde_expanded(confopt opt) { - char *str = getstroption (opt); + char *str = getstroption(opt); if (!str) return str; if (str[0] == '~') - return tilde_expand (str); + return tilde_expand(str); return strdup(str); } /* connects to server */ -int -vc_connect (const char *server, const char *port) -{ +int vc_connect(const char *server, const char *port) { /* vchat connection x509 store */ vc_x509store_t vc_store; @@ -90,11 +90,11 @@ vc_connect (const char *server, const char *port) char *certfile, *cafile; /* Connect to the server */ - serverfd = connect_tcp_socket( server, port ); - if( serverfd < 0 ) { + serverfd = connect_tcp_socket(server, port); + if (serverfd < 0) { /* inform user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port); + writechan(tmpstr); return -1; } @@ -105,11 +105,11 @@ vc_connect (const char *server, const char *port) vc_init_x509store(&vc_store); /* get name of certificate file */ - certfile = get_tilde_expanded (CF_CERTFILE); + certfile = get_tilde_expanded(CF_CERTFILE); /* do we have a certificate file? */ if (certfile) { /* get name of key file */ - char *keyfile = get_tilde_expanded (CF_KEYFILE); + char *keyfile = get_tilde_expanded(CF_KEYFILE); vc_x509store_setcertfile(&vc_store, certfile); vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt); @@ -122,13 +122,13 @@ vc_connect (const char *server, const char *port) } /* get name of ca file */ - cafile = get_tilde_expanded (CF_CAFILE); + cafile = get_tilde_expanded(CF_CAFILE); if (cafile && !access(cafile, F_OK)) vc_x509store_setcafile(&vc_store, cafile); free(cafile); /* upgrade our plain BIO to ssl */ - int result = vc_tls_connect( serverfd, &vc_store ); + int result = vc_tls_connect(serverfd, &vc_store); vc_cleanup_x509store(&vc_store); if (result) { @@ -136,17 +136,17 @@ vc_connect (const char *server, const char *port) serverfd = -1; errno = EIO; vc_tls_cleanup(); - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port); + writechan(tmpstr); return -1; } /* inform user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); + writechan(tmpstr); #ifdef DEBUG - dumpfile = fopen( "dumpfile", "a"); + dumpfile = fopen("dumpfile", "a"); #endif /* if we didn't fail until now, we've got a connection. */ @@ -154,25 +154,24 @@ vc_connect (const char *server, const char *port) } /* Poll for activity on the socket or stdin */ -int vc_poll (int timeout_seconds) { +int vc_poll(int timeout_seconds) { fd_set readfds; - FD_ZERO (&readfds); - FD_SET (0, &readfds); + FD_ZERO(&readfds); + FD_SET(0, &readfds); if (serverfd != -1) - FD_SET (serverfd, &readfds); - struct timeval tv = { timeout_seconds, 0}; - int result = select (serverfd + 2, &readfds, NULL, NULL, &tv); + FD_SET(serverfd, &readfds); + struct timeval tv = {timeout_seconds, 0}; + int result = select(serverfd + 2, &readfds, NULL, NULL, &tv); if (result <= 0) return result; - result = FD_ISSET (0, &readfds) ? 1 : 0; + result = FD_ISSET(0, &readfds) ? 1 : 0; if (serverfd != -1) - result += FD_ISSET (serverfd, &readfds) ? 2 : 0; + result += FD_ISSET(serverfd, &readfds) ? 2 : 0; return result; } /* disconnect from server */ -void -vc_disconnect () { +void vc_disconnect() { if (serverfd > 0) { close(serverfd); serverfd = -1; @@ -183,21 +182,19 @@ vc_disconnect () { #define STAGINGSIZE 16384 static char _staging[STAGINGSIZE]; -void -vc_sendmessage (const char *msg) -{ +void vc_sendmessage(const char *msg) { size_t sent, len = snprintf(_staging, sizeof(_staging), "%s\r\n", msg); #ifdef DEBUG /* debugging? log network output! */ - fprintf (dumpfile, ">| (%zd) %s\n", len - 2, msg); + fprintf(dumpfile, ">| (%zd) %s\n", len - 2, msg); #endif if (getintoption(CF_USESSL)) - sent = vc_tls_sendmessage (_staging, len); + sent = vc_tls_sendmessage(_staging, len); else - sent = write (serverfd, _staging, len); + sent = write(serverfd, _staging, len); if (sent != len) - writecf (FS_ERR,"Message sending fuzzy."); + writecf(FS_ERR, "Message sending fuzzy."); } /* offset in buffer (for linebreaks at packet borders) */ @@ -206,9 +203,7 @@ static char _buf[BUFSIZE]; static size_t _buf_fill; /* get data from servers connection */ -void -vc_receive (void) -{ +void vc_receive(void) { char *endmsg; size_t freebytes = BUFSIZE - _buf_fill; ssize_t bytes; @@ -218,26 +213,27 @@ vc_receive (void) else bytes = vc_tls_receivemessage(_buf + _buf_fill, freebytes); - /* Our tls functions may require retries with handshakes etc, this is signalled by -2 */ + /* Our tls functions may require retries with handshakes etc, this is + * signalled by -2 */ if (bytes == -2) return; /* Error on the socket read? raise error message, bail out */ if (bytes == -1) { - snprintf (tmpstr, TMPSTRSIZE, "Receive fails, %s.", strerror(errno)); - snprintf (errstr, ERRSTRSIZE, "Receive fails, %s.\n", strerror(errno)); - writecf (FS_ERR,tmpstr); - status = 0; - return; + snprintf(tmpstr, TMPSTRSIZE, "Receive fails, %s.", strerror(errno)); + snprintf(errstr, ERRSTRSIZE, "Receive fails, %s.\n", strerror(errno)); + writecf(FS_ERR, tmpstr); + status = 0; + return; } /* end of file from server? */ if (bytes == 0) { - /* inform user, bail out */ - writecf (FS_SERV, "* EOF from server."); - snprintf (errstr, ERRSTRSIZE, "* EOF from server.\n"); - status = 0; - return; + /* inform user, bail out */ + writecf(FS_SERV, "* EOF from server."); + snprintf(errstr, ERRSTRSIZE, "* EOF from server.\n"); + status = 0; + return; } _buf_fill += bytes; @@ -249,13 +245,14 @@ vc_receive (void) endmsg[0] = 0; if (endmsg[-1] == '\r') endmsg[-1] = 0; - /* If terminating and chomping left us with a message, give it to line handler */ + /* If terminating and chomping left us with a message, give it to line + * handler */ if (_buf[0]) { #ifdef DEBUG /* debugging? log network input! */ - fprintf (stderr, "<| %s\n", _buf); + fprintf(stderr, "<| %s\n", _buf); #endif - protocol_parsemsg (_buf); + protocol_parsemsg(_buf); } } _buf_fill -= 1 + endmsg - _buf; diff --git a/vchat-connection.h b/vchat-connection.h index a56dc29..9b3ccaa 100644 --- a/vchat-connection.h +++ b/vchat-connection.h @@ -2,8 +2,8 @@ #include -int vc_connect(const char *host, const char *port); -void vc_sendmessage(const char *message); -void vc_receive(); -int vc_poll(); -void vc_disconnect(); +int vc_connect(const char *host, const char *port); +void vc_sendmessage(const char *message); +void vc_receive(); +int vc_poll(); +void vc_disconnect(); diff --git a/vchat-protocol.c b/vchat-protocol.c index 2b98779..ac65639 100755 --- a/vchat-protocol.c +++ b/vchat-protocol.c @@ -10,49 +10,51 @@ * without even the implied warranty of merchantability or fitness for a * particular purpose. In no event shall the copyright holder be liable for * any direct, indirect, incidental or special damages arising in any way out - * of the use of this software. + * of the use of this software. * */ /* general includes */ -#include +#include +#include +#include #include +#include #include -#include + #include -#include -#include #ifdef DEBUG -FILE * dumpfile; +FILE *dumpfile; #endif /* local includes */ -#include "vchat.h" -#include "vchat-user.h" #include "vchat-connection.h" +#include "vchat-user.h" +#include "vchat.h" /* version of this module */ -const char *vchat_io_version = "vchat-protocol.c $Id$"; +const char *vchat_io_version = + "vchat-protocol.c $Id$"; /* declaration of local helper functions */ -static void usersignon (char *); -static void usersignoff (char *); -static void usernickchange (char *); -static void userjoin (char *); -static void userleave (char *); -static void receivenicks (char *message); -static void justloggedin (char *message); -static void nickerr (char *message); -static void login (char *message); -static void anonlogin (char *message); -static void topicinfo (char *message); -static void pubaction (char *message); -static void pubthoughts (char *message); -static void serverlogin (char *message); -static void idleprompt (char *message); -static void topicchange (char *message); -static void pmnotsent (char *message); +static void usersignon(char *); +static void usersignoff(char *); +static void usernickchange(char *); +static void userjoin(char *); +static void userleave(char *); +static void receivenicks(char *message); +static void justloggedin(char *message); +static void nickerr(char *message); +static void login(char *message); +static void anonlogin(char *message); +static void topicinfo(char *message); +static void pubaction(char *message); +static void pubthoughts(char *message); +static void serverlogin(char *message); +static void idleprompt(char *message); +static void topicchange(char *message); +static void pmnotsent(char *message); /* declaration of server message array */ #include "vchat-messages.h" @@ -61,61 +63,53 @@ char *encoding; /* handle a pm not sent error * format: 412 %s */ -static void -pmnotsent (char *message) -{ - while(*message && *message!=' ') message++; - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_ERR),message+1); - writepriv( tmpstr, 0); - +static void pmnotsent(char *message) { + while (*message && *message != ' ') + message++; + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), message + 1); + writepriv(tmpstr, 0); } /* parse and handle an action string * format: 118 %s %s * vars: %s nick * %s action */ -static void -pubaction (char *message) -{ +static void pubaction(char *message) { char *nick = NULL, *action = NULL; - nick = strchr (message, ' '); + nick = strchr(message, ' '); nick[0] = '\0'; nick++; - action = strchr (nick, ' '); + action = strchr(nick, ' '); action[0] = '\0'; action++; ul_public_action(nick); - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_PUBACTION),nick,action); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_PUBACTION), nick, action); + writechan(tmpstr); } /* parse and handle an thought string * format: 124 %s %s * vars: %s nick * %s thought */ -static void -pubthoughts (char *message) -{ +static void pubthoughts(char *message) { char *nick = NULL, *thoughts = NULL; - nick = strchr (message, ' '); + nick = strchr(message, ' '); nick[0] = '\0'; nick++; - thoughts = strchr (nick, ' '); + thoughts = strchr(nick, ' '); thoughts[0] = '\0'; thoughts++; ul_public_action(nick); - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_PUBTHOUGHT),nick,thoughts); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_PUBTHOUGHT), nick, thoughts); + writechan(tmpstr); } /* parse and handle server logon */ -static void -serverlogin (char *message) -{ +static void serverlogin(char *message) { (void)message; int utf8 = !strcmp(nl_langinfo(CODESET), "UTF-8"); if (utf8) @@ -125,274 +119,257 @@ serverlogin (char *message) /* parse and handle an idle message * format: 305 * vars: %s message */ -static void -idleprompt (char *message) -{ +static void idleprompt(char *message) { char *msg = NULL; - msg = strchr (message, ' '); + msg = strchr(message, ' '); msg[0] = '\0'; msg++; - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_IDLE),msg); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_IDLE), msg); + writechan(tmpstr); } /* parse and handle a topic information string * format: 115 %d %s * vars: %d chan - channel number * %s topic - topic */ -static void -topicinfo (char *message) -{ +static void topicinfo(char *message) { char *channel = NULL, *topic = NULL; int tmpchan = 0, ownchan = own_channel_get(); /* search start of channel number */ - channel = strchr (message, ' '); + channel = strchr(message, ' '); channel++; /* search start of topic and terminate channel number */ - topic = strchr (channel, ' '); + topic = strchr(channel, ' '); topic[0] = '\0'; topic++; /* convert channel number to integer */ - tmpchan = atoi (channel); - - if (tmpchan == ownchan ) { - /* show change in topic window */ - if (strlen(topic)) - snprintf (topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic); - else - snprintf (topicstr, TOPICSTRSIZE, getformatstr(FS_NOTOPICW), ownchan ); - topicline(NULL); + tmpchan = atoi(channel); + + if (tmpchan == ownchan) { + /* show change in topic window */ + if (strlen(topic)) + snprintf(topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic); + else + snprintf(topicstr, TOPICSTRSIZE, getformatstr(FS_NOTOPICW), ownchan); + topicline(NULL); } /* announce change in channel window */ if (strlen(topic)) - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TOPIC), tmpchan, topic); - else - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_NOTOPIC), tmpchan); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_TOPIC), tmpchan, topic); + else + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_NOTOPIC), tmpchan); + writechan(tmpstr); } /* parse and handle a topic change string * format: 114 %s changes topic to '%s' * vars: %s nick * %s topic */ -static void -topicchange (char *message) -{ +static void topicchange(char *message) { char *nick = NULL, *topic = NULL; int len, ownchan = own_channel_get(); /* search start of nickname */ - nick = strchr (message, ' '); + nick = strchr(message, ' '); nick++; /* search start of message before topic, terminate nick */ - topic = strchr (nick, ' '); + topic = strchr(nick, ' '); topic[0] = '\0'; topic++; /* search start of real topic and terminate channel number */ - topic = strchr (topic, '\''); + topic = strchr(topic, '\''); topic[0] = '\0'; topic++; /* remove ending '\'', if there */ - len = strlen (topic); - if (topic[len-1] == '\'') - topic[len-1] = '\0'; + len = strlen(topic); + if (topic[len - 1] == '\'') + topic[len - 1] = '\0'; ul_public_action(nick); /* show change in topic window */ - snprintf (topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic); + snprintf(topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic); topicline(NULL); /* announce change in channel window */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CHGTOPIC), nick, topic); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CHGTOPIC), nick, topic); + writechan(tmpstr); } /* parse and handle a login message * format: 212 %s %s * vars: %s str1 - nick used to login * %s str2 - servers message */ -static void -justloggedin (char *message) -{ +static void justloggedin(char *message) { char *str1 = NULL, *str2 = NULL; /* search start of nickname */ - str1 = strchr (message, ' '); + str1 = strchr(message, ' '); str1++; /* search start of message, terminate nick */ - str2 = strchr (str1, ' '); + str2 = strchr(str1, ' '); str2[0] = '\0'; str2++; /* if we have a new nick, store it */ - own_nick_set( str1 ); + own_nick_set(str1); /* show change in console window */ - snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), str1, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); - consoleline (NULL); + snprintf(consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), str1, + getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT)); + consoleline(NULL); /* announce login as servermessage */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), str1, str2); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), str1, str2); + writechan(tmpstr); /* we're not logged in, change status and request nicks */ - if (!loggedin) - { - loadcfg(getstroption(CF_LOGINSCRIPT),0,handleline); - handleline(".S"); - loggedin = 1; - } + if (!loggedin) { + loadcfg(getstroption(CF_LOGINSCRIPT), 0, handleline); + handleline(".S"); + loggedin = 1; + } } /* this user joins a different channel */ -void -ownjoin (int channel) -{ +void ownjoin(int channel) { vc_sendmessage(".t"); - snprintf(tmpstr, TMPSTRSIZE, ".S %d",channel); + snprintf(tmpstr, TMPSTRSIZE, ".S %d", channel); vc_sendmessage(tmpstr); } /* this user changes his nick */ -void -ownnickchange (const char *newnick) -{ - (void)newnick; -} +void ownnickchange(const char *newnick) { (void)newnick; } /* parse and handle a nick error message * format: 401 %s * 403 %s * 415 %s * vars: %s - server message */ -static void -nickerr (char *message) -{ +static void nickerr(char *message) { char *helpkiller = NULL; /* mutate message for output */ message[2] = '!'; /* help information found? remove it. */ - if ((helpkiller = strstr (message, " Type .h for help"))) + if ((helpkiller = strstr(message, " Type .h for help"))) helpkiller[0] = '\0'; /* nickchange not done? eliminate message */ - if (loggedin && (helpkiller = strstr (message, " - Nick not changed"))) + if (loggedin && (helpkiller = strstr(message, " - Nick not changed"))) helpkiller[0] = '\0'; /* show errormessage */ - writecf (FS_ERR,&message[2]); + writecf(FS_ERR, &message[2]); /* not logged in? insist on getting a new nick */ - if (!loggedin) - { - /* free bogus nick */ - own_nick_set(NULL); + if (!loggedin) { + /* free bogus nick */ + own_nick_set(NULL); - /* get new nick via vchat-ui.c */ - nickprompt (); + /* get new nick via vchat-ui.c */ + nickprompt(); - /* form login message and send it to server */ - snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); - vc_sendmessage (tmpstr); - } + /* form login message and send it to server */ + snprintf(tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), + getstroption(CF_FROM), getintoption(CF_CHANNEL)); + vc_sendmessage(tmpstr); + } } /* parse and handle a registered nick information * format: 120 %s %s * vars: %s - this users registered nick * %s msg - server message */ -static void -login (char *message) { +static void login(char *message) { char *msg = NULL; /* mutate message for output */ message[2] = '*'; /* show message to user */ - writecf (FS_SERV,&message[2]); + writecf(FS_SERV, &message[2]); /* we don't know our nick? */ - if (!own_nick_get() ) { + if (!own_nick_get()) { /* find message after nick */ - msg = strchr (&message[4], ' '); + msg = strchr(&message[4], ' '); if (msg) { /* terminate string before message and copy nick */ msg[0] = '\0'; own_nick_set(&message[4]); } else { /* no string in servers message (huh?), ask user for nick */ - nickprompt (); + nickprompt(); } } /* form login message and send it to server */ - snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); - vc_sendmessage (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), + getstroption(CF_FROM), getintoption(CF_CHANNEL)); + vc_sendmessage(tmpstr); } /* parse and handle anon login request * format: 121 %s * vars: %s - server message */ -static void -anonlogin (char *message) -{ +static void anonlogin(char *message) { /* mutate message for output */ message[2] = '*'; /* show message to user */ - writecf (FS_SERV,&message[2]); + writecf(FS_SERV, &message[2]); /* we don't know our nick? ask for it! */ if (!own_nick_get()) - nickprompt (); + nickprompt(); /* form login message and send it to server */ - snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); - vc_sendmessage (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), + getstroption(CF_FROM), getintoption(CF_CHANNEL)); + vc_sendmessage(tmpstr); } /* parse and handle list of nicks (from '.S') * format: 119 %s .. * vars: %s nick - a users nick */ -static void -receivenicks (char *message) { +static void receivenicks(char *message) { char *str1 = NULL, *str2 = NULL; int chanflag = -1; /* show message to user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_USONLINE), &message[4]); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_USONLINE), &message[4]); + writechan(tmpstr); /* search for channelnumber */ - if( !(str1 = strchr (message, ' ') ) ) return; + if (!(str1 = strchr(message, ' '))) + return; str1++; if (str1[0] == '*') { - ul_rebuild_list(); - str1++; + ul_rebuild_list(); + str1++; } else { - int mychan; - str2 = str1; - str1 = strchr(str2,' '); - str1[0] = '\0'; - mychan = atoi(str2); - if( mychan != own_channel_get() ) - return; - - /* Kick all users from the IN_MY_CHANNEL list */ - own_channel_set( own_channel_get() ); - chanflag = 1; + int mychan; + str2 = str1; + str1 = strchr(str2, ' '); + str1[0] = '\0'; + mychan = atoi(str2); + if (mychan != own_channel_get()) + return; + + /* Kick all users from the IN_MY_CHANNEL list */ + own_channel_set(own_channel_get()); + chanflag = 1; } str1++; /* while user .. */ while (str1) { /* search next user */ - str2 = strchr (str1, ' '); + str2 = strchr(str1, ' '); /* there is another user? terminate this one */ if (str2) { str2[0] = '\0'; @@ -412,52 +389,48 @@ receivenicks (char *message) { * format: 211 %s %s * vars: %s nick - who logged on * %s msg - servers message */ -static void -usersignon (char *message) -{ +static void usersignon(char *message) { char *nick = NULL, *msg = NULL; /* search start of nickname */ - nick = strchr (message, ' '); + nick = strchr(message, ' '); nick++; /* search start of message, terminate nick */ - msg = strchr (nick, ' '); + msg = strchr(nick, ' '); msg[0] = '\0'; msg++; /* add this user via vchat-user.c */ - ul_add (nick, 0); + ul_add(nick, 0); /* show message to user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), nick, msg); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), nick, msg); + writechan(tmpstr); } /* parse and handle a logoff message * format: 221 %s %s * vars: %s nick - who logged off * %s msg - servers message */ -static void -usersignoff (char *message) -{ +static void usersignoff(char *message) { char *nick = NULL, *msg = NULL; /* search start of nickname */ - nick = strchr (message, ' '); + nick = strchr(message, ' '); nick++; /* search start of message, terminate nick */ - msg = strchr (nick, ' '); - if( msg ) { + msg = strchr(nick, ' '); + if (msg) { msg[0] = '\0'; msg++; } /* delete this user via vchat-user.c */ - ul_del (nick); + ul_del(nick); /* show message to user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNOFF), nick, msg); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNOFF), nick, msg); + writechan(tmpstr); } /* parse and handle a join message @@ -465,40 +438,38 @@ usersignoff (char *message) * vars: %s nick - who joined * %s msg - servers message * %d chan - channel joined */ -static void -userjoin (char *message) -{ +static void userjoin(char *message) { char *nick = NULL, *msg = NULL, *channel = NULL; int chan = 0; /* search start of nickname */ - nick = strchr (message, ' '); + nick = strchr(message, ' '); nick++; /* search start of message, terminate nick */ - msg = strchr (nick, ' '); + msg = strchr(nick, ' '); msg[0] = '\0'; msg++; /* search start of channel, terminate message */ - channel = strrchr (msg, ' '); + channel = strrchr(msg, ' '); channel[0] = '\0'; channel++; /* convert channel to integer */ - chan = atoi (channel); + chan = atoi(channel); /* is it myself joining */ - if( own_nick_check(nick) ) + if (own_nick_check(nick)) own_channel_set(chan); /* notice channel join via vchat-user.c */ - if( own_channel_get() == chan ) + if (own_channel_get() == chan) ul_enter_chan(nick); /* show message to user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_JOIN), nick, msg, chan); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_JOIN), nick, msg, chan); + writechan(tmpstr); } /* parse and handle a leave message @@ -506,35 +477,33 @@ userjoin (char *message) * vars: %s nick - who left * %s msg - servers message * %d chan - channel joined */ -static void -userleave (char *message) -{ +static void userleave(char *message) { char *nick = NULL, *msg = NULL, *channel = NULL; int chan = 0; /* search start of nickname */ - nick = strchr (message, ' '); + nick = strchr(message, ' '); nick++; /* search start of message, terminate nick */ - msg = strchr (nick, ' '); + msg = strchr(nick, ' '); msg[0] = '\0'; msg++; /* convert channel to integer */ - channel = strrchr (msg, ' '); + channel = strrchr(msg, ' '); channel[0] = '\0'; channel++; /* convert channel to integer */ - chan = atoi (channel); + chan = atoi(channel); /* notice channel leave via vchat-user.c */ ul_leave_chan(nick); /* show message to user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_LEAVE), nick, msg, chan); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_LEAVE), nick, msg, chan); + writechan(tmpstr); } /* parse and handle a nickchange message @@ -542,151 +511,140 @@ userleave (char *message) * vars: %s oldnick - users old nick * %s newnick - users new nick * %s msg - server message */ -static void -usernickchange (char *message) -{ +static void usernickchange(char *message) { char *oldnick = NULL, *newnick = NULL, *msg = NULL; /* search start of old nickname */ - oldnick = strchr (message, ' '); + oldnick = strchr(message, ' '); oldnick++; /* search start of new nickname, terminate old nick */ - newnick = strchr (oldnick, ' '); + newnick = strchr(oldnick, ' '); newnick[0] = '\0'; newnick++; /* search start of message, terminate new nick */ - msg = strchr (newnick, ' '); + msg = strchr(newnick, ' '); msg[0] = '\0'; msg++; /* notice nickchange via vchat-user.c */ - ul_rename (oldnick, newnick); + ul_rename(oldnick, newnick); - if( own_nick_check(newnick) ) { + if (own_nick_check(newnick)) { /* show change in console window */ - snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), newnick, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); - consoleline (NULL); + snprintf(consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), newnick, + getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT)); + consoleline(NULL); } /* show message to user */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_NICKCHANGE), oldnick, newnick, msg); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_NICKCHANGE), oldnick, newnick, + msg); + writechan(tmpstr); } /* handle received message from server */ -void -protocol_parsemsg (char *message) -{ +void protocol_parsemsg(char *message) { char *str1, *str2; int i; /* message to short or starts with '<'? must be channel */ - if (message[0] == '<') - { + if (message[0] == '<') { str1 = &message[1]; - str2 = strchr(str1,'>'); + str2 = strchr(str1, '>'); str2[0] = '\0'; str2++; - if (str2[0] == ' ') str2++; + if (str2[0] == ' ') + str2++; if (own_nick_check(str1)) - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_MYPUBMSG),str1,str2); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_MYPUBMSG), str1, str2); else - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_RXPUBMSG),str1,str2); - writechan (tmpstr); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_RXPUBMSG), str1, str2); + writechan(tmpstr); ul_public_action(str1); - } - else if (message[0] == '[') - { + } else if (message[0] == '[') { str1 = &message[1]; - str2 = strchr(str1,']'); + str2 = strchr(str1, ']'); str2[0] = '\0'; str2++; - if (str2[0] == ' ') str2++; - if (own_nick_check( str1 )) - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_MYPUBURL),str1,str2); + if (str2[0] == ' ') + str2++; + if (own_nick_check(str1)) + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_MYPUBURL), str1, str2); else - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_RXPUBURL),str1,str2); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_RXPUBURL), str1, str2); ul_public_action(str1); - writechan (tmpstr); + writechan(tmpstr); } /* message starts with '*'? must be private */ - else if (message[0] == '*') - { + else if (message[0] == '*') { str1 = &message[1]; - str2 = strchr(str1,'*'); + str2 = strchr(str1, '*'); str2[0] = '\0'; str2++; - if (str2[0] == ' ') str2++; - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_RXPRIVMSG),str1,str2); - writepriv (tmpstr, 1); + if (str2[0] == ' ') + str2++; + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_RXPRIVMSG), str1, str2); + writepriv(tmpstr, 1); ul_private_action(str1); } /* message starts with a number? must be a servermessage */ - else if ((message[0] >= '0') && (message[0] <= '9')) - { - /* walk server message array */ - for (i = 0; servermessages[i].id[0]; i++) - { - /* is this the message? */ - if (!(strncmp (servermessages[i].id, message, 3))) - { - /* scripting hook available - call it */ - if (servermessages[i].hook) - servermessages[i].hook (message); - /* function available - call it */ - else if (servermessages[i].funct) - servermessages[i].funct (message); - /* no function available, but known - give output */ - else - { - /* remove continutation mark */ - if (message[3] == '-') - message[3] = ' '; - - /* mutate message for display */ - message[2] = '*'; - /* giveout message by type */ - switch (servermessages[i].type) - { - case SM_IGNORE: - break; - case SM_INFO: - /* change marker and send as servermessage */ - message[2] = '#'; - writecf (FS_SERV,&message[2]); - break; - case SM_USERINFO: - /* keep marker and send as servermessage */ - writecf (FS_SERV,&message[2]); - break; - case SM_CHANNEL: - /* keep marker and send as channelmessage */ - writechan (&message[2]); - break; - case SM_ERROR: - /* change marker and send as errormessage */ - message[2] = '!'; - writecf (FS_ERR,&message[2]); - break; - default: - /* fallback: keep marker and send as servermessage */ - writecf (FS_SERV,&message[2]); - } - } - return; - } - } - /* message not in list, raise errormessage */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_UNKNOWNMSG), message); - writecf (FS_ERR,tmpstr); - } - else - { - /* message neither public, private or server, raise errormessage */ - snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_BOGUSMSG), message); - writecf (FS_ERR,tmpstr); + else if ((message[0] >= '0') && (message[0] <= '9')) { + /* walk server message array */ + for (i = 0; servermessages[i].id[0]; i++) { + /* is this the message? */ + if (!(strncmp(servermessages[i].id, message, 3))) { + /* scripting hook available - call it */ + if (servermessages[i].hook) + servermessages[i].hook(message); + /* function available - call it */ + else if (servermessages[i].funct) + servermessages[i].funct(message); + /* no function available, but known - give output */ + else { + /* remove continutation mark */ + if (message[3] == '-') + message[3] = ' '; + + /* mutate message for display */ + message[2] = '*'; + /* giveout message by type */ + switch (servermessages[i].type) { + case SM_IGNORE: + break; + case SM_INFO: + /* change marker and send as servermessage */ + message[2] = '#'; + writecf(FS_SERV, &message[2]); + break; + case SM_USERINFO: + /* keep marker and send as servermessage */ + writecf(FS_SERV, &message[2]); + break; + case SM_CHANNEL: + /* keep marker and send as channelmessage */ + writechan(&message[2]); + break; + case SM_ERROR: + /* change marker and send as errormessage */ + message[2] = '!'; + writecf(FS_ERR, &message[2]); + break; + default: + /* fallback: keep marker and send as servermessage */ + writecf(FS_SERV, &message[2]); + } + } + return; + } } + /* message not in list, raise errormessage */ + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_UNKNOWNMSG), message); + writecf(FS_ERR, tmpstr); + } else { + /* message neither public, private or server, raise errormessage */ + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_BOGUSMSG), message); + writecf(FS_ERR, tmpstr); + } } - diff --git a/vchat-tls.c b/vchat-tls.c index 7b0f1fa..187f10b 100755 --- a/vchat-tls.c +++ b/vchat-tls.c @@ -15,663 +15,703 @@ * */ +#include +#include #include #include #include -#include -#include #include -#include "vchat.h" #include "vchat-tls.h" +#include "vchat.h" -const char *vchat_tls_version = "vchat-tls.c $Id$"; -const char *vchat_tls_version_external = "Unknown implementation; version unknown"; +const char *vchat_tls_version = + "vchat-tls.c $Id$"; +const char *vchat_tls_version_external = + "Unknown implementation; version unknown"; /* Helpers to work with vc_x509store_t used by all tls libs */ void vc_cleanup_x509store(vc_x509store_t *store) { - free(store->cafile); - free(store->capath); - free(store->crlfile); - free(store->certfile); - free(store->keyfile); - memset(store, 0, sizeof(vc_x509store_t)); + free(store->cafile); + free(store->capath); + free(store->crlfile); + free(store->certfile); + free(store->keyfile); + memset(store, 0, sizeof(vc_x509store_t)); } -void vc_x509store_setflags(vc_x509store_t *store, int flags) { store->flags |= flags; } -void vc_x509store_clearflags(vc_x509store_t *store, int flags) { store->flags &= ~flags; } -void vc_x509store_set_pkeycb(vc_x509store_t *store, vc_askpass_cb_t callback) { store->askpass_callback = callback; } +void vc_x509store_setflags(vc_x509store_t *store, int flags) { + store->flags |= flags; +} +void vc_x509store_clearflags(vc_x509store_t *store, int flags) { + store->flags &= ~flags; +} +void vc_x509store_set_pkeycb(vc_x509store_t *store, vc_askpass_cb_t callback) { + store->askpass_callback = callback; +} void vc_x509store_setcafile(vc_x509store_t *store, char *file) { - free(store->cafile); - store->cafile = ( file ? strdup(file) : 0 ); - store->flags |= VC_X509S_USE_CAFILE; + free(store->cafile); + store->cafile = (file ? strdup(file) : 0); + store->flags |= VC_X509S_USE_CAFILE; } void vc_x509store_setcapath(vc_x509store_t *store, char *path) { - free(store->capath); - store->capath = ( path ? strdup(path) : 0 ); + free(store->capath); + store->capath = (path ? strdup(path) : 0); } void vc_x509store_setcrlfile(vc_x509store_t *store, char *file) { - free(store->crlfile); - store->crlfile = ( file ? strdup(file) : 0 ); + free(store->crlfile); + store->crlfile = (file ? strdup(file) : 0); } void vc_x509store_setkeyfile(vc_x509store_t *store, char *file) { - free(store->keyfile); - store->keyfile = ( file ? strdup(file) : 0 ); + free(store->keyfile); + store->keyfile = (file ? strdup(file) : 0); } void vc_x509store_setcertfile(vc_x509store_t *store, char *file) { - free(store->certfile); - store->certfile = ( file ? strdup(file) : 0 ); - store->flags |= VC_X509S_USE_CERTIFICATE; + free(store->certfile); + store->certfile = (file ? strdup(file) : 0); + store->flags |= VC_X509S_USE_CERTIFICATE; } static int verify_or_store_fingerprint(const char *fingerprint) { - char *fingerprint_file_path = tilde_expand(getstroption(CF_FINGERPRINT)); - if (!fingerprint_file_path) { - writecf(FS_ERR, "Error: The CF_FINGERPRINT path is not set but CF_PINFINGER was requested."); - return -1; + char *fingerprint_file_path = tilde_expand(getstroption(CF_FINGERPRINT)); + if (!fingerprint_file_path) { + writecf(FS_ERR, "Error: The CF_FINGERPRINT path is not set but " + "CF_PINFINGER was requested."); + return -1; + } + + FILE *fingerprint_file = fopen(fingerprint_file_path, "r"); + if (fingerprint_file) { + /* Read fingerprint from file */ + char old_fingerprint[128]; + char *r = fgets(old_fingerprint, sizeof(old_fingerprint), fingerprint_file); + fclose(fingerprint_file); + + if (r) { + /* chomp */ + char *nl = strchr(r, '\n'); + if (nl) + *nl = 0; + + /* verify fingerprint matches stored version */ + if (!strcmp(fingerprint, old_fingerprint)) { + writecf(FS_SERV, "[FINGERPRINT MATCH ]"); + goto cleanup_happy; + } } - FILE *fingerprint_file = fopen(fingerprint_file_path, "r"); - if (fingerprint_file) { - /* Read fingerprint from file */ - char old_fingerprint[128]; - char * r = fgets(old_fingerprint, sizeof(old_fingerprint), fingerprint_file); - fclose(fingerprint_file); - - if (r) { - /* chomp */ - char *nl = strchr(r, '\n'); - if (nl) *nl = 0; - - /* verify fingerprint matches stored version */ - if (!strcmp(fingerprint, old_fingerprint)) { - writecf(FS_SERV, "[FINGERPRINT MATCH ]"); - goto cleanup_happy; - } - } - - snprintf(tmpstr, TMPSTRSIZE, "Error: Found pinned fingerprint (in %s) %s but expected %s", r ? old_fingerprint : "", getstroption(CF_FINGERPRINT), fingerprint); - writecf(FS_ERR, tmpstr); - writecf(FS_ERR, "Error: Fingerprint mismatch! Server cert updated?"); - free(fingerprint_file_path); - return 1; - } else - writecf(FS_ERR, "Warning: No pinned fingerprint found, writing the current one."); - - fingerprint_file = fopen(fingerprint_file_path, "w"); - if (!fingerprint_file) { - snprintf (tmpstr, TMPSTRSIZE, "Warning: Can't write fingerprint file, %s.", strerror(errno)); - writecf(FS_ERR, tmpstr); - } else { - fputs(fingerprint, fingerprint_file); - fclose(fingerprint_file); - writecf(FS_SERV, "[FINGERPRINT STORED ]"); - } -cleanup_happy: + snprintf(tmpstr, TMPSTRSIZE, + "Error: Found pinned fingerprint (in %s) %s but expected %s", + r ? old_fingerprint : "", + getstroption(CF_FINGERPRINT), fingerprint); + writecf(FS_ERR, tmpstr); + writecf(FS_ERR, "Error: Fingerprint mismatch! Server cert updated?"); free(fingerprint_file_path); - return 0; + return 1; + } else + writecf(FS_ERR, + "Warning: No pinned fingerprint found, writing the current one."); + + fingerprint_file = fopen(fingerprint_file_path, "w"); + if (!fingerprint_file) { + snprintf(tmpstr, TMPSTRSIZE, "Warning: Can't write fingerprint file, %s.", + strerror(errno)); + writecf(FS_ERR, tmpstr); + } else { + fputs(fingerprint, fingerprint_file); + fclose(fingerprint_file); + writecf(FS_SERV, "[FINGERPRINT STORED ]"); + } +cleanup_happy: + free(fingerprint_file_path); + return 0; } #if defined(TLS_LIB_OPENSSL) && defined(TLS_LIB_MBEDTLS) -#error "Both TLS_LIB_OPENSSL and TLS_LIB_MBEDTLS are defined. Please select only one." +#error \ + "Both TLS_LIB_OPENSSL and TLS_LIB_MBEDTLS are defined. Please select only one." #endif #if !defined(TLS_LIB_OPENSSL) && !defined(TLS_LIB_MBEDTLS) -#error "Neither TLS_LIB_OPENSSL nor TLS_LIB_MBEDTLS are defined. Please select exactly one." +#error \ + "Neither TLS_LIB_OPENSSL nor TLS_LIB_MBEDTLS are defined. Please select exactly one." #endif #ifdef TLS_LIB_OPENSSL -#include -#include #include +#include +#include #include +#include #include #include -#include -void vchat_tls_get_version_external() -{ - snprintf(tmpstr, sizeof(tmpstr), "OpenSSL %s with %s", SSLeay_version(SSLEAY_VERSION), SSLeay_version(SSLEAY_CFLAGS)); - vchat_tls_version_external = strdup(tmpstr); +void vchat_tls_get_version_external() { + snprintf(tmpstr, sizeof(tmpstr), "OpenSSL %s with %s", + SSLeay_version(SSLEAY_VERSION), SSLeay_version(SSLEAY_CFLAGS)); + vchat_tls_version_external = strdup(tmpstr); } -void vc_init_x509store(vc_x509store_t *store) -{ - static int sslinit; - if (!sslinit++) { - SSL_library_init (); - SSL_load_error_strings(); - } - memset(store, 0, sizeof(vc_x509store_t)); +void vc_init_x509store(vc_x509store_t *store) { + static int sslinit; + if (!sslinit++) { + SSL_library_init(); + SSL_load_error_strings(); + } + memset(store, 0, sizeof(vc_x509store_t)); - /* We want to make verifying the peer the default */ - store->flags |= VC_X509S_SSL_VERIFY_PEER; + /* We want to make verifying the peer the default */ + store->flags |= VC_X509S_SSL_VERIFY_PEER; } /* connection BIO for openssl */ static BIO *server_conn = NULL; -static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ); +static SSL_CTX *vc_create_sslctx(vc_x509store_t *vc_store); static int vc_verify_callback(int, X509_STORE_CTX *); -static X509_STORE * vc_x509store_create(vc_x509store_t *); - -static SSL_CTX * vc_create_sslctx( vc_x509store_t *vc_store ) -{ - int flags = 0; - - /* Explicitly use TLSv1 (or maybe later) */ - SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); - X509_STORE *store = vc_x509store_create(vc_store); - - if (!ctx || !store) { - snprintf(tmpstr, sizeof(tmpstr), "CREATE CTX: %s",ERR_error_string (ERR_get_error (), NULL)); - writecf(FS_ERR, tmpstr); - if (store) - X509_STORE_free(store); - if (ctx) - SSL_CTX_free(ctx); - return NULL; - } - - SSL_CTX_set_cert_store(ctx, store); - - /* Disable some insecure protocols explicitly */ - SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); - if (getstroption(CF_CIPHERSUITE)) - SSL_CTX_set_cipher_list(ctx, getstroption(CF_CIPHERSUITE)); - else - SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA"); - - SSL_CTX_set_verify_depth (ctx, getintoption(CF_VERIFYSSL)); - - if( !(vc_store->flags & VC_X509S_SSL_VERIFY_MASK) ) { - writecf(FS_DBG, tmpstr); - flags = SSL_VERIFY_NONE; - } else { - if(vc_store->flags & VC_X509S_SSL_VERIFY_PEER) - flags |= SSL_VERIFY_PEER; - if(vc_store->flags & VC_X509S_SSL_VERIFY_FAIL_IF_NO_PEER_CERT) - flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - if(vc_store->flags & VC_X509S_SSL_VERIFY_CLIENT_ONCE) - flags |= SSL_VERIFY_CLIENT_ONCE; - } - - SSL_CTX_set_verify(ctx, flags, vc_verify_callback); - - if(vc_store->flags & VC_X509S_USE_CERTIFICATE) { - int r = 0; - if(vc_store->certfile) - SSL_CTX_use_certificate_chain_file(ctx, vc_store->certfile); +static X509_STORE *vc_x509store_create(vc_x509store_t *); - SSL_CTX_set_default_passwd_cb(ctx, vc_store->askpass_callback); +static SSL_CTX *vc_create_sslctx(vc_x509store_t *vc_store) { + int flags = 0; - if(vc_store->keyfile) - r=SSL_CTX_use_PrivateKey_file(ctx, vc_store->keyfile, - SSL_FILETYPE_PEM); + /* Explicitly use TLSv1 (or maybe later) */ + SSL_CTX *ctx = SSL_CTX_new(TLS_client_method()); + X509_STORE *store = vc_x509store_create(vc_store); - if( r!=1 || !SSL_CTX_check_private_key(ctx)) { - snprintf(tmpstr, sizeof(tmpstr), "CREATE CTX: Load private key failed"); - writecf(FS_ERR, tmpstr); - SSL_CTX_free(ctx); - return NULL; - } + if (!ctx || !store) { + snprintf(tmpstr, sizeof(tmpstr), "CREATE CTX: %s", + ERR_error_string(ERR_get_error(), NULL)); + writecf(FS_ERR, tmpstr); + if (store) + X509_STORE_free(store); + if (ctx) + SSL_CTX_free(ctx); + return NULL; + } + + SSL_CTX_set_cert_store(ctx, store); + + /* Disable some insecure protocols explicitly */ + SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + if (getstroption(CF_CIPHERSUITE)) + SSL_CTX_set_cipher_list(ctx, getstroption(CF_CIPHERSUITE)); + else + SSL_CTX_set_cipher_list(ctx, + "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA"); + + SSL_CTX_set_verify_depth(ctx, getintoption(CF_VERIFYSSL)); + + if (!(vc_store->flags & VC_X509S_SSL_VERIFY_MASK)) { + writecf(FS_DBG, tmpstr); + flags = SSL_VERIFY_NONE; + } else { + if (vc_store->flags & VC_X509S_SSL_VERIFY_PEER) + flags |= SSL_VERIFY_PEER; + if (vc_store->flags & VC_X509S_SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + if (vc_store->flags & VC_X509S_SSL_VERIFY_CLIENT_ONCE) + flags |= SSL_VERIFY_CLIENT_ONCE; + } + + SSL_CTX_set_verify(ctx, flags, vc_verify_callback); + + if (vc_store->flags & VC_X509S_USE_CERTIFICATE) { + int r = 0; + if (vc_store->certfile) + SSL_CTX_use_certificate_chain_file(ctx, vc_store->certfile); + + SSL_CTX_set_default_passwd_cb(ctx, vc_store->askpass_callback); + + if (vc_store->keyfile) + r = SSL_CTX_use_PrivateKey_file(ctx, vc_store->keyfile, SSL_FILETYPE_PEM); + + if (r != 1 || !SSL_CTX_check_private_key(ctx)) { + snprintf(tmpstr, sizeof(tmpstr), "CREATE CTX: Load private key failed"); + writecf(FS_ERR, tmpstr); + SSL_CTX_free(ctx); + return NULL; } + } - SSL_CTX_set_app_data(ctx, vc_store); - return(ctx); + SSL_CTX_set_app_data(ctx, vc_store); + return (ctx); } -int vc_tls_connect( int serverfd, vc_x509store_t *vc_store ) -{ - SSL_CTX * ctx = vc_create_sslctx(vc_store); - X509 *peercert = NULL; - BIO *ssl_conn = NULL; - const SSL *sslp = NULL; - const SSL_CIPHER * cipher = NULL; - - server_conn = BIO_new_socket( serverfd, 1 ); - - /* To display and check server fingerprint */ - char fingerprint[EVP_MAX_MD_SIZE*4]; - unsigned char fingerprint_bin[EVP_MAX_MD_SIZE]; - unsigned int fingerprint_len; +int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { + SSL_CTX *ctx = vc_create_sslctx(vc_store); + X509 *peercert = NULL; + BIO *ssl_conn = NULL; + const SSL *sslp = NULL; + const SSL_CIPHER *cipher = NULL; - char * fp = fingerprint; + server_conn = BIO_new_socket(serverfd, 1); - long j; + /* To display and check server fingerprint */ + char fingerprint[EVP_MAX_MD_SIZE * 4]; + unsigned char fingerprint_bin[EVP_MAX_MD_SIZE]; + unsigned int fingerprint_len; - if( !ctx ) - goto all_errors; + char *fp = fingerprint; - ssl_conn = BIO_new_ssl(ctx, 1); - SSL_CTX_free(ctx); + long j; - if( !ssl_conn ) - goto ssl_error; + if (!ctx) + goto all_errors; - BIO_push( ssl_conn, server_conn ); - server_conn = ssl_conn; - fflush(stdout); + ssl_conn = BIO_new_ssl(ctx, 1); + SSL_CTX_free(ctx); - if( BIO_do_handshake( server_conn ) <= 0 ) - goto ssl_error; + if (!ssl_conn) + goto ssl_error; - /* Show information about cipher used */ - /* Get cipher object */ - BIO_get_ssl(ssl_conn, &sslp); - if (!sslp) - goto ssl_error; + BIO_push(ssl_conn, server_conn); + server_conn = ssl_conn; + fflush(stdout); - cipher = SSL_get_current_cipher(sslp); - if (cipher) { - char cipher_desc[TMPSTRSIZE]; - snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); - writecf(FS_SERV, tmpstr); - } else { - snprintf(tmpstr, TMPSTRSIZE, "[SSL ERROR ] Cipher not known / SSL object can't be queried!"); - writecf(FS_ERR, tmpstr); - } + if (BIO_do_handshake(server_conn) <= 0) + goto ssl_error; - /* Accept being connected, _if_ verification passed */ - peercert = SSL_get_peer_certificate(sslp); - if (!peercert) - goto ssl_error; + /* Show information about cipher used */ + /* Get cipher object */ + BIO_get_ssl(ssl_conn, &sslp); + if (!sslp) + goto ssl_error; - /* show basic information about peer cert */ - snprintf(tmpstr, TMPSTRSIZE, "[SSL SUBJECT ] %s", X509_NAME_oneline(X509_get_subject_name(peercert),0,0)); - writecf(FS_SERV, tmpstr); - snprintf(tmpstr, TMPSTRSIZE, "[SSL ISSUER ] %s", X509_NAME_oneline(X509_get_issuer_name(peercert),0,0)); + cipher = SSL_get_current_cipher(sslp); + if (cipher) { + char cipher_desc[TMPSTRSIZE]; + snprintf(tmpstr, TMPSTRSIZE, "[SSL CIPHER ] %s", + SSL_CIPHER_description(cipher, cipher_desc, TMPSTRSIZE)); writecf(FS_SERV, tmpstr); + } else { + snprintf( + tmpstr, TMPSTRSIZE, + "[SSL ERROR ] Cipher not known / SSL object can't be queried!"); + writecf(FS_ERR, tmpstr); + } + + /* Accept being connected, _if_ verification passed */ + peercert = SSL_get_peer_certificate(sslp); + if (!peercert) + goto ssl_error; + + /* show basic information about peer cert */ + snprintf(tmpstr, TMPSTRSIZE, "[SSL SUBJECT ] %s", + X509_NAME_oneline(X509_get_subject_name(peercert), 0, 0)); + writecf(FS_SERV, tmpstr); + snprintf(tmpstr, TMPSTRSIZE, "[SSL ISSUER ] %s", + X509_NAME_oneline(X509_get_issuer_name(peercert), 0, 0)); + writecf(FS_SERV, tmpstr); + + /* calculate fingerprint */ + if (!X509_digest(peercert, EVP_sha1(), fingerprint_bin, &fingerprint_len)) + goto ssl_error; + + assert((fingerprint_len > 1) && (fingerprint_len <= EVP_MAX_MD_SIZE)); + for (j = 0; j < (int)fingerprint_len; j++) + fp += sprintf(fp, "%02X:", fingerprint_bin[j]); + assert(fp > fingerprint); + fp[-1] = 0; + snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] %s (from server)", + fingerprint); + writecf(FS_SERV, tmpstr); + + /* we don't need the peercert anymore */ + X509_free(peercert); + + if (getintoption(CF_PINFINGER) && verify_or_store_fingerprint(fingerprint)) + return 1; - /* calculate fingerprint */ - if (!X509_digest(peercert,EVP_sha1(),fingerprint_bin,&fingerprint_len)) - goto ssl_error; - - assert ( ( fingerprint_len > 1 ) && (fingerprint_len <= EVP_MAX_MD_SIZE )); - for (j=0; j<(int)fingerprint_len; j++) - fp += sprintf(fp, "%02X:", fingerprint_bin[j]); - assert ( fp > fingerprint ); - fp[-1] = 0; - snprintf(tmpstr, TMPSTRSIZE, "[SSL FINGERPRINT ] %s (from server)", fingerprint); - writecf(FS_SERV, tmpstr); - - /* we don't need the peercert anymore */ - X509_free(peercert); - - if (getintoption(CF_PINFINGER) && verify_or_store_fingerprint(fingerprint)) - return 1; - - /* If verify of x509 chain was requested, do the check here */ - if (X509_V_OK == SSL_get_verify_result(sslp)) - return 0; + /* If verify of x509 chain was requested, do the check here */ + if (X509_V_OK == SSL_get_verify_result(sslp)) + return 0; - if (getintoption(CF_IGNSSL)) { - writecf(FS_ERR, "[SSL VERIFY ERROR ] FAILURE IGNORED!!!"); - return 0; - } + if (getintoption(CF_IGNSSL)) { + writecf(FS_ERR, "[SSL VERIFY ERROR ] FAILURE IGNORED!!!"); + return 0; + } ssl_error: - snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR] %s", ERR_error_string (ERR_get_error (), NULL)); - writecf(FS_ERR, tmpstr); + snprintf(tmpstr, TMPSTRSIZE, "[SSL CONNECT ERROR] %s", + ERR_error_string(ERR_get_error(), NULL)); + writecf(FS_ERR, tmpstr); all_errors: - BIO_free_all( server_conn ); - server_conn = NULL; - return 1; + BIO_free_all(server_conn); + server_conn = NULL; + return 1; } -#define VC_STORE_ERR_EXIT(s) do { \ - fprintf(stderr, "[E] SSL_STORE: %s\n", ERR_error_string (ERR_get_error (), NULL)); \ - if(s) X509_STORE_free(s); \ - return(0); \ -} while(0) +#define VC_STORE_ERR_EXIT(s) \ + do { \ + fprintf(stderr, "[E] SSL_STORE: %s\n", \ + ERR_error_string(ERR_get_error(), NULL)); \ + if (s) \ + X509_STORE_free(s); \ + return (0); \ + } while (0) X509_STORE *vc_x509store_create(vc_x509store_t *vc_store) { - X509_STORE *store = NULL; - X509_LOOKUP *lookup = NULL; + X509_STORE *store = NULL; + X509_LOOKUP *lookup = NULL; - store = X509_STORE_new(); + store = X509_STORE_new(); - X509_STORE_set_verify_cb_func(store, vc_verify_callback); + X509_STORE_set_verify_cb_func(store, vc_verify_callback); - if( !(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) ) - VC_STORE_ERR_EXIT(store); + if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) + VC_STORE_ERR_EXIT(store); - if (!vc_store->cafile) { - if( !(vc_store->flags & VC_X509S_USE_CAFILE) ) - X509_LOOKUP_load_file(lookup, 0, X509_FILETYPE_DEFAULT); - } else if( !X509_LOOKUP_load_file(lookup, vc_store->cafile, - X509_FILETYPE_PEM) ) - VC_STORE_ERR_EXIT(store); + if (!vc_store->cafile) { + if (!(vc_store->flags & VC_X509S_USE_CAFILE)) + X509_LOOKUP_load_file(lookup, 0, X509_FILETYPE_DEFAULT); + } else if (!X509_LOOKUP_load_file(lookup, vc_store->cafile, + X509_FILETYPE_PEM)) + VC_STORE_ERR_EXIT(store); - if (vc_store->crlfile) { - if( !X509_load_crl_file(lookup, vc_store->crlfile, - X509_FILETYPE_PEM) ) - VC_STORE_ERR_EXIT(store); + if (vc_store->crlfile) { + if (!X509_load_crl_file(lookup, vc_store->crlfile, X509_FILETYPE_PEM)) + VC_STORE_ERR_EXIT(store); - X509_STORE_set_flags( store, - X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); - } + X509_STORE_set_flags(store, + X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + } - if ( !(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir())) ) - VC_STORE_ERR_EXIT(store); + if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()))) + VC_STORE_ERR_EXIT(store); - if ( !vc_store->capath ) { - if( !(vc_store->flags & VC_X509S_USE_CAPATH) ) - X509_LOOKUP_add_dir(lookup, 0, X509_FILETYPE_DEFAULT); - } else if( !X509_LOOKUP_add_dir(lookup, vc_store->capath, - X509_FILETYPE_PEM) ) - VC_STORE_ERR_EXIT(store); + if (!vc_store->capath) { + if (!(vc_store->flags & VC_X509S_USE_CAPATH)) + X509_LOOKUP_add_dir(lookup, 0, X509_FILETYPE_DEFAULT); + } else if (!X509_LOOKUP_add_dir(lookup, vc_store->capath, X509_FILETYPE_PEM)) + VC_STORE_ERR_EXIT(store); - return(store); + return (store); } int vc_verify_callback(int ok, X509_STORE_CTX *store) { - if(!ok) { - snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR ] %s", - X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); - writecf(FS_ERR, tmpstr); - } - return (ok | getintoption(CF_IGNSSL)); + if (!ok) { + snprintf(tmpstr, TMPSTRSIZE, "[SSL VERIFY ERROR ] %s", + X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + writecf(FS_ERR, tmpstr); + } + return (ok | getintoption(CF_IGNSSL)); } ssize_t vc_tls_sendmessage(const void *buf, size_t size) { - return BIO_write(server_conn, buf, size); + return BIO_write(server_conn, buf, size); } ssize_t vc_tls_receivemessage(void *buf, size_t size) { - ssize_t received = (ssize_t)BIO_read (server_conn, buf, size); - if (received != 0) - return received; - if (BIO_should_retry(server_conn)) - return -2; - return 0; + ssize_t received = (ssize_t)BIO_read(server_conn, buf, size); + if (received != 0) + return received; + if (BIO_should_retry(server_conn)) + return -2; + return 0; } void vc_tls_cleanup() { - BIO_free_all( server_conn ); - server_conn = NULL; + BIO_free_all(server_conn); + server_conn = NULL; } #endif #ifdef TLS_LIB_MBEDTLS +#include "mbedtls/error.h" +#include "mbedtls/version.h" +#include +#include +#include +#include #include +#include #include -#include -#include #include -#include -#include -#include -#include "mbedtls/error.h" -#include "mbedtls/version.h" #include const char *DRBG_PERS = "mbed TLS vchat client"; #define MAX_SUITES 512 typedef struct { - mbedtls_entropy_context _entropy; - mbedtls_ctr_drbg_context _ctr_drbg; - mbedtls_x509_crt _cacert; - mbedtls_x509_crt _cert; - mbedtls_pk_context _key; - mbedtls_ssl_context _ssl; - mbedtls_ssl_config _conf; - int ciphersuits[MAX_SUITES]; + mbedtls_entropy_context _entropy; + mbedtls_ctr_drbg_context _ctr_drbg; + mbedtls_x509_crt _cacert; + mbedtls_x509_crt _cert; + mbedtls_pk_context _key; + mbedtls_ssl_context _ssl; + mbedtls_ssl_config _conf; + int ciphersuits[MAX_SUITES]; } mbedstate; static mbedstate _mbedtls_state; -void vchat_tls_get_version_external() -{ - snprintf(tmpstr, sizeof(tmpstr), "%s", MBEDTLS_VERSION_STRING_FULL); - vchat_tls_version_external = strdup(tmpstr); +void vchat_tls_get_version_external() { + snprintf(tmpstr, sizeof(tmpstr), "%s", MBEDTLS_VERSION_STRING_FULL); + vchat_tls_version_external = strdup(tmpstr); } -static int static_tcp_recv(void *ctx, unsigned char *buf, size_t len ) { - return recv((int)(intptr_t)ctx, buf, len, 0); +static int static_tcp_recv(void *ctx, unsigned char *buf, size_t len) { + return recv((int)(intptr_t)ctx, buf, len, 0); } -static int static_tcp_send(void *ctx, const unsigned char *buf, size_t len ) { - return send((int)(intptr_t)ctx, buf, len, 0); +static int static_tcp_send(void *ctx, const unsigned char *buf, size_t len) { + return send((int)(intptr_t)ctx, buf, len, 0); } static int map_openssl_suite(char *openssl_name); -void vc_init_x509store(vc_x509store_t *store) -{ - static int sslinit; - if (!sslinit++) { - mbedtls_entropy_init(&_mbedtls_state._entropy); - mbedtls_ctr_drbg_init(&_mbedtls_state._ctr_drbg); - - mbedtls_ctr_drbg_seed(&_mbedtls_state._ctr_drbg, mbedtls_entropy_func, &_mbedtls_state._entropy, - (const unsigned char *) DRBG_PERS, sizeof (DRBG_PERS)); - } - memset(store, 0, sizeof(vc_x509store_t)); - - /* We want to make verifying the peer the default */ - store->flags |= VC_X509S_SSL_VERIFY_PEER; +void vc_init_x509store(vc_x509store_t *store) { + static int sslinit; + if (!sslinit++) { + mbedtls_entropy_init(&_mbedtls_state._entropy); + mbedtls_ctr_drbg_init(&_mbedtls_state._ctr_drbg); + + mbedtls_ctr_drbg_seed(&_mbedtls_state._ctr_drbg, mbedtls_entropy_func, + &_mbedtls_state._entropy, + (const unsigned char *)DRBG_PERS, sizeof(DRBG_PERS)); + } + memset(store, 0, sizeof(vc_x509store_t)); + + /* We want to make verifying the peer the default */ + store->flags |= VC_X509S_SSL_VERIFY_PEER; } static void vc_tls_report_error(int error, char *message) { - size_t used = snprintf(tmpstr, sizeof(tmpstr), "Error: %s", message); - mbedtls_strerror(error, tmpstr + used, sizeof(tmpstr) - used); - writecf(FS_ERR, tmpstr); + size_t used = snprintf(tmpstr, sizeof(tmpstr), "Error: %s", message); + mbedtls_strerror(error, tmpstr + used, sizeof(tmpstr) - used); + writecf(FS_ERR, tmpstr); } -int vc_tls_connect( int serverfd, vc_x509store_t *vc_store ) -{ - /* Some aliases for shorter references */ - mbedstate *s = &_mbedtls_state; - mbedtls_ssl_config *conf = &_mbedtls_state._conf; - mbedtls_ssl_context *ssl = &_mbedtls_state._ssl; - int ret, suitecount = 0; - char fingerprint[128], *token; - uint8_t digest[20]; - - mbedtls_x509_crt_init(&s->_cacert); - mbedtls_x509_crt_init(&s->_cert); - mbedtls_pk_init(&s->_key); - mbedtls_ssl_init(ssl); - mbedtls_ssl_config_init(conf); - - writecf(FS_SERV, "[SOCKET CONNECTED ]"); - writecf(FS_SERV, "[UPGRADING TO TLS ]"); - - if ((ret = mbedtls_ssl_config_defaults(conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - vc_tls_report_error(ret, "Can not initialise tls parameters, mbedtls reports: "); - return -1; - } - - /* TODO: Always verify peer */ - mbedtls_ssl_conf_authmode(conf, getintoption(CF_IGNSSL) ? MBEDTLS_SSL_VERIFY_OPTIONAL : MBEDTLS_SSL_VERIFY_REQUIRED); - mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, &s->_ctr_drbg); - - char *ciphers = getstroption(CF_CIPHERSUITE); - if (!ciphers) - ciphers = "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA"; - ciphers = strdup(ciphers); - for (token = strtok(ciphers, ":"); token && suitecount < MAX_SUITES - 1; token = strtok(NULL, ":")) { - int suite = mbedtls_ssl_get_ciphersuite_id(token); - if (!suite) - suite = map_openssl_suite(token); - if (suite) - s->ciphersuits[suitecount++] = suite; +int vc_tls_connect(int serverfd, vc_x509store_t *vc_store) { + /* Some aliases for shorter references */ + mbedstate *s = &_mbedtls_state; + mbedtls_ssl_config *conf = &_mbedtls_state._conf; + mbedtls_ssl_context *ssl = &_mbedtls_state._ssl; + int ret, suitecount = 0; + char fingerprint[128], *token; + uint8_t digest[20]; + + mbedtls_x509_crt_init(&s->_cacert); + mbedtls_x509_crt_init(&s->_cert); + mbedtls_pk_init(&s->_key); + mbedtls_ssl_init(ssl); + mbedtls_ssl_config_init(conf); + + writecf(FS_SERV, "[SOCKET CONNECTED ]"); + writecf(FS_SERV, "[UPGRADING TO TLS ]"); + + if ((ret = mbedtls_ssl_config_defaults(conf, MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + vc_tls_report_error(ret, + "Can not initialise tls parameters, mbedtls reports: "); + return -1; + } + + /* TODO: Always verify peer */ + mbedtls_ssl_conf_authmode(conf, getintoption(CF_IGNSSL) + ? MBEDTLS_SSL_VERIFY_OPTIONAL + : MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, &s->_ctr_drbg); + + char *ciphers = getstroption(CF_CIPHERSUITE); + if (!ciphers) + ciphers = "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA"; + ciphers = strdup(ciphers); + for (token = strtok(ciphers, ":"); token && suitecount < MAX_SUITES - 1; + token = strtok(NULL, ":")) { + int suite = mbedtls_ssl_get_ciphersuite_id(token); + if (!suite) + suite = map_openssl_suite(token); + if (suite) + s->ciphersuits[suitecount++] = suite; + } + s->ciphersuits[suitecount++] = 0; + free(ciphers); + + mbedtls_ssl_conf_ciphersuites(conf, s->ciphersuits); + + if (vc_store->cafile) { + if ((ret = mbedtls_x509_crt_parse_file(&s->_cacert, vc_store->cafile)) != + 0) { + vc_tls_report_error(ret, "Can not load CA cert, mbedtls reports: "); + return -1; } - s->ciphersuits[suitecount++] = 0; - free(ciphers); - - mbedtls_ssl_conf_ciphersuites(conf, s->ciphersuits); - - if (vc_store->cafile) { - if ((ret = mbedtls_x509_crt_parse_file(&s->_cacert, vc_store->cafile)) != 0) { - vc_tls_report_error(ret, "Can not load CA cert, mbedtls reports: "); - return -1; - } - mbedtls_ssl_conf_ca_chain(conf, &s->_cacert, NULL); - writecf(FS_SERV, "[CA CERT LOADED ]"); + mbedtls_ssl_conf_ca_chain(conf, &s->_cacert, NULL); + writecf(FS_SERV, "[CA CERT LOADED ]"); + } + + if (vc_store->flags & VC_X509S_USE_CERTIFICATE) { + char *password = NULL; + char password_buf[1024]; + + if ((ret = mbedtls_x509_crt_parse_file(&s->_cert, vc_store->certfile)) != + 0) { + vc_tls_report_error(ret, "Can not load client cert, mbedtls reports: "); + return -1; } + writecf(FS_SERV, "[CLIENT CERT LOADED ]"); - if (vc_store->flags & VC_X509S_USE_CERTIFICATE) { - char *password = NULL; - char password_buf[1024]; - - if ((ret = mbedtls_x509_crt_parse_file(&s->_cert, vc_store->certfile)) != 0) { - vc_tls_report_error(ret, "Can not load client cert, mbedtls reports: "); - return -1; - } - writecf(FS_SERV, "[CLIENT CERT LOADED ]"); - - while (1) { - if ((ret = mbedtls_pk_parse_keyfile(&s->_key, vc_store->keyfile, password + while (1) { + if ((ret = mbedtls_pk_parse_keyfile(&s->_key, vc_store->keyfile, password #if MBEDTLS_VERSION_MAJOR >= 3 - , mbedtls_ctr_drbg_random, &s->_ctr_drbg + , + mbedtls_ctr_drbg_random, &s->_ctr_drbg #endif - )) == 0) - break; - if (ret != MBEDTLS_ERR_PK_PASSWORD_REQUIRED && ret != MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { - vc_tls_report_error(ret, "Can not load client key, mbedtls reports: "); - return -1; - } - if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) - vc_tls_report_error(ret, "Wrong passphrase, mbedtls reports: "); - vc_store->askpass_callback(password_buf, sizeof(password_buf), 0, NULL); - password = password_buf; - } - memset_s(password_buf, sizeof(password_buf), 0, sizeof(password_buf)); - writecf(FS_SERV, "[CLIENT KEY LOADED ]"); - + )) == 0) + break; + if (ret != MBEDTLS_ERR_PK_PASSWORD_REQUIRED && + ret != MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { + vc_tls_report_error(ret, "Can not load client key, mbedtls reports: "); + return -1; + } + if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) + vc_tls_report_error(ret, "Wrong passphrase, mbedtls reports: "); + vc_store->askpass_callback(password_buf, sizeof(password_buf), 0, NULL); + password = password_buf; + } + memset_s(password_buf, sizeof(password_buf), 0, sizeof(password_buf)); + writecf(FS_SERV, "[CLIENT KEY LOADED ]"); #if MBEDTLS_VERSION_MAJOR == 3 && MBEDTLS_VERSION_MINOR == 0 - mbedtls_pk_context *pubkey = &(s->_cert.MBEDTLS_PRIVATE(pk)); + mbedtls_pk_context *pubkey = &(s->_cert.MBEDTLS_PRIVATE(pk)); #else - mbedtls_pk_context *pubkey = &(s->_cert.pk); + mbedtls_pk_context *pubkey = &(s->_cert.pk); #endif - if ((ret = mbedtls_pk_check_pair(pubkey, &s->_key + if ((ret = mbedtls_pk_check_pair(pubkey, &s->_key #if MBEDTLS_VERSION_MAJOR >= 3 - , mbedtls_ctr_drbg_random, &s->_ctr_drbg + , + mbedtls_ctr_drbg_random, &s->_ctr_drbg #endif - )) != 0) { - vc_tls_report_error(ret, "Cert and key mismatch, mbedtls reports: "); - return 1; - } - - if ((ret = mbedtls_ssl_conf_own_cert(conf, &s->_cert, &s->_key)) != 0) { - vc_tls_report_error(ret, "Setting key and cert to tls session fails, mbedtls reports: "); - return -1; - } + )) != 0) { + vc_tls_report_error(ret, "Cert and key mismatch, mbedtls reports: "); + return 1; } - /* Config constructed, pass to ssl */ - /* Init ssl and config structs and configure ssl ctx */ - if ((ret = mbedtls_ssl_setup(ssl, conf)) != 0) { - vc_tls_report_error(ret, "Can not configure parameters on tls context, mbedtls reports: "); - return -1; + if ((ret = mbedtls_ssl_conf_own_cert(conf, &s->_cert, &s->_key)) != 0) { + vc_tls_report_error( + ret, "Setting key and cert to tls session fails, mbedtls reports: "); + return -1; + } + } + + /* Config constructed, pass to ssl */ + /* Init ssl and config structs and configure ssl ctx */ + if ((ret = mbedtls_ssl_setup(ssl, conf)) != 0) { + vc_tls_report_error( + ret, "Can not configure parameters on tls context, mbedtls reports: "); + return -1; + } + /* TODO: mbedtls_ssl_set_hostname(&ssl, SERVER_NAME) */ + + mbedtls_ssl_set_bio(ssl, (void *)(intptr_t)serverfd, static_tcp_send, + static_tcp_recv, NULL); + + while ((ret = mbedtls_ssl_handshake(ssl)) != 0) + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + vc_tls_report_error(ret, "TLS handshake failed, mbedtls reports: "); + return -1; } - /* TODO: mbedtls_ssl_set_hostname(&ssl, SERVER_NAME) */ - - mbedtls_ssl_set_bio(ssl, (void*)(intptr_t)serverfd, static_tcp_send, static_tcp_recv, NULL ); - while ((ret = mbedtls_ssl_handshake(ssl)) != 0) - if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { - vc_tls_report_error(ret, "TLS handshake failed, mbedtls reports: "); - return -1; - } + writecf(FS_SERV, "[TLS HANDSHAKE DONE ]"); + snprintf(tmpstr, TMPSTRSIZE, "[TLS CIPHER SUITE ] %s", + mbedtls_ssl_get_ciphersuite(ssl)); + writecf(FS_SERV, tmpstr); - writecf(FS_SERV,"[TLS HANDSHAKE DONE ]"); - snprintf(tmpstr, TMPSTRSIZE, "[TLS CIPHER SUITE ] %s", mbedtls_ssl_get_ciphersuite(ssl)); - writecf(FS_SERV, tmpstr); + const mbedtls_x509_crt *peer_cert = mbedtls_ssl_get_peer_cert(ssl); + mbedtls_x509_crt_info(tmpstr, sizeof(tmpstr), "[TLS PEER INFO ] ", + peer_cert); - const mbedtls_x509_crt* peer_cert = mbedtls_ssl_get_peer_cert(ssl); - mbedtls_x509_crt_info(tmpstr, sizeof(tmpstr), "[TLS PEER INFO ] ", peer_cert); - - for (token = strtok(tmpstr, "\n"); token; token = strtok(NULL, "\n")) - writecf(FS_SERV, token); + for (token = strtok(tmpstr, "\n"); token; token = strtok(NULL, "\n")) + writecf(FS_SERV, token); #if MBEDTLS_VERSION_MAJOR == 3 && MBEDTLS_VERSION_MINOR == 0 - const uint8_t * const rawcert_buf = peer_cert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p); - size_t rawcert_len = peer_cert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len); + const uint8_t *const rawcert_buf = + peer_cert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p); + size_t rawcert_len = peer_cert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len); #else - const uint8_t * const rawcert_buf = peer_cert->raw.p; - size_t rawcert_len = peer_cert->raw.len; + const uint8_t *const rawcert_buf = peer_cert->raw.p; + size_t rawcert_len = peer_cert->raw.len; #endif - const mbedtls_md_info_t *mdinfo = mbedtls_md_info_from_string("SHA1"); - if (mdinfo) { - mbedtls_md(mdinfo, rawcert_buf, rawcert_len, digest); - - char *fp = fingerprint; - for (int j=0; j fingerprint ); - fp[-1] = 0; - snprintf(tmpstr, TMPSTRSIZE, "[TLS FINGERPRINT ] %s (from server)", fingerprint); - writecf(FS_SERV, tmpstr); - - if (getintoption(CF_PINFINGER) && verify_or_store_fingerprint(fingerprint)) - return 1; - } else { - writecf(FS_ERR, "Warning: Unable to load SHA-1 md"); - if (getintoption(CF_PINFINGER)) { - writecf(FS_ERR, "ERROR: Can not compute fingerprint, but pinning check is required"); - return 1; - } - } + const mbedtls_md_info_t *mdinfo = mbedtls_md_info_from_string("SHA1"); + if (mdinfo) { + mbedtls_md(mdinfo, rawcert_buf, rawcert_len, digest); + + char *fp = fingerprint; + for (int j = 0; j < mbedtls_md_get_size(mdinfo); j++) + fp += sprintf(fp, "%02X:", digest[j]); + assert(fp > fingerprint); + fp[-1] = 0; + snprintf(tmpstr, TMPSTRSIZE, "[TLS FINGERPRINT ] %s (from server)", + fingerprint); + writecf(FS_SERV, tmpstr); - ret = mbedtls_ssl_get_verify_result(ssl); - switch (ret) { - case 0: - writecf(FS_SERV, "[TLS HANDSHAKE OK ]"); - break; - case -1: - writecf(FS_ERR, "Error: TLS verify for an unknown reason"); - return -1; - case MBEDTLS_X509_BADCERT_SKIP_VERIFY: - case MBEDTLS_X509_BADCERT_NOT_TRUSTED: - if (getintoption(CF_IGNSSL) || !getintoption(CF_VERIFYSSL)) - return 0; - vc_tls_report_error(ret, "TLS verify failed, mbedtls reports: "); - return -1; - default: - vc_tls_report_error(ret, "TLS verify failed, mbedtls reports: "); - return -1; + if (getintoption(CF_PINFINGER) && verify_or_store_fingerprint(fingerprint)) + return 1; + } else { + writecf(FS_ERR, "Warning: Unable to load SHA-1 md"); + if (getintoption(CF_PINFINGER)) { + writecf( + FS_ERR, + "ERROR: Can not compute fingerprint, but pinning check is required"); + return 1; } - - return 0; + } + + ret = mbedtls_ssl_get_verify_result(ssl); + switch (ret) { + case 0: + writecf(FS_SERV, "[TLS HANDSHAKE OK ]"); + break; + case -1: + writecf(FS_ERR, "Error: TLS verify for an unknown reason"); + return -1; + case MBEDTLS_X509_BADCERT_SKIP_VERIFY: + case MBEDTLS_X509_BADCERT_NOT_TRUSTED: + if (getintoption(CF_IGNSSL) || !getintoption(CF_VERIFYSSL)) + return 0; + vc_tls_report_error(ret, "TLS verify failed, mbedtls reports: "); + return -1; + default: + vc_tls_report_error(ret, "TLS verify failed, mbedtls reports: "); + return -1; + } + + return 0; } ssize_t vc_tls_sendmessage(const void *buf, size_t size) { - return mbedtls_ssl_write( &_mbedtls_state._ssl, buf, size); + return mbedtls_ssl_write(&_mbedtls_state._ssl, buf, size); } ssize_t vc_tls_receivemessage(void *buf, size_t size) { - ssize_t received = (ssize_t)mbedtls_ssl_read (&_mbedtls_state._ssl, buf, size); - switch (received) { - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - return -2; - case MBEDTLS_ERR_SSL_CONN_EOF: - case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: - case 0: - return 0; - default: - if (received > 0) - return received; - return -1; - } + ssize_t received = (ssize_t)mbedtls_ssl_read(&_mbedtls_state._ssl, buf, size); + switch (received) { + case MBEDTLS_ERR_SSL_WANT_READ: + case MBEDTLS_ERR_SSL_WANT_WRITE: + return -2; + case MBEDTLS_ERR_SSL_CONN_EOF: + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + case 0: + return 0; + default: + if (received > 0) + return received; + return -1; + } } void vc_tls_cleanup() { - mbedtls_x509_crt_free(&_mbedtls_state._cacert); - mbedtls_x509_crt_free(&_mbedtls_state._cert); - mbedtls_pk_free(&_mbedtls_state._key); - mbedtls_ssl_free(&_mbedtls_state._ssl ); - mbedtls_ssl_config_free(&_mbedtls_state._conf ); - mbedtls_ctr_drbg_free(&_mbedtls_state._ctr_drbg ); + mbedtls_x509_crt_free(&_mbedtls_state._cacert); + mbedtls_x509_crt_free(&_mbedtls_state._cert); + mbedtls_pk_free(&_mbedtls_state._key); + mbedtls_ssl_free(&_mbedtls_state._ssl); + mbedtls_ssl_config_free(&_mbedtls_state._conf); + mbedtls_ctr_drbg_free(&_mbedtls_state._ctr_drbg); } /* Taken from https://testssl.sh/openssl-iana.mapping.html */ @@ -924,12 +964,12 @@ NULL }; // fprintf(stderr, "SUCCESS: %s => %s => %d\n\n", xlate_openssl[i], xlate_openssl[i+1], mbedtls_ssl_get_ciphersuite_id(xlate_openssl[i+1])); static int map_openssl_suite(char *openssl_name) { - int i; - for (i=0; xlate_openssl[i]; i+=2) { - if (!strcmp(xlate_openssl[i], openssl_name)) - return mbedtls_ssl_get_ciphersuite_id(xlate_openssl[i+1]); - } - return 0; + int i; + for (i = 0; xlate_openssl[i]; i += 2) { + if (!strcmp(xlate_openssl[i], openssl_name)) + return mbedtls_ssl_get_ciphersuite_id(xlate_openssl[i + 1]); + } + return 0; } #endif diff --git a/vchat-tls.h b/vchat-tls.h index 440d08e..17d2687 100755 --- a/vchat-tls.h +++ b/vchat-tls.h @@ -4,13 +4,13 @@ typedef int (*vc_askpass_cb_t)(char *, int, int, void *); struct vc_x509store_t { - char *cafile; - char *capath; - char *crlfile; - vc_askpass_cb_t askpass_callback; - char *certfile; - char *keyfile; - int flags; + char *cafile; + char *capath; + char *crlfile; + vc_askpass_cb_t askpass_callback; + char *certfile; + char *keyfile; + int flags; }; typedef struct vc_x509store_t vc_x509store_t; @@ -25,7 +25,7 @@ void vc_x509store_setcapath(vc_x509store_t *, char *); void vc_x509store_setcrlfile(vc_x509store_t *, char *); void vc_cleanup_x509store(vc_x509store_t *s); -int vc_tls_connect(int serverfd, vc_x509store_t * ); +int vc_tls_connect(int serverfd, vc_x509store_t *); ssize_t vc_tls_sendmessage(const void *buf, size_t size); ssize_t vc_tls_receivemessage(void *buf, size_t size); void vc_tls_cleanup(); diff --git a/vchat-ui.c b/vchat-ui.c index 62ef372..bb33287 100755 --- a/vchat-ui.c +++ b/vchat-ui.c @@ -10,116 +10,123 @@ * without even the implied warranty of merchantability or fitness for a * particular purpose. In no event shall the copyright holder be liable for * any direct, indirect, incidental or special damages arising in any way out - * of the use of this software. + * of the use of this software. * */ /* general includes */ -#include -#include +#include #include +#include +#include +#include #include +#include #include +#include #include -#include -#include #include +#include #include -#include -#include -#include -#include +#include #include -#include "vchat.h" #include "vchat-user.h" +#include "vchat.h" /* version of this module */ -const char *vchat_ui_version = "vchat-ui.c $Id$"; +const char *vchat_ui_version = + "vchat-ui.c $Id$"; /* externally used variables */ /* current string in topic window */ char topicstr[TOPICSTRSIZE] = "[] VChat 0.20"; /* current string in console window */ -char consolestr[CONSOLESTRSIZE] = "[ Get help: .h for server /h for client commands"; +char consolestr[CONSOLESTRSIZE] = + "[ Get help: .h for server /h for client commands"; -static unsigned int ui_init = 0; +static unsigned int ui_init = 0; /* our windows */ -static WINDOW *console = NULL; -static WINDOW *input = NULL; -static WINDOW *topic = NULL; -static WINDOW *channel = NULL; -static WINDOW *private = NULL; -static WINDOW *output = NULL; +static WINDOW *console = NULL; +static WINDOW *input = NULL; +static WINDOW *topic = NULL; +static WINDOW *channel = NULL; +static WINDOW *private = NULL; +static WINDOW *output = NULL; /* our screen dimensions */ -static int screensx = 0; -static int screensy = 0; +static int screensx = 0; +static int screensy = 0; /* current horizontal scrolling offset for input line */ -static int scroff = 0; +static int scroff = 0; /* cache for stepping value of horizontal scrolling */ -unsigned int hscroll = 0; +unsigned int hscroll = 0; -static int outputshown = 0; -static int outputwidth_desired = 0; +static int outputshown = 0; +static int outputwidth_desired = 0; -static int privheight = 0; -static int privheight_desired = 0; -static int privwinhidden = 0; -int usetime = 1; -int outputcountdown = 0; -char *querypartner = NULL; +static int privheight = 0; +static int privheight_desired = 0; +static int privwinhidden = 0; +int usetime = 1; +int outputcountdown = 0; +char *querypartner = NULL; struct sb_entry { - int id; - time_t when; - int stamp; - char *what; - struct sb_entry *link; + int id; + time_t when; + int stamp; + char *what; + struct sb_entry *link; }; struct sb_data { - struct sb_entry *entries; - struct sb_entry *last; - int count; - int scroll; + struct sb_entry *entries; + struct sb_entry *last; + int count; + int scroll; }; -static struct sb_data *sb_pub = NULL; -static struct sb_data *sb_priv = NULL; -static struct sb_data *sb_out = NULL; +static struct sb_data *sb_pub = NULL; +static struct sb_data *sb_priv = NULL; +static struct sb_data *sb_out = NULL; /* Tells, which window is active */ -static int sb_win = 0; /* 0 for pub, 1 for priv */ +static int sb_win = 0; /* 0 for pub, 1 for priv */ /* struct to keep filter list */ struct filt { - char colour; - unsigned int id; - char *text; - regex_t regex; - struct filt *next; + char colour; + unsigned int id; + char *text; + regex_t regex; + struct filt *next; }; -typedef struct filt filt; +typedef struct filt filt; -static filt *filterlist = NULL; -static int filtertype = 0; -static int currentstamp = 0; +static filt *filterlist = NULL; +static int filtertype = 0; +static int currentstamp = 0; /* Prototype declarations */ -static void resize (int); -static void forceredraw (void); -static void forceredraw_wrapper (int a) {(void)a; forceredraw();} -static void drawwin (WINDOW *win, struct sb_data *sb); -static int writescr (WINDOW *win, struct sb_entry *entry); -static int testfilter ( struct sb_entry *entry); -static int gettextwidth (const char *textbuffer); -static void resize_output (void); -static int getsbeheight (struct sb_entry *entry, const int xwidth, int needstime ); -static int getsbdataheight (struct sb_data *data, const int xwidth, int needstime ); +static void resize(int); +static void forceredraw(void); +static void forceredraw_wrapper(int a) { + (void)a; + forceredraw(); +} +static void drawwin(WINDOW *win, struct sb_data *sb); +static int writescr(WINDOW *win, struct sb_entry *entry); +static int testfilter(struct sb_entry *entry); +static int gettextwidth(const char *textbuffer); +static void resize_output(void); +static int getsbeheight(struct sb_entry *entry, const int xwidth, + int needstime); +static int getsbdataheight(struct sb_data *data, const int xwidth, + int needstime); /* CURRENTLY UNUSED static void writecolorized (WINDOW *win, char *string); */ @@ -132,22 +139,29 @@ enum { }; /* */ -static void -togglequery() { - if( querypartner && private ) { - { struct sb_data *tmp = sb_pub; sb_pub = sb_priv; sb_priv = tmp; } - { WINDOW *tmp= private; private = channel; channel = tmp; } +static void togglequery() { + if (querypartner && private) { + { + struct sb_data *tmp = sb_pub; + sb_pub = sb_priv; + sb_priv = tmp; + } + { + WINDOW *tmp = private; + private + = channel; + channel = tmp; + } } } -const char * skip_to_character( const char * string, size_t offset ) { +const char *skip_to_character(const char *string, size_t offset) { size_t ch_size; mbstate_t mbs; memset(&mbs, 0, sizeof(mbs)); - while( offset-- > 0 ) { - switch( ch_size = mbrlen( string, MB_CUR_MAX, &mbs ) ) - { + while (offset-- > 0) { + switch (ch_size = mbrlen(string, MB_CUR_MAX, &mbs)) { case (size_t)-1: case (size_t)-2: return NULL; @@ -161,15 +175,14 @@ const char * skip_to_character( const char * string, size_t offset ) { return string; } -size_t offset_to_character( const char * string, size_t offset ) { +size_t offset_to_character(const char *string, size_t offset) { mbstate_t mbs; memset(&mbs, 0, sizeof(mbs)); - const char * string_offset = string + offset; + const char *string_offset = string + offset; size_t ch_size, nchars = 0; - while( string < string_offset ) { - switch( ch_size = mbrlen( string, MB_CUR_MAX, &mbs ) ) - { + while (string < string_offset) { + switch (ch_size = mbrlen(string, MB_CUR_MAX, &mbs)) { case (size_t)-1: case (size_t)-2: return -1; @@ -184,117 +197,117 @@ size_t offset_to_character( const char * string, size_t offset ) { } /* readlines callback when a line is completed */ -static void -linecomplete (char *line) -{ +static void linecomplete(char *line) { char *c; int i; /* send linefeed, return pointer, reset cursors */ - waddch (input, '\n'); - wmove (input, 0, 0); + waddch(input, '\n'); + wmove(input, 0, 0); scroff = 0; if (line) { i = strlen(line) - 1; - while (line[i] == ' ') line[i--]='\0'; + while (line[i] == ' ') + line[i--] = '\0'; - if (line[0] && strchr(line,' ') == NULL && line[i] == ':') + if (line[0] && strchr(line, ' ') == NULL && line[i] == ':') line[i--] = '\0'; /* empty line? nada. */ if (line[0]) { /* add line to history and have it handled in vchat-protocol.c */ - add_history (line); - handleline (line); + add_history(line); + handleline(line); } - free (line); + free(line); rl_reset_line_state(); rl_point = rl_end = rl_done = 0; /* If in query mode, feed query prefix */ - if (( c = querypartner )) - while( *c ) rl_stuff_char( *c++ ); + if ((c = querypartner)) + while (*c) + rl_stuff_char(*c++); /* wipe input line and reset cursor */ - wrefresh (input); + wrefresh(input); } } /* redraw-callback for readline */ -static void -vciredraw (void) -{ +static void vciredraw(void) { int i; size_t readline_point; /* readline offers us information we don't need so ignore outabound cursor positions */ - if( rl_point < 0 ) rl_point = 0; - //if( rl_point > rl_end ) rl_point = rl_end; + if (rl_point < 0) + rl_point = 0; + // if( rl_point > rl_end ) rl_point = rl_end; - readline_point = offset_to_character( rl_line_buffer, rl_point ); + readline_point = offset_to_character(rl_line_buffer, rl_point); /* hscroll value cache set up? */ if (!hscroll) { /* check config-option or set hardcoded default */ - hscroll = getintoption (CF_HSCROLL); + hscroll = getintoption(CF_HSCROLL); if (!hscroll) hscroll = 15; } /* calculate horizontal scrolling offset */ - /* Case 1: readline is left of current scroll offset: Adjust to left to reveal more text */ - if( readline_point < scroff ) + /* Case 1: readline is left of current scroll offset: Adjust to left to reveal + * more text */ + if (readline_point < scroff) scroff = readline_point - hscroll; - if( scroff < 1 ) + if (scroff < 1) scroff = 0; - /* Case 2: readline just hit the last char on the line: Adjust to right to leave more space on screen */ - if( readline_point >= scroff + getmaxx(input) - 1 ) + /* Case 2: readline just hit the last char on the line: Adjust to right to + * leave more space on screen */ + if (readline_point >= scroff + getmaxx(input) - 1) scroff = readline_point - getmaxx(input) + hscroll; /* wipe input line */ - wmove (input, 0, 0); + wmove(input, 0, 0); for (i = 0; i < getmaxx(input) - 1; i++) - waddch (input, ' '); + waddch(input, ' '); /* show current line, move cursor, redraw! */ - const char *start_line = skip_to_character( rl_line_buffer, scroff ); - const char *end_line = skip_to_character( start_line, getmaxx(input) - 1 ); - - mvwaddnstr (input, 0, 0, start_line, end_line - start_line ); - wmove (input, 0, readline_point - scroff ); - wrefresh (input); + const char *start_line = skip_to_character(rl_line_buffer, scroff); + const char *end_line = skip_to_character(start_line, getmaxx(input) - 1); + mvwaddnstr(input, 0, 0, start_line, end_line - start_line); + wmove(input, 0, readline_point - scroff); + wrefresh(input); } /* called by the eventloop in vchat-client.c */ -void -userinput (void) -{ +void userinput(void) { /* let readline handle what the user typed .. */ - rl_callback_read_char (); + rl_callback_read_char(); } -static int -calcdrawcus (char * const str) { +static int calcdrawcus(char *const str) { char *tmp = str; int zero = 0; - while( *tmp && (*tmp!=' ') && (*tmp!='\n')) { if(*tmp==1) zero+=2; tmp++; } + while (*tmp && (*tmp != ' ') && (*tmp != '\n')) { + if (*tmp == 1) + zero += 2; + tmp++; + } return (tmp - str) - zero; } -static void -sb_flush ( struct sb_data *sb ) { +static void sb_flush(struct sb_data *sb) { struct sb_entry *now = sb->entries, *prev = NULL, *tmp; - while( now ) { - tmp = (struct sb_entry*)((unsigned long)prev ^ (unsigned long)now->link); - free(now->what ); - free(now); - prev = now; - now = tmp; + while (now) { + tmp = (struct sb_entry *)((unsigned long)prev ^ (unsigned long)now->link); + free(now->what); + free(now); + prev = now; + now = tmp; } sb->entries = NULL; } @@ -306,69 +319,69 @@ sb_clear ( struct sb_data **sb ) { *sb = NULL; }*/ -static struct sb_entry* -sb_add (struct sb_data *sb, const char *line, time_t when) { - struct sb_entry *newone = malloc (sizeof(struct sb_entry)); - if( newone ) { - if( sb->count == sb->scroll ) sb->scroll++; - newone->id = sb->count++; - newone->when = when; - newone->what = strdup(line); - newone->link = sb->entries; - newone->stamp= 0xffff; - if( sb->entries ) - sb->entries->link = (struct sb_entry*)((unsigned long)sb->entries->link ^ (unsigned long)newone); - else - sb->last = newone; - sb->entries = newone; +static struct sb_entry *sb_add(struct sb_data *sb, const char *line, + time_t when) { + struct sb_entry *newone = malloc(sizeof(struct sb_entry)); + if (newone) { + if (sb->count == sb->scroll) + sb->scroll++; + newone->id = sb->count++; + newone->when = when; + newone->what = strdup(line); + newone->link = sb->entries; + newone->stamp = 0xffff; + if (sb->entries) + sb->entries->link = (struct sb_entry *)((unsigned long)sb->entries->link ^ + (unsigned long)newone); + else + sb->last = newone; + sb->entries = newone; } return newone; } -void flushout ( ) -{ +void flushout() { sb_flush(sb_out); writeout(" "); outputwidth_desired = 0; outputshown = 0; } -void hideout( ) -{ - if( outputshown ) { - outputshown = 0; - resize(0); +void hideout() { + if (outputshown) { + outputshown = 0; + resize(0); } } -void showout (void) -{ +void showout(void) { writeout(" "); outputcountdown = 6; outputshown = 1; resize(0); } -void writeout (const char *str) -{ +void writeout(const char *str) { int i; - sb_add(sb_out,str,time(NULL)); - i = 1 + gettextwidth( str ); - if( i > outputwidth_desired ) outputwidth_desired = i; + sb_add(sb_out, str, time(NULL)); + i = 1 + gettextwidth(str); + if (i > outputwidth_desired) + outputwidth_desired = i; } -int writechan (char *str) { +int writechan(char *str) { struct sb_entry *tmp; int i = 0; time_t now = time(NULL); - tmp = sb_add(sb_pub,str,now); + tmp = sb_add(sb_pub, str, now); - if ( (sb_pub->scroll == sb_pub->count) && ((filtertype == 0) || ( testfilter(tmp)))) { - i = writescr(channel, tmp); - wnoutrefresh(channel); + if ((sb_pub->scroll == sb_pub->count) && + ((filtertype == 0) || (testfilter(tmp)))) { + i = writescr(channel, tmp); + wnoutrefresh(channel); } - if( querypartner && private ) + if (querypartner && private) topicline(NULL); else consoleline(NULL); @@ -376,20 +389,20 @@ int writechan (char *str) { return i; } -int writecf (formtstr id, char *str) { +int writecf(formtstr id, char *str) { struct sb_entry *tmp; int i = 0; time_t now = time(NULL); - snprintf(tmpstr,TMPSTRSIZE,getformatstr(id),str); - tmp = sb_add(sb_pub,tmpstr,now); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(id), str); + tmp = sb_add(sb_pub, tmpstr, now); - if ( (sb_pub->scroll == sb_pub->count) && - ((filtertype == 0) || ( testfilter(tmp)))) { - i = writescr(channel, tmp); - wnoutrefresh(channel); + if ((sb_pub->scroll == sb_pub->count) && + ((filtertype == 0) || (testfilter(tmp)))) { + i = writescr(channel, tmp); + wnoutrefresh(channel); } - if( querypartner && private ) + if (querypartner && private) topicline(NULL); else consoleline(NULL); @@ -397,34 +410,34 @@ int writecf (formtstr id, char *str) { return i; } -int writepriv (char *str, int maybeep) { +int writepriv(char *str, int maybeep) { int i = 0; if (private) { - time_t now = time (NULL); - struct sb_entry *tmp; - tmp = sb_add(sb_priv,str,now); + time_t now = time(NULL); + struct sb_entry *tmp; + tmp = sb_add(sb_priv, str, now); - if ( !privwinhidden && (sb_priv->scroll == sb_priv->count) && - ((filtertype == 0) || ( testfilter(tmp)))) { - i = writescr(private, tmp); - } - if( privwinhidden && !querypartner ) { - if( (maybeep != 0) && (getintoption( CF_BELLPRIV ) != 0 )) - putchar( 7 ); - privheight_desired = privwinhidden; - privwinhidden = 0; - resize(0); - } - wnoutrefresh(private); + if (!privwinhidden && (sb_priv->scroll == sb_priv->count) && + ((filtertype == 0) || (testfilter(tmp)))) { + i = writescr(private, tmp); + } + if (privwinhidden && !querypartner) { + if ((maybeep != 0) && (getintoption(CF_BELLPRIV) != 0)) + putchar(7); + privheight_desired = privwinhidden; + privwinhidden = 0; + resize(0); + } + wnoutrefresh(private); - if( querypartner && private ) - consoleline(NULL); - else - topicline(NULL); + if (querypartner && private) + consoleline(NULL); + else + topicline(NULL); } else - i = writechan( str ); + i = writechan(str); return i; } @@ -434,339 +447,364 @@ int writepriv (char *str, int maybeep) { #if NCURSES_VERSION_MAJOR >= 5 typedef struct { - attr_t attr; - short pair; + attr_t attr; + short pair; } ncurs_attr; -#define WATTR_GET( win, orgattr ) wattr_get( win, &orgattr.attr, &orgattr.pair, NULL) -#define WATTR_SET( win, orgattr ) wattr_set( win, orgattr.attr, orgattr.pair, NULL) -#define BCOLR_SET( attr, colour ) attr->pair = colour; +#define WATTR_GET(win, orgattr) \ + wattr_get(win, &orgattr.attr, &orgattr.pair, NULL) +#define WATTR_SET(win, orgattr) wattr_set(win, orgattr.attr, orgattr.pair, NULL) +#define BCOLR_SET(attr, colour) attr->pair = colour; #else typedef struct { - attr_t attr; + attr_t attr; } ncurs_attr; -#define WATTR_GET( win, orgattr ) orgattr.attr = wattr_get(win); -#define WATTR_SET( win, orgattr ) wattr_set( win, orgattr.attr); -#define BCOLR_SET( attr, colour ) attr->attr = ((attr->attr) & ~A_COLOR) | COLOR_PAIR((colour)); +#define WATTR_GET(win, orgattr) orgattr.attr = wattr_get(win); +#define WATTR_SET(win, orgattr) wattr_set(win, orgattr.attr); +#define BCOLR_SET(attr, colour) \ + attr->attr = ((attr->attr) & ~A_COLOR) | COLOR_PAIR((colour)); #endif /* 'A' - 'Z' attriute type */ -static int attributes[] = { A_ALTCHARSET, A_BOLD, 0, A_DIM, 0, 0, 0, 0, A_INVIS, 0, 0, A_BLINK, - 0, A_NORMAL, 0, A_PROTECT, 0, A_REVERSE, A_STANDOUT, 0, A_UNDERLINE, - 0, 0, 1, 0, 0 }; - -static void -docolorize (char colour, ncurs_attr *attr, ncurs_attr orgattr) { - if( colour== '0') { - *attr = orgattr; - } else if( ( colour > '0') && ( colour <= '9')) { - BCOLR_SET( attr, colour - '0' ); +static int attributes[] = {A_ALTCHARSET, + A_BOLD, + 0, + A_DIM, + 0, + 0, + 0, + 0, + A_INVIS, + 0, + 0, + A_BLINK, + 0, + A_NORMAL, + 0, + A_PROTECT, + 0, + A_REVERSE, + A_STANDOUT, + 0, + A_UNDERLINE, + 0, + 0, + 1, + 0, + 0}; + +static void docolorize(char colour, ncurs_attr *attr, ncurs_attr orgattr) { + if (colour == '0') { + *attr = orgattr; + } else if ((colour > '0') && (colour <= '9')) { + BCOLR_SET(attr, colour - '0'); } else { - char upc = colour & ( 0x20 ^ 0xff ); /* colour AND NOT 0x20 */ - attr_t newattr; - if( ( upc >= 'A') && ( upc<='Z' ) && ( newattr = attributes[upc - 'A']) ) - attr->attr = ( colour & 0x20 ) ? attr->attr | newattr : attr->attr & ~newattr; + char upc = colour & (0x20 ^ 0xff); /* colour AND NOT 0x20 */ + attr_t newattr; + if ((upc >= 'A') && (upc <= 'Z') && (newattr = attributes[upc - 'A'])) + attr->attr = + (colour & 0x20) ? attr->attr | newattr : attr->attr & ~newattr; } -} +} /* draw arbitrary strings */ -static int -writescr ( WINDOW *win, struct sb_entry *entry ) { - char tmp [64]; +static int writescr(WINDOW *win, struct sb_entry *entry) { + char tmp[64]; int charcount = 0; int i; - int textlen = strlen( entry->what ); - int timelen = ((win == channel)||(win == private)) && usetime ? - (int)strftime(tmp,64,getformatstr(FS_TIME),localtime(&entry->when)) : 0; - char textbuffer[ textlen+timelen+1 ]; - ncurs_attr attrbuffer[ textlen+timelen+1 ]; - ncurs_attr orgattr; + int textlen = strlen(entry->what); + int timelen = ((win == channel) || (win == private)) && usetime + ? (int)strftime(tmp, 64, getformatstr(FS_TIME), + localtime(&entry->when)) + : 0; + char textbuffer[textlen + timelen + 1]; + ncurs_attr attrbuffer[textlen + timelen + 1]; + ncurs_attr orgattr; /* illegal window? return */ - if( !win || !(textlen+timelen)) return 0; + if (!win || !(textlen + timelen)) + return 0; /* store original attributes */ - WATTR_GET( win, orgattr); - attrbuffer[ 0 ] = orgattr; + WATTR_GET(win, orgattr); + attrbuffer[0] = orgattr; /* copy time string */ - for( i = 0; i < timelen; i++ ) - if( tmp[ i ] == 1 ) { - docolorize( tmp[++i], attrbuffer+charcount, orgattr); - } else { - attrbuffer[ charcount+1 ] = attrbuffer[ charcount ]; - textbuffer[ charcount++ ] = tmp[ i ]; - } + for (i = 0; i < timelen; i++) + if (tmp[i] == 1) { + docolorize(tmp[++i], attrbuffer + charcount, orgattr); + } else { + attrbuffer[charcount + 1] = attrbuffer[charcount]; + textbuffer[charcount++] = tmp[i]; + } - timelen = charcount; + timelen = charcount; /* copy text */ - for( i = 0; i< textlen; i++ ) - if( entry->what[ i ] == 1 ) { - docolorize( entry->what[++i], attrbuffer+charcount, orgattr); - } else { - attrbuffer[ charcount+1 ] = attrbuffer[ charcount ]; - textbuffer[ charcount++ ] = entry->what[ i ]; - } + for (i = 0; i < textlen; i++) + if (entry->what[i] == 1) { + docolorize(entry->what[++i], attrbuffer + charcount, orgattr); + } else { + attrbuffer[charcount + 1] = attrbuffer[charcount]; + textbuffer[charcount++] = entry->what[i]; + } /* zero terminate text --- very important :) */ - textbuffer[ charcount ] = 0; + textbuffer[charcount] = 0; /* hilite */ - if((win == channel)||(win == private)) { /* do not higlight bars */ - filt *flt = filterlist; - char *instr = textbuffer; - regmatch_t match; - int j; - - while( flt ) { - if ( (flt->colour != '-') && (flt->colour != '+')) { - i = timelen; - while( i < charcount ) { - if( regexec( &flt->regex, instr+i, 1, &match, 0 )) { - i = charcount; - } else { - for( j = i + match.rm_so; j < i + match.rm_eo; j++) - docolorize( flt->colour, attrbuffer+j, orgattr ); - i += 1 + match.rm_so; - } - } + if ((win == channel) || (win == private)) { /* do not higlight bars */ + filt *flt = filterlist; + char *instr = textbuffer; + regmatch_t match; + int j; + + while (flt) { + if ((flt->colour != '-') && (flt->colour != '+')) { + i = timelen; + while (i < charcount) { + if (regexec(&flt->regex, instr + i, 1, &match, 0)) { + i = charcount; + } else { + for (j = i + match.rm_so; j < i + match.rm_eo; j++) + docolorize(flt->colour, attrbuffer + j, orgattr); + i += 1 + match.rm_so; } - flt = flt->next; + } } + flt = flt->next; + } } - if (getcurx(win)) waddch(win,'\n'); - - for( i = 0; i < charcount; i++ ) { - /* on start of line or attribute changes set new attribute */ - if( !i || memcmp( attrbuffer+i, attrbuffer+i-1, sizeof(ncurs_attr))) - WATTR_SET( win, attrbuffer[i]); - if( textbuffer[ i ] == ' ') { - if ((calcdrawcus(textbuffer+i+1) + getcurx(win) > getmaxx(win) - 1 - 1)&& - (calcdrawcus(textbuffer+i+1) < getmaxx(win) - 1 )) { - /* line wrap found */ - WATTR_SET( win, orgattr); - waddstr( win, "\n "); - WATTR_SET( win, attrbuffer[ i ]); - } + if (getcurx(win)) + waddch(win, '\n'); + + for (i = 0; i < charcount; i++) { + /* on start of line or attribute changes set new attribute */ + if (!i || memcmp(attrbuffer + i, attrbuffer + i - 1, sizeof(ncurs_attr))) + WATTR_SET(win, attrbuffer[i]); + if (textbuffer[i] == ' ') { + if ((calcdrawcus(textbuffer + i + 1) + getcurx(win) > + getmaxx(win) - 1 - 1) && + (calcdrawcus(textbuffer + i + 1) < getmaxx(win) - 1)) { + /* line wrap found */ + WATTR_SET(win, orgattr); + waddstr(win, "\n "); + WATTR_SET(win, attrbuffer[i]); } - /* plot character */ - waddch( win, (unsigned char)textbuffer[ i ]); + } + /* plot character */ + waddch(win, (unsigned char)textbuffer[i]); } /* restore old attributes */ - WATTR_SET (win, orgattr); + WATTR_SET(win, orgattr); return charcount; } -static void -resize_output ( ) -{ - int outputwidth = (outputwidth_desired + 7 > screensx) ? screensx - 7 : outputwidth_desired; - int outputheight = getsbdataheight(sb_out, outputwidth-1, 0); +static void resize_output() { + int outputwidth = + (outputwidth_desired + 7 > screensx) ? screensx - 7 : outputwidth_desired; + int outputheight = getsbdataheight(sb_out, outputwidth - 1, 0); - if (outputheight + 5 > screensy ) outputheight = screensy - 5; - wresize(output,outputheight,outputwidth); - mvwin(output,(screensy-outputheight)>>1,(screensx-outputwidth)>>1); + if (outputheight + 5 > screensy) + outputheight = screensy - 5; + wresize(output, outputheight, outputwidth); + mvwin(output, (screensy - outputheight) >> 1, (screensx - outputwidth) >> 1); drawwin(output, sb_out); } -static void -doscroll ( int up ) { +static void doscroll(int up) { togglequery(); { - WINDOW *destwin = (sb_win && private) ? private : channel; - struct sb_data *sb = (sb_win && private) ? sb_priv : sb_pub; - struct sb_entry *now = sb->entries, *prev = NULL, *tmp; - int lines = (getmaxy(destwin) - 1 ) >>1; - - if( sb->scroll != sb->count ) - while( now && (now->id != sb->scroll) ) { - tmp = now; now = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); prev = tmp; + WINDOW *destwin = (sb_win && private) ? private : channel; + struct sb_data *sb = (sb_win && private) ? sb_priv : sb_pub; + struct sb_entry *now = sb->entries, *prev = NULL, *tmp; + int lines = (getmaxy(destwin) - 1) >> 1; + + if (sb->scroll != sb->count) + while (now && (now->id != sb->scroll)) { + tmp = now; + now = + (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + prev = tmp; } - if( !up ) { - prev = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); - tmp = now; now = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); prev = tmp; - } + if (!up) { + prev = + (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + tmp = now; + now = (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + prev = tmp; + } - while( now && (lines > 0)) { - if ( (!filtertype) || ( (now->stamp != currentstamp) && ( (now->stamp == (currentstamp | (1<<15))) || testfilter( now ) ) ) ) - { - lines -= getsbeheight( now, getmaxx(destwin) - 1, usetime ); + while (now && (lines > 0)) { + if ((!filtertype) || + ((now->stamp != currentstamp) && + ((now->stamp == (currentstamp | (1 << 15))) || testfilter(now)))) { + lines -= getsbeheight(now, getmaxx(destwin) - 1, usetime); } - tmp = now; now = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); prev = tmp; - } - if( now ) + tmp = now; + now = (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + prev = tmp; + } + if (now) sb->scroll = now->id; - else - if( !up ) sb->scroll = sb->count; + else if (!up) + sb->scroll = sb->count; - drawwin(destwin, sb); - wnoutrefresh(destwin); + drawwin(destwin, sb); + wnoutrefresh(destwin); - togglequery(); + togglequery(); - if( private && (destwin == channel) ) - consoleline( NULL); - else - topicline( NULL); + if (private && (destwin == channel)) + consoleline(NULL); + else + topicline(NULL); } } +void scrollup(void) { doscroll(1); } -void -scrollup (void) -{ - doscroll( 1 ); -} +void scrolldown(void) { doscroll(0); } -void -scrolldown (void) -{ - doscroll( 0 ); -} - -void -scrollwin (void) -{ - if (!sb_win && private && !privwinhidden) sb_win = 1; - else sb_win = 0; - topicline(NULL); - consoleline(NULL); +void scrollwin(void) { + if (!sb_win && private && !privwinhidden) + sb_win = 1; + else + sb_win = 0; + topicline(NULL); + consoleline(NULL); } -void -growprivwin (void) { - if( private ) { - if( privwinhidden) - privwinhidden = 0; - if( ++privheight_desired > screensy - 5) - privheight_desired = screensy - 5; - resize(0); - } +void growprivwin(void) { + if (private) { + if (privwinhidden) + privwinhidden = 0; + if (++privheight_desired > screensy - 5) + privheight_desired = screensy - 5; + resize(0); + } } -void toggleprivwin (void) { - if( outputshown ) { +void toggleprivwin(void) { + if (outputshown) { outputshown = 0; resize(0); } else { - if( private ) { - if( privwinhidden ) { - privheight_desired = privwinhidden; - privwinhidden = 0; - } else { - privwinhidden = privheight_desired; - privheight_desired = 1; - sb_win = 0; - sb_priv->scroll = sb_priv->count; - } - resize(0); + if (private) { + if (privwinhidden) { + privheight_desired = privwinhidden; + privwinhidden = 0; + } else { + privwinhidden = privheight_desired; + privheight_desired = 1; + sb_win = 0; + sb_priv->scroll = sb_priv->count; + } + resize(0); } } } -void -shrinkprivwin (void) { - if( private && !privwinhidden ) { - if( --privheight_desired < 1) privheight_desired = 1; - if( privheight_desired > screensy - 5) privheight_desired = screensy - 5; +void shrinkprivwin(void) { + if (private && !privwinhidden) { + if (--privheight_desired < 1) + privheight_desired = 1; + if (privheight_desired > screensy - 5) + privheight_desired = screensy - 5; resize(0); } } /* clear message window */ -void -clearpriv () -{ +void clearpriv() { WINDOW *dest = NULL; /* do we have a private window? */ - if (private && !privwinhidden ) - dest = private; + if (private && !privwinhidden) + dest = private; else - dest = channel; + dest = channel; /* clear window, move cursor to bottom, redraw */ - wclear (dest); - wmove (dest, getmaxy(dest) - 1, getmaxx(dest) - 1); - wrefresh (dest); - + wclear(dest); + wmove(dest, getmaxy(dest) - 1, getmaxx(dest) - 1); + wrefresh(dest); } /* clear channel window */ -void -clearchan () -{ +void clearchan() { /* clear window, move cursor to bottom, redraw */ - wclear (channel); - wmove (channel, getmaxy(channel) - 1, getmaxx(channel) - 1); - wrefresh (channel); + wclear(channel); + wmove(channel, getmaxy(channel) - 1, getmaxx(channel) - 1); + wrefresh(channel); } /* Get window size */ -void ttgtsz(int *x,int *y) { +void ttgtsz(int *x, int *y) { #ifdef TIOCGSIZE - struct ttysize getit; + struct ttysize getit; #else #ifdef TIOCGWINSZ - struct winsize getit; + struct winsize getit; #endif #endif - *x=0; *y=0; + *x = 0; + *y = 0; #ifdef TIOCGSIZE - if(ioctl(1,TIOCGSIZE,&getit)!= -1) { - *x=getit.ts_cols; - *y=getit.ts_lines; - } + if (ioctl(1, TIOCGSIZE, &getit) != -1) { + *x = getit.ts_cols; + *y = getit.ts_lines; + } #else #ifdef TIOCGWINSZ - if(ioctl(1,TIOCGWINSZ,&getit)!= -1) { - *x=getit.ws_col; - *y=getit.ws_row; - } + if (ioctl(1, TIOCGWINSZ, &getit) != -1) { + *x = getit.ws_col; + *y = getit.ws_row; + } #endif #endif - } +} -static void -forceredraw (void) -{ +static void forceredraw(void) { sb_pub->scroll = sb_pub->count; sb_priv->scroll = sb_priv->count; resize(0); - if(console) wclear(console); - if(topic) wclear(topic); - if(private) wclear(private); - if(channel) wclear(channel); - if(output) wclear(output); - if(input) wclear(input); + if (console) + wclear(console); + if (topic) + wclear(topic); + if (private) + wclear(private); + if (channel) + wclear(channel); + if (output) + wclear(output); + if (input) + wclear(input); resize(0); - } /* resize display on SIGWINCH Nowadays used as our main redraw trigger engine */ -void -resize (int signal) -{ - int xsize,ysize,topicheight=topic?1:0; +void resize(int signal) { + int xsize, ysize, topicheight = topic ? 1 : 0; (void)signal; - ttgtsz(&xsize,&ysize); - resizeterm(ysize,xsize); + ttgtsz(&xsize, &ysize); + resizeterm(ysize, xsize); /* store screen-dimensions to local functions */ - getmaxyx (stdscr, screensy, screensx); + getmaxyx(stdscr, screensy, screensx); /* desired height of PM window is user controllable, actual size depends on space available on screen */ @@ -775,24 +813,34 @@ resize (int signal) /* Leave at least 5 lines for input, console and pubchannel */ - if ( privheight_desired > screensy - 5) - privheight = screensy - 5; + if (privheight_desired > screensy - 5) + privheight = screensy - 5; else - privheight = privheight_desired; + privheight = privheight_desired; /* check dimensions or bump user */ - if (screensy - privheight < 4) - { - fprintf (stderr, "vchat-client: screen to short (only %d rows, at least %d expected), bailing out.\n", screensy, privheight + 6); - snprintf (errstr, ERRSTRSIZE, "vchat-client: screen to short (only %d rows, at least %d expected), bailing out.\n", screensy, privheight + 6); - cleanup (0); - } - if (screensx < 14) - { - fprintf (stderr, "vchat-client: screen to thin (only %d cols, at least %d expected), bailing out.\n", screensx, 14); - snprintf (errstr, ERRSTRSIZE, "vchat-client: screen to thin (only %d cols, at least %d expected), bailing out.\n", screensx, 14); - cleanup (0); - } + if (screensy - privheight < 4) { + fprintf(stderr, + "vchat-client: screen to short (only %d rows, at least %d " + "expected), bailing out.\n", + screensy, privheight + 6); + snprintf(errstr, ERRSTRSIZE, + "vchat-client: screen to short (only %d rows, at least %d " + "expected), bailing out.\n", + screensy, privheight + 6); + cleanup(0); + } + if (screensx < 14) { + fprintf(stderr, + "vchat-client: screen to thin (only %d cols, at least %d " + "expected), bailing out.\n", + screensx, 14); + snprintf(errstr, ERRSTRSIZE, + "vchat-client: screen to thin (only %d cols, at least %d " + "expected), bailing out.\n", + screensx, 14); + cleanup(0); + } /***** * Arrange windows on screen @@ -801,38 +849,44 @@ resize (int signal) togglequery(); /* console and input are always there and always 1 line tall */ - wresize(console,1,screensx); - wresize(input,1,screensx); + wresize(console, 1, screensx); + wresize(input, 1, screensx); /* If we got a private window and it is not hidden, set its size */ if (private && !privwinhidden) - wresize(private,privheight,screensx); + wresize(private, privheight, screensx); /* If oldschool vchat is not enabled, we have a topic line */ - if( topic ) - wresize(topic,1,screensx); + if (topic) + wresize(topic, 1, screensx); /* public channel is always there and its height depends on: - * existence and visibility of priv window - * existence of a topic line (oldschool vchat style) - */ - wresize(channel, ( !private || privwinhidden ) ? screensy - ( topicheight + 2 ) : screensy - (privheight + ( topicheight + 2 )), screensx); + * existence and visibility of priv window + * existence of a topic line (oldschool vchat style) + */ + wresize(channel, + (!private || privwinhidden) + ? screensy - (topicheight + 2) + : screensy - (privheight + (topicheight + 2)), + screensx); /* Console and input alway take bottommost lines */ - mvwin(console,screensy-2,0); - mvwin(input,screensy-1,0); + mvwin(console, screensy - 2, 0); + mvwin(input, screensy - 1, 0); /* Private window always is top left */ - if(private && !privwinhidden) - mvwin(private,0,0); + if (private && !privwinhidden) + mvwin(private, 0, 0); /* Topic window may not exist without priv window, so it is safe to assume sane values for privwinhidden and privheight */ - if( topic ) - mvwin(topic,privwinhidden ? 0 : privheight, 0); + if (topic) + mvwin(topic, privwinhidden ? 0 : privheight, 0); /* chan window starts below private window and topic line */ - mvwin(channel, ( !private || privwinhidden ) ? topicheight : privheight + topicheight, 0); + mvwin(channel, + (!private || privwinhidden) ? topicheight : privheight + topicheight, + 0); /******* * Now actual redraw starts, note, that we only fill @@ -847,97 +901,104 @@ resize (int signal) /* pub channel is always there, paint scrollback buffers */ drawwin(channel, sb_pub); /* if priv exists and is visible, paint scrollback buffers */ - if(private && !privwinhidden) - drawwin(private, sb_priv); + if (private && !privwinhidden) + drawwin(private, sb_priv); /* Send window's contents to curses virtual buffers */ wnoutrefresh(channel); - if(private && !privwinhidden) - wnoutrefresh(private); + if (private && !privwinhidden) + wnoutrefresh(private); togglequery(); /* Resize and draw our message window, render topic and console line */ - if(outputshown) - resize_output(); - if(topic) - topicline(NULL); + if (outputshown) + resize_output(); + if (topic) + topicline(NULL); consoleline(NULL); - if(loggedin) - vciredraw(); + if (loggedin) + vciredraw(); } -static int -gettextwidth (const char *textbuffer) -{ - int width = 0; +static int gettextwidth(const char *textbuffer) { + int width = 0; - do switch( *(textbuffer++) ) { - case 1: - if (!*(textbuffer++)) return width; + do + switch (*(textbuffer++)) { + case 1: + if (!*(textbuffer++)) + return width; break; - case 0: + case 0: return width; break; - default: + default: width++; break; - } while( 1 ); + } + while (1); } -static int -getsbdataheight (struct sb_data *data, const int xwidth, int needstime ) -{ +static int getsbdataheight(struct sb_data *data, const int xwidth, + int needstime) { struct sb_entry *now = data->entries, *prev = NULL, *tmp; int height = 0; - while( now ) { - height += getsbeheight( now, xwidth, needstime); - tmp = now; now = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); prev = tmp; + while (now) { + height += getsbeheight(now, xwidth, needstime); + tmp = now; + now = (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + prev = tmp; } return height; } -static int -getsbeheight (struct sb_entry *entry, const int xwidth, int needstime ) -{ +static int getsbeheight(struct sb_entry *entry, const int xwidth, + int needstime) { int curx = 0, lines = 1; - char tmp[ 64 ], *textbuffer; + char tmp[64], *textbuffer; - if( needstime ) { - int timelen = (int)strftime(tmp,64,getformatstr(FS_TIME),localtime(&entry->when)); - tmp[ timelen ] = 2; - textbuffer=tmp; + if (needstime) { + int timelen = + (int)strftime(tmp, 64, getformatstr(FS_TIME), localtime(&entry->when)); + tmp[timelen] = 2; + textbuffer = tmp; } else { - textbuffer = entry->what; + textbuffer = entry->what; } - do switch( *textbuffer++ ) { - case ' ': + do + switch (*textbuffer++) { + case ' ': if ((calcdrawcus(textbuffer) + curx > xwidth - 1) && (calcdrawcus(textbuffer) < xwidth)) { - lines++; curx = 4; - } else { - if( curx++ == xwidth ) { - curx = 0; lines++; - } - } + lines++; + curx = 4; + } else { + if (curx++ == xwidth) { + curx = 0; + lines++; + } + } break; - case 1: - if (!*textbuffer++) return lines; + case 1: + if (!*textbuffer++) + return lines; break; - case 0: + case 0: return lines; break; - case 2: - textbuffer=entry->what; + case 2: + textbuffer = entry->what; break; - default: - if( curx++ == xwidth ) { - curx = 0; lines++; + default: + if (curx++ == xwidth) { + curx = 0; + lines++; } break; - } while( 1 ); - + } + while (1); } /* Check, which kind of filter we have to apply: @@ -947,8 +1008,7 @@ getsbeheight (struct sb_entry *entry, const int xwidth, int needstime ) If no, or only colouring rules have been found, no line filtering applies. */ -static int -analyzefilters( void ) { +static int analyzefilters(void) { filt *filters = filterlist; int type = 0; @@ -965,96 +1025,106 @@ analyzefilters( void ) { tested the line against. This Stamp is updated for each change to the filter list */ - if( ++currentstamp == 0x3fff ) currentstamp = 1; - - while( (type!=1) && filters ) { - if( filters->colour == '-' ) type = 2; - if( filters->colour == '+' ) type = 1; - filters=filters->next; + if (++currentstamp == 0x3fff) + currentstamp = 1; + + while ((type != 1) && filters) { + if (filters->colour == '-') + type = 2; + if (filters->colour == '+') + type = 1; + filters = filters->next; } return type; } -static int -testfilter ( struct sb_entry* entry ) { - int match = 0; - filt *filters = filterlist; - char filtercolour = filtertype == 2 ? '-' : '+'; +static int testfilter(struct sb_entry *entry) { + int match = 0; + filt *filters = filterlist; + char filtercolour = filtertype == 2 ? '-' : '+'; - while( !match && filters ) { - if( filters->colour == filtercolour ) - match = regexec( &filters->regex, entry->what, 0, NULL, 0 ) ? 0 : 1; - filters=filters->next; - } - match = ( filtertype == 2 ) ? ( 1 - match ) : match; - entry->stamp = (match << 15) | currentstamp; + while (!match && filters) { + if (filters->colour == filtercolour) + match = regexec(&filters->regex, entry->what, 0, NULL, 0) ? 0 : 1; + filters = filters->next; + } + match = (filtertype == 2) ? (1 - match) : match; + entry->stamp = (match << 15) | currentstamp; - return match; + return match; } -static void -drawwin (WINDOW *win, struct sb_data *sb ) -{ +static void drawwin(WINDOW *win, struct sb_data *sb) { if (win) { - struct sb_entry *now = sb->entries, *prev = NULL, *tmp; - struct sb_entry *vis[getmaxy(win)]; - int sumlines = 0, sumbuffers = 0; - - /* public scrollback */ - if( sb->scroll != sb->count ) - while( now && (now->id != sb->scroll) ) { - tmp = now; now = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); prev = tmp; - } + struct sb_entry *now = sb->entries, *prev = NULL, *tmp; + struct sb_entry *vis[getmaxy(win)]; + int sumlines = 0, sumbuffers = 0; + + /* public scrollback */ + if (sb->scroll != sb->count) + while (now && (now->id != sb->scroll)) { + tmp = now; + now = + (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + prev = tmp; + } - if( (win == output) || (filtertype == 0)) { - while( now && (sumlines <= getmaxy(win) - 1 )) { - sumlines += getsbeheight( now, getmaxx(win) - 1, ((win == channel)||(win == private)) && usetime ); - vis[ sumbuffers++ ] = now; - tmp = now; now = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); prev = tmp; - } - } else { - while( now && (sumlines <= getmaxy(win) - 1 )) { - - /* If stamp matches exactly, line has been filtered out, since top - bit off means hidden */ - if( now->stamp != currentstamp) { - - /* If stamp matches and has top bit set, it has been identified - positively. Else stamp does not match and line has to be - tested against filters, which updates stamp. */ - if( (now->stamp == (currentstamp | 0x8000) ) || testfilter( now )) - { - sumlines += getsbeheight( now, getmaxx(win) - 1, ((win == channel)||(win == private)) && usetime ); - vis[ sumbuffers++ ] = now; - } - - } - tmp = now; now = (struct sb_entry*)((unsigned long)now->link ^ (unsigned long)prev); prev = tmp; + if ((win == output) || (filtertype == 0)) { + while (now && (sumlines <= getmaxy(win) - 1)) { + sumlines += + getsbeheight(now, getmaxx(win) - 1, + ((win == channel) || (win == private)) && usetime); + vis[sumbuffers++] = now; + tmp = now; + now = + (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + prev = tmp; + } + } else { + while (now && (sumlines <= getmaxy(win) - 1)) { + + /* If stamp matches exactly, line has been filtered out, since top + bit off means hidden */ + if (now->stamp != currentstamp) { + + /* If stamp matches and has top bit set, it has been identified + positively. Else stamp does not match and line has to be + tested against filters, which updates stamp. */ + if ((now->stamp == (currentstamp | 0x8000)) || testfilter(now)) { + sumlines += + getsbeheight(now, getmaxx(win) - 1, + ((win == channel) || (win == private)) && usetime); + vis[sumbuffers++] = now; } + } + tmp = now; + now = + (struct sb_entry *)((unsigned long)now->link ^ (unsigned long)prev); + prev = tmp; } + } - /* If buffer is not completely filled, clear window */ - if( sumlines < getmaxy(win) ) - wclear(win); + /* If buffer is not completely filled, clear window */ + if (sumlines < getmaxy(win)) + wclear(win); - /* Move pointer to bottom to let curses scroll */ - wmove(win, getmaxy(win) - 1, getmaxx(win) - 1); + /* Move pointer to bottom to let curses scroll */ + wmove(win, getmaxy(win) - 1, getmaxx(win) - 1); - /* Plot visible lines */ - while (sumbuffers--) writescr( win, vis[sumbuffers] ); + /* Plot visible lines */ + while (sumbuffers--) + writescr(win, vis[sumbuffers]); } } /* initialize curses and display */ -void -initui (void) -{ +void initui(void) { Keymap keymap; /* init curses */ if (!ui_init) { - initscr (); - ui_init = 1; + initscr(); + ui_init = 1; } /* install signalhandler */ @@ -1063,131 +1133,144 @@ initui (void) signal(SIGCONT, forceredraw_wrapper); /* set options */ - keypad (stdscr, TRUE); - nonl (); - cbreak (); + keypad(stdscr, TRUE); + nonl(); + cbreak(); /* color or monochome display? */ - if (has_colors ()) - { - /* start color and set a colorset */ - start_color (); - use_default_colors(); - init_pair (1, COLOR_RED, -1); - init_pair (2, COLOR_GREEN, -1); - init_pair (3, COLOR_YELLOW, -1); - init_pair (4, COLOR_BLUE, -1); - init_pair (5, COLOR_MAGENTA, -1); - init_pair (6, COLOR_CYAN, -1); - init_pair (7, COLOR_WHITE, -1); - init_pair (8, COLOR_WHITE, COLOR_RED); - init_pair (9, COLOR_WHITE, COLOR_BLUE); - init_pair (10, COLOR_WHITE, COLOR_BLACK); - } - else - { - /* monochrome, start color and set a colorset anyways */ - start_color (); - init_pair (1, -1, -1); - init_pair (2, -1, -1); - init_pair (3, -1, -1); - init_pair (4, -1, -1); - init_pair (5, -1, -1); - init_pair (6, -1, -1); - init_pair (7, -1, -1); - init_pair (8, -1, -1); - init_pair (9, -1, -1); - init_pair (10, -1, -1); - } + if (has_colors()) { + /* start color and set a colorset */ + start_color(); + use_default_colors(); + init_pair(1, COLOR_RED, -1); + init_pair(2, COLOR_GREEN, -1); + init_pair(3, COLOR_YELLOW, -1); + init_pair(4, COLOR_BLUE, -1); + init_pair(5, COLOR_MAGENTA, -1); + init_pair(6, COLOR_CYAN, -1); + init_pair(7, COLOR_WHITE, -1); + init_pair(8, COLOR_WHITE, COLOR_RED); + init_pair(9, COLOR_WHITE, COLOR_BLUE); + init_pair(10, COLOR_WHITE, COLOR_BLACK); + } else { + /* monochrome, start color and set a colorset anyways */ + start_color(); + init_pair(1, -1, -1); + init_pair(2, -1, -1); + init_pair(3, -1, -1); + init_pair(4, -1, -1); + init_pair(5, -1, -1); + init_pair(6, -1, -1); + init_pair(7, -1, -1); + init_pair(8, -1, -1); + init_pair(9, -1, -1); + init_pair(10, -1, -1); + } /* store screen-dimensions to local functions */ - getmaxyx (stdscr, screensy, screensx); + getmaxyx(stdscr, screensy, screensx); - if (!privheight_desired) privheight_desired = getintoption(CF_PRIVHEIGHT); - if ( privheight_desired > screensy - 5) privheight = screensy - 5; else privheight = privheight_desired; + if (!privheight_desired) + privheight_desired = getintoption(CF_PRIVHEIGHT); + if (privheight_desired > screensy - 5) + privheight = screensy - 5; + else + privheight = privheight_desired; /* check dimensions or bump user */ - if (screensy - privheight < 4) - { - fprintf (stderr, "vchat-client: screen to short (only %d rows, at least %d expected), bailing out.\n", screensy, privheight + 6); - snprintf (errstr, ERRSTRSIZE, "vchat-client: screen to short (only %d rows, at least %d expected), bailing out.\n", screensy, privheight + 6); - cleanup (0); - } - if (screensx < 14) - { - fprintf (stderr, "vchat-client: screen to thin (only %d cols, at least %d expected), bailing out.\n", screensx, 14); - snprintf (errstr, ERRSTRSIZE, "vchat-client: screen to thin (only %d cols, at least %d expected), bailing out.\n", screensx, 14); - cleanup (0); - } + if (screensy - privheight < 4) { + fprintf(stderr, + "vchat-client: screen to short (only %d rows, at least %d " + "expected), bailing out.\n", + screensy, privheight + 6); + snprintf(errstr, ERRSTRSIZE, + "vchat-client: screen to short (only %d rows, at least %d " + "expected), bailing out.\n", + screensy, privheight + 6); + cleanup(0); + } + if (screensx < 14) { + fprintf(stderr, + "vchat-client: screen to thin (only %d cols, at least %d " + "expected), bailing out.\n", + screensx, 14); + snprintf(errstr, ERRSTRSIZE, + "vchat-client: screen to thin (only %d cols, at least %d " + "expected), bailing out.\n", + screensx, 14); + cleanup(0); + } /* setup our windows */ - console = newwin (1, screensx, screensy - 2, 0); - input = newwin (1, screensx, screensy - 1, 0); - if (privheight) private = newwin (privheight, screensx, 0, 0); - if( private || getintoption(CF_USETOPIC)) - topic = newwin (1, screensx, privheight, 0); - channel = newwin (screensy - (privheight+3), screensx, (privheight+1), 0); - output = newwin (1, screensx, 1, 0); + console = newwin(1, screensx, screensy - 2, 0); + input = newwin(1, screensx, screensy - 1, 0); + if (privheight) + private + = newwin(privheight, screensx, 0, 0); + if (private || getintoption(CF_USETOPIC)) + topic = newwin(1, screensx, privheight, 0); + channel = newwin(screensy - (privheight + 3), screensx, (privheight + 1), 0); + output = newwin(1, screensx, 1, 0); /* promblems opening windows? bye! */ - if (!console || !input || (!topic && getintoption(CF_USETOPIC))|| !channel || !output || ( !private && privheight )) - { - fprintf (stderr, "vchat-client: could not open windows, bailing out.\n"); - cleanup (0); - } + if (!console || !input || (!topic && getintoption(CF_USETOPIC)) || !channel || + !output || (!private && privheight)) { + fprintf(stderr, "vchat-client: could not open windows, bailing out.\n"); + cleanup(0); + } /* Prepare our scrollback buffers */ - sb_pub = (struct sb_data*)malloc( sizeof(struct sb_data)); - sb_out = (struct sb_data*)malloc( sizeof(struct sb_data)); - if( privheight) - sb_priv = (struct sb_data*)malloc( sizeof(struct sb_data)); + sb_pub = (struct sb_data *)malloc(sizeof(struct sb_data)); + sb_out = (struct sb_data *)malloc(sizeof(struct sb_data)); + if (privheight) + sb_priv = (struct sb_data *)malloc(sizeof(struct sb_data)); else - sb_priv = sb_pub; + sb_priv = sb_pub; - memset( sb_pub, 0, sizeof(struct sb_data)); - memset( sb_priv, 0, sizeof(struct sb_data)); - memset( sb_out, 0, sizeof(struct sb_data)); + memset(sb_pub, 0, sizeof(struct sb_data)); + memset(sb_priv, 0, sizeof(struct sb_data)); + memset(sb_out, 0, sizeof(struct sb_data)); /* set colors for windows */ if (has_colors()) { - if (getintoption(CF_INVWINBAR)) { - wbkgd (console, COLOR_PAIR (0)); - wattron (console, A_REVERSE); - } else { - wattrset (console, COLOR_PAIR (9)); - wbkgd (console, COLOR_PAIR (9)); - } - wattrset (input, COLOR_PAIR (0)); - wbkgd (output, COLOR_PAIR(8)); - wbkgd (channel, COLOR_PAIR (0)); - wbkgd (input, COLOR_PAIR (0)); - if (private) - wbkgd (private, COLOR_PAIR (0)); - if (topic) { - if (getintoption(CF_INVWINBAR)) { - wbkgd (input, COLOR_PAIR (0)); - wattron(topic, A_REVERSE); - } else { - wattrset (topic, COLOR_PAIR (9)); - wbkgd (topic, COLOR_PAIR (9)); - } - } + if (getintoption(CF_INVWINBAR)) { + wbkgd(console, COLOR_PAIR(0)); + wattron(console, A_REVERSE); + } else { + wattrset(console, COLOR_PAIR(9)); + wbkgd(console, COLOR_PAIR(9)); + } + wattrset(input, COLOR_PAIR(0)); + wbkgd(output, COLOR_PAIR(8)); + wbkgd(channel, COLOR_PAIR(0)); + wbkgd(input, COLOR_PAIR(0)); + if (private) + wbkgd(private, COLOR_PAIR(0)); + if (topic) { + if (getintoption(CF_INVWINBAR)) { + wbkgd(input, COLOR_PAIR(0)); + wattron(topic, A_REVERSE); + } else { + wattrset(topic, COLOR_PAIR(9)); + wbkgd(topic, COLOR_PAIR(9)); + } + } } else { - wattron (console, A_REVERSE); - wattron (output, A_REVERSE); - wbkgd(output, A_REVERSE); - if( topic ) - wattron (topic, A_REVERSE); + wattron(console, A_REVERSE); + wattron(output, A_REVERSE); + wbkgd(output, A_REVERSE); + if (topic) + wattron(topic, A_REVERSE); } /* set some options */ - scrollok (channel, TRUE); + scrollok(channel, TRUE); if (private) - scrollok (private, TRUE); - scrollok (input, TRUE); - scrollok (output, TRUE); - //idlok(channel,TRUE); - wtimeout (input, 100); + scrollok(private, TRUE); + scrollok(input, TRUE); + scrollok(output, TRUE); + // idlok(channel,TRUE); + wtimeout(input, 100); /* setup readlines display */ /* FIXME: present only in newer readline versions @@ -1198,88 +1281,88 @@ initui (void) rl_redisplay_function = vciredraw; /* get keymap, throw out unwanted binding */ - keymap = rl_get_keymap (); - rl_unbind_command_in_map ("clear-screen", keymap); - rl_unbind_command_in_map ("complete", keymap); - rl_unbind_command_in_map ("possible-completions", keymap); - rl_unbind_command_in_map ("insert-completions", keymap); + keymap = rl_get_keymap(); + rl_unbind_command_in_map("clear-screen", keymap); + rl_unbind_command_in_map("complete", keymap); + rl_unbind_command_in_map("possible-completions", keymap); + rl_unbind_command_in_map("insert-completions", keymap); /* bind CTRL-L to clearmsg() */ - rl_bind_key ('J'-'@', (rl_command_func_t *) clearpriv); - rl_bind_key ('O'-'@', (rl_command_func_t *) clearchan); - rl_bind_key ('L'-'@', (rl_command_func_t *) forceredraw); - rl_bind_key ('B'-'@', (rl_command_func_t *) scrollup); - rl_bind_key ('P'-'@', (rl_command_func_t *) scrollup); - rl_bind_key ('F'-'@', (rl_command_func_t *) scrolldown); - rl_bind_key ('N'-'@', (rl_command_func_t *) scrolldown); - rl_bind_key ('R'-'@', (rl_command_func_t *) scrollwin); - rl_bind_key ('T'-'@', (rl_command_func_t *) shrinkprivwin); - rl_bind_key ('G'-'@', (rl_command_func_t *) growprivwin); - rl_bind_key ('X'-'@', (rl_command_func_t *) toggleprivwin); - - rl_generic_bind (ISFUNC, "\\M-[5~", (void *)scrollup, keymap); - rl_generic_bind (ISFUNC, "\\M-[6~", (void *)scrolldown, keymap); + rl_bind_key('J' - '@', (rl_command_func_t *)clearpriv); + rl_bind_key('O' - '@', (rl_command_func_t *)clearchan); + rl_bind_key('L' - '@', (rl_command_func_t *)forceredraw); + rl_bind_key('B' - '@', (rl_command_func_t *)scrollup); + rl_bind_key('P' - '@', (rl_command_func_t *)scrollup); + rl_bind_key('F' - '@', (rl_command_func_t *)scrolldown); + rl_bind_key('N' - '@', (rl_command_func_t *)scrolldown); + rl_bind_key('R' - '@', (rl_command_func_t *)scrollwin); + rl_bind_key('T' - '@', (rl_command_func_t *)shrinkprivwin); + rl_bind_key('G' - '@', (rl_command_func_t *)growprivwin); + rl_bind_key('X' - '@', (rl_command_func_t *)toggleprivwin); + + rl_generic_bind(ISFUNC, "\\M-[5~", (void *)scrollup, keymap); + rl_generic_bind(ISFUNC, "\\M-[6~", (void *)scrolldown, keymap); /* bind TAB to menu complete from readline */ - rl_bind_key ('\t', (rl_command_func_t *) rl_menu_complete); + rl_bind_key('\t', (rl_command_func_t *)rl_menu_complete); /* application name for .inputrc - err, we don't load it */ rl_readline_name = "vchat-client"; /* set up nick completion functions .. */ rl_ignore_completion_duplicates = 0; - rl_attempted_completion_function = (rl_completion_func_t *) ul_complete_user; + rl_attempted_completion_function = (rl_completion_func_t *)ul_complete_user; /* .. and 'line completed' callback */ - rl_callback_handler_install ("", (rl_vcpfunc_t *) linecomplete); + rl_callback_handler_install("", (rl_vcpfunc_t *)linecomplete); - if( getintoption(CF_PRIVCOLLAPS) ) + if (getintoption(CF_PRIVCOLLAPS)) toggleprivwin(); resize(0); } /* render consoleline to screen */ -void -consoleline (char *message) -{ +void consoleline(char *message) { /* clear console, set string (or default), redraw display */ int i; ncurs_attr old_att, new_att; togglequery(); - memset( &new_att, 0, sizeof(new_att)); - BCOLR_SET( (&new_att), 8 ); - wmove (console, 0, 0); - WATTR_GET( console, old_att); - if(sb_pub->scroll!=sb_pub->count) - WATTR_SET( console, new_att); + memset(&new_att, 0, sizeof(new_att)); + BCOLR_SET((&new_att), 8); + wmove(console, 0, 0); + WATTR_GET(console, old_att); + if (sb_pub->scroll != sb_pub->count) + WATTR_SET(console, new_att); for (i = 0; i < getmaxx(console) - 1; i++) - waddch (console, ' '); - - if( !message && usetime ) - { - char date[10]; - time_t now = time(NULL); - strftime( date, sizeof(date), getformatstr(FS_CONSOLETIME), localtime(&now)); - snprintf( tmpstr, TMPSTRSIZE, "%s%s", date, consolestr); - mvwaddnstr (console, 0, 0, tmpstr, getmaxx(console) - 1); + waddch(console, ' '); + + if (!message && usetime) { + char date[10]; + time_t now = time(NULL); + strftime(date, sizeof(date), getformatstr(FS_CONSOLETIME), localtime(&now)); + snprintf(tmpstr, TMPSTRSIZE, "%s%s", date, consolestr); + mvwaddnstr(console, 0, 0, tmpstr, getmaxx(console) - 1); } else { - mvwaddnstr (console, 0, 0, message ? message : consolestr, getmaxx(console) - 1); + mvwaddnstr(console, 0, 0, message ? message : consolestr, + getmaxx(console) - 1); } - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_SBINF),sb_pub->scroll,sb_pub->count); - mvwaddstr (console, 0, getmaxx(console) - 1 - (strlen(tmpstr)-1),tmpstr); - if (sb_win == 0) mvwaddch (console, 0, getmaxx(console) - 1,'*'); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SBINF), sb_pub->scroll, + sb_pub->count); + mvwaddstr(console, 0, getmaxx(console) - 1 - (strlen(tmpstr) - 1), tmpstr); + if (sb_win == 0) + mvwaddch(console, 0, getmaxx(console) - 1, '*'); - WATTR_SET( console, old_att); + WATTR_SET(console, old_att); wnoutrefresh(console); - if(outputshown) { - redrawwin(output); - wnoutrefresh(output); + if (outputshown) { + redrawwin(output); + wnoutrefresh(output); } togglequery(); @@ -1288,41 +1371,41 @@ consoleline (char *message) } /* render topicline to screen */ -void -topicline (char *message) -{ +void topicline(char *message) { int i; ncurs_attr old_att, new_att; - if( !topic ) - return; + if (!topic) + return; togglequery(); - memset( &new_att, 0, sizeof(new_att)); - BCOLR_SET( (&new_att), 8 ); + memset(&new_att, 0, sizeof(new_att)); + BCOLR_SET((&new_att), 8); /* clear topic, set string (or default), redraw display */ - wmove (topic, 0, 0); + wmove(topic, 0, 0); - WATTR_GET( topic, old_att); - if( private && (sb_priv->scroll!=sb_priv->count)) - WATTR_SET( topic, new_att); + WATTR_GET(topic, old_att); + if (private && (sb_priv->scroll != sb_priv->count)) + WATTR_SET(topic, new_att); for (i = 0; i < getmaxx(topic) - 1; i++) - waddch (topic, ' '); - mvwaddnstr (topic, 0, 0, message ? message : topicstr, getmaxx(topic) - 1); + waddch(topic, ' '); + mvwaddnstr(topic, 0, 0, message ? message : topicstr, getmaxx(topic) - 1); if (private) { - snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_SBINF),sb_priv->scroll,sb_priv->count); - mvwaddstr (topic, 0, getmaxx(topic) - 1 - (strlen(tmpstr)-1),tmpstr); - if (sb_win == 1) mvwaddch (topic, 0, getmaxx(topic) - 1,'*'); + snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SBINF), sb_priv->scroll, + sb_priv->count); + mvwaddstr(topic, 0, getmaxx(topic) - 1 - (strlen(tmpstr) - 1), tmpstr); + if (sb_win == 1) + mvwaddch(topic, 0, getmaxx(topic) - 1, '*'); } - WATTR_SET( topic, old_att); + WATTR_SET(topic, old_att); wnoutrefresh(topic); - if(outputshown) { - redrawwin(output); - wnoutrefresh(output); + if (outputshown) { + redrawwin(output); + wnoutrefresh(output); } togglequery(); @@ -1331,23 +1414,19 @@ topicline (char *message) } /* end userinterface */ -void -exitui (void) -{ +void exitui(void) { if (ui_init) { - rl_callback_handler_remove (); - endwin (); - ui_init = 0; + rl_callback_handler_remove(); + endwin(); + ui_init = 0; } } /* prompt for a nick */ /* FIXME: must not be called when used rl_callback_read_char()/userinput() * before */ -void -nickprompt (void) -{ - char * newnick = 0; +void nickprompt(void) { + char *newnick = 0; if (own_nick_get()) return; @@ -1358,15 +1437,15 @@ nickprompt (void) newnick = readline(""); own_nick_set(newnick); - setstroption(CF_NICK,newnick); + setstroption(CF_NICK, newnick); /* try to get readlines stats clean again */ - //rl_free_line_state (); - memset( rl_line_buffer, 0, rl_end ); + // rl_free_line_state (); + memset(rl_line_buffer, 0, rl_end); rl_point = rl_end = rl_done = 0; /* wipe input line and reset cursor */ - rl_kill_full_line(0,0); + rl_kill_full_line(0, 0); wclear(input); /* reset consoleline */ @@ -1374,20 +1453,18 @@ nickprompt (void) } /* special callback for readline, doesn't show the characters */ -static void -vcnredraw (void) -{ +static void vcnredraw(void) { int i; - char *passbof="-*-*-*-*-*-*-"; + char *passbof = "-*-*-*-*-*-*-"; /* wipe input line and reset cursor */ wmove(input, 0, 0); for (i = 0; i < getmaxx(input) - 1; i++) - waddch(input, ' '); + waddch(input, ' '); wmove(input, 0, 0); /* draw as many stars as there are characters */ - mvwaddnstr(input, 0, 0, &passbof[rl_point%2], 12); + mvwaddnstr(input, 0, 0, &passbof[rl_point % 2], 12); wmove(input, 0, getmaxx(input) - 1); wrefresh(input); } @@ -1395,9 +1472,7 @@ vcnredraw (void) /* passphrase callback for OpenSSL */ /* FIXME: must not be called when used rl_callback_read_char()/userinput() * before */ -int -passprompt (char *buf, int size, int rwflag, void *userdata) -{ +int passprompt(char *buf, int size, int rwflag, void *userdata) { int i; char *passphrase = NULL; (void)rwflag; @@ -1409,45 +1484,43 @@ passprompt (char *buf, int size, int rwflag, void *userdata) /* prompt user for non-empty passphrase */ consoleline("Please enter PEM passphrase for private key:"); - while (!passphrase || !passphrase[0]) - { - if (passphrase) - free (passphrase); - passphrase = readline (""); - } + while (!passphrase || !passphrase[0]) { + if (passphrase) + free(passphrase); + passphrase = readline(""); + } /* reset redrawing function to default, reset consoleline */ rl_redisplay_function = vciredraw; consoleline(NULL); /* copy passphrase to buffer */ - strncpy (buf, passphrase, size); + strncpy(buf, passphrase, size); /* try to get readlines stats clean again */ - //rl_free_line_state (); - memset( rl_line_buffer, 0, rl_end ); + // rl_free_line_state (); + memset(rl_line_buffer, 0, rl_end); rl_point = rl_end = rl_done = 0; /* wipe input line and reset cursor */ - wmove (input, 0, 0); + wmove(input, 0, 0); for (i = 0; i < getmaxx(input) - 1; i++) - waddch (input, ' '); - wmove (input, 0, 0); - wrefresh (input); + waddch(input, ' '); + wmove(input, 0, 0); + wrefresh(input); /* return passphrase to OpenSSL */ - return strlen (buf); + return strlen(buf); } /* Filter stuff */ -static int -check_valid_colour( char colour ) { - return !( (colour !='-')&&(colour !='+') && (colour < '0' || colour > '9') && - (colour < 'A' || colour > 'Z' || !attributes[ colour-'A' ]) && - (colour < 'a' || colour > 'z' || !attributes[ colour-'a' ])); +static int check_valid_colour(char colour) { + return !((colour != '-') && (colour != '+') && + (colour < '0' || colour > '9') && + (colour < 'A' || colour > 'Z' || !attributes[colour - 'A']) && + (colour < 'a' || colour > 'z' || !attributes[colour - 'a'])); } - /* scans filterlist and removes possible matches test functions may return: RMFILTER_RMANDCONT @@ -1456,102 +1529,101 @@ check_valid_colour( char colour ) { RMFILTER_KEEPANDSTOP returns number of removed entries */ -static int -removefromfilterlist( int(*test)(filt *flt, void *data, char colour), void *data, char colour) { +static int removefromfilterlist(int (*test)(filt *flt, void *data, char colour), + void *data, char colour) { filt **flt = &filterlist, *tmp; - int removed = 0, stop = 0; - - while( *flt && !stop ) { - switch( test( *flt, data, colour ) ) { - case RMFILTER_RMANDSTOP: /* remove */ - stop = 1; - case RMFILTER_RMANDCONT: - snprintf( tmpstr, TMPSTRSIZE, " Removed ID: [% 3d] Color: [%c] Regex: [%s] ", (*flt)->id, (*flt)->colour, (*flt)->text); - writeout(tmpstr); - /* Release regex.h resources */ - regfree( &((*flt)->regex)); - /* free ASCII text memory */ - free( (*flt)->text); - /* unlink from list */ - tmp = *flt; - *flt = (*flt)->next; - /* free filter block itself */ - free( tmp ); - /* reflect changes on whole screen */ - removed++; - break; - case RMFILTER_KEEPANDSTOP: /* don't remove but stop scanning */ - stop = 1; - break; - default: - /* advance in list */ - if( *flt ) flt = &((*flt)->next); - break; - } + int removed = 0, stop = 0; + + while (*flt && !stop) { + switch (test(*flt, data, colour)) { + case RMFILTER_RMANDSTOP: /* remove */ + stop = 1; + case RMFILTER_RMANDCONT: + snprintf(tmpstr, TMPSTRSIZE, + " Removed ID: [% 3d] Color: [%c] Regex: [%s] ", (*flt)->id, + (*flt)->colour, (*flt)->text); + writeout(tmpstr); + /* Release regex.h resources */ + regfree(&((*flt)->regex)); + /* free ASCII text memory */ + free((*flt)->text); + /* unlink from list */ + tmp = *flt; + *flt = (*flt)->next; + /* free filter block itself */ + free(tmp); + /* reflect changes on whole screen */ + removed++; + break; + case RMFILTER_KEEPANDSTOP: /* don't remove but stop scanning */ + stop = 1; + break; + default: + /* advance in list */ + if (*flt) + flt = &((*flt)->next); + break; + } } /* return number of removed items */ return removed; } -static int -test_clear( filt *flt, void *data, char c ) { +static int test_clear(filt *flt, void *data, char c) { (void)data; - if( !c || ( c == flt->colour ) || ( (c == '*') && (flt->colour != '-') && (flt->colour != '+') ) ) - return RMFILTER_RMANDCONT; + if (!c || (c == flt->colour) || + ((c == '*') && (flt->colour != '-') && (flt->colour != '+'))) + return RMFILTER_RMANDCONT; else - return RMFILTER_KEEPANDCONT; + return RMFILTER_KEEPANDCONT; } -static int -test_simplerm( filt *flt, void *data, char colour) { - if( !strcmp( flt->text, (char*)data)) - return test_clear(flt, NULL, colour); +static int test_simplerm(filt *flt, void *data, char colour) { + if (!strcmp(flt->text, (char *)data)) + return test_clear(flt, NULL, colour); else - return RMFILTER_KEEPANDCONT; + return RMFILTER_KEEPANDCONT; } -static int -test_numericrm( filt *flt, void *data, char colour) { - if( flt->id == (long)data) - return test_clear(flt, NULL, colour); +static int test_numericrm(filt *flt, void *data, char colour) { + if (flt->id == (long)data) + return test_clear(flt, NULL, colour); else - return RMFILTER_KEEPANDCONT; + return RMFILTER_KEEPANDCONT; } /* clears filter list */ -void -clearfilters( char colour ) { - flushout( ); - if( removefromfilterlist( test_clear, NULL, colour ) ) { - /* There actually WERE items removed */ - filtertype = analyzefilters( ); +void clearfilters(char colour) { + flushout(); + if (removefromfilterlist(test_clear, NULL, colour)) { + /* There actually WERE items removed */ + filtertype = analyzefilters(); } else { - writeout(" No matches on filter list. "); + writeout(" No matches on filter list. "); } showout(); } /* removes filter pattern */ -void -removefilter( char *tail ) { +void removefilter(char *tail) { int rmv = 0, val; - char* end; + char *end; - flushout( ); + flushout(); - rmv = removefromfilterlist( test_simplerm, (void *)tail, 0 ); - if(!rmv) { - val = strtol(tail, &end, 10); - if( (tail != end) && (!*end) ) - rmv = removefromfilterlist( test_numericrm, (void *)(uintptr_t)val, 0); + rmv = removefromfilterlist(test_simplerm, (void *)tail, 0); + if (!rmv) { + val = strtol(tail, &end, 10); + if ((tail != end) && (!*end)) + rmv = removefromfilterlist(test_numericrm, (void *)(uintptr_t)val, 0); } - if( rmv ) { - /* There actually WERE items removed */ - filtertype = analyzefilters( ); + if (rmv) { + /* There actually WERE items removed */ + filtertype = analyzefilters(); } else { - snprintf( tmpstr, TMPSTRSIZE, " Not on filter list: %s ", tail); - writeout( tmpstr ); + snprintf(tmpstr, TMPSTRSIZE, " Not on filter list: %s ", tail); + writeout(tmpstr); } showout(); } @@ -1559,139 +1631,158 @@ removefilter( char *tail ) { static unsigned int uniqueidpool = 1; /* returns unique id for filter pattern or 0 for failure */ -unsigned int -addfilter( char colour, char *regex ) { - filt *newflt = malloc( sizeof(filt)), **flt = &filterlist; +unsigned int addfilter(char colour, char *regex) { + filt *newflt = malloc(sizeof(filt)), **flt = &filterlist; - if( !newflt ) return 0; - flushout( ); + if (!newflt) + return 0; + flushout(); /* check colour validity */ - if( !check_valid_colour( colour ) ){ - free( newflt ); - writeout( " Not a valid colour code. " ); - showout( ); - return 0; + if (!check_valid_colour(colour)) { + free(newflt); + writeout(" Not a valid colour code. "); + showout(); + return 0; } - if( regcomp( &newflt->regex, regex, REG_ICASE | REG_EXTENDED | REG_NEWLINE) ) { - /* couldn't compile regex ... print error, return */ - free( newflt ); + if (regcomp(&newflt->regex, regex, REG_ICASE | REG_EXTENDED | REG_NEWLINE)) { + /* couldn't compile regex ... print error, return */ + free(newflt); - snprintf( tmpstr, TMPSTRSIZE, " %s ", regex); - writeout( " Bad regular expression: "); - writeout( tmpstr ); - showout( ); - return 0; + snprintf(tmpstr, TMPSTRSIZE, " %s ", regex); + writeout(" Bad regular expression: "); + writeout(tmpstr); + showout(); + return 0; } else { - int len = strlen(regex) + 1; - /* grab id from ID pool an increase free ID counter */ - newflt->id = uniqueidpool++; - newflt->colour = colour; - newflt->next = NULL; - /* take a copy of plain regex text for later identification by user */ - newflt->text = malloc( len ); - memcpy( newflt->text, regex, len ); + int len = strlen(regex) + 1; + /* grab id from ID pool an increase free ID counter */ + newflt->id = uniqueidpool++; + newflt->colour = colour; + newflt->next = NULL; + /* take a copy of plain regex text for later identification by user */ + newflt->text = malloc(len); + memcpy(newflt->text, regex, len); } /* append new filter to filterlist */ - while( *flt ) flt=&((*flt)->next); + while (*flt) + flt = &((*flt)->next); *flt = newflt; - filtertype = analyzefilters( ); + filtertype = analyzefilters(); - if ( colour == '-' ) { - snprintf( tmpstr, TMPSTRSIZE, " \"%s\" successfully added to ignorance list. ( ID = %d). ", (*flt)->text, (*flt)->id); - } else if( colour == '+' ) { - snprintf( tmpstr, TMPSTRSIZE, " \"%s\" successfully added to zoom list. ( ID = %d). ", (*flt)->text, (*flt)->id); + if (colour == '-') { + snprintf(tmpstr, TMPSTRSIZE, + " \"%s\" successfully added to ignorance list. ( ID = %d). ", + (*flt)->text, (*flt)->id); + } else if (colour == '+') { + snprintf(tmpstr, TMPSTRSIZE, + " \"%s\" successfully added to zoom list. ( ID = %d). ", + (*flt)->text, (*flt)->id); } else { - snprintf( tmpstr, TMPSTRSIZE, " \"%s\" successfully added to hilitelist. (ID = %d). ", (*flt)->text, (*flt)->id); + snprintf(tmpstr, TMPSTRSIZE, + " \"%s\" successfully added to hilitelist. (ID = %d). ", + (*flt)->text, (*flt)->id); } - writeout(tmpstr ); - showout( ); + writeout(tmpstr); + showout(); return newflt->id; } -void -listfilters( void ) { - filt *flt = filterlist; - int shownhi = 0, shownign = 0, shownzoom = 0; +void listfilters(void) { + filt *flt = filterlist; + int shownhi = 0, shownign = 0, shownzoom = 0; - flushout( ); + flushout(); - while( flt ) { - if( (flt->colour != '-') && (flt->colour != '+')) { - if(!shownhi) { - writeout(" Your hilites:"); - shownhi = 1; - } - snprintf( tmpstr, TMPSTRSIZE, " ID: [% 3d] Color: [%c] Regex: [%s]", flt->id, flt->colour, flt->text); - writeout( tmpstr ); + while (flt) { + if ((flt->colour != '-') && (flt->colour != '+')) { + if (!shownhi) { + writeout(" Your hilites:"); + shownhi = 1; } - flt = flt->next; + snprintf(tmpstr, TMPSTRSIZE, " ID: [% 3d] Color: [%c] Regex: [%s]", + flt->id, flt->colour, flt->text); + writeout(tmpstr); + } + flt = flt->next; } flt = filterlist; - while( flt ) { - if( flt->colour == '-') { - if(!shownign) { - if(shownhi) writeout(" "); - writeout(" You do ignore:"); - shownign = 1; - } - snprintf( tmpstr, TMPSTRSIZE, " ID: [% 3d] Regex: [%s]", flt->id, flt->text); - writeout( tmpstr ); + while (flt) { + if (flt->colour == '-') { + if (!shownign) { + if (shownhi) + writeout(" "); + writeout(" You do ignore:"); + shownign = 1; } - flt = flt->next; + snprintf(tmpstr, TMPSTRSIZE, " ID: [% 3d] Regex: [%s]", + flt->id, flt->text); + writeout(tmpstr); + } + flt = flt->next; } flt = filterlist; - while( flt ) { - if( flt->colour == '+') { - if(!shownzoom) { - if(shownhi || shownign) writeout(" "); - writeout(" On your whitelist:"); - shownzoom = 1; - } - snprintf( tmpstr, TMPSTRSIZE, " ID: [% 3d] Regex: [%s]", flt->id, flt->text); - writeout( tmpstr ); + while (flt) { + if (flt->colour == '+') { + if (!shownzoom) { + if (shownhi || shownign) + writeout(" "); + writeout(" On your whitelist:"); + shownzoom = 1; } - flt = flt->next; + snprintf(tmpstr, TMPSTRSIZE, " ID: [% 3d] Regex: [%s]", + flt->id, flt->text); + writeout(tmpstr); + } + flt = flt->next; } - if( !shownign && !shownhi && !shownzoom) { - writeout(" No entries on your filter list. "); + if (!shownign && !shownhi && !shownzoom) { + writeout(" No entries on your filter list. "); } showout(); } -void -handlequery( char *tail ) { - if( *tail ) { +void handlequery(char *tail) { + if (*tail) { // ".m %s " -> string + 4 - if( querypartner && private ) { - WINDOW *tmp= private; private = channel; channel = tmp; + if (querypartner && private) { + WINDOW *tmp = private; + private + = channel; + channel = tmp; } - querypartner = (char *)realloc( querypartner, 5 + strlen( tail )); - if( querypartner ) { - snprintf( querypartner, 5 + strlen( tail ), ".m %s ", tail ); - if( private ) { - WINDOW *tmp= private; private = channel; channel = tmp; + querypartner = (char *)realloc(querypartner, 5 + strlen(tail)); + if (querypartner) { + snprintf(querypartner, 5 + strlen(tail), ".m %s ", tail); + if (private) { + WINDOW *tmp = private; + private + = channel; + channel = tmp; } } - resize( 0 ); + resize(0); } else { // QUERY ends - if( querypartner ) { - free( querypartner ); + if (querypartner) { + free(querypartner); querypartner = NULL; - if( private ) { - WINDOW *tmp= private; private = channel; channel = tmp; + if (private) { + WINDOW *tmp = private; + private + = channel; + channel = tmp; } - resize( 0 ); + resize(0); } } } diff --git a/vchat-user.c b/vchat-user.c index 881a3cf..1ab2048 100755 --- a/vchat-user.c +++ b/vchat-user.c @@ -3,42 +3,48 @@ */ +#include #include +#include #include #include -#include #include -#include + #include -#include "vchat.h" #include "vchat-user.h" +#include "vchat.h" /* version of this module */ -char *vchat_us_version = "vchat-user.c $Id$"; - -typedef struct -{ - char *nick; - enum { UL_NONE = 0x00, UL_ME = 0x01, UL_IN_MY_CHAN = 0x02, UL_NOT_IN_LIST = 0x04 } flags; +char *vchat_us_version = + "vchat-user.c $Id$"; + +typedef struct { + char *nick; + enum { + UL_NONE = 0x00, + UL_ME = 0x01, + UL_IN_MY_CHAN = 0x02, + UL_NOT_IN_LIST = 0x04 + } flags; uint64_t last_public; uint64_t last_private; } user; -static user *g_users; //< all users, incl self -static size_t g_users_count; //< number of users in list -static char *g_nick; //< own nick -static int g_channel; //< own channel -unsigned int ul_case_first = 0; +static user *g_users; //< all users, incl self +static size_t g_users_count; //< number of users in list +static char *g_nick; //< own nick +static int g_channel; //< own channel +unsigned int ul_case_first = 0; -static char **g_dict; -static size_t g_dict_len; +static char **g_dict; +static size_t g_dict_len; -static int ul_nick_lookup( const char *nick, int *exact_match ) { +static int ul_nick_lookup(const char *nick, int *exact_match) { int i; *exact_match = 1; - for( i=0; i= 0 ) { + base = ul_add(nick, 0); + if (base >= 0) { g_users[base].flags |= UL_ME; g_nick = g_users[base].nick; } } else - ul_del( g_nick ); + ul_del(g_nick); setstroption(CF_NICK, nick); } -void own_channel_set( int channel ) { - if( channel != g_channel ) { +void own_channel_set(int channel) { + if (channel != g_channel) { /* Remove all users from my chan, will be re-set on join message */ int i; - for( i=0; i= 0 ) { - free( g_users[base].nick ); - g_users[base].nick = strdup( newname ); - if( g_users[base].flags & UL_ME ) + int base = ul_add(oldname, -1); + if (base >= 0) { + free(g_users[base].nick); + g_users[base].nick = strdup(newname); + if (g_users[base].flags & UL_ME) g_nick = g_users[base].nick; - if( g_users[base].flags & UL_IN_MY_CHAN ) + if (g_users[base].flags & UL_IN_MY_CHAN) ul_public_action(newname); } return base; @@ -156,23 +170,23 @@ int ul_rename(char *oldname, char *newname) { void ul_clear() { int i; - for( i=0; i= 0 ) + if (base >= 0) ul_public_action(name); /* Reflect in UI */ - if( own_nick_check( name ) ) - ownjoin( g_channel ); + if (own_nick_check(name)) + ownjoin(g_channel); } void ul_private_action(char *name) { /* Ensure user and keep channel state */ int base = ul_add(name, -1); - if( base >= 0 ) + if (base >= 0) g_users[base].last_private = ul_now(); } void ul_public_action(char *name) { /* Ensure user and put him on the channel */ int base = ul_add(name, 1); - if( base >= 0 ) + if (base >= 0) g_users[base].last_public = ul_now(); } void ul_add_to_dict(char *dict_items) { char *i; - for(i=strtok(dict_items," ");i;i=strtok(0," ")) { - g_dict = realloc( g_dict, sizeof(char*) * ( 1 + g_dict_len ) ); - if( !g_dict ) exit(1); + for (i = strtok(dict_items, " "); i; i = strtok(0, " ")) { + g_dict = realloc(g_dict, sizeof(char *) * (1 + g_dict_len)); + if (!g_dict) + exit(1); g_dict[g_dict_len++] = strdup(i); } } /* Finding users ul_finduser? */ -char * ul_match_user(char *regex) { - char *dest = tmpstr; - int i; - regex_t preg; +char *ul_match_user(char *regex) { + char *dest = tmpstr; + int i; + regex_t preg; *dest = 0; - if( !regcomp( &preg, regex, REG_ICASE | REG_EXTENDED | REG_NEWLINE)) { + if (!regcomp(&preg, regex, REG_ICASE | REG_EXTENDED | REG_NEWLINE)) { /* does the username match? */ /* XXX overflow for too many matches */ - for( i=0; ilast_private > _b->last_private ) return -1; + if (_a->last_private > _b->last_private) + return -1; return 1; } -static int ul_compare_begin_of_line_ncase( const void *a, const void *b ) { +static int ul_compare_begin_of_line_ncase(const void *a, const void *b) { const user *_a = (const user *)a, *_b = (const user *)b; size_t tmpstr_len; int a_i, b_i; /* First ensure that users in current channel win */ - if( !(_a->flags & UL_IN_MY_CHAN ) ) return 1; - if( !(_b->flags & UL_IN_MY_CHAN ) ) return -1; - - tmpstr_len = strlen( tmpstr ); - a_i = strncasecmp( _a->nick, tmpstr, tmpstr_len ); - b_i = strncasecmp( _b->nick, tmpstr, tmpstr_len ); - - if( a_i && b_i ) return 0; // Both nicks dont match - if( !a_i && b_i ) return -1; // a matches insensitive, b doesnt - if( a_i && !b_i ) return 1; // b matches insensitive, a doesnt + if (!(_a->flags & UL_IN_MY_CHAN)) + return 1; + if (!(_b->flags & UL_IN_MY_CHAN)) + return -1; + + tmpstr_len = strlen(tmpstr); + a_i = strncasecmp(_a->nick, tmpstr, tmpstr_len); + b_i = strncasecmp(_b->nick, tmpstr, tmpstr_len); + + if (a_i && b_i) + return 0; // Both nicks dont match + if (!a_i && b_i) + return -1; // a matches insensitive, b doesnt + if (a_i && !b_i) + return 1; // b matches insensitive, a doesnt /* From here both nicks match the prefix, ensure that own_nick always appears last */ - if( _a->flags & UL_ME ) return 1; - if( _b->flags & UL_ME ) return -1; + if (_a->flags & UL_ME) + return 1; + if (_b->flags & UL_ME) + return -1; /* Now the user with the most recent public activity wins */ - if( _a->last_public > _b->last_public ) return -1; + if (_a->last_public > _b->last_public) + return -1; return 1; } -static int ul_compare_begin_of_line_case( const void *a, const void *b ) { +static int ul_compare_begin_of_line_case(const void *a, const void *b) { const user *_a = (const user *)a, *_b = (const user *)b; size_t tmpstr_len; int a_i, b_i, a_s, b_s; /* First ensure that users in current channel win */ - if( !(_a->flags & UL_IN_MY_CHAN ) ) return 1; - if( !(_b->flags & UL_IN_MY_CHAN ) ) return -1; - - tmpstr_len = strlen( tmpstr ); - a_i = strncasecmp( _a->nick, tmpstr, tmpstr_len ); - a_s = strncmp ( _a->nick, tmpstr, tmpstr_len ); - b_i = strncasecmp( _b->nick, tmpstr, tmpstr_len ); - b_s = strncmp ( _b->nick, tmpstr, tmpstr_len ); - - if( a_i && b_i ) return 0; // Both nicks dont match at all - if( !a_i && b_i ) return -1; // a matches insensitive, b doesnt - if( a_i && !b_i ) return 1; // b matches insensitive, a doesnt - - if( !a_s && b_s ) return -1; // a matches sensitive, b doesnt - if( a_s && !b_s ) return 1; // b matches sensitive, a doesnt + if (!(_a->flags & UL_IN_MY_CHAN)) + return 1; + if (!(_b->flags & UL_IN_MY_CHAN)) + return -1; + + tmpstr_len = strlen(tmpstr); + a_i = strncasecmp(_a->nick, tmpstr, tmpstr_len); + a_s = strncmp(_a->nick, tmpstr, tmpstr_len); + b_i = strncasecmp(_b->nick, tmpstr, tmpstr_len); + b_s = strncmp(_b->nick, tmpstr, tmpstr_len); + + if (a_i && b_i) + return 0; // Both nicks dont match at all + if (!a_i && b_i) + return -1; // a matches insensitive, b doesnt + if (a_i && !b_i) + return 1; // b matches insensitive, a doesnt + + if (!a_s && b_s) + return -1; // a matches sensitive, b doesnt + if (a_s && !b_s) + return 1; // b matches sensitive, a doesnt /* From now we know that both match with same quality, ensure that own nick always appears last */ - if( _a->flags & UL_ME ) return 1; - if( _b->flags & UL_ME ) return -1; + if (_a->flags & UL_ME) + return 1; + if (_b->flags & UL_ME) + return -1; /* Now the user with the most recent public activity wins */ - if( _a->last_public > _b->last_public ) return -1; + if (_a->last_public > _b->last_public) + return -1; return 1; } -static int ul_compare_middle_ncase( const void *a, const void *b ) { +static int ul_compare_middle_ncase(const void *a, const void *b) { const user *_a = (const user *)a, *_b = (const user *)b; /* Ensure that own nick appears last in list */ - if( _a->flags & UL_ME ) return 1; - if( _b->flags & UL_ME ) return -1; + if (_a->flags & UL_ME) + return 1; + if (_b->flags & UL_ME) + return -1; - return strcasecmp( _a->nick, _b->nick ); + return strcasecmp(_a->nick, _b->nick); } -static int ul_compare_middle_case( const void *a, const void *b ) { +static int ul_compare_middle_case(const void *a, const void *b) { const user *_a = (const user *)a, *_b = (const user *)b; size_t tmpstr_len; int a_s, b_s; /* Ensure that own nick appears last in list */ - if( _a->flags & UL_ME ) return 1; - if( _b->flags & UL_ME ) return -1; + if (_a->flags & UL_ME) + return 1; + if (_b->flags & UL_ME) + return -1; - tmpstr_len = strlen( tmpstr ); - a_s = strncmp( _a->nick, tmpstr, tmpstr_len ); - b_s = strncmp( _b->nick, tmpstr, tmpstr_len ); + tmpstr_len = strlen(tmpstr); + a_s = strncmp(_a->nick, tmpstr, tmpstr_len); + b_s = strncmp(_b->nick, tmpstr, tmpstr_len); - if( !a_s && b_s ) return -1; // a matches sensitive, b doesnt - if( a_s && !b_s ) return 1; // b matches sensitive, a doesnt + if (!a_s && b_s) + return -1; // a matches sensitive, b doesnt + if (a_s && !b_s) + return 1; // b matches sensitive, a doesnt /* From now both strings either both or both dont match decide their position by case insensitive match */ - return strcasecmp( _a->nick, _b->nick ); + return strcasecmp(_a->nick, _b->nick); } /* Nick completion function for readline */ -char **ul_complete_user(char *text, int start, int end ) { +char **ul_complete_user(char *text, int start, int end) { char **result = 0; - int i, result_count = 0, dict_result_count = 0; + int i, result_count = 0, dict_result_count = 0; /* Never want readline to complete filenames */ rl_attempted_completion_over = 1; /* Check for amount of custom dict matches */ - if( end && ( start != end ) ) - for( i=0; i 0 ) { + } else if (start == 0 && end > 0) { /* Completion on begin of line with some chars already typed yields a list of everyone in channel, matching prefix, sorted by last public activity */ - snprintf( tmpstr, end + 1, "%s", text ); - if( ul_case_first ) - qsort( g_users, g_users_count, sizeof(user), ul_compare_begin_of_line_case ); + snprintf(tmpstr, end + 1, "%s", text); + if (ul_case_first) + qsort(g_users, g_users_count, sizeof(user), + ul_compare_begin_of_line_case); else - qsort( g_users, g_users_count, sizeof(user), ul_compare_begin_of_line_ncase ); + qsort(g_users, g_users_count, sizeof(user), + ul_compare_begin_of_line_ncase); - for( i=0; i and thus should complete all users, sorted alphabetically without preferences. */ - snprintf( tmpstr, end - start + 1, "%s", text ); - if( ul_case_first ) - qsort( g_users, g_users_count, sizeof(user), ul_compare_middle_case ); + snprintf(tmpstr, end - start + 1, "%s", text); + if (ul_case_first) + qsort(g_users, g_users_count, sizeof(user), ul_compare_middle_case); else - qsort( g_users, g_users_count, sizeof(user), ul_compare_middle_ncase ); + qsort(g_users, g_users_count, sizeof(user), ul_compare_middle_ncase); - for( i=0; i