From: Hugo Villeneuve Date: Sat, 25 May 2013 13:20:06 +0000 (-0400) Subject: Indentation with GNU indent X-Git-Url: http://gitweb.hugovil.com/?a=commitdiff_plain;h=a6c4c0c8d8224cdc455f0d184e91d0cf881f0077;p=dockapps%2Fwmnotify.git Indentation with GNU indent Fixed warnings issued by checkpath.pl --- diff --git a/src/Makefile.am b/src/Makefile.am index a21af49..067e08f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,4 +12,4 @@ DISTCLEANFILES = .deps/*.P MAINTAINERCLEANFILES = Makefile.in # we want these in the dist tarball -EXTRA_DIST = +EXTRA_DIST = diff --git a/src/common.h b/src/common.h index a460d27..0b16fe4 100644 --- a/src/common.h +++ b/src/common.h @@ -47,12 +47,10 @@ #define STREQ_LEN(a, b, c) (strncmp((a), (b), (c)) == 0) -inline void -ErrorLocation( const char *file, int line ); +inline void ErrorLocation(const char *file, int line); -/*@out@*/ /*@only@*/ -void * -xmalloc( size_t size, const char *filename, int line_number ); + /*@out@*//*@only@ */ +void *xmalloc(size_t size, const char *filename, int line_number); -#endif /* COMMON_H */ +#endif /* COMMON_H */ diff --git a/src/configfile.c b/src/configfile.c index 58134e8..be8f77a 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -40,388 +40,418 @@ #include "wmnotify.h" #include "configfile.h" - #define LINE_BUFFER_LEN 256 /* Name of configuration file in user's home directory. */ -const static char default_config_filename[] = ".wmnotifyrc"; -const static char delimiter_single_arg[] = " \n"; -const static char delimiter_multiple_arg[] = "#\n"; - +static const char default_config_filename[] = ".wmnotifyrc"; +static const char delimiter_single_arg[] = " \n"; +static const char delimiter_multiple_arg[] = "#\n"; -static void -CreateDefaultConfigurationFile( char *file ) +static void CreateDefaultConfigurationFile(char *file) { - int status; - FILE *fp; - - fp = fopen( file, "w" ); - if( fp == NULL ) { - fprintf( stderr, "%s: Can't create file \"%s\"\n", PACKAGE, file ); - exit( EXIT_FAILURE ); - } - - /* Changing permissions so that only the user can read/modify the file. */ - status = chmod( file, S_IRUSR | S_IWUSR ); - if( status < 0 ) { - fprintf( stderr, "%s: Can't set permission bits on file \"%s\"\n", PACKAGE, file ); - exit( EXIT_FAILURE ); - } - - fprintf( fp, "# ~/.wmnotifyrc -- Default configuration file for wmnotify\n\n" ); - fprintf( fp, "# Replace all 'xxxxxxxx' fields with your own settings.\n\n" ); - fprintf( fp, "# Parameters preceded by a '#' character are optional.\n" ); - fprintf( fp, "# You can set their values by removing the leading '#'.\n\n" ); - fprintf( fp, "# Mail Protocol: POP3 or IMAP4.\n" ); - fprintf( fp, "protocol POP3\n\n" ); - fprintf( fp, "# Use SSL encrytion: 0=disable, 1=enable (optional, default is " - "disabled).\n" ); - fprintf( fp, "use_ssl 0\n\n" ); - fprintf( fp, "# Mail Server Name.\n" ); - fprintf( fp, "server xxxxxxxx\n\n" ); - fprintf( fp, "# Mail Server Port Number (optional, default is 110).\n" ); - fprintf( fp, "port 110\n\n" ); - fprintf( fp, "# Username.\n" ); - fprintf( fp, "username xxxxxxxx\n\n" ); - fprintf( fp, "# Password.\n" ); - fprintf( fp, "password xxxxxxxx\n\n" ); - fprintf( fp, "# IMAP folder name (optional, default is INBOX).\n" ); - fprintf( fp, "# folder INBOX.some_folder\n\n" ); - fprintf( fp, "# Mail Check Interval (in minutes, default is 5 minutes).\n" ); - fprintf( fp, "#mailcheckdelay 5\n\n" ); - fprintf( fp, "# Default mail client (optional).\n" ); - fprintf( fp, "#mailclient sylpheed\n\n" ); - fprintf( fp, "# Audio notification, 0=disable, 1=enable (optional, default is " - "disabled).\n" ); - fprintf( fp, "enablebeep 0\n\n" ); - fprintf( fp, "# Location of sound file for audio notification. If no sound file is\n" ); - fprintf( fp, "# specified, the console beep will be used instead.\n" ); - fprintf( fp, "audiofile /usr/local/share/sounds/halmsgs.wav\n\n" ); - fprintf( fp, "# Volume (0 to 100%%).\n" ); - fprintf( fp, "volume 100\n" ); - - fprintf( stderr, "%s: A default configuration file has been created in your " - "home directory: \"%s\"\n", PACKAGE, file ); - fprintf( stderr, "You must edit it before running %s.\n", PACKAGE ); - - status = fclose( fp ); - if( status != EXIT_SUCCESS ) { - fprintf( stderr, "%s: Error closing file \"%s\"\n", PACKAGE, file ); - } + int status; + FILE *fp; + + fp = fopen(file, "w"); + if (fp == NULL) { + fprintf(stderr, "%s: Can't create file \"%s\"\n", PACKAGE, + file); + exit(EXIT_FAILURE); + } + + /* + * Changing permissions so that only the user can read/modify the file + */ + status = chmod(file, S_IRUSR | S_IWUSR); + if (status < 0) { + fprintf(stderr, + "%s: Can't set permission bits on file \"%s\"\n", + PACKAGE, file); + exit(EXIT_FAILURE); + } + + fprintf(fp, + "# ~/.wmnotifyrc -- Default configuration file for wmnotify\n\n"); + fprintf(fp, + "# Replace all 'xxxxxxxx' fields with your own settings.\n\n"); + fprintf(fp, + "# Parameters preceded by a '#' character are optional.\n"); + fprintf(fp, + "# You can set their values by removing the leading '#'.\n\n"); + fprintf(fp, "# Mail Protocol: POP3 or IMAP4.\n"); + fprintf(fp, "protocol POP3\n\n"); + fprintf(fp, + "# Use SSL encrytion: 0=disable, 1=enable (optional, default is " + "disabled).\n"); + fprintf(fp, "use_ssl 0\n\n"); + fprintf(fp, "# Mail Server Name.\n"); + fprintf(fp, "server xxxxxxxx\n\n"); + fprintf(fp, + "# Mail Server Port Number (optional, default is 110).\n"); + fprintf(fp, "port 110\n\n"); + fprintf(fp, "# Username.\n"); + fprintf(fp, "username xxxxxxxx\n\n"); + fprintf(fp, "# Password.\n"); + fprintf(fp, "password xxxxxxxx\n\n"); + fprintf(fp, "# IMAP folder name (optional, default is INBOX).\n"); + fprintf(fp, "# folder INBOX.some_folder\n\n"); + fprintf(fp, + "# Mail Check Interval (in minutes, default is 5 minutes).\n"); + fprintf(fp, "#mailcheckdelay 5\n\n"); + fprintf(fp, "# Default mail client (optional).\n"); + fprintf(fp, "#mailclient sylpheed\n\n"); + fprintf(fp, + "# Audio notification, 0=disable, 1=enable (optional, default is " + "disabled).\n"); + fprintf(fp, "enablebeep 0\n\n"); + fprintf(fp, + "# Location of sound file for audio notification. If no sound file is\n"); + fprintf(fp, + "# specified, the console beep will be used instead.\n"); + fprintf(fp, "audiofile /usr/local/share/sounds/halmsgs.wav\n\n"); + fprintf(fp, "# Volume (0 to 100%%).\n"); + fprintf(fp, "volume 100\n"); + + fprintf(stderr, + "%s: A default configuration file has been created in your " + "home directory: \"%s\"\n", PACKAGE, file); + fprintf(stderr, "You must edit it before running %s.\n", PACKAGE); + + status = fclose(fp); + if (status != EXIT_SUCCESS) { + fprintf(stderr, "%s: Error closing file \"%s\"\n", PACKAGE, + file); + } } -static void -ParseCommand( char *line, /*@out@*/ char *argv[] ) +static void ParseCommand(char *line, /*@out@ */ char *argv[]) { - int argc = 0; - - while( *line != '\0' ) { /* if not the end of line ....... */ - while( *line == ' ' || *line == '\t' || *line == '\n' ) { - *line++ = '\0'; /* replace white spaces with 0 */ - } - *argv++ = line; /* save the argument position */ - while( *line != '\0' && *line != ' ' && *line != '\t' && *line != '\n' ) { - line++; /* skip the argument until ... */ - } - - argc++; - - if( argc == ARGV_LIMIT ) { - fprintf( stderr, "%s: Too much arguments for external command\n", - PACKAGE ); - exit( EXIT_FAILURE ); - } - } - - *argv = NULL; /* mark the end of argument list */ + int argc = 0; + + while (*line != '\0') { /* if not the end of line ....... */ + while (*line == ' ' || *line == '\t' || *line == '\n') + *line++ = '\0'; /* replace white spaces with 0 */ + + *argv++ = line; /* save the argument position */ + while (*line != '\0' && *line != ' ' && *line != '\t' + && *line != '\n') { + line++; /* skip the argument until ... */ + } + + argc++; + + if (argc == ARGV_LIMIT) { + fprintf(stderr, + "%s: Too much arguments for external command\n", + PACKAGE); + exit(EXIT_FAILURE); + } + } + + *argv = NULL; /* mark the end of argument list */ } -static char * -GetArguments( char *parameter, bool single_argument ) +static char *GetArguments(char *parameter, bool single_argument) { - char *token; - - if( single_argument ) { - token = strtok( NULL, delimiter_single_arg ); - } - else { - /* We search for a string terminated by either a '#' character (the rest of - the line is then a comment, which is simply ignored ), or the end of line - character '\n'. */ - token = strtok( NULL, delimiter_multiple_arg ); - } - - if( token == NULL ) { - fprintf( stderr, "%s: Missing argument for \"%s\" parameter in " - "configuration file.\n", PACKAGE, parameter ); - exit( EXIT_FAILURE ); - } - - return token; + char *token; + + if (single_argument) { + token = strtok(NULL, delimiter_single_arg); + } else { + /* + * We search for a string terminated by either a '#' character + * (the rest of the line is then a comment, which is simply + * ignored ), or the end of line character '\n'. + */ + token = strtok(NULL, delimiter_multiple_arg); + } + + if (token == NULL) { + fprintf(stderr, + "%s: Missing argument for \"%s\" parameter in " + "configuration file.\n", PACKAGE, parameter); + exit(EXIT_FAILURE); + } + + return token; } -static int -GetNumber( char *token, char *parameter ) +static int GetNumber(char *token, char *parameter) { - char temp[32]; /* Check size ??? */ - - if( sscanf( token, "%[0123456789]", temp ) == 0 ) { - fprintf( stderr, "%s: Invalid argument for \"%s\" parameter in " - "configuration file.\n", PACKAGE, parameter ); - exit( EXIT_FAILURE ); - } - - return atoi( temp ); -} + char temp[32]; /* Check size ??? */ + if (sscanf(token, "%[0123456789]", temp) == 0) { + fprintf(stderr, + "%s: Invalid argument for \"%s\" parameter in " + "configuration file.\n", PACKAGE, parameter); + exit(EXIT_FAILURE); + } + + return atoi(temp); +} -static void -ParseConfigurationFile( FILE *file ) +static void ParseConfigurationFile(FILE *file) { - char line[LINE_BUFFER_LEN]; - char *token; - bool protocol_found = false; - bool server_found = false; - bool username_found = false; - bool password_found = false; - const char *err_string = NULL; - - /* Default values for optional parameters. */ - strcpy( wmnotify_infos.imap_folder, "INBOX"); /* Default IMAP folder. */ - wmnotify_infos.port = 110; - wmnotify_infos.mail_check_interval = 60; /* 1 minute interval. */ - wmnotify_infos.audible_notification = false; /* Disabled. */ - wmnotify_infos.use_ssl = false; /* Disabled. */ - wmnotify_infos.mail_client_argv[0] = NULL; /* No default command. */ - wmnotify_infos.audiofile[0] = '\0'; /* No default audio file. */ - wmnotify_infos.volume = 100; /* 100% volume. */ - - /* Reading one line of data from the configuration file. */ - /* char *fgets(char *s, int size, FILE *stream); - Reading stops after an EOF or a newline. If a newline is read, it is - stored into the buffer. A '\0' is stored after the last character in - the buffer. */ - while( fgets( line, LINE_BUFFER_LEN, file ) != NULL ) { - token = strtok( line, delimiter_single_arg ); - - if( ( token == NULL ) || ( token[0] == '#' ) ) { - continue; /* Next iteration of the while() loop (next line). */ - } - - if( STREQ( token, "protocol" ) ) { - token = GetArguments( "protocol", true ); - if( STREQ( token, "POP3" ) == true ) { - wmnotify_infos.protocol = POP3_PROTOCOL; - } - else if( STREQ( token, "IMAP4" ) == true ) { - wmnotify_infos.protocol = IMAP4_PROTOCOL; - } - else { - fprintf( stderr, "%s: protocol must be POP3 or IMAP4.\n", PACKAGE ); - exit( EXIT_FAILURE ); - } - - protocol_found = true; - } - else if( STREQ( token, "imap_folder" ) ) { - token = GetArguments( "imap_folder", true ); - /* Should check size before using strcpy(), or use strncopy() instead. */ - strcpy( wmnotify_infos.imap_folder, token ); - } - else if( STREQ( token, "use_ssl" ) ){ - int number; - - token = GetArguments( "use_ssl", true ); - number = GetNumber( token, "use_ssl" ); - if( number == 0 ) { - wmnotify_infos.use_ssl = false; - } - else if( number == 1 ) { + char line[LINE_BUFFER_LEN]; + char *token; + bool protocol_found = false; + bool server_found = false; + bool username_found = false; + bool password_found = false; + const char *err_string = NULL; + + /* Default values for optional parameters. */ + strcpy(wmnotify_infos.imap_folder, "INBOX"); /* Default IMAP folder. */ + wmnotify_infos.port = 110; + wmnotify_infos.mail_check_interval = 60; /* 1 minute interval. */ + wmnotify_infos.audible_notification = false; /* Disabled. */ + wmnotify_infos.use_ssl = false; /* Disabled. */ + wmnotify_infos.mail_client_argv[0] = NULL; /* No default command. */ + wmnotify_infos.audiofile[0] = '\0'; /* No default audio file. */ + wmnotify_infos.volume = 100; /* 100% volume. */ + + /* + * Reading one line of data from the configuration file. + * char *fgets(char *s, int size, FILE *stream); + * Reading stops after an EOF or a newline. If a newline is read, it is + * stored into the buffer. A '\0' is stored after the last character + * in the buffer. + */ + while (fgets(line, LINE_BUFFER_LEN, file) != NULL) { + token = strtok(line, delimiter_single_arg); + + if ((token == NULL) || (token[0] == '#')) { + continue; /* + * Next iteration of the while() loop (next + * line). + */ + } + + if (STREQ(token, "protocol")) { + token = GetArguments("protocol", true); + if (STREQ(token, "POP3") == true) { + wmnotify_infos.protocol = POP3_PROTOCOL; + } else if (STREQ(token, "IMAP4") == true) { + wmnotify_infos.protocol = IMAP4_PROTOCOL; + } else { + fprintf(stderr, + "%s: protocol must be POP3 or IMAP4.\n", + PACKAGE); + exit(EXIT_FAILURE); + } + + protocol_found = true; + } else if (STREQ(token, "imap_folder")) { + token = GetArguments("imap_folder", true); + /* + * Should check size before using strcpy(), or use + * strncopy() instead. + */ + strcpy(wmnotify_infos.imap_folder, token); + } else if (STREQ(token, "use_ssl")) { + int number; + + token = GetArguments("use_ssl", true); + number = GetNumber(token, "use_ssl"); + if (number == 0) { + wmnotify_infos.use_ssl = false; + } else if (number == 1) { #if HAVE_SSL - wmnotify_infos.use_ssl = true; + wmnotify_infos.use_ssl = true; #else - fprintf( stderr, "%s error: You must compile %s with SSL support to\n" \ - "set parameter 'use_ssl' to true in configuration file\n", PACKAGE, PACKAGE ); - exit( EXIT_FAILURE ); + fprintf(stderr, + "%s error: You must compile %s with SSL support to\n" + "set parameter 'use_ssl' to true in configuration file\n", + PACKAGE, PACKAGE); + exit(EXIT_FAILURE); #endif - } - else { - fprintf( stderr, "%s: Invalid value for parameter 'use_ssl' in\n" \ - "configuration file (must be 0 or 1): %d\n", PACKAGE, number ); - exit( EXIT_FAILURE ); - } - } - else if( STREQ( token, "server" ) ) { - token = GetArguments( "server", true ); - strncpy( wmnotify_infos.server_name, token, MAX_STR_LEN ); - server_found = true; - } - else if( STREQ( token, "port" ) ) { - token = GetArguments( "port", true ); - wmnotify_infos.port = (u_int16_t) GetNumber( token, "port" ); - } - - else if( STREQ( token, "username" ) ) { - token = GetArguments( "username", true ); - strncpy( wmnotify_infos.username, token, MAX_STR_LEN ); - username_found = true; - } - else if( STREQ( token, "password" ) ) { - token = GetArguments( "password", true ); - strncpy( wmnotify_infos.password, token, MAX_STR_LEN ); - password_found = true; - } - else if( STREQ( token, "mailcheckdelay" ) ) { - int delay; /* delay in minutes. */ - - token = GetArguments( "mailcheckdelay", true ); - /* GetNumber() will exit if a negative number is entered. */ - delay = GetNumber( token, "mailcheckdelay" ); - if( delay == 0 ) { - fprintf( stderr, "%s: Mail check interval must be greater than '0'\n", - PACKAGE ); - exit( EXIT_FAILURE ); - } - wmnotify_infos.mail_check_interval = (unsigned int) delay * 60; - } - else if( STREQ( token, "mailclient" ) ) { - token = GetArguments( "mailclient", false ); /* Multiple arguments */ - strcpy( wmnotify_infos.mail_client_command, token ); - ParseCommand( wmnotify_infos.mail_client_command, - wmnotify_infos.mail_client_argv ); - } - else if( STREQ( token, "enablebeep" ) ){ - int number; - - token = GetArguments( "enablebeep", true ); - number = GetNumber( token, "enablebeep" ); - if( number == 0 ) { - wmnotify_infos.audible_notification = false; - } - else if( number == 1 ) { - wmnotify_infos.audible_notification = true; - } - else { - fprintf( stderr, "%s: Invalid value for for parameter 'enablebeep' in\n" \ - "configuration file (must be 0 or 1): %d\n", PACKAGE, number ); - exit( EXIT_FAILURE ); - } - } - else if( STREQ( token, "audiofile" ) ) { - token = GetArguments( "audiofile", true ); - /* Should check size before using strcpy(), or use strncopy() instead. */ - strcpy( wmnotify_infos.audiofile, token ); - } - else if( STREQ( token, "volume" ) ) { - token = GetArguments( "volume", true ); - wmnotify_infos.volume = GetNumber( token, "volume" ); - } - else { - fprintf( stderr, "%s: invalid parameter in configuration file: %s\n", PACKAGE, - token ); - exit( EXIT_FAILURE ); - } - - token = strtok( NULL, delimiter_single_arg ); - if( ( token != NULL ) && ( token[0] != '#' ) ) { - fprintf( stderr, "%s: Garbage at end of line in configuration file: %s\n", PACKAGE, - token ); - exit( EXIT_FAILURE ); - } - } - - if( protocol_found == false ) { - err_string = "protocol"; - } - else if( server_found == false ) { - err_string = "server"; - } - else if( username_found == false ) { - err_string = "username"; - } - else if( password_found == false ) { - err_string = "password"; - } - else { - return; /* success */ - } - - /* Failure. */ - fprintf( stderr, "%s: Mandatory parameter \"%s\" missing from configuration " - "file.\n", PACKAGE, err_string ); - exit( EXIT_FAILURE ); + } else { + fprintf(stderr, + "%s: Invalid value for parameter 'use_ssl' in\n" + "configuration file (must be 0 or 1): %d\n", + PACKAGE, number); + exit(EXIT_FAILURE); + } + } else if (STREQ(token, "server")) { + token = GetArguments("server", true); + strncpy(wmnotify_infos.server_name, token, + MAX_STR_LEN); + server_found = true; + } else if (STREQ(token, "port")) { + token = GetArguments("port", true); + wmnotify_infos.port = + (u_int16_t) GetNumber(token, "port"); + } + + else if (STREQ(token, "username")) { + token = GetArguments("username", true); + strncpy(wmnotify_infos.username, token, + MAX_STR_LEN); + username_found = true; + } else if (STREQ(token, "password")) { + token = GetArguments("password", true); + strncpy(wmnotify_infos.password, token, + MAX_STR_LEN); + password_found = true; + } else if (STREQ(token, "mailcheckdelay")) { + int delay; /* delay in minutes. */ + + token = GetArguments("mailcheckdelay", true); + /* + * GetNumber() will exit if a negative number is + * entered. + */ + delay = GetNumber(token, "mailcheckdelay"); + if (delay == 0) { + fprintf(stderr, + "%s: Mail check interval must be greater than '0'\n", + PACKAGE); + exit(EXIT_FAILURE); + } + wmnotify_infos.mail_check_interval = + (unsigned int)delay * 60; + } else if (STREQ(token, "mailclient")) { + /* Multiple arguments */ + token = GetArguments("mailclient", false); + strcpy(wmnotify_infos.mail_client_command, token); + ParseCommand(wmnotify_infos.mail_client_command, + wmnotify_infos.mail_client_argv); + } else if (STREQ(token, "enablebeep")) { + int number; + + token = GetArguments("enablebeep", true); + number = GetNumber(token, "enablebeep"); + if (number == 0) { + wmnotify_infos.audible_notification = + false; + } else if (number == 1) { + wmnotify_infos.audible_notification = true; + } else { + fprintf(stderr, + "%s: Invalid value for for parameter 'enablebeep' in\n" + "configuration file (must be 0 or 1): %d\n", + PACKAGE, number); + exit(EXIT_FAILURE); + } + } else if (STREQ(token, "audiofile")) { + token = GetArguments("audiofile", true); + /* + * Should check size before using strcpy(), or use + * strncopy() instead. + */ + strcpy(wmnotify_infos.audiofile, token); + } else if (STREQ(token, "volume")) { + token = GetArguments("volume", true); + wmnotify_infos.volume = GetNumber(token, "volume"); + } else { + fprintf(stderr, + "%s: invalid parameter in configuration file: %s\n", + PACKAGE, token); + exit(EXIT_FAILURE); + } + + token = strtok(NULL, delimiter_single_arg); + if ((token != NULL) && (token[0] != '#')) { + fprintf(stderr, + "%s: Garbage at end of line in configuration file: %s\n", + PACKAGE, token); + exit(EXIT_FAILURE); + } + } + + if (protocol_found == false) + err_string = "protocol"; + else if (server_found == false) + err_string = "server"; + else if (username_found == false) + err_string = "username"; + else if (password_found == false) + err_string = "password"; + else + return; /* success */ + + /* Failure. */ + fprintf(stderr, + "%s: Mandatory parameter \"%s\" missing from configuration " + "file.\n", PACKAGE, err_string); + exit(EXIT_FAILURE); } /******************************************************************************* * Read and parse the configuration file in the user's home directory ******************************************************************************/ -void -ConfigurationFileInit( void ) +void ConfigurationFileInit(void) { - FILE *fp; - int status; - size_t len; - - /* Check if an optional configuration file was specified on the command - line. */ - if( wmnotify_infos.optional_config_file != NULL ) { - /* Trying to open the file. */ - fp = fopen( wmnotify_infos.optional_config_file, "r" ); - if( fp == NULL ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - } - else { - /* Using the default configuration file. */ - char *home_dir; - char *default_config_file; - - home_dir = getenv("HOME"); - if( home_dir == NULL ) { - /* We're trying to expand ~/, but HOME isn't set. */ - struct passwd *pw = getpwuid( getuid() ); - - if( pw != NULL ) { - home_dir = pw->pw_dir; - } - else { - fprintf( stderr, "%s: Couldn't determine user's home directory path\n", - PACKAGE ); - exit( EXIT_FAILURE ); - } - } - - /* We add 1 to the length for the terminating character '\0'. */ - len = strlen( home_dir ) + strlen( "/" ) + strlen( default_config_filename ) - + 1; - default_config_file = xmalloc( len, __FILE__, __LINE__ ); - - sprintf( default_config_file, "%s/%s", home_dir, default_config_filename ); - - fp = fopen( default_config_file, "r" ); - if( fp == NULL ) { - /* If we cannot open the default configuration file, it probably means - it is missing, so we create it. */ - CreateDefaultConfigurationFile( default_config_file ); - free( default_config_file ); - exit( EXIT_FAILURE ); - } - - free( default_config_file ); - } - - ParseConfigurationFile( fp ); - - status = fclose( fp ); - if( status != EXIT_SUCCESS ) { - fprintf( stderr, "%s: Error closing configuration file.\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } + FILE *fp; + int status; + size_t len; + + /* Check if an optional configuration file was specified on the command + line. */ + if (wmnotify_infos.optional_config_file != NULL) { + /* Trying to open the file. */ + fp = fopen(wmnotify_infos.optional_config_file, "r"); + if (fp == NULL) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + } else { + /* Using the default configuration file. */ + char *home_dir; + char *default_config_file; + + home_dir = getenv("HOME"); + if (home_dir == NULL) { + /* We're trying to expand ~/, but HOME isn't set. */ + struct passwd *pw = getpwuid(getuid()); + + if (pw != NULL) { + home_dir = pw->pw_dir; + } else { + fprintf(stderr, + "%s: Couldn't determine user's home directory path\n", + PACKAGE); + exit(EXIT_FAILURE); + } + } + + /* We add 1 to the length for the terminating character '\0'. */ + len = + strlen(home_dir) + strlen("/") + + strlen(default_config_filename) + + 1; + default_config_file = xmalloc(len, __FILE__, __LINE__); + + sprintf(default_config_file, "%s/%s", home_dir, + default_config_filename); + + fp = fopen(default_config_file, "r"); + if (fp == NULL) { + /* + * If we cannot open the default configuration file, it + * probably means it is missing, so we create it. + */ + CreateDefaultConfigurationFile + (default_config_file); + free(default_config_file); + exit(EXIT_FAILURE); + } + + free(default_config_file); + } + + ParseConfigurationFile(fp); + + status = fclose(fp); + if (status != EXIT_SUCCESS) { + fprintf(stderr, "%s: Error closing configuration file.\n", + PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } } diff --git a/src/configfile.h b/src/configfile.h index 4fca101..50ad74c 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -21,7 +21,6 @@ #ifndef CONFIGFILE_H #define CONFIGFILE_H 1 -void -ConfigurationFileInit( void ); +void ConfigurationFileInit(void); -#endif /* CONFIGFILE_H */ +#endif /* CONFIGFILE_H */ diff --git a/src/dockapp.c b/src/dockapp.c index 5cdbefa..b50a373 100644 --- a/src/dockapp.c +++ b/src/dockapp.c @@ -46,101 +46,109 @@ #define ICON_SIZE 64 -static void -CreateIconFromXpmData( char *pixmap_data[] ) +static void CreateIconFromXpmData(char *pixmap_data[]) { - int status; - - dockapp.xpm_icon.attributes.valuemask |= - ( XpmReturnPixels | XpmReturnExtensions ); - - /* Using the XPM library to read XPM data from the array in the included XPM - file. The 'shapemask' Pixmap variable is set to an additional 1-bit deep - pixmap that can then be used as a shape mask for the XShapeCombineMask() - function. */ - status = XpmCreatePixmapFromData( dockapp.display, dockapp.root_win, - pixmap_data, &dockapp.xpm_icon.image, - &dockapp.xpm_icon.shapemask, - &dockapp.xpm_icon.attributes ); - if( status != XpmSuccess ) { - fprintf( stderr, "%s: XpmCreatePixmapFromData() failed\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } + int status; + + dockapp.xpm_icon.attributes.valuemask |= + (XpmReturnPixels | XpmReturnExtensions); + + /* + * Using the XPM library to read XPM data from the array in the included + * XPM file. The 'shapemask' Pixmap variable is set to an additional + * 1-bit deep pixmap that can then be used as a shape mask for the + * XShapeCombineMask() function. + */ + status = XpmCreatePixmapFromData(dockapp.display, dockapp.root_win, + pixmap_data, + &dockapp.xpm_icon.image, + &dockapp.xpm_icon.shapemask, + &dockapp.xpm_icon.attributes); + if (status != XpmSuccess) { + fprintf(stderr, "%s: XpmCreatePixmapFromData() failed\n", + PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } } -static Pixel -GetColor( char *name ) +static Pixel GetColor(char *name) { - int status; - bool res; - XColor color; - XWindowAttributes attributes; - - status = XGetWindowAttributes( dockapp.display, dockapp.root_win, - &attributes ); - if( status == XLIB_FAILURE ) { - fprintf( stderr, "%s: XGetWindowAttributes() failed\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - color.pixel = 0; - res = (bool) XParseColor( dockapp.display, attributes.colormap, name, - &color ); - if( res == false ) { - fprintf( stderr, "%s: Can't parse %s.\n", PACKAGE, name ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - res = (bool) XAllocColor( dockapp.display, attributes.colormap, &color ); - if( res == false ) { - fprintf( stderr, "%s: Can't allocate %s.\n", PACKAGE, name ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - return color.pixel; + int status; + bool res; + XColor color; + XWindowAttributes attributes; + + status = XGetWindowAttributes(dockapp.display, dockapp.root_win, + &attributes); + if (status == XLIB_FAILURE) { + fprintf(stderr, "%s: XGetWindowAttributes() failed\n", + PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + color.pixel = 0; + res = + (bool) XParseColor(dockapp.display, attributes.colormap, name, + &color); + if (res == false) { + fprintf(stderr, "%s: Can't parse %s.\n", PACKAGE, name); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + res = + (bool) XAllocColor(dockapp.display, attributes.colormap, + &color); + if (res == false) { + fprintf(stderr, "%s: Can't allocate %s.\n", PACKAGE, name); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + return color.pixel; } -static void -flush_expose( Window win ) +static void flush_expose(Window win) { - XEvent dummy; - bool res = true; + XEvent dummy; + bool res = true; - while( res != false ) { - res = (bool) XCheckTypedWindowEvent( dockapp.display, win, Expose, &dummy ); - } + while (res != false) { + res = + (bool) XCheckTypedWindowEvent(dockapp.display, win, + Expose, &dummy); + } } -void -RedrawWindow( void ) +void RedrawWindow(void) { - flush_expose( dockapp.iconwin ); - - (void) XCopyArea( dockapp.display, dockapp.xpm_icon.image, dockapp.iconwin, - dockapp.NormalGC, 0, 0, dockapp.xpm_icon.attributes.width, - dockapp.xpm_icon.attributes.height, 0, 0 ); - - flush_expose( dockapp.win ); - - (void) XCopyArea( dockapp.display, dockapp.xpm_icon.image, dockapp.win, - dockapp.NormalGC, 0, 0, dockapp.xpm_icon.attributes.width, - dockapp.xpm_icon.attributes.height, 0, 0 ); + flush_expose(dockapp.iconwin); + + (void) XCopyArea(dockapp.display, dockapp.xpm_icon.image, + dockapp.iconwin, dockapp.NormalGC, 0, 0, + dockapp.xpm_icon.attributes.width, + dockapp.xpm_icon.attributes.height, 0, 0); + + flush_expose(dockapp.win); + + (void) XCopyArea(dockapp.display, dockapp.xpm_icon.image, + dockapp.win, dockapp.NormalGC, 0, 0, + dockapp.xpm_icon.attributes.width, + dockapp.xpm_icon.attributes.height, 0, 0); } void -copyXPMArea( int x, int y, unsigned int sx, unsigned int sy, int dx, int dy ) +copyXPMArea(int x, int y, unsigned int sx, unsigned int sy, int dx, int dy) { - (void) XCopyArea( dockapp.display, dockapp.xpm_icon.image, - dockapp.xpm_icon.image, dockapp.NormalGC, x, y, sx, sy, - dx, dy ); + (void) XCopyArea(dockapp.display, dockapp.xpm_icon.image, + dockapp.xpm_icon.image, dockapp.NormalGC, x, y, + sx, sy, dx, dy); } @@ -148,153 +156,178 @@ copyXPMArea( int x, int y, unsigned int sx, unsigned int sy, int dx, int dy ) * New window creation and initialization for a Dockable Application ******************************************************************************/ void -InitDockAppWindow( int argc, char *argv[], char *pixmap_data[], - char *display_arg, char *geometry_arg ) +InitDockAppWindow(int argc, char *argv[], char *pixmap_data[], + char *display_arg, char *geometry_arg) { - XGCValues gcv; - XSizeHints size_hints; - XWMHints wm_hints; - int status; - int gravity = 0; /* Used to store the gravity value returned by XWMGeometry, - but not used. */ - - /* Opening a connection to the X server. */ - dockapp.display = XOpenDisplay( display_arg ); - if( dockapp.display == NULL ) { - fprintf( stderr, "%s: Can't open display: %s\n", PACKAGE, - XDisplayName( display_arg ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - dockapp.screen = DefaultScreen( dockapp.display ); - dockapp.root_win = RootWindow( dockapp.display, dockapp.screen ); - dockapp.d_depth = DefaultDepth( dockapp.display, dockapp.screen ); - - /* Create a window to hold the stuff */ - size_hints.flags = USSize | USPosition; - size_hints.x = 0; - size_hints.y = 0; - - /* Constructing window's geometry information. */ - /* XWMGeometry() returns an 'int', but Xlib documentation doesn't explain - it's meaning. */ - XWMGeometry( dockapp.display, dockapp.screen, geometry_arg, NULL, BWIDTH, - &size_hints, &size_hints.x, &size_hints.y, &size_hints.width, - &size_hints.height, &gravity ); - - size_hints.width = ICON_SIZE; - size_hints.height = ICON_SIZE; - dockapp.back_pix = GetColor("white"); - dockapp.fore_pix = GetColor("black"); - - dockapp.win = XCreateSimpleWindow( dockapp.display, dockapp.root_win, - size_hints.x, size_hints.y, - (unsigned int) size_hints.width, - (unsigned int) size_hints.height, - BWIDTH, dockapp.fore_pix, - dockapp.back_pix ); - - dockapp.iconwin = XCreateSimpleWindow( dockapp.display, dockapp.win, - size_hints.x, size_hints.y, - (unsigned int) size_hints.width, - (unsigned int) size_hints.height, - BWIDTH, dockapp.fore_pix, - dockapp.back_pix ); - - /* Configuring Client to Window Manager Communications. */ - - /* WM_NORMAL_HINTS property: size hints for a window in it's normal state. */ - /* Replaces the size hints for the WM_NORMAL_HINTS property on the specified - window. */ - XSetWMNormalHints( dockapp.display, dockapp.win, &size_hints ); - - /* Setting the WM_CLASS property. */ - { - char *app_name = argv[0]; - XClassHint wm_class; - - /* The res_name member contains the application name. - The res_class member contains the application class. */ - /* The name set in this property may differ from the name set as WM_NAME. - That is, WM_NAME specifies what should be displayed in the title bar and, - therefore, can contain temporal information (for example, the name of a - file currently in an editor's buffer). On the other hand, the name - specified as part of WM_CLASS is the formal name of the application that - should be used when retrieving the application's resources from the - resource database. */ - wm_class.res_name = app_name; - wm_class.res_class = app_name; - (void) XSetClassHint( dockapp.display, dockapp.win, &wm_class ); - } - - /* Setting the WM_NAME property. - This specifies what should be displayed in the title bar (usually the - application name). */ - { - XTextProperty text_prop; - - char *app_name = argv[0]; - const int string_count = 1; - - status = XStringListToTextProperty( &app_name, string_count, &text_prop ); - if( status == 0 ) { - fprintf( stderr, "%s: XStringListToTextProperty() failed\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - XSetWMName( dockapp.display, dockapp.win, &text_prop ); - - /* Freing the storage for the value field. */ - (void) XFree( text_prop.value ); - } - - /* WM_HINTS --> Additional hints set by the client for use by the Window - Manager. */ - /* XWMHints wm_hints; */ - - /* WithdrawnState, NormalState or IconicState. Must be set to WithdrawnState - for DockApp. */ - wm_hints.flags = StateHint | IconWindowHint | IconPositionHint | - WindowGroupHint; - wm_hints.initial_state = WithdrawnState; /* Withdrawn, Normal */ - wm_hints.icon_window = dockapp.iconwin; - wm_hints.icon_x = size_hints.x; - wm_hints.icon_y = size_hints.y; - wm_hints.window_group = dockapp.win; - (void) XSetWMHints( dockapp.display, dockapp.win, &wm_hints ); - - /* Sets the WM_COMMAND property. This sets the command and arguments used to - invoke the application. */ - (void) XSetCommand( dockapp.display, dockapp.win, argv, argc ); - - /* ... */ - (void) XSelectInput( dockapp.display, dockapp.win, - ButtonPressMask | ExposureMask | ButtonReleaseMask | - PointerMotionMask | StructureNotifyMask ); - - (void) XSelectInput( dockapp.display, dockapp.iconwin, - ButtonPressMask | ExposureMask | ButtonReleaseMask | - PointerMotionMask | StructureNotifyMask ); - - /* Create GC for drawing */ - gcv.foreground = dockapp.fore_pix; - gcv.background = dockapp.back_pix; - gcv.graphics_exposures = 0; - dockapp.NormalGC = XCreateGC( dockapp.display, dockapp.root_win, - GCForeground | GCBackground | - GCGraphicsExposures, &gcv ); - - /* Convert XPM data to XImage */ - CreateIconFromXpmData( pixmap_data ); - - XShapeCombineMask( dockapp.display, dockapp.win, ShapeBounding, 0, 0, - dockapp.xpm_icon.shapemask, ShapeSet ); - - XShapeCombineMask( dockapp.display, dockapp.iconwin, ShapeBounding, 0, 0, - dockapp.xpm_icon.shapemask, ShapeSet ); - - /* Making the new window visible. */ - (void) XMapWindow( dockapp.display, dockapp.win ); + XGCValues gcv; + XSizeHints size_hints; + XWMHints wm_hints; + int status; + int gravity = 0; /* + * Used to store the gravity value returned by + * XWMGeometry, but not used. + */ + + /* Opening a connection to the X server. */ + dockapp.display = XOpenDisplay(display_arg); + if (dockapp.display == NULL) { + fprintf(stderr, "%s: Can't open display: %s\n", PACKAGE, + XDisplayName(display_arg)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + dockapp.screen = DefaultScreen(dockapp.display); + dockapp.root_win = RootWindow(dockapp.display, dockapp.screen); + dockapp.d_depth = DefaultDepth(dockapp.display, dockapp.screen); + + /* Create a window to hold the stuff */ + size_hints.flags = USSize | USPosition; + size_hints.x = 0; + size_hints.y = 0; + + /* + * Constructing window's geometry information. + * XWMGeometry() returns an 'int', but Xlib documentation doesn't + * explain it's meaning. + */ + XWMGeometry(dockapp.display, dockapp.screen, geometry_arg, NULL, + BWIDTH, &size_hints, &size_hints.x, &size_hints.y, + &size_hints.width, &size_hints.height, &gravity); + + size_hints.width = ICON_SIZE; + size_hints.height = ICON_SIZE; + dockapp.back_pix = GetColor("white"); + dockapp.fore_pix = GetColor("black"); + + dockapp.win = + XCreateSimpleWindow(dockapp.display, dockapp.root_win, + size_hints.x, size_hints.y, + (unsigned int) size_hints.width, + (unsigned int) size_hints.height, BWIDTH, + dockapp.fore_pix, dockapp.back_pix); + + dockapp.iconwin = XCreateSimpleWindow(dockapp.display, dockapp.win, + size_hints.x, size_hints.y, + (unsigned int) size_hints. + width, + (unsigned int) size_hints. + height, BWIDTH, + dockapp.fore_pix, + dockapp.back_pix); + + /* Configuring Client to Window Manager Communications. */ + + /* + * WM_NORMAL_HINTS property: size hints for a window in it's normal + * state. + * Replaces the size hints for the WM_NORMAL_HINTS property on the + * specified window. + */ + XSetWMNormalHints(dockapp.display, dockapp.win, &size_hints); + + /* Setting the WM_CLASS property. */ + { + char *app_name = argv[0]; + XClassHint wm_class; + + /* + * The res_name member contains the application name. + * The res_class member contains the application class. + */ + /* + * The name set in this property may differ from the name set as + * WM_NAME. That is, WM_NAME specifies what should be displayed + * in the title bar and, therefore, can contain temporal + * information (for example, the name of a file currently in an + * editor's buffer). On the other hand, the name specified as + * part of WM_CLASS is the formal name of the application that + * should be used when retrieving the application's resources + * from the resource database. + */ + wm_class.res_name = app_name; + wm_class.res_class = app_name; + (void) XSetClassHint(dockapp.display, dockapp.win, + &wm_class); + } + + /* Setting the WM_NAME property. + This specifies what should be displayed in the title bar (usually the + application name). */ + { + XTextProperty text_prop; + + char *app_name = argv[0]; + const int string_count = 1; + + status = + XStringListToTextProperty(&app_name, string_count, + &text_prop); + if (status == 0) { + fprintf(stderr, + "%s: XStringListToTextProperty() failed\n", + PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + XSetWMName(dockapp.display, dockapp.win, &text_prop); + + /* Freing the storage for the value field. */ + (void) XFree(text_prop.value); + } + + /* WM_HINTS --> Additional hints set by the client for use by the Window + Manager. */ + /* XWMHints wm_hints; */ + + /* + * WithdrawnState, NormalState or IconicState. Must be set to + * WithdrawnState for DockApp. + */ + wm_hints.flags = StateHint | IconWindowHint | IconPositionHint | + WindowGroupHint; + wm_hints.initial_state = WithdrawnState; /* Withdrawn, Normal */ + wm_hints.icon_window = dockapp.iconwin; + wm_hints.icon_x = size_hints.x; + wm_hints.icon_y = size_hints.y; + wm_hints.window_group = dockapp.win; + (void) XSetWMHints(dockapp.display, dockapp.win, &wm_hints); + + /* + * Sets the WM_COMMAND property. This sets the command and arguments + * used to invoke the application. + */ + (void) XSetCommand(dockapp.display, dockapp.win, argv, argc); + + /* ... */ + (void) XSelectInput(dockapp.display, dockapp.win, + ButtonPressMask | ExposureMask | + ButtonReleaseMask | PointerMotionMask | + StructureNotifyMask); + + (void) XSelectInput(dockapp.display, dockapp.iconwin, + ButtonPressMask | ExposureMask | + ButtonReleaseMask | PointerMotionMask | + StructureNotifyMask); + + /* Create GC for drawing */ + gcv.foreground = dockapp.fore_pix; + gcv.background = dockapp.back_pix; + gcv.graphics_exposures = 0; + dockapp.NormalGC = XCreateGC(dockapp.display, dockapp.root_win, + GCForeground | GCBackground | + GCGraphicsExposures, &gcv); + + /* Convert XPM data to XImage */ + CreateIconFromXpmData(pixmap_data); + + XShapeCombineMask(dockapp.display, dockapp.win, ShapeBounding, 0, + 0, dockapp.xpm_icon.shapemask, ShapeSet); + + XShapeCombineMask(dockapp.display, dockapp.iconwin, ShapeBounding, + 0, 0, dockapp.xpm_icon.shapemask, ShapeSet); + + /* Making the new window visible. */ + (void) XMapWindow(dockapp.display, dockapp.win); } diff --git a/src/dockapp.h b/src/dockapp.h index 65cbb6e..5f1317b 100644 --- a/src/dockapp.h +++ b/src/dockapp.h @@ -23,36 +23,34 @@ #include -struct XpmIcon -{ - XpmAttributes attributes; - Pixmap shapemask; - Pixmap image; +struct XpmIcon { + XpmAttributes attributes; + Pixmap shapemask; + Pixmap image; }; -struct dockapp_t -{ - Display *display; - Window root_win; - int screen; - int d_depth; - Pixel back_pix; - Pixel fore_pix; - Window iconwin; - Window win; - GC NormalGC; - struct XpmIcon xpm_icon; +struct dockapp_t { + Display *display; + Window root_win; + int screen; + int d_depth; + Pixel back_pix; + Pixel fore_pix; + Window iconwin; + Window win; + GC NormalGC; + struct XpmIcon xpm_icon; }; void -InitDockAppWindow( int argc, char *argv[], char *pixmap_data[], - char *display_arg, char *geometry_arg ); +InitDockAppWindow(int argc, char *argv[], char *pixmap_data[], + char *display_arg, char *geometry_arg); -void -RedrawWindow( void ); +void RedrawWindow(void); void -copyXPMArea( int x, int y, unsigned int sx, unsigned int sy, int dx, int dy ); +copyXPMArea(int x, int y, unsigned int sx, unsigned int sy, int dx, + int dy); /* Exported variables */ #undef _SCOPE_ @@ -64,4 +62,4 @@ copyXPMArea( int x, int y, unsigned int sx, unsigned int sy, int dx, int dy ); _SCOPE_ struct dockapp_t dockapp; -#endif /* DOCKAPP_H */ +#endif /* DOCKAPP_H */ diff --git a/src/imap.c b/src/imap.c index da11e47..61f83b8 100644 --- a/src/imap.c +++ b/src/imap.c @@ -34,7 +34,7 @@ #include #include #include -#include /* for isdigit() */ +#include /* for isdigit() */ #include "common.h" #include "wmnotify.h" @@ -42,7 +42,7 @@ #include "imap.h" -#define IMAP4_ENDL "\r\n" /* CRLF */ +#define IMAP4_ENDL "\r\n" /* CRLF */ #define IMAP4_CMD_CAPABILITY "CAPABILITY" #define IMAP4_CMD_LOGIN "LOGIN" @@ -55,13 +55,16 @@ #define IMAP4_RSP_SUCCESS "OK" #define IMAP4_RSP_FAILURE "NO" #define IMAP4_RSP_PROTOCOL_ERR "BAD" -#define IMAP4_RSP_SEARCH_UNSEEN "* SEARCH " /* This is the line that will be returned by - * the IMAP4 server after receiving the - * "SEARCH UNSEEN" command, followed by the - * messages ID of the unseen messages. */ - - -static int tlabel = 0; +#define IMAP4_RSP_SEARCH_UNSEEN "* SEARCH " /* + * This is the line that will be + * returned by the IMAP4 server + * after receiving the + * "SEARCH UNSEEN" command, followed + * by the messages ID of the unseen + * messages. + */ + +static int tlabel; static int tlabel_len; static int unseen_string_found; @@ -69,241 +72,289 @@ static int unseen_string_found; extern char tx_buffer[WMNOTIFY_BUFSIZE + 1]; extern char rx_buffer[WMNOTIFY_BUFSIZE + 1]; - -static int -IMAP4_ReceiveResponse( void ) +static int IMAP4_ReceiveResponse(void) { - int len; - char *token; - char *stringp; - - /* All interactions transmitted by client and server are in the form of - lines, that is, strings that end with a CRLF. The protocol receiver - of an IMAP4rev1 client or server is either reading a line, or is - reading a sequence of octets with a known count followed by a line. */ - - get_packet: - len = WmnotifyGetResponse( rx_buffer, WMNOTIFY_BUFSIZE ); - if( len < 0 ) { - /* An error occured. WmnotifyGetResponse() should have printed an error message. */ - goto error; - } - else if( len == 0 ) { - /* The return value will be 0 when the peer has performed an orderly shutdown. */ - if( wmnotify_infos.debug ) { - fprintf( stderr, "IMAP server has closed connection.\n" ); - } - goto error; - } - else if( len == WMNOTIFY_BUFSIZE ) { - if( wmnotify_infos.debug ) { - ErrorLocation( __FILE__, __LINE__ ); - fprintf( stderr, "Response too big (%d bytes) to fit in receive buffer.\n", len ); - } - goto error; - } - - /* We suppose that, if a partial response packet was sent, it is not broken in the middle - of a line (to confirm). Normally, each string is terminated by CRLF. */ - if( STREQ_LEN( &rx_buffer[ len - 2 ], IMAP4_ENDL, 2 ) == false ) { - /* No CRLF found at the end of the buffer --> not handled by wmnotify. */ - ErrorLocation( __FILE__, __LINE__ ); - fprintf( stderr, "Response buffer doesn't contain CRLF at the end.\n" ); - goto error; - } - - if( wmnotify_infos.debug ) { - printf( "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n" ); - printf( "IMAP4 Server Response (size %d bytes):\n", len ); - printf( "%s", rx_buffer ); - printf( "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n" ); - } - - /* Converting the last CRLF into a LF followed by a NULL termination character. */ - rx_buffer[ len - 2 ] = '\n'; - rx_buffer[ len - 1 ] = '\0'; - - /* Check the Server Completion Response returned by the IMAP4 server. There are currently - * three Server Completion Responses codes: success ("OK"), failure ("NO") and protocol error - * ("BAD"). */ - stringp = rx_buffer; - - while( ( token = strsep( &stringp, "\n" ) ) != NULL ) { - - /* In case no delimiter was found, the token is taken to - be the entire string *stringp, and *stringp is made NULL. */ - if( stringp == NULL ) { - if( token[0] == '\0' ) { - /* This means we finished parsing the last line of the buffer, but we need to - get more data to continue process the next part of the IMAP4 response. */ - goto get_packet; - } - else { - /* This should never happen. */ - ErrorLocation( __FILE__, __LINE__ ); - fprintf( stderr, " Delimiter not found in strsep() call.\n" ); - goto error; - } - } - - if( token == NULL ) { - /* This should never happen. */ - ErrorLocation( __FILE__, __LINE__ ); - fprintf( stderr, " NULL token returned by strsep().\n" ); - goto error; - } - - if( token[0] == '*' ) { - /* Untagged response. If there is a space after the SEARCH response, it means - * at least 1 message is unseen. */ - if( STREQ_LEN( token, IMAP4_RSP_SEARCH_UNSEEN, strlen(IMAP4_RSP_SEARCH_UNSEEN) ) == true ) { - unseen_string_found = true; - } - } - else { - /* Must be the status... */ - - /* We check for the correct transaction label plus a space. */ - if( STREQ_LEN( token, tx_buffer, tlabel_len + 1 ) == true ) { - token += tlabel_len + 1; - if( STREQ_LEN( token, IMAP4_RSP_SUCCESS, strlen(IMAP4_RSP_SUCCESS) ) == true ) { - goto end; /* OK, no errors. */ + int len; + char *token; + char *stringp; + + /* + * All interactions transmitted by client and server are in the form of + * lines, that is, strings that end with a CRLF. The protocol receiver + * of an IMAP4rev1 client or server is either reading a line, or is + * reading a sequence of octets with a known count followed by a line. + */ + +get_packet: + len = WmnotifyGetResponse(rx_buffer, WMNOTIFY_BUFSIZE); + if (len < 0) { + /* + * An error occured. WmnotifyGetResponse() should have printed + * an error message. + */ + goto error; + } else if (len == 0) { + /* + * The return value will be 0 when the peer has performed an + * orderly shutdown. + */ + if (wmnotify_infos.debug) { + fprintf(stderr, + "IMAP server has closed connection.\n"); + } + goto error; + } else if (len == WMNOTIFY_BUFSIZE) { + if (wmnotify_infos.debug) { + ErrorLocation(__FILE__, __LINE__); + fprintf(stderr, + "Response too big (%d bytes) to fit in receive buffer.\n", + len); + } + goto error; } - else if( STREQ_LEN( token, IMAP4_RSP_PROTOCOL_ERR, strlen(IMAP4_RSP_PROTOCOL_ERR) ) == true ) { - fprintf( stderr, "%s: Protocol error (%s).\n", PACKAGE, token ); - goto error; - } - else if( STREQ_LEN( token, IMAP4_RSP_FAILURE, strlen(IMAP4_RSP_FAILURE) ) == true ) { - fprintf( stderr, "%s: Failure (%s).\n", PACKAGE, token ); - goto error; + + /* + * We suppose that, if a partial response packet was sent, it is not + * broken in the middle of a line (to confirm). Normally, each string is + * terminated by CRLF. + */ + if (STREQ_LEN(&rx_buffer[len - 2], IMAP4_ENDL, 2) == false) { + /* + * No CRLF found at the end of the buffer --> not handled by + * wmnotify. + */ + ErrorLocation(__FILE__, __LINE__); + fprintf(stderr, + "Response buffer doesn't contain CRLF at the end.\n"); + goto error; } - else { - fprintf( stderr, "%s: Unknown error code (%s).\n", PACKAGE, token ); - goto error; + + if (wmnotify_infos.debug) { + printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); + printf("IMAP4 Server Response (size %d bytes):\n", len); + printf("%s", rx_buffer); + printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); } - } - else { - fprintf( stderr, "%s: Error, transaction label mismatch.\n", PACKAGE ); - goto error; - } - } - } /* while( token ) */ - - /* Get next part of IMAP4 response. */ - goto get_packet; - - end: - /* No error. */ - return len; - - error: - return -1; + + /* + * Converting the last CRLF into a LF followed by a NULL termination + * character. + */ + rx_buffer[len - 2] = '\n'; + rx_buffer[len - 1] = '\0'; + + /* + * Check the Server Completion Response returned by the IMAP4 server. + * There are currently three Server Completion Responses codes: + * success ("OK") + * failure ("NO") + * protocol error ("BAD") + */ + stringp = rx_buffer; + + while ((token = strsep(&stringp, "\n")) != NULL) { + /* + * In case no delimiter was found, the token is taken to + * be the entire string *stringp, and *stringp is made NULL. + */ + if (stringp == NULL) { + if (token[0] == '\0') { + /* + * This means we finished parsing the last line + * of the buffer, but we need to get more data + * to continue process the next part of the + * IMAP4 response. + */ + goto get_packet; + } else { + /* This should never happen. */ + ErrorLocation(__FILE__, __LINE__); + fprintf(stderr, + " Delimiter not found in strsep() call.\n"); + goto error; + } + } + + if (token == NULL) { + /* This should never happen. */ + ErrorLocation(__FILE__, __LINE__); + fprintf(stderr, + " NULL token returned by strsep().\n"); + goto error; + } + + if (token[0] == '*') { + /* + * Untagged response. If there is a space after the + * SEARCH response, it means at least 1 message is + * unseen. + */ + if (STREQ_LEN + (token, IMAP4_RSP_SEARCH_UNSEEN, + strlen(IMAP4_RSP_SEARCH_UNSEEN)) == true) { + unseen_string_found = true; + } + } else { + /* Must be the status... */ + + /* + * We check for the correct transaction label plus a + * space. + */ + if (STREQ_LEN(token, tx_buffer, tlabel_len + 1) == + true) { + token += tlabel_len + 1; + if (STREQ_LEN + (token, IMAP4_RSP_SUCCESS, + strlen(IMAP4_RSP_SUCCESS)) == true) { + goto end; /* OK, no errors. */ + } else + if (STREQ_LEN + (token, IMAP4_RSP_PROTOCOL_ERR, + strlen(IMAP4_RSP_PROTOCOL_ERR)) == + true) { + fprintf(stderr, + "%s: Protocol error (%s).\n", + PACKAGE, token); + goto error; + } else + if (STREQ_LEN + (token, IMAP4_RSP_FAILURE, + strlen(IMAP4_RSP_FAILURE)) == + true) { + fprintf(stderr, + "%s: Failure (%s).\n", + PACKAGE, token); + goto error; + } else { + fprintf(stderr, + "%s: Unknown error code (%s).\n", + PACKAGE, token); + goto error; + } + } else { + fprintf(stderr, + "%s: Error, transaction label mismatch.\n", + PACKAGE); + goto error; + } + } + } /* while( token ) */ + + /* Get next part of IMAP4 response. */ + goto get_packet; + +end: + /* No error. */ + return len; + +error: + return -1; } -static int -IMAP4_SendCommand( int argc, char *argv[] ) +static int IMAP4_SendCommand(int argc, char *argv[]) { - int len; - int i; - - /* Adding Transaction Label. */ - tlabel++; - tx_buffer[0] = 'A'; - len = 1; - len += sprintf( tx_buffer + len, "%d", tlabel ); - tlabel_len = len; - - /* Adding command and it's arguments. */ - for( i = 0; i < argc; i++ ) { - len += sprintf( tx_buffer + len, " %s", argv[i] ); - } - - if( wmnotify_infos.debug ) { - tx_buffer[len] = '\0'; - printf( ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" ); - printf( "IMAP4 Client Command (size %d bytes):\n%s\n", len, tx_buffer ); - printf( ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" ); - } - - /* Adding termination characters. */ - len += sprintf( tx_buffer + len, IMAP4_ENDL ); - - len = WmnotifySendData( tx_buffer, len ); - if( len < 0 ) { - return EXIT_FAILURE; - } - - len = IMAP4_ReceiveResponse(); - if( len < 0 ) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + int len; + int i; + + /* Adding Transaction Label. */ + tlabel++; + tx_buffer[0] = 'A'; + len = 1; + len += sprintf(tx_buffer + len, "%d", tlabel); + tlabel_len = len; + + /* Adding command and it's arguments. */ + for (i = 0; i < argc; i++) + len += sprintf(tx_buffer + len, " %s", argv[i]); + + if (wmnotify_infos.debug) { + tx_buffer[len] = '\0'; + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + printf("IMAP4 Client Command (size %d bytes):\n%s\n", len, + tx_buffer); + printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + } + + /* Adding termination characters. */ + len += sprintf(tx_buffer + len, IMAP4_ENDL); + + len = WmnotifySendData(tx_buffer, len); + if (len < 0) + return EXIT_FAILURE; + + len = IMAP4_ReceiveResponse(); + if (len < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; } -int -IMAP4_CheckForNewMail( void ) +int IMAP4_CheckForNewMail(void) { - char *argv[10]; - int new_messages = 0; - int status; - - status = ConnectionEstablish( wmnotify_infos.server_name, wmnotify_infos.port ); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - goto end; - } - - argv[0] = IMAP4_CMD_LOGIN; - argv[1] = wmnotify_infos.username; - argv[2] = wmnotify_infos.password; - status = IMAP4_SendCommand( 3, argv ); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - goto imap4_logout; - } - - /* Selecting the mailbox first. */ - argv[0] = IMAP4_CMD_EXAMINE; - argv[1] = wmnotify_infos.imap_folder; - status = IMAP4_SendCommand( 2, argv ); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - goto imap4_logout; - } - - /* Searching in selected mailbox for new messages. We must use the UNSEEN search criteria - * instead of NEW (combination of RECENT and UNSEEN). If there is a new message, RECENT - * and UNSEEN will have entries. But if we recheck again later, RECENT will report zero. - * RECENT, when set, simply means that there are new messages since our last visit. - But, on the other hand, when using EXAMINE, no messages should lose their RECENT flag. */ - unseen_string_found = false; - argv[0] = IMAP4_CMD_SEARCH_UNSEEN; - argv[1] = ""; - status = IMAP4_SendCommand( 1, argv ); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - goto imap4_logout; - } - - if( unseen_string_found == true ) { - new_messages = 1; - } - - imap4_logout: - argv[0] = IMAP4_CMD_LOGOUT; - status = IMAP4_SendCommand( 1, argv ); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - } - - status = ConnectionTerminate(); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - } - - end: - return new_messages; + char *argv[10]; + int new_messages = 0; + int status; + + status = + ConnectionEstablish(wmnotify_infos.server_name, + wmnotify_infos.port); + if (status != EXIT_SUCCESS) { + new_messages = -1; + goto end; + } + + argv[0] = IMAP4_CMD_LOGIN; + argv[1] = wmnotify_infos.username; + argv[2] = wmnotify_infos.password; + status = IMAP4_SendCommand(3, argv); + if (status != EXIT_SUCCESS) { + new_messages = -1; + goto imap4_logout; + } + + /* Selecting the mailbox first. */ + argv[0] = IMAP4_CMD_EXAMINE; + argv[1] = wmnotify_infos.imap_folder; + status = IMAP4_SendCommand(2, argv); + if (status != EXIT_SUCCESS) { + new_messages = -1; + goto imap4_logout; + } + + /* + * Searching in selected mailbox for new messages. We must use the + * UNSEEN search criteria instead of NEW (combination of RECENT and + * UNSEEN). If there is a new message, RECENT and UNSEEN will have + * entries. But if we recheck again later, RECENT will report zero. + * RECENT, when set, simply means that there are new messages since our + * last visit. But, on the other hand, when using EXAMINE, no messages + * should lose their RECENT flag. + */ + unseen_string_found = false; + argv[0] = IMAP4_CMD_SEARCH_UNSEEN; + argv[1] = ""; + status = IMAP4_SendCommand(1, argv); + if (status != EXIT_SUCCESS) { + new_messages = -1; + goto imap4_logout; + } + + if (unseen_string_found == true) + new_messages = 1; + +imap4_logout: + argv[0] = IMAP4_CMD_LOGOUT; + status = IMAP4_SendCommand(1, argv); + if (status != EXIT_SUCCESS) + new_messages = -1; + + status = ConnectionTerminate(); + if (status != EXIT_SUCCESS) + new_messages = -1; + +end: + return new_messages; } diff --git a/src/imap.h b/src/imap.h index 9308d34..5337e20 100644 --- a/src/imap.h +++ b/src/imap.h @@ -29,7 +29,6 @@ # define _SCOPE_ extern #endif -int -IMAP4_CheckForNewMail( void ); +int IMAP4_CheckForNewMail(void); -#endif /* IMAP_H */ +#endif /* IMAP_H */ diff --git a/src/network.c b/src/network.c index e264205..b953882 100644 --- a/src/network.c +++ b/src/network.c @@ -52,202 +52,206 @@ char tx_buffer[WMNOTIFY_BUFSIZE + 1]; char rx_buffer[WMNOTIFY_BUFSIZE + 1]; -int -SocketOpen( char *server_name, int port ) +int SocketOpen(char *server_name, int port) { - int status; - int sock_fd = -1; - struct hostent *hostinfo; - struct sockaddr_in serv_addr; - - hostinfo = gethostbyname(server_name); - if( hostinfo == NULL ) { - herror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - goto error; - } - - /* Open socket for Stream (TCP) */ - sock_fd = socket( PF_INET, SOCK_STREAM, 0 ); - if( sock_fd < 0 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - goto error; - } - + int status; + int sock_fd = -1; + struct hostent *hostinfo; + struct sockaddr_in serv_addr; + + hostinfo = gethostbyname(server_name); + if (hostinfo == NULL) { + herror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + goto error; + } + + /* Open socket for Stream (TCP) */ + sock_fd = socket(PF_INET, SOCK_STREAM, 0); + if (sock_fd < 0) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + goto error; + } + /*---Initialize server address/port struct---*/ - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(port); - serv_addr.sin_addr = *((struct in_addr *) hostinfo->h_addr ); - memset( &( serv_addr.sin_zero ), '\0', 8 ); /* Clear the rest of the structure. */ - - if( wmnotify_infos.debug ) { - printf( " Server IP = %s\n", inet_ntoa( serv_addr.sin_addr ) ); - printf( " Server port = %d\n", ntohs(serv_addr.sin_port) ); - } - - /* Establishing connection. */ - status = connect( sock_fd, (struct sockaddr *) &(serv_addr), sizeof(serv_addr) ); - if( status < 0 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - goto error; - } - - end: - return sock_fd; - - error: - if( sock_fd >= 0 ) { - status = close( sock_fd ); - if( status < 0 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - } - } - - sock_fd = -1; - goto end; + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); + serv_addr.sin_addr = *((struct in_addr *)hostinfo->h_addr); + memset(&(serv_addr.sin_zero), '\0', 8); /* Clear rest of structure. */ + + if (wmnotify_infos.debug) { + printf(" Server IP = %s\n", + inet_ntoa(serv_addr.sin_addr)); + printf(" Server port = %d\n", ntohs(serv_addr.sin_port)); + } + + /* Establishing connection. */ + status = connect(sock_fd, (struct sockaddr *)&(serv_addr), + sizeof(serv_addr)); + if (status < 0) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + goto error; + } + +end: + return sock_fd; + +error: + if (sock_fd >= 0) { + status = close(sock_fd); + if (status < 0) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + } + } + + sock_fd = -1; + goto end; } -int -ConnectionEstablish( char *server_name, int port ) +int ConnectionEstablish(char *server_name, int port) { - int len; - char rx_buffer[1024]; /* Temporary... */ + int len; + char rx_buffer[1024]; /* Temporary... */ - wmnotify_infos.sock_fd = SocketOpen( wmnotify_infos.server_name, wmnotify_infos.port ); - if( wmnotify_infos.sock_fd < 0 ) { - goto error; - } + wmnotify_infos.sock_fd = + SocketOpen(wmnotify_infos.server_name, wmnotify_infos.port); + if (wmnotify_infos.sock_fd < 0) + goto error; #if HAVE_SSL - if( wmnotify_infos.use_ssl == true ) { - int status; - status = InitSSL( wmnotify_infos.sock_fd ); - if( status != EXIT_SUCCESS ) { - goto error; - } - } -#endif - - /* Testing connection. */ - len = WmnotifyGetResponse( rx_buffer, 1024 ); - if( len < 0 ) { - goto error; - } - - if( wmnotify_infos.debug ) { - rx_buffer[len] = 0; - printf(" Connect response:\n%s\n", rx_buffer ); - } - - return EXIT_SUCCESS; - - error: - return EXIT_FAILURE; + if (wmnotify_infos.use_ssl == true) { + int status; + status = InitSSL(wmnotify_infos.sock_fd); + if (status != EXIT_SUCCESS) + goto error; + } +#endif + + /* Testing connection. */ + len = WmnotifyGetResponse(rx_buffer, 1024); + if (len < 0) + goto error; + + if (wmnotify_infos.debug) { + rx_buffer[len] = 0; + printf(" Connect response:\n%s\n", rx_buffer); + } + + return EXIT_SUCCESS; + +error: + return EXIT_FAILURE; } -int -ConnectionTerminate( void ) +int ConnectionTerminate(void) { #if HAVE_SSL - if( wmnotify_infos.use_ssl == true ) { - SSL_free( ssl_infos.ssl ); /* release connection state */ - } + if (wmnotify_infos.use_ssl == true) + SSL_free(ssl_infos.ssl); /* release connection state */ #endif - close( wmnotify_infos.sock_fd ); /* close socket */ + close(wmnotify_infos.sock_fd); /* close socket */ #if HAVE_SSL - if( wmnotify_infos.use_ssl == true ) { - SSL_CTX_free( ssl_infos.ctx ); /* release context */ - } + if (wmnotify_infos.use_ssl == true) + SSL_CTX_free(ssl_infos.ctx); /* release context */ #endif - - return EXIT_SUCCESS; + + return EXIT_SUCCESS; } -int -WmnotifySendData( char *buffer, int size ) +int WmnotifySendData(char *buffer, int size) { - int len; + int len; #if HAVE_SSL - if( wmnotify_infos.use_ssl == true ) { - len = SSL_write( ssl_infos.ssl, buffer, size ); /* Encrypt & send message */ - if( len <= 0 ) { - SSL_get_error( ssl_infos.ssl, len ); - len = -1; - } - - return len; - } -#endif /* HAVE_SSL */ - - /* if errno = EINTR, it means the operation was interrupted by a signal before any data was - * sent. We must retry the operation in this case. */ - do { - len = send( wmnotify_infos.sock_fd, buffer, size, SEND_FLAGS ); - } - while( ( len < 0 ) && ( errno == EINTR ) ); - - if( len < 0 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - } - - return len; + if (wmnotify_infos.use_ssl == true) { + /* Encrypt & send message */ + len = SSL_write(ssl_infos.ssl, buffer, size); + if (len <= 0) { + SSL_get_error(ssl_infos.ssl, len); + len = -1; + } + + return len; + } +#endif /* HAVE_SSL */ + + /* + * if errno = EINTR, it means the operation was interrupted by a signal + * before any data was sent. We must retry the operation in this case. + */ + do { + len = send(wmnotify_infos.sock_fd, buffer, size, SEND_FLAGS); + } while ((len < 0) && (errno == EINTR)); + + if (len < 0) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + } + + return len; } -int -WmnotifyGetResponse( char *buffer, int max_size ) +int WmnotifyGetResponse(char *buffer, int max_size) { - int len; + int len; #if HAVE_SSL - if( wmnotify_infos.use_ssl == true ) { - len = SSL_read( ssl_infos.ssl, buffer, max_size ); /* Get reply & decrypt. */ - switch( SSL_get_error( ssl_infos.ssl, len ) ) { - case SSL_ERROR_NONE: - /* Success. */ - break; - case SSL_ERROR_ZERO_RETURN: - fprintf( stderr, "%s: SSL_read() connection closed.\n", PACKAGE ); - break; - case SSL_ERROR_SYSCALL: - fprintf( stderr, "%s: SSL_read() I/O error.\n", PACKAGE ); - goto ssl_error; - case SSL_ERROR_SSL: - fprintf( stderr, "%s: SSL_read() protocol error.\n", PACKAGE ); - goto ssl_error; - default: - fprintf( stderr, "%s: SSL_read() error.\n", PACKAGE ); - goto ssl_error; - } - - return len; - - ssl_error: - return -1; - } + if (wmnotify_infos.use_ssl == true) { + /* Get reply & decrypt. */ + len = SSL_read(ssl_infos.ssl, buffer, max_size); + switch (SSL_get_error(ssl_infos.ssl, len)) { + case SSL_ERROR_NONE: + /* Success. */ + break; + case SSL_ERROR_ZERO_RETURN: + fprintf(stderr, + "%s: SSL_read() connection closed.\n", + PACKAGE); + break; + case SSL_ERROR_SYSCALL: + fprintf(stderr, "%s: SSL_read() I/O error.\n", + PACKAGE); + goto ssl_error; + case SSL_ERROR_SSL: + fprintf(stderr, "%s: SSL_read() protocol error.\n", + PACKAGE); + goto ssl_error; + default: + fprintf(stderr, "%s: SSL_read() error.\n", + PACKAGE); + goto ssl_error; + } + + return len; + +ssl_error: + return -1; + } #endif /* HAVE_SSL */ - /* if errno = EINTR, it means the operation was interrupted by a signal before any data was - * read. We must retry the operation in this case. */ - do { - len = recv( wmnotify_infos.sock_fd, buffer, max_size, RECV_FLAGS ); - } - while( ( len < 0 ) && ( errno == EINTR ) ); - - if( len < 0 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - } - - return len; + /* + * if errno = EINTR, it means the operation was interrupted by a signal + * before any data was read. We must retry the operation in this case. + */ + do { + len = + recv(wmnotify_infos.sock_fd, buffer, max_size, + RECV_FLAGS); + } while ((len < 0) && (errno == EINTR)); + + if (len < 0) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + } + + return len; } diff --git a/src/network.h b/src/network.h index f1fdc1b..8f7b71a 100644 --- a/src/network.h +++ b/src/network.h @@ -34,19 +34,14 @@ CRLF. IMAP4 responses can be more than 1024 characters. */ #define WMNOTIFY_BUFSIZE 10240 -int -SocketOpen( char *server_name, int port ); +int SocketOpen(char *server_name, int port); -int -ConnectionEstablish( char *server_name, int port ); +int ConnectionEstablish(char *server_name, int port); -int -ConnectionTerminate( void ); +int ConnectionTerminate(void); -int -WmnotifySendData( char *buffer, int size ); +int WmnotifySendData(char *buffer, int size); -int -WmnotifyGetResponse( char *buffer, int max_size ); +int WmnotifyGetResponse(char *buffer, int max_size); -#endif /* NETWORK_H */ +#endif /* NETWORK_H */ diff --git a/src/options.c b/src/options.c index d56f2ba..1c398e8 100644 --- a/src/options.c +++ b/src/options.c @@ -40,144 +40,137 @@ /******************************************************************************* * Display the help message and exit ******************************************************************************/ -static void -DisplayUsage( void ) +static void DisplayUsage(void) { - printf( "Usage: %s [OPTIONS]...\n", PACKAGE ); - printf( "Email notification for single POP3 or IMAP4 account.\n\n" ); - printf( " -c use alternate configuration file\n" ); - printf( " -d Display debugging messages.\n" ); - printf( " -display X display name\n" ); - printf( " -geometry +XPOS+YPOS initial window position\n" ); - printf( " -h display this help and exit\n" ); - printf( " -version display version information and exit\n"); - printf( "\n" ); + printf("Usage: %s [OPTIONS]...\n", PACKAGE); + printf("Email notification for single POP3 or IMAP4 account.\n\n"); + printf(" -c "); + printf("use alternate configuration file\n"); + printf(" -d "); + printf("Display debugging messages.\n"); + printf(" -display "); + printf("X display name\n"); + printf(" -geometry +XPOS+YPOS "); + printf("initial window position\n"); + printf(" -h "); + printf("display this help and exit\n"); + printf(" -version "); + printf("display version information and exit\n"); + printf("\n"); } /******************************************************************************* * Display version information and exit ******************************************************************************/ -static void -DisplayVersion( void ) +static void DisplayVersion(void) { - printf( "\n" ); - printf( " %s, version %s\n", PACKAGE, VERSION ); - printf( " Written by Hugo Villeneuve\n\n" ); + printf("\n"); + printf(" %s, version %s\n", PACKAGE, VERSION); + printf(" Written by Hugo Villeneuve\n\n"); } static void -InvalidOption( const char *message, /*@null@*/ const char *string ) +InvalidOption(const char *message, /*@null@ */ const char *string) { - if( string == NULL ) { - fprintf(stderr, "%s: %s\n", PACKAGE, message ); - } - else { - fprintf(stderr, "%s: %s %s\n", PACKAGE, message, string ); - } + if (string == NULL) + fprintf(stderr, "%s: %s\n", PACKAGE, message); + else + fprintf(stderr, "%s: %s %s\n", PACKAGE, message, string); - fprintf(stderr, "Try `%s -h' for more information.\n", PACKAGE ); + fprintf(stderr, "Try `%s -h' for more information.\n", PACKAGE); - exit( EXIT_FAILURE ); + exit(EXIT_FAILURE); } /******************************************************************************* * Initializes the different options passed as arguments on the command line. ******************************************************************************/ -void -ParseCommandLineOptions( int argc, char *argv[] ) +void ParseCommandLineOptions(int argc, char *argv[]) { - int i; - char *token; - bool config_file_on = false; - bool display_on = false; - bool geometry_on = false; - - /* Default values. */ - wmnotify_infos.debug = false; - - for( i = 1; i < argc; i++ ) { - token = argv[i]; - switch( token[0] ) { - case '-': - /* Processing options names */ - switch( token[1] ) { - case 'c': - if( strlen( &token[1] ) == 1 ) { - config_file_on = true; - } - else { - InvalidOption( "invalid option", token ); - } - break; - case 'd': - if( STREQ( "display", &token[1] ) ) { - display_on = true; - } - else if( strlen( &token[1] ) == 1 ) { - wmnotify_infos.debug = true; - } - break; - case 'g': - if( STREQ( "geometry", &token[1] ) ) { - geometry_on = true; - } - else { - InvalidOption( "invalid option", token ); - } - break; - case 'h': - if( strlen( &token[1] ) == 1 ) { - DisplayUsage(); - exit( EXIT_SUCCESS ); - } - InvalidOption( "invalid option", token ); - break; - case 'v' : - if( STREQ( "version", &token[1] ) ) { - DisplayVersion(); - exit( EXIT_SUCCESS ); - } - else { - InvalidOption( "invalid option", token ); + int i; + char *token; + bool config_file_on = false; + bool display_on = false; + bool geometry_on = false; + + /* Default values. */ + wmnotify_infos.debug = false; + + for (i = 1; i < argc; i++) { + token = argv[i]; + switch (token[0]) { + case '-': + /* Processing options names */ + switch (token[1]) { + case 'c': + if (strlen(&token[1]) == 1) { + config_file_on = true; + } else { + InvalidOption("invalid option", + token); + } + break; + case 'd': + if (STREQ("display", &token[1])) + display_on = true; + else if (strlen(&token[1]) == 1) + wmnotify_infos.debug = true; + break; + case 'g': + if (STREQ("geometry", &token[1])) + geometry_on = true; + else + InvalidOption("invalid option", token); + break; + case 'h': + if (strlen(&token[1]) == 1) { + DisplayUsage(); + exit(EXIT_SUCCESS); + } + InvalidOption("invalid option", token); + break; + case 'v': + if (STREQ("version", &token[1])) { + DisplayVersion(); + exit(EXIT_SUCCESS); + } else { + InvalidOption("invalid option", token); + } + break; + default: + InvalidOption("invalid option", token); + break; + } /* end switch( token[1] ) */ + break; + default: + /* Processing options arguments */ + if (config_file_on != false) { + wmnotify_infos.optional_config_file = + token; + /*strcpy( config_file_name, token ); */ + config_file_on = false; + } else if (display_on != false) { + display_on = false; + wmnotify_infos.display_arg = token; + } else if (geometry_on != false) { + geometry_on = false; + wmnotify_infos.geometry_arg = token; + } else { + InvalidOption("invalid option", token); + } + break; + } /* end switch( token[0] ) */ + } /* end for */ + + if (config_file_on != false) { + InvalidOption("missing configuration file parameter", + NULL); + } else if (display_on != false) { + InvalidOption("missing display parameter", NULL); + } else if (geometry_on != false) { + InvalidOption("missing geometry parameter", NULL); } - break; - default: - InvalidOption( "invalid option", token ); - break; - } /* end switch( token[1] ) */ - break; - default: - /* Processing options arguments */ - if( config_file_on != false ) { - wmnotify_infos.optional_config_file = token; - /*strcpy( config_file_name, token );*/ - config_file_on = false; - } - else if( display_on != false ) { - display_on = false; - wmnotify_infos.display_arg = token; - } - else if( geometry_on != false ) { - geometry_on = false; - wmnotify_infos.geometry_arg = token; - } - else { - InvalidOption( "invalid option", token ); - } - break; - } /* end switch( token[0] ) */ - } /* end for */ - - if( config_file_on != false ) { - InvalidOption( "missing configuration file parameter", NULL ); - } - else if( display_on != false ) { - InvalidOption( "missing display parameter", NULL ); - } - else if( geometry_on != false ) { - InvalidOption( "missing geometry parameter", NULL ); - } } diff --git a/src/options.h b/src/options.h index 94def52..b230ae7 100644 --- a/src/options.h +++ b/src/options.h @@ -21,7 +21,6 @@ #ifndef OPTIONS_H #define OPTIONS_H 1 -void -ParseCommandLineOptions( int argc, char *argv[] ); +void ParseCommandLineOptions(int argc, char *argv[]); -#endif /* OPTIONS_H */ +#endif /* OPTIONS_H */ diff --git a/src/pop3.c b/src/pop3.c index 373897d..cd43dda 100644 --- a/src/pop3.c +++ b/src/pop3.c @@ -39,159 +39,159 @@ #include "network.h" #include "pop3.h" - /* Defined in network.c */ extern char tx_buffer[WMNOTIFY_BUFSIZE + 1]; extern char rx_buffer[WMNOTIFY_BUFSIZE + 1]; - -static int -POP3_ReceiveResponse( void ) +static int POP3_ReceiveResponse(void) { - int len; - - len = WmnotifyGetResponse( rx_buffer, WMNOTIFY_BUFSIZE ); - if( len < 0 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - return len; - } - - rx_buffer[ len - 2 ] = '\0'; - - if( wmnotify_infos.debug ) { - printf( "Response: \"%s\"\n", rx_buffer ); - } - - /* No error in recv at this point. Now we parse response from POP3 server. */ - - /* Check the status indicator returned by the POP3 server. - There are currently two status indicators: positive ("+OK") and negative - ("-ERR"). Servers MUST send the status indicators in upper case. */ - if( STREQ_LEN( rx_buffer, POP3_RSP_SUCCESS, strlen(POP3_RSP_SUCCESS) ) == false ) { - fprintf( stderr, "%s: Error, POP3 server responded:\n \"%s\"\n", PACKAGE, rx_buffer ); - len = -1; - } - - return len; + int len; + + len = WmnotifyGetResponse(rx_buffer, WMNOTIFY_BUFSIZE); + if (len < 0) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + return len; + } + + rx_buffer[len - 2] = '\0'; + + if (wmnotify_infos.debug) + printf("Response: \"%s\"\n", rx_buffer); + + /* + * No error in recv at this point. Now we parse response from POP3 + * server. + */ + + /* + * Check the status indicator returned by the POP3 server. + * There are currently two status indicators: positive ("+OK") and + * negative ("-ERR"). Servers MUST send the status indicators in upper + * case. + */ + if (STREQ_LEN + (rx_buffer, POP3_RSP_SUCCESS, + strlen(POP3_RSP_SUCCESS)) == false) { + fprintf(stderr, + "%s: Error, POP3 server responded:\n \"%s\"\n", + PACKAGE, rx_buffer); + len = -1; + } + + return len; } -static int -POP3_SendCommand( int argc, char *argv[] ) +static int POP3_SendCommand(int argc, char *argv[]) { - int len; - int i; - - /* Adding command and it's arguments. */ - for( i = 0, len = 0; i < argc; i++ ) { - len += sprintf( tx_buffer + len, "%s", argv[i] ); - if( i != ( argc - 1 ) ) { - len += sprintf( tx_buffer + len, " " ); - } - } - - if( wmnotify_infos.debug ) { - tx_buffer[len] = '\0'; - printf( "Command: \"%s\"\n", tx_buffer ); - } - - /* Adding termination characters. */ - len += sprintf( tx_buffer + len, POP3_ENDL ); - - len = WmnotifySendData( tx_buffer, len ); - if( len < 0 ) { - return EXIT_FAILURE; - } - - len = POP3_ReceiveResponse(); - if( len < 0 ) { - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + int len; + int i; + + /* Adding command and it's arguments. */ + for (i = 0, len = 0; i < argc; i++) { + len += sprintf(tx_buffer + len, "%s", argv[i]); + + if (i != (argc - 1)) + len += sprintf(tx_buffer + len, " "); + } + + if (wmnotify_infos.debug) { + tx_buffer[len] = '\0'; + printf("Command: \"%s\"\n", tx_buffer); + } + + /* Adding termination characters. */ + len += sprintf(tx_buffer + len, POP3_ENDL); + + len = WmnotifySendData(tx_buffer, len); + if (len < 0) + return EXIT_FAILURE; + + len = POP3_ReceiveResponse(); + if (len < 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; } /* Return the number of new messages on success, -1 on error. */ -static int -POP3_ParseStatCommand( void ) +static int POP3_ParseStatCommand(void) { - int new_messages; - char *token; - - /* STAT command: - * The positive response consists of "+OK" followed by a single space, the number of messages - * in the maildrop, a single space, and the size of the maildrop in octets. */ - token = strtok( rx_buffer, " " ); - token = strtok( NULL, " " ); - if( token != NULL ) { - /* Do more checks for digits... */ - new_messages = atoi( token ); - } - else { - fprintf( stderr, "%s: Error parsing \"STAT\" response", PACKAGE ); - new_messages = -1; - } - - return new_messages; + int new_messages; + char *token; + + /* + * STAT command: + * The positive response consists of "+OK" followed by a single space, + * the number of messages in the maildrop, a single space, and the size + * of the maildrop in octets. + */ + token = strtok(rx_buffer, " "); + token = strtok(NULL, " "); + if (token != NULL) { + /* Do more checks for digits... */ + new_messages = atoi(token); + } else { + fprintf(stderr, "%s: Error parsing \"STAT\" response", + PACKAGE); + new_messages = -1; + } + + return new_messages; } -int -POP3_CheckForNewMail( void ) +int POP3_CheckForNewMail(void) { - int status; - int new_messages = -1; - char *argv[10]; - - status = ConnectionEstablish( wmnotify_infos.server_name, wmnotify_infos.port ); - if( status != EXIT_SUCCESS ) { - return -1; - } - - /* Sending username. */ - argv[0] = POP3_CMD_USERNAME; - argv[1] = wmnotify_infos.username; - status = POP3_SendCommand( 2, argv ); - if( status != EXIT_SUCCESS ) { - goto pop3_close_connection; - } - - /* Sending password. */ - argv[0] = POP3_CMD_PASSWORD; - argv[1] = wmnotify_infos.password; - status = POP3_SendCommand( 2, argv ); - if( status != EXIT_SUCCESS ) { - goto pop3_close_connection; - } - - /* Sending STAT command to inquiry about new messages. */ - argv[0] = POP3_CMD_STAT; - status = POP3_SendCommand( 1, argv ); - if( status != EXIT_SUCCESS ) { - goto pop3_close_connection; - } - - /* Parsing STAT command. */ - new_messages = POP3_ParseStatCommand(); - if( new_messages < 0 ) { - goto pop3_close_connection; - } - - /* Sending QUIT command. */ - argv[0] = POP3_CMD_QUIT; - status = POP3_SendCommand( 1, argv ); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - goto pop3_close_connection; - } - - pop3_close_connection: - status = ConnectionTerminate(); - if( status != EXIT_SUCCESS ) { - new_messages = -1; - } - - return new_messages; + int status; + int new_messages = -1; + char *argv[10]; + + status = + ConnectionEstablish(wmnotify_infos.server_name, + wmnotify_infos.port); + if (status != EXIT_SUCCESS) + return -1; + + /* Sending username. */ + argv[0] = POP3_CMD_USERNAME; + argv[1] = wmnotify_infos.username; + status = POP3_SendCommand(2, argv); + if (status != EXIT_SUCCESS) + goto pop3_close_connection; + + /* Sending password. */ + argv[0] = POP3_CMD_PASSWORD; + argv[1] = wmnotify_infos.password; + status = POP3_SendCommand(2, argv); + if (status != EXIT_SUCCESS) + goto pop3_close_connection; + + /* Sending STAT command to inquiry about new messages. */ + argv[0] = POP3_CMD_STAT; + status = POP3_SendCommand(1, argv); + if (status != EXIT_SUCCESS) + goto pop3_close_connection; + + /* Parsing STAT command. */ + new_messages = POP3_ParseStatCommand(); + if (new_messages < 0) + goto pop3_close_connection; + + /* Sending QUIT command. */ + argv[0] = POP3_CMD_QUIT; + status = POP3_SendCommand(1, argv); + if (status != EXIT_SUCCESS) { + new_messages = -1; + goto pop3_close_connection; + } + +pop3_close_connection: + status = ConnectionTerminate(); + if (status != EXIT_SUCCESS) + new_messages = -1; + + return new_messages; } diff --git a/src/pop3.h b/src/pop3.h index 996d611..1080d08 100644 --- a/src/pop3.h +++ b/src/pop3.h @@ -48,7 +48,6 @@ #define POP3_RSP_SUCCESS "+OK" #define POP3_RSP_FAILURE "-ERR" -int -POP3_CheckForNewMail( void ); +int POP3_CheckForNewMail(void); #endif /* POP3_H */ diff --git a/src/sound.c b/src/sound.c index ff0f05b..7fde90c 100644 --- a/src/sound.c +++ b/src/sound.c @@ -34,7 +34,7 @@ # include # include # include -#elif( defined(sun) && defined(unix) ) +#elif(defined(sun) && defined(unix)) # include # include # include @@ -50,287 +50,313 @@ #define BUFFER_LEN ((sf_count_t) 2048) -static int -OpenDspDevice( int channels, int srate ) +static int OpenDspDevice(int channels, int srate) { - int fd, status; -#if defined (__linux__) - int stereo, temp; - const char audio_device[] = "/dev/dsp"; -#elif( defined(sun) && defined(unix) ) - audio_info_t audio_info; - const char audio_device[] = "/dev/audio"; + int fd, status; +#if defined(__linux__) + int stereo, temp; + const char audio_device[] = "/dev/dsp"; +#elif(defined(sun) && defined(unix)) + audio_info_t audio_info; + const char audio_device[] = "/dev/audio"; #endif - -#if defined (__linux__) - fd = open( audio_device, O_WRONLY, 0 ); -#elif( defined(sun) && defined(unix) ) - /* Open the audio device - write only, non-blocking */ - fd = open( audio_device, O_WRONLY | O_NONBLOCK ); + +#if defined(__linux__) + fd = open(audio_device, O_WRONLY, 0); +#elif(defined(sun) && defined(unix)) + /* Open the audio device - write only, non-blocking */ + fd = open(audio_device, O_WRONLY | O_NONBLOCK); #endif - - if( fd < 0 ) { - fprintf( stderr, "%s: open() failed trying to open device '%s':\n", PACKAGE, - audio_device ); - fprintf( stderr, " %s\n", strerror( errno ) ); - fprintf( stderr, - " Check if device file exists and has correct write permissions.\n" ); - ErrorLocation( __FILE__, __LINE__ ); - return -1; - } - -#if defined (__linux__) - stereo = 0; - status = ioctl( fd, SNDCTL_DSP_STEREO, &stereo ); - if( status == -1 ) { - fprintf( stderr, "%s: ioctl() failed: %s\n", PACKAGE, strerror( errno ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - status = ioctl( fd, SNDCTL_DSP_RESET, 0 ); - if( status > 0 ) { - fprintf( stderr, "%s: ioctl() failed: %s\n", PACKAGE, strerror( errno ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - temp = 16; - status = ioctl( fd, SOUND_PCM_WRITE_BITS, &temp ); - if( status != 0 ) { - fprintf( stderr, "%s: ioctl() failed: %s\n", PACKAGE, strerror( errno ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - status = ioctl( fd, SOUND_PCM_WRITE_CHANNELS, &channels ); - if( status != 0 ) { - fprintf( stderr, "%s: ioctl() failed: %s\n", PACKAGE, strerror( errno ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - status = ioctl( fd, SOUND_PCM_WRITE_RATE, &srate ); - if( status != 0 ) { - fprintf( stderr, "%s: ioctl() failed: %s\n", PACKAGE, strerror( errno ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - status = ioctl( fd, SNDCTL_DSP_SYNC, 0 ); - if( status != 0 ) { - fprintf( stderr, "%s: ioctl() failed: %s\n", PACKAGE, strerror( errno ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - -#elif( defined(sun) && defined(unix) ) - /* Retrieve standard values. */ - AUDIO_INITINFO( &audio_info ); - - audio_info.play.sample_rate = sfinfo.samplerate; - audio_info.play.channels = sfinfo.channels; - audio_info.play.precision = 16; - audio_info.play.encoding = AUDIO_ENCODING_LINEAR; - audio_info.play.gain = AUDIO_MAX_GAIN; - audio_info.play.balance = AUDIO_MID_BALANCE; - - status = ioctl( audio_fd, AUDIO_SETINFO, &audio_info ); - if( status > 0 ) { - fprintf( stderr, "%s: ioctl() failed: %s\n", PACKAGE, strerror( errno ) ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } + + if (fd < 0) { + fprintf(stderr, + "%s: open() failed trying to open device '%s':\n", + PACKAGE, audio_device); + fprintf(stderr, " %s\n", strerror(errno)); + fprintf(stderr, + " Check if device file exists and has correct write permissions.\n"); + ErrorLocation(__FILE__, __LINE__); + return -1; + } +#if defined(__linux__) + stereo = 0; + status = ioctl(fd, SNDCTL_DSP_STEREO, &stereo); + if (status == -1) { + fprintf(stderr, "%s: ioctl() failed: %s\n", PACKAGE, + strerror(errno)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + status = ioctl(fd, SNDCTL_DSP_RESET, 0); + if (status > 0) { + fprintf(stderr, "%s: ioctl() failed: %s\n", PACKAGE, + strerror(errno)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + temp = 16; + status = ioctl(fd, SOUND_PCM_WRITE_BITS, &temp); + if (status != 0) { + fprintf(stderr, "%s: ioctl() failed: %s\n", PACKAGE, + strerror(errno)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &channels); + if (status != 0) { + fprintf(stderr, "%s: ioctl() failed: %s\n", PACKAGE, + strerror(errno)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + status = ioctl(fd, SOUND_PCM_WRITE_RATE, &srate); + if (status != 0) { + fprintf(stderr, "%s: ioctl() failed: %s\n", PACKAGE, + strerror(errno)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + status = ioctl(fd, SNDCTL_DSP_SYNC, 0); + if (status != 0) { + fprintf(stderr, "%s: ioctl() failed: %s\n", PACKAGE, + strerror(errno)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } +#elif(defined(sun) && defined(unix)) + /* Retrieve standard values. */ + AUDIO_INITINFO(&audio_info); + + audio_info.play.sample_rate = sfinfo.samplerate; + audio_info.play.channels = sfinfo.channels; + audio_info.play.precision = 16; + audio_info.play.encoding = AUDIO_ENCODING_LINEAR; + audio_info.play.gain = AUDIO_MAX_GAIN; + audio_info.play.balance = AUDIO_MID_BALANCE; + + status = ioctl(audio_fd, AUDIO_SETINFO, &audio_info); + if (status > 0) { + fprintf(stderr, "%s: ioctl() failed: %s\n", PACKAGE, + strerror(errno)); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } #endif - - return fd; + + return fd; } -void -PlayAudioFile( char *filename, int volume ) +void PlayAudioFile(char *filename, int volume) { - static short buffer[BUFFER_LEN]; - SNDFILE *sndfile; - SF_INFO sfinfo; - int audio_fd; - int readcount; - int status; -#if defined (__linux__) - int subformat; - int m; -#elif( defined(sun) && defined(unix) ) - unsigned long delay_time; - long start_count, output_count, write_count; - bool done; + static short buffer[BUFFER_LEN]; + SNDFILE *sndfile; + SF_INFO sfinfo; + int audio_fd; + int readcount; + int status; +#if defined(__linux__) + int subformat; + int m; +#elif(defined(sun) && defined(unix)) + unsigned long delay_time; + long start_count, output_count, write_count; + bool done; #endif - if( wmnotify_infos.debug ) { - printf( "%s: PlayAudioFile() Entry\n", PACKAGE ); - } - - if( filename == NULL ) { - fprintf( stderr, "%s: No audio file specified.\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - sndfile = sf_open( filename, SFM_READ, &sfinfo ); - - if( sndfile == NULL ) { - fprintf( stderr, "%s: sf_open() failed trying to open '%s':\n", PACKAGE, filename ); - fprintf( stderr, " %s\n", sf_strerror(NULL) ); - fprintf( stderr, " Check if file exists and has correct read permissions.\n" ); - ErrorLocation( __FILE__, __LINE__ ); - return; - } - - if( sfinfo.channels < 1 || sfinfo.channels > 2 ) { - fprintf( stderr, "%s: Audio file has %d channel(s), but ", PACKAGE, sfinfo.channels ); - fprintf( stderr, "we support only 1 or 2 channels.\n" ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - audio_fd = OpenDspDevice( sfinfo.channels, sfinfo.samplerate ); - if( audio_fd < 0 ) { - goto play_audio_file_close_file; - } - -#if( defined(sun) && defined(unix) ) - /* Delay time equal to 1/4 of a buffer in microseconds. */ - delay_time = (BUFFER_LEN * 1000000) / (sfinfo.samplerate * 4); -#endif + if (wmnotify_infos.debug) + printf("%s: PlayAudioFile() Entry\n", PACKAGE); - subformat = sfinfo.format & SF_FORMAT_SUBMASK; - - if( subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE ) { - static float flt_buffer[BUFFER_LEN]; - double scale; - - status = sf_command( sndfile, SFC_CALC_SIGNAL_MAX, &scale, (int) sizeof(scale) ); - if( status == 0 ) { - fprintf( stderr, "%s: Warning, sf_command() failed.\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - goto play_audio_file_close_audio; - } - - if (scale < 1e-10) { - scale = 1.0; - } - else { - scale = 32700.0 / scale; - } - - while( ( readcount = (int) sf_read_float( sndfile, flt_buffer, BUFFER_LEN ) ) != 0 ) { - /* Linux/OSS -- FLOAT samples */ -#if defined (__linux__) - for( m = 0 ; m < readcount ; m++ ) { - /* Float to integer conversion. */ - buffer[m] = (short) ( scale * flt_buffer[m] ); - /* Changing volume */ - buffer[m] = buffer[m] * volume / 100; - } - status = (int) write( audio_fd, buffer, readcount * sizeof(short) ); - if( status == -1 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - goto play_audio_file_close_audio; - } - - /* Solaris -- FLOAT samples */ -#elif( defined(sun) && defined(unix) ) - start_count = 0; - output_count = read_count * sizeof(short); - - while( output_count > 0 ) { - /* Write as much data as possible */ - for( m = 0 ; m < readcount ; m++ ) { - /* Float to integer conversion. */ - buffer[m] = (short) ( scale * flt_buffer[m] ); - /* Changing volume */ - buffer[m] = buffer[m] * volume / 100; + if (filename == NULL) { + fprintf(stderr, "%s: No audio file specified.\n", PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); } - - write_count = write( audio_fd, &(buffer[start_count]), output_count ); - if( write_count > 0 ) { - output_count -= write_count; - start_count += write_count; + + sndfile = sf_open(filename, SFM_READ, &sfinfo); + + if (sndfile == NULL) { + fprintf(stderr, + "%s: sf_open() failed trying to open '%s':\n", + PACKAGE, filename); + fprintf(stderr, " %s\n", sf_strerror(NULL)); + fprintf(stderr, + " Check if file exists and has correct read permissions.\n"); + ErrorLocation(__FILE__, __LINE__); + return; } - else { - /* Give the audio output time to catch up. */ - usleep( delay_time ); + + if (sfinfo.channels < 1 || sfinfo.channels > 2) { + fprintf(stderr, "%s: Audio file has %d channel(s), but ", + PACKAGE, sfinfo.channels); + fprintf(stderr, "we support only 1 or 2 channels.\n"); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); } - } /* while( output_count > 0 ) */ + + audio_fd = OpenDspDevice(sfinfo.channels, sfinfo.samplerate); + if (audio_fd < 0) + goto play_audio_file_close_file; + +#if (defined(sun) && defined(unix)) + /* Delay time equal to 1/4 of a buffer in microseconds. */ + delay_time = (BUFFER_LEN * 1000000) / (sfinfo.samplerate * 4); #endif - } /* while( ( readcount... ) */ - } - else { - while( ( readcount = (int) sf_read_short( sndfile, buffer, BUFFER_LEN ) ) != 0 ) { - /* Linux/OSS -- INTEGER samples */ -#if defined (__linux__) - /* Changing volume... */ - for( m = 0 ; m < readcount ; m++ ) { - buffer[m] = ( buffer[m] * volume ) / 100; - } - - status = (int) write( audio_fd, buffer, readcount * sizeof(short) ); - if( status == -1 ) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - goto play_audio_file_close_audio; - } - - /* Solaris -- INTEGER samples */ -#elif( defined(sun) && defined(unix) ) - start_count = 0; - output_count = read_count * sizeof(short); - - while( output_count > 0 ) { - /* Write as much data as possible */ - - /* Changing volume. */ - for( m = 0 ; m < read_count ; m++ ) { - buffer[m] = ( buffer[m] * volume ) / 100; - } - - write_count = write( audio_fd, &(buffer[start_count]), output_count ); - if( write_count > 0 ) { - output_count -= write_count; - start_count += write_count; + + subformat = sfinfo.format & SF_FORMAT_SUBMASK; + + if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) { + static float flt_buffer[BUFFER_LEN]; + double scale; + + status = + sf_command(sndfile, SFC_CALC_SIGNAL_MAX, &scale, + (int) sizeof(scale)); + if (status == 0) { + fprintf(stderr, + "%s: Warning, sf_command() failed.\n", + PACKAGE); + ErrorLocation(__FILE__, __LINE__); + goto play_audio_file_close_audio; + } + + if (scale < 1e-10) + scale = 1.0; + else + scale = 32700.0 / scale; + + while ((readcount = + (int) sf_read_float(sndfile, flt_buffer, + BUFFER_LEN)) != 0) { + /* Linux/OSS -- FLOAT samples */ +#if defined(__linux__) + for (m = 0; m < readcount; m++) { + /* Float to integer conversion. */ + buffer[m] = + (short) (scale * flt_buffer[m]); + /* Changing volume */ + buffer[m] = buffer[m] * volume / 100; + } + status = + (int) write(audio_fd, buffer, + readcount * sizeof(short)); + if (status == -1) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + goto play_audio_file_close_audio; + } + + /* Solaris -- FLOAT samples */ +#elif(defined(sun) && defined(unix)) + start_count = 0; + output_count = read_count * sizeof(short); + + while (output_count > 0) { + /* Write as much data as possible */ + for (m = 0; m < readcount; m++) { + /* Float to integer conversion. */ + buffer[m] = + (short) (scale * + flt_buffer[m]); + /* Changing volume */ + buffer[m] = + buffer[m] * volume / 100; + } + + write_count = + write(audio_fd, &(buffer[start_count]), + output_count); + if (write_count > 0) { + output_count -= write_count; + start_count += write_count; + } else { + /* + * Give the audio output time to catch + * up. + */ + usleep(delay_time); + } + } /* while( output_count > 0 ) */ +#endif + } /* while( ( readcount... ) */ + } else { + while ((readcount = + (int) sf_read_short(sndfile, buffer, + BUFFER_LEN)) != 0) { + /* Linux/OSS -- INTEGER samples */ +#if defined(__linux__) + /* Changing volume... */ + for (m = 0; m < readcount; m++) + buffer[m] = (buffer[m] * volume) / 100; + + status = (int) write(audio_fd, buffer, + readcount * sizeof(short)); + if (status == -1) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + goto play_audio_file_close_audio; + } + + /* Solaris -- INTEGER samples */ +#elif(defined(sun) && defined(unix)) + start_count = 0; + output_count = read_count * sizeof(short); + + while (output_count > 0) { + /* Write as much data as possible */ + + /* Changing volume. */ + for (m = 0; m < read_count; m++) { + buffer[m] = + (buffer[m] * volume) / 100; + } + + write_count = + write(audio_fd, &(buffer[start_count]), + output_count); + if (write_count > 0) { + output_count -= write_count; + start_count += write_count; + } else { + /* + * Give the audio output time to catch + * up. + */ + usleep(delay_time); + } + } /* while( output_count > 0 ) */ +#endif + } /* while( ( readcount... ) */ + } /* else */ + +play_audio_file_close_audio: + + status = close(audio_fd); + if (status != 0) { + fprintf(stderr, "%s: Error, close() failed.\n", PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); } - else { - /* Give the audio output time to catch up. */ - usleep( delay_time ); + +play_audio_file_close_file: + + status = sf_close(sndfile); + if (status != 0) { + fprintf(stderr, "%s: Error, sf_close() failed.\n", + PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); } - } /* while( output_count > 0 ) */ -#endif - } /* while( ( readcount... ) */ - } /* else */ - - play_audio_file_close_audio: - - status = close( audio_fd ); - if( status != 0 ) { - fprintf( stderr, "%s: Error, close() failed.\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - play_audio_file_close_file: - - status = sf_close( sndfile ); - if( status != 0 ) { - fprintf( stderr, "%s: Error, sf_close() failed.\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - if( wmnotify_infos.debug ) { - printf( "%s: PlayAudioFile() Exit\n", PACKAGE ); - } - - return; + + if (wmnotify_infos.debug) + printf("%s: PlayAudioFile() Exit\n", PACKAGE); + + return; } #endif /* HAVE_SNDFILE */ diff --git a/src/sound.h b/src/sound.h index 84a7304..6334d46 100644 --- a/src/sound.h +++ b/src/sound.h @@ -21,7 +21,6 @@ #ifndef SOUND_H #define SOUND_H 1 -void -PlayAudioFile(char *filename, int volume); +void PlayAudioFile(char *filename, int volume); -#endif /* SOUND_H */ +#endif /* SOUND_H */ diff --git a/src/ssl.c b/src/ssl.c index 3acb529..df140c7 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1,115 +1,113 @@ -/* - * ssl.c - * - * Copyright (C) 2003 Hugo Villeneuve - * Based on ssl_client.c (Sean Walton and Macmillan Publishers). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#if HAVE_SSL - -/* Define filename_M */ -#define SSL_M 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "wmnotify.h" -#include "ssl.h" - - -/* InitCTX - initialize the SSL engine. */ -SSL_CTX * -InitCTX( void ) -{ - const SSL_METHOD *method; - SSL_CTX *ctx; - - SSL_library_init(); /* Load cryptos, et.al. */ - SSL_load_error_strings(); /* Bring in and register error messages */ - method = SSLv23_client_method(); /* Indicate we support SSLv2, SSLv3 and TLSv1 methods. */ - ctx = SSL_CTX_new(method); /* Create new context */ - if( ctx == NULL ) { - ERR_print_errors_fp(stderr); - abort(); - } - return ctx; -} - - -/* ShowCerts - print out the certificates. */ -void -ShowCerts( SSL *ssl ) -{ - X509 *cert; - char *line; - - cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */ - if ( cert != NULL ) { - printf("Server certificates:\n"); - line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); - printf("Subject: %s\n", line); - free(line); /* free the malloc'ed string */ - line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); - printf("Issuer: %s\n", line); - free(line); /* free the malloc'ed string */ - X509_free(cert); /* free the malloc'ed certificate copy */ - } - else { - printf("No certificates.\n"); - } -} - - -int -InitSSL( int sock_fd ) -{ - ssl_infos.ctx = InitCTX(); - ssl_infos.ssl = SSL_new( ssl_infos.ctx ); /* create new SSL connection state */ - if( ssl_infos.ssl == NULL ) { - printf( "%s: Error in SSL_new()\n", PACKAGE ); - return EXIT_FAILURE; - } - - SSL_set_fd( ssl_infos.ssl, sock_fd ); /* attach the socket descriptor */ - if( SSL_connect( ssl_infos.ssl ) == FAIL ) { /* perform the connection */ - ERR_print_errors_fp(stderr); - return EXIT_FAILURE; - } - - if( wmnotify_infos.debug ) { - printf("Connected with %s encryption\n", SSL_get_cipher( ssl_infos.ssl )); - ShowCerts( ssl_infos.ssl ); /* get any certs */ - } - - return EXIT_SUCCESS; -} - - -#endif /* HAVE_SSL */ +/* + * ssl.c + * + * Copyright (C) 2003 Hugo Villeneuve + * Based on ssl_client.c (Sean Walton and Macmillan Publishers). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif /* */ + +#if HAVE_SSL + +/* Define filename_M */ +#define SSL_M 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "wmnotify.h" +#include "ssl.h" + +/* InitCTX - initialize the SSL engine. */ +SSL_CTX *InitCTX(void) +{ + const SSL_METHOD *method; + SSL_CTX *ctx; + SSL_library_init(); /* Load cryptos, et.al. */ + SSL_load_error_strings(); /* Bring in and register error messages */ + method = SSLv23_client_method(); /* + * Indicate we support SSLv2, SSLv3 and + * TLSv1 methods. + */ + ctx = SSL_CTX_new(method); /* Create new context */ + if (ctx == NULL) { + ERR_print_errors_fp(stderr); + abort(); + } + return ctx; +} + + +/* ShowCerts - print out the certificates. */ +void ShowCerts(SSL *ssl) +{ + X509 *cert; + char *line; + cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */ + if (cert != NULL) { + printf("Server certificates:\n"); + line = + X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); + printf("Subject: %s\n", line); + free(line); /* free the malloc'ed string */ + line = + X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); + printf("Issuer: %s\n", line); + free(line); /* free the malloc'ed string */ + X509_free(cert); /* free the malloc'ed certificate copy */ + } else { + printf("No certificates.\n"); + } +} + +int InitSSL(int sock_fd) +{ + ssl_infos.ctx = InitCTX(); + ssl_infos.ssl = SSL_new(ssl_infos.ctx); /* + * create new SSL connection + * state + */ + if (ssl_infos.ssl == NULL) { + printf("%s: Error in SSL_new()\n", PACKAGE); + return EXIT_FAILURE; + } + SSL_set_fd(ssl_infos.ssl, sock_fd); /* attach the socket descriptor */ + if (SSL_connect(ssl_infos.ssl) == FAIL) { /* perform the connection */ + ERR_print_errors_fp(stderr); + return EXIT_FAILURE; + } + if (wmnotify_infos.debug) { + printf("Connected with %s encryption\n", + SSL_get_cipher(ssl_infos.ssl)); + ShowCerts(ssl_infos.ssl); /* get any certs */ + } + return EXIT_SUCCESS; +} + + +#endif /* HAVE_SSL */ diff --git a/src/ssl.h b/src/ssl.h index b692b2f..67be27a 100644 --- a/src/ssl.h +++ b/src/ssl.h @@ -41,20 +41,17 @@ #define FAIL -1 struct ssl_infos_t { - SSL_CTX *ctx; - SSL *ssl; + SSL_CTX *ctx; + SSL *ssl; }; _SCOPE_ struct ssl_infos_t ssl_infos; -SSL_CTX * -InitCTX( void ); +SSL_CTX *InitCTX(void); -void -ShowCerts( SSL *ssl ); +void ShowCerts(SSL *ssl); -int -InitSSL( int sock_fd ); +int InitSSL(int sock_fd); #endif /* HAVE_SSL */ diff --git a/src/wmnotify.c b/src/wmnotify.c index b2c7b27..8847a24 100644 --- a/src/wmnotify.c +++ b/src/wmnotify.c @@ -53,416 +53,450 @@ #include "wmnotify.h" -/* Set in DoubleClick() to stop the new mail animation when the mail client is - opened. */ -static bool animation_stop = false; +/* + * Set in DoubleClick() to stop the new mail animation when the mail client is + * opened. + */ +static bool animation_stop; static int animation_image = MAILBOX_FULL; -/* Set in response to signal sent by SingleClick() to force mail check. Also set to true at - * startup to force initial check. */ +/* + * Set in response to signal sent by SingleClick() to force mail check. Also set + * to true at startup to force initial check. + */ static bool manual_check = true; /* Used to signal TimerThread to quit. Inactive for now. */ -static bool quit = false; +static bool quit; -static int double_click_notif = false; +static int double_click_notif; /* TimerThread ID */ static pthread_t timer_thread; -inline void -ErrorLocation( const char *file, int line ) +inline void ErrorLocation(const char *file, int line) { - fprintf( stderr, " Error in file \"%s\" at line #%d\n", file, line ); + fprintf(stderr, " Error in file \"%s\" at line #%d\n", file, + line); } -void * -xmalloc( size_t size, const char *filename, int line_number ) +void *xmalloc(size_t size, const char *filename, int line_number) { - void *value; + void *value; - value = malloc( size ); - - if( value == NULL ) { - perror( PACKAGE ); - ErrorLocation( filename, line_number ); - exit( EXIT_FAILURE ); - } + value = malloc(size); - return value; + if (value == NULL) { + perror(PACKAGE); + ErrorLocation(filename, line_number); + exit(EXIT_FAILURE); + } + + return value; } -static void -DisplayOpenedEmptyMailbox( void ) +static void DisplayOpenedEmptyMailbox(void) { - /* Opened and empty mailbox image */ - copyXPMArea( MAILBOX_OPENED_EMPTY_SRC_X, MAILBOX_OPENED_EMPTY_SRC_Y, - MAILBOX_SIZE_X, MAILBOX_SIZE_Y, MAILBOX_DEST_X, MAILBOX_DEST_Y ); - RedrawWindow(); + /* Opened and empty mailbox image */ + copyXPMArea(MAILBOX_OPENED_EMPTY_SRC_X, MAILBOX_OPENED_EMPTY_SRC_Y, + MAILBOX_SIZE_X, MAILBOX_SIZE_Y, MAILBOX_DEST_X, + MAILBOX_DEST_Y); + RedrawWindow(); } -static void -DisplayOpenedFullMailbox( void ) +static void DisplayOpenedFullMailbox(void) { - /* Full mailbox image */ - copyXPMArea( MAILBOX_OPENED_FULL_SRC_X, MAILBOX_OPENED_FULL_SRC_Y, - MAILBOX_SIZE_X, MAILBOX_SIZE_Y, - MAILBOX_DEST_X, MAILBOX_DEST_Y ); - RedrawWindow(); + /* Full mailbox image */ + copyXPMArea(MAILBOX_OPENED_FULL_SRC_X, MAILBOX_OPENED_FULL_SRC_Y, + MAILBOX_SIZE_X, MAILBOX_SIZE_Y, + MAILBOX_DEST_X, MAILBOX_DEST_Y); + RedrawWindow(); } -static void -DisplayClosedMailbox( void ) +static void DisplayClosedMailbox(void) { - /* Opened mailbox image */ - copyXPMArea( MAILBOX_CLOSED_SRC_X, MAILBOX_CLOSED_SRC_Y, - MAILBOX_SIZE_X, MAILBOX_SIZE_Y, - MAILBOX_DEST_X, MAILBOX_DEST_Y ); - RedrawWindow(); + /* Opened mailbox image */ + copyXPMArea(MAILBOX_CLOSED_SRC_X, MAILBOX_CLOSED_SRC_Y, + MAILBOX_SIZE_X, MAILBOX_SIZE_Y, + MAILBOX_DEST_X, MAILBOX_DEST_Y); + RedrawWindow(); } -static void -DisplayExecuteCommandNotification( void ) +static void DisplayExecuteCommandNotification(void) { - /* Visual notification that the double-click was catched. */ - copyXPMArea( EXEC_CMD_IMG_SRC_X, EXEC_CMD_IMG_SRC_Y, - MAILBOX_SIZE_X, MAILBOX_SIZE_Y, MAILBOX_DEST_X, MAILBOX_DEST_Y ); - RedrawWindow(); + /* Visual notification that the double-click was catched. */ + copyXPMArea(EXEC_CMD_IMG_SRC_X, EXEC_CMD_IMG_SRC_Y, + MAILBOX_SIZE_X, MAILBOX_SIZE_Y, MAILBOX_DEST_X, + MAILBOX_DEST_Y); + RedrawWindow(); } -static void -ExecuteCommand( char *argv[] ) +static void ExecuteCommand(char *argv[]) { - pid_t pid; - char *msg; - - /* No command defined, this is not an error. */ - if( argv[0] == NULL ) { - return; - } - - pid = fork(); /* fork a child process. */ - - if( pid < 0) { - perror( PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - else if( pid == 0 ) { /* Child process */ - /* When execvp() is successful, it doesn't return; otherwise, it returns - -1 and sets errno. */ - (void) execvp( argv[0], argv ); - - msg = strerror( errno ); - fprintf( stderr, "%s: The external mail program couldn't be started.\n", - PACKAGE); - fprintf( stderr, "Check your path or your configuration file for errors.\n" - ); - fprintf( stderr, "%s: \"%s\"\n", msg, argv[0] ); - exit( EXIT_FAILURE ); - } + pid_t pid; + char *msg; + + /* No command defined, this is not an error. */ + if (argv[0] == NULL) + return; + + pid = fork(); /* fork a child process. */ + + if (pid < 0) { + perror(PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } else if (pid == 0) { /* Child process */ + /* + * When execvp() is successful, it doesn't return; otherwise, it + * returns -1 and sets errno. + */ + (void) execvp(argv[0], argv); + + msg = strerror(errno); + fprintf(stderr, + "%s: The external mail program couldn't be started.\n", + PACKAGE); + fprintf(stderr, + "Check your path or your configuration file for errors.\n"); + fprintf(stderr, "%s: \"%s\"\n", msg, argv[0]); + exit(EXIT_FAILURE); + } } /* single-click --> Checking mail */ -static void -SingleClick( void ) +static void SingleClick(void) { - int status; - - if( wmnotify_infos.debug ) { - printf( "%s: SingleClick() Entry\n", PACKAGE ); - } - - /* Sending a signal to awake the TimerThread() thread. */ - status = pthread_kill( timer_thread, SIGUSR1 ); - if( status != EXIT_SUCCESS ) { - fprintf( stderr, "%s: pthread_kill() error (%d)\n", PACKAGE, status ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - if( wmnotify_infos.debug ) { - printf( "%s: SingleClick() Exit\n", PACKAGE ); - } + int status; + + if (wmnotify_infos.debug) + printf("%s: SingleClick() Entry\n", PACKAGE); + + /* Sending a signal to awake the TimerThread() thread. */ + status = pthread_kill(timer_thread, SIGUSR1); + if (status != EXIT_SUCCESS) { + fprintf(stderr, "%s: pthread_kill() error (%d)\n", PACKAGE, + status); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + if (wmnotify_infos.debug) + printf("%s: SingleClick() Exit\n", PACKAGE); } /* Double-click --> Starting external mail client. */ -static void -DoubleClick( void ) +static void DoubleClick(void) { - int status; - - if( wmnotify_infos.mail_client_argv[0] != NULL ) { - /* Starting external mail client. */ - ExecuteCommand( wmnotify_infos.mail_client_argv ); - - double_click_notif = true; - - /* Sending a signal to awake the TimerThread() thread. This was previously - done with a mutex variable (animation_stop), but this caused a bug when the - following sequence was encountered: - -The user double-click to start the external mail client - -A new E-mail is received shortly after that - -The user exit the external mail client - -The user manually check for new E-mail - -The audio notification sound is played, but no animation image is - displayed. - This was because setting the mutex variable 'animation_stop' didn't - awakened the TimerThread(), but single-clicking awakened it. Since the - 'animation_stop' variable was still set to true, no animation occured. */ - status = pthread_kill( timer_thread, SIGUSR2 ); - if( status != EXIT_SUCCESS ) { - fprintf( stderr, "%s: pthread_kill() error (%d)\n", PACKAGE, status ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - DisplayExecuteCommandNotification(); - sleep(1); - DisplayClosedMailbox(); - - double_click_notif = false; - } - else { - fprintf( stderr, "%s: Warning: No email-client defined.\n", PACKAGE ); - } + int status; + + if (wmnotify_infos.mail_client_argv[0] != NULL) { + /* Starting external mail client. */ + ExecuteCommand(wmnotify_infos.mail_client_argv); + + double_click_notif = true; + + /* + * Sending a signal to awake the TimerThread() thread. This was + * previously done with a mutex variable (animation_stop), but + * this caused a bug when the following sequence was + * encountered: + * -The user double-click to start the external mail client + * -A new E-mail is received shortly after that + * -The user exit the external mail client + * -The user manually check for new E-mail + * -The audio notification sound is played, but no animation + * image is displayed. + * This was because setting the mutex variable 'animation_stop' + * didn't awakened the TimerThread(), but single-clicking + * awakened it. Since the 'animation_stop' variable was still + * set to true, no animation occured. + */ + status = pthread_kill(timer_thread, SIGUSR2); + if (status != EXIT_SUCCESS) { + fprintf(stderr, "%s: pthread_kill() error (%d)\n", + PACKAGE, status); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + DisplayExecuteCommandNotification(); + sleep(1); + DisplayClosedMailbox(); + + double_click_notif = false; + } else { + fprintf(stderr, "%s: Warning: No email-client defined.\n", + PACKAGE); + } } -static void -CatchChildTerminationSignal( int signal ) +static void CatchChildTerminationSignal(int signal) { - switch( signal ) { - case SIGCHLD: - /* Wait for Mail Client child process termination. Child enters zombie - state: process is dead and most resources are released, but process - descriptor remains until parent reaps exit status via wait. */ - - /* The WNOHANG option prevents the call to waitpid from suspending execution - of the caller. */ - (void) waitpid( 0, NULL, WNOHANG ); - break; - default: - fprintf( stderr, "%s: Unregistered signal received, exiting.\n", PACKAGE ); - exit( EXIT_FAILURE ); - } + switch (signal) { + case SIGCHLD: + /* + * Wait for Mail Client child process termination. Child enters + * zombie state: process is dead and most resources are + * released, but process descriptor remains until parent reaps + * exit status via wait. + */ + + /* + * The WNOHANG option prevents the call to waitpid from + * suspending execution of the caller. + */ + (void) waitpid(0, NULL, WNOHANG); + break; + default: + fprintf(stderr, + "%s: Unregistered signal received, exiting.\n", + PACKAGE); + exit(EXIT_FAILURE); + } } -static void -CatchTimerSignal( int signal ) +static void CatchTimerSignal(int signal) { - switch( signal ) { - case SIGUSR1: - /* Catching the signal sent by the SingleClick() function. */ - manual_check = true; - break; - case SIGUSR2: - /* Catching the signal sent by the DoubleClick() function. */ - animation_stop = true; - break; - default: - fprintf( stderr, "%s: CatchTimerSignal(): unknown signal (%d)\n", PACKAGE, - signal ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } + switch (signal) { + case SIGUSR1: + /* Catching the signal sent by the SingleClick() function. */ + manual_check = true; + break; + case SIGUSR2: + /* Catching the signal sent by the DoubleClick() function. */ + animation_stop = true; + break; + default: + fprintf(stderr, + "%s: CatchTimerSignal(): unknown signal (%d)\n", + PACKAGE, signal); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } } -static void -NewMailAnimation( void ) +static void NewMailAnimation(void) { - if( animation_image == MAILBOX_FULL ) { - DisplayOpenedFullMailbox(); - animation_image = MAILBOX_CLOSED; - if( wmnotify_infos.debug ) { - printf( "%s: NewMailAnimation() MAILBOX_FULL.\n", PACKAGE ); - } - } - else { - DisplayClosedMailbox(); - animation_image = MAILBOX_FULL; - if( wmnotify_infos.debug ) { - printf( "%s: NewMailAnimation() MAILBOX_CLOSED.\n", PACKAGE ); - } - } + if (animation_image == MAILBOX_FULL) { + DisplayOpenedFullMailbox(); + animation_image = MAILBOX_CLOSED; + if (wmnotify_infos.debug) { + printf("%s: NewMailAnimation() MAILBOX_FULL.\n", + PACKAGE); + } + } else { + DisplayClosedMailbox(); + animation_image = MAILBOX_FULL; + if (wmnotify_infos.debug) { + printf("%s: NewMailAnimation() MAILBOX_CLOSED.\n", + PACKAGE); + } + } } /* We display the opened mailbox image only when doing a manual check. */ -static int -CheckForNewMail( bool manual_check ) +static int CheckForNewMail(bool manual_check) { - int new_messages; - - if( manual_check == true ) { - DisplayOpenedEmptyMailbox(); - } - - if( wmnotify_infos.protocol == POP3_PROTOCOL ) { - new_messages = POP3_CheckForNewMail(); - } - else if( wmnotify_infos.protocol == IMAP4_PROTOCOL ) { - new_messages = IMAP4_CheckForNewMail(); - } - else { - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - if( ( manual_check == true ) && ( new_messages > 0 ) ) { - animation_image = MAILBOX_FULL; - } - - return new_messages; -} + int new_messages; + + if (manual_check == true) + DisplayOpenedEmptyMailbox(); + + if (wmnotify_infos.protocol == POP3_PROTOCOL) { + new_messages = POP3_CheckForNewMail(); + } else if (wmnotify_infos.protocol == IMAP4_PROTOCOL) { + new_messages = IMAP4_CheckForNewMail(); + } else { + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + if ((manual_check == true) && (new_messages > 0)) + animation_image = MAILBOX_FULL; + + return new_messages; +} -static void * -TimerThread( /*@unused@*/ void *arg ) +static void check_audio_notification(bool *animation_running) { - int new_messages = 0; - int counter = -1; - bool animation_running = false; - - /* For catching the signal SIGUSR1. This signal is sent by the main program thread when the - * user is issuing a single-click to manually check for new mails. */ - (void) signal( SIGUSR1, CatchTimerSignal ); - - /* For catching the signal SIGUSR2. This signal is sent by the main program thread when the - * user is issuing a double-click to start ther external mail client. */ - (void) signal( SIGUSR2, CatchTimerSignal ); - - while( quit == false ) { - if( wmnotify_infos.debug ) { - printf( "%s: Timer thread iteration.\n", PACKAGE ); - } - if( ( manual_check == true ) || ( counter == 0 ) ) { - new_messages = CheckForNewMail( manual_check ); - manual_check = false; - - if( wmnotify_infos.debug ) { - printf( "%s: new messages = %d.\n", PACKAGE, new_messages ); - } - - if( new_messages > 0 ) { - /* Checking if audio notification was already produced. */ - if( animation_running == false ) { - /* Audible notification, if requested in configuration file. */ - if( wmnotify_infos.audible_notification != false ) { - if( strlen( wmnotify_infos.audiofile ) != 0 ) { + /* + * Checking if audio notification was already + * produced. + */ + if (*animation_running == false) { + /* Audible notification, if requested in configuration file. */ + if (wmnotify_infos.audible_notification) { + if (strlen(wmnotify_infos.audiofile) != 0) { #if defined(HAVE_SNDFILE) - PlayAudioFile( wmnotify_infos.audiofile, wmnotify_infos.volume ); + PlayAudioFile(wmnotify_infos.audiofile, + wmnotify_infos.volume); #endif - } - else { - AudibleBeep(); - } - } - - animation_running = true; - } - /* Number of times to execute timer loop before checking again for new mails when the - * animation is running (when the animation is running, we sleep for - * NEW_MAIL_ANIMATION_DURATION instead of wmnotify_infos.mail_check_interval). We set - * the check interval to 30 seconds because we want the new mail condition to be - * removed as soon as possible when the new messages are checked. */ - counter = 30 * 1000000 / NEW_MAIL_ANIMATION_DURATION; - } - } - - if( ( animation_stop == true ) || ( new_messages <= 0 ) ) { - if( wmnotify_infos.debug ) { - if( animation_stop != false ) { - printf( "%s: animation_stop is true\n", PACKAGE ); + } else { + AudibleBeep(); + } + } + + *animation_running = true; } - } - animation_running = false; - animation_stop = false; - if( double_click_notif == false ) { - /* Before exiting, be sure to put NO MAIL image back in place... */ - DisplayClosedMailbox(); - } - } - - /* If sleep() returns because the requested time has elapsed, the value returned will be - * 0. If sleep() returns because of premature arousal due to delivery of a signal, the - * return value will be the "unslept" amount (the requested time minus the time actually - * slept) in seconds. */ - - if( animation_running == false ) { - (void) sleep( wmnotify_infos.mail_check_interval ); - counter = 0; - } - else { - NewMailAnimation(); - (void) usleep( NEW_MAIL_ANIMATION_DURATION ); - counter--; - } - - if( wmnotify_infos.debug ) { - printf( "%s: counter = %d\n", PACKAGE, counter ); - } - } /* end while */ - - if( wmnotify_infos.debug ) { - printf( "%s: Error, TimerThread() exited abnormally\n", PACKAGE ); - } - - /* This code is never reached for now, because quit is always false. */ - pthread_exit( NULL ); +} + +static void *TimerThread(void *arg) +{ + int new_messages = 0; + int counter = -1; + bool animation_running = false; + + /* + * For catching the signal SIGUSR1. This signal is sent by the main + * program thread when the user is issuing a single-click to manually + * check for new mails. + */ + (void) signal(SIGUSR1, CatchTimerSignal); + + /* + * For catching the signal SIGUSR2. This signal is sent by the main + * program thread when the user is issuing a double-click to start their + * external mail client. + */ + (void) signal(SIGUSR2, CatchTimerSignal); + + while (quit == false) { + if (wmnotify_infos.debug) + printf("%s: Timer thread iteration.\n", PACKAGE); + + if ((manual_check == true) || (counter == 0)) { + new_messages = CheckForNewMail(manual_check); + manual_check = false; + + if (wmnotify_infos.debug) { + printf("%s: new messages = %d.\n", PACKAGE, + new_messages); + } + + if (new_messages > 0) { + check_audio_notification(&animation_running); + + /* + * Number of times to execute timer loop before + * checking again for new mails when the + * animation is running (when the animation is + * running, we sleep for + * NEW_MAIL_ANIMATION_DURATION instead of + * wmnotify_infos.mail_check_interval). We set + * the check interval to 30 seconds because we + * want the new mail condition to be removed as + * soon as possible when the new messages are + * checked. + */ + counter = 30 * 1000000 / + NEW_MAIL_ANIMATION_DURATION; + } + } + + if ((animation_stop == true) || (new_messages <= 0)) { + if (wmnotify_infos.debug) { + if (animation_stop != false) { + printf + ("%s: animation_stop is true\n", + PACKAGE); + } + } + animation_running = false; + animation_stop = false; + if (double_click_notif == false) { + /* + * Before exiting, be sure to put NO MAIL image + * back in place. + */ + DisplayClosedMailbox(); + } + } + + /* + * If sleep() returns because the requested time has elapsed, + * the value returned will be 0. If sleep() returns because of + * premature arousal due to delivery of a signal, the return + * value will be the "unslept" amount (the requested time minus + * the time actually slept) in seconds. + */ + if (animation_running == false) { + (void) sleep(wmnotify_infos.mail_check_interval); + counter = 0; + } else { + NewMailAnimation(); + (void) usleep(NEW_MAIL_ANIMATION_DURATION); + counter--; + } + + if (wmnotify_infos.debug) + printf("%s: counter = %d\n", PACKAGE, counter); + } /* end while */ + + if (wmnotify_infos.debug) + printf("%s: Error, TimerThread() exited abnormally\n", PACKAGE); + + /* This code is never reached for now, because quit is always false. */ + pthread_exit(NULL); } /******************************************************************************* * Main function ******************************************************************************/ -int -main( int argc, char *argv[] ) +int main(int argc, char *argv[]) { - int status; - - /* Initialization */ - ParseCommandLineOptions( argc, argv ); - - /* Reading configuration options from configuration file. */ - ConfigurationFileInit(); - - /* For catching the termination signal SIGCHLD when the external mail client - program is terminated, thus permitting removing zombi processes... */ - (void) signal( SIGCHLD, CatchChildTerminationSignal ); - - /* Initialize callback function pointers. */ - ProcessXlibEventsInit( SingleClick, DoubleClick ); - - /* Initializing and creating a DockApp window. */ - InitDockAppWindow( argc, argv, wmnotify_xpm, wmnotify_infos.display_arg, - wmnotify_infos.geometry_arg ); - - /* Starting thread for periodically checking for new mail. */ - status = pthread_create( &timer_thread, NULL, TimerThread, NULL ); - if( status != 0 ) { - fprintf( stderr, "%s: Thread creation failed (%d)\n", PACKAGE, status ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - /* Main loop, processing X Events */ - ProcessXlibEvents(); - - /* This code is never reached for now. */ - fprintf( stderr, "%s: Program exit\n", PACKAGE ); - - exit( EXIT_SUCCESS ); + int status; + + /* Initialization */ + ParseCommandLineOptions(argc, argv); + + /* Reading configuration options from configuration file. */ + ConfigurationFileInit(); + + /* + * For catching the termination signal SIGCHLD when the external mail + * client program is terminated, thus permitting removing zombi + * processes... + */ + (void) signal(SIGCHLD, CatchChildTerminationSignal); + + /* Initialize callback function pointers. */ + ProcessXlibEventsInit(SingleClick, DoubleClick); + + /* Initializing and creating a DockApp window. */ + InitDockAppWindow(argc, argv, wmnotify_xpm, + wmnotify_infos.display_arg, + wmnotify_infos.geometry_arg); + + /* Starting thread for periodically checking for new mail. */ + status = pthread_create(&timer_thread, NULL, TimerThread, NULL); + if (status != 0) { + fprintf(stderr, "%s: Thread creation failed (%d)\n", + PACKAGE, status); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + /* Main loop, processing X Events */ + ProcessXlibEvents(); + + /* This code is never reached for now. */ + fprintf(stderr, "%s: Program exit\n", PACKAGE); + + exit(EXIT_SUCCESS); } diff --git a/src/wmnotify.h b/src/wmnotify.h index 0588e97..6c5e88d 100644 --- a/src/wmnotify.h +++ b/src/wmnotify.h @@ -36,15 +36,24 @@ #define MAILBOX_CLOSED_SRC_X 64 #define MAILBOX_CLOSED_SRC_Y 4 -/* Source coordinates in global pixmap for the opened and empty mailbox image. */ +/* + * Source coordinates in global pixmap for the opened and empty mailbox + * image. + */ #define MAILBOX_OPENED_EMPTY_SRC_X 64 #define MAILBOX_OPENED_EMPTY_SRC_Y 64 -/* Source coordinates in global pixmap for the opened and full mailbox image. */ +/* + * Source coordinates in global pixmap for the opened and full mailbox + * image. + */ #define MAILBOX_OPENED_FULL_SRC_X 4 #define MAILBOX_OPENED_FULL_SRC_Y 64 -/* Source coordinates in global pixmap for the opened and full mailbox image. */ +/* + * Source coordinates in global pixmap for the opened and full mailbox + * image. + */ #define EXEC_CMD_IMG_SRC_X 124 #define EXEC_CMD_IMG_SRC_Y 4 @@ -60,26 +69,25 @@ #define MAX_STR_LEN 256 -struct wmnotify_t -{ - bool debug; - char *display_arg; - char *geometry_arg; - char *optional_config_file; - char mail_client_command[512]; - char *mail_client_argv[ARGV_LIMIT]; - unsigned int mail_check_interval; /* In seconds. */ - bool audible_notification; - char audiofile[512]; - int volume; - int protocol; - char imap_folder[MAX_STR_LEN]; - bool use_ssl; - char server_name[MAX_STR_LEN]; - int port; - char username[MAX_STR_LEN]; - char password[MAX_STR_LEN]; - int sock_fd; +struct wmnotify_t { + bool debug; + char *display_arg; + char *geometry_arg; + char *optional_config_file; + char mail_client_command[512]; + char *mail_client_argv[ARGV_LIMIT]; + unsigned int mail_check_interval; /* In seconds. */ + bool audible_notification; + char audiofile[512]; + int volume; + int protocol; + char imap_folder[MAX_STR_LEN]; + bool use_ssl; + char server_name[MAX_STR_LEN]; + int port; + char username[MAX_STR_LEN]; + char password[MAX_STR_LEN]; + int sock_fd; }; /* Exported variables */ diff --git a/src/xevents.c b/src/xevents.c index 976aaad..3eec774 100644 --- a/src/xevents.c +++ b/src/xevents.c @@ -44,105 +44,118 @@ /* Function pointers to handle single and double mouse click events. */ -static void (*SingleClickCallback)( void ) = NULL; +static void (*SingleClickCallback) (void); -static void (*DoubleClickCallback)( void ) = NULL; +static void (*DoubleClickCallback) (void); -void -AudibleBeep( void ) +void AudibleBeep(void) { - /* The specified volume is relative to the base volume for the keyboard. - To change the base volume of the keyboard, use XChangeKeyboardControl(). */ - (void) XBell( dockapp.display, 100 ); /* Volume = 100% */ + /* + * The specified volume is relative to the base volume for the keyboard. + * To change the base volume of the keyboard, use + * XChangeKeyboardControl(). + */ + (void) XBell(dockapp.display, 100); /* Volume = 100% */ } /* This function must be called at the beginning of your program to initialize the function pointers to handle single and double click mouse events. */ void -ProcessXlibEventsInit( void (*single_click_callback)( void ), - void (*double_click_callback)( void ) ) +ProcessXlibEventsInit(void (*single_click_callback) (void), + void (*double_click_callback) (void)) { - int status; - - /* This must be called before any other XLib functions. */ - status = XInitThreads(); - if( status == 0 ) { - fprintf( stderr, "%s: XInitThreads() initialization failed\n", PACKAGE ); - ErrorLocation( __FILE__, __LINE__ ); - exit( EXIT_FAILURE ); - } - - SingleClickCallback = single_click_callback; - DoubleClickCallback = double_click_callback; + int status; + + /* This must be called before any other XLib functions. */ + status = XInitThreads(); + if (status == 0) { + fprintf(stderr, + "%s: XInitThreads() initialization failed\n", + PACKAGE); + ErrorLocation(__FILE__, __LINE__); + exit(EXIT_FAILURE); + } + + SingleClickCallback = single_click_callback; + DoubleClickCallback = double_click_callback; } +static void detect_double_click(bool *double_click) +{ + /* + * We act only when the button is + * released. + */ + if (*double_click) { + /* Double-click */ + if (DoubleClickCallback != NULL) + (*DoubleClickCallback)(); + + *double_click = false; + } else { + (void) usleep( + DOUBLE_CLICK_MAX_INTERVAL_MS + * 1000); + *double_click = true; + } +} /* Processing of X events */ -void -ProcessXlibEvents( void ) +void ProcessXlibEvents(void) { - bool quit = false; - bool button1_pressed = false; - bool check_for_double_click = false; - XEvent Event; - - while( quit == false ) { - if( ( check_for_double_click != false ) && - ( XPending( dockapp.display ) == 0 ) ) { - /* If no other button 1 events are received after the delay, then it is a - single-click mouse event. */ - if( SingleClickCallback != NULL ) { - (*SingleClickCallback)(); - } - - check_for_double_click = false; - } - /* XNextEvent is a blocking call: it will return only when an event is - ready to be processed, thus freeing the CPU for other tasks when no - events are available. */ - (void) XNextEvent( dockapp.display, &Event ); - switch( Event.type ) { - case Expose: - /* Window was uncovered... */ - RedrawWindow(); - break; - case DestroyNotify: - /* Window was killed... */ - /* Is this necessary ? */ - (void) XCloseDisplay( dockapp.display ); - quit = true; - break; - case ClientMessage: - /* Doesn't seem to work... */ - printf( "Client message received...\n" ); - break; - case ButtonPress: - if( Event.xbutton.button == Button1 ) { - /* Mouse LEFT button pressed. */ - button1_pressed = true; - } - break; - case ButtonRelease: - if( Event.xbutton.button == Button1 ) { - /* Mouse LEFT button released. */ - if( button1_pressed != false ) { - /* We act only when the button is released */ - if( check_for_double_click != false ) { - /* Double-click */ - if( DoubleClickCallback != NULL ) { - (*DoubleClickCallback)(); - } - check_for_double_click = false; - } - else { - (void) usleep( DOUBLE_CLICK_MAX_INTERVAL_MS * 1000 ); - check_for_double_click = true; - } - } - } - break; - } - } /* end while */ + bool quit = false; + bool button1_pressed = false; + bool double_click = false; + XEvent Event; + + while (quit == false) { + if ((double_click) && + (XPending(dockapp.display) == 0)) { + /* + * If no other button 1 events are received after the + * delay, then it is a single-click mouse event. + */ + if (SingleClickCallback != NULL) + (*SingleClickCallback)(); + + double_click = false; + } + /* + * XNextEvent is a blocking call: it will return only when an + * event is ready to be processed, thus freeing the CPU for + * other tasks when no events are available. + */ + (void) XNextEvent(dockapp.display, &Event); + switch (Event.type) { + case Expose: + /* Window was uncovered... */ + RedrawWindow(); + break; + case DestroyNotify: + /* Window was killed... */ + /* Is this necessary ? */ + (void) XCloseDisplay(dockapp.display); + quit = true; + break; + case ClientMessage: + /* Doesn't seem to work... */ + printf("Client message received...\n"); + break; + case ButtonPress: + if (Event.xbutton.button == Button1) { + /* Mouse LEFT button pressed. */ + button1_pressed = true; + } + break; + case ButtonRelease: + if (Event.xbutton.button == Button1) { + /* Mouse LEFT button released. */ + if (button1_pressed) + detect_double_click(&double_click); + } + break; + } + } /* end while */ } diff --git a/src/xevents.h b/src/xevents.h index 9159b7d..7ffc74f 100644 --- a/src/xevents.h +++ b/src/xevents.h @@ -21,14 +21,12 @@ #ifndef XEVENTS_H #define XEVENTS_H 1 -void -AudibleBeep(void); +void AudibleBeep(void); void -ProcessXlibEventsInit(void (*single_click_callback)(void), - void (*double_click_callback)(void)); +ProcessXlibEventsInit(void (*single_click_callback) (void), + void (*double_click_callback) (void)); -void -ProcessXlibEvents(void); +void ProcessXlibEvents(void); -#endif /* XEVENTS_H */ +#endif /* XEVENTS_H */