X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fmisc.c;h=b50abca74f18ac64e7e8580d93d7c131acace21c;hb=466240bdd432835656962afbc3ab9ed9f9d5797a;hp=b1ea74e078f22d7e01dbf225d13692f7f74e3b0c;hpb=343ecd1bed93fa862903ff981ede342825f14401;p=rocksndiamonds.git diff --git a/src/libgame/misc.c b/src/libgame/misc.c index b1ea74e0..b50abca7 100644 --- a/src/libgame/misc.c +++ b/src/libgame/misc.c @@ -21,7 +21,7 @@ #include "platform.h" -#if !defined(PLATFORM_WIN32) +#if defined(PLATFORM_UNIX) #include #include #endif @@ -252,7 +252,7 @@ void PrintLineWithPrefix(char *prefix, char *line_chars, int line_length) // ---------------------------------------------------------------------------- -// generic logging functions +// generic logging and error handling functions // ---------------------------------------------------------------------------- enum log_levels @@ -288,11 +288,29 @@ static void printf_log_prefix(int log_level, char *mode) printf_log_nonewline("[%s] ", log_token); } -static void Log(int log_level, char *mode, char *format, va_list ap) +static void vLog(int log_level, char *mode, char *format, va_list ap) { if (log_level < 0 || log_level > LOG_FATAL) return; + if (log_level == LOG_DEBUG) + { + // only show debug messages when in debug mode + if (!options.debug) + return; + + // if optional debug mode specified, limit debug output accordingly + if (options.debug_mode != NULL && + strstr(mode, options.debug_mode) == NULL) + return; + } + else if (log_level == LOG_WARN) + { + // only show warning messages when in verbose mode + if (!options.verbose) + return; + } + #if defined(PLATFORM_ANDROID) android_log_prio = (log_level == LOG_DEBUG ? ANDROID_LOG_DEBUG : log_level == LOG_INFO ? ANDROID_LOG_INFO : @@ -336,20 +354,53 @@ static void Log(int log_level, char *mode, char *format, va_list ap) vprintf_log(format, ap); } -void Debug(char *mode, char *format, ...) +static void Log(int log_level, char *mode, char *format, ...) { va_list ap; - if (!options.debug) - return; + va_start(ap, format); + vLog(log_level, mode, format, ap); + va_end(ap); +} + +void DebugContinued(char *mode, char *format, ...) +{ + static char message[MAX_LINE_LEN] = { 0 }; + + // initialize message (optional) + if (strEqual(format, "")) + { + message[0] = '\0'; - // if optional debug mode specified, limit debug output accordingly - if (options.debug_mode != NULL && - !strEqual(options.debug_mode, mode)) return; + } + + char *message_ptr = message + strlen(message); + int size_left = MAX_LINE_LEN - strlen(message); + va_list ap; + // append message va_start(ap, format); - Log(LOG_DEBUG, mode, format, ap); + vsnprintf(message_ptr, size_left, format, ap); + va_end(ap); + + // finalize message + if (strSuffix(format, "\n")) + { + message[strlen(message) - 1] = '\0'; + + Debug(mode, message); + + message[0] = '\0'; + } +} + +void Debug(char *mode, char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vLog(LOG_DEBUG, mode, format, ap); va_end(ap); } @@ -358,7 +409,7 @@ void Info(char *format, ...) va_list ap; va_start(ap, format); - Log(LOG_INFO, NULL, format, ap); + vLog(LOG_INFO, NULL, format, ap); va_end(ap); } @@ -367,10 +418,59 @@ void Warn(char *format, ...) va_list ap; va_start(ap, format); - Log(LOG_WARN, NULL, format, ap); + vLog(LOG_WARN, NULL, format, ap); va_end(ap); } +void Error(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vLog(LOG_ERROR, NULL, format, ap); + va_end(ap); +} + +void Fail(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vLog(LOG_FATAL, NULL, format, ap); + va_end(ap); + + if (!network.is_server_thread) + { + va_start(ap, format); + program.exit_message_function(format, ap); + va_end(ap); + } + + Log(LOG_FATAL, NULL, "aborting"); + + // network server thread: normal exit + if (network.is_server_thread) + exit(1); + + // main process: clean up stuff + program.exit_function(1); +} + +void FailWithHelp(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vLog(LOG_FATAL, NULL, format, ap); + va_end(ap); + + Log(LOG_FATAL, NULL, "try option '--help' for more information"); + Log(LOG_FATAL, NULL, "aborting"); + + // main process: clean up stuff + program.exit_function(1); +} + // ---------------------------------------------------------------------------- // string functions @@ -683,6 +783,43 @@ static char *get_corrected_real_name(char *real_name) } #endif +#if defined(PLATFORM_UNIX) +static struct passwd *getPasswdEntry(void) +{ + return getpwuid(getuid()); +} + +char *getUnixLoginName(void) +{ + struct passwd *pwd = getPasswdEntry(); + + if (pwd != NULL && strlen(pwd->pw_name) != 0) + return pwd->pw_name; + + return NULL; +} + +char *getUnixRealName(void) +{ + struct passwd *pwd = getPasswdEntry(); + + if (pwd != NULL && strlen(pwd->pw_gecos) != 0) + return pwd->pw_gecos; + + return NULL; +} + +char *getUnixHomeDir(void) +{ + struct passwd *pwd = getPasswdEntry(); + + if (pwd != NULL && strlen(pwd->pw_dir) != 0) + return pwd->pw_dir; + + return NULL; +} +#endif + char *getLoginName(void) { static char *login_name = NULL; @@ -691,6 +828,7 @@ char *getLoginName(void) if (login_name == NULL) { unsigned long buffer_size = MAX_USERNAME_LEN + 1; + login_name = checked_malloc(buffer_size); if (GetUserName(login_name, &buffer_size) == 0) @@ -699,12 +837,12 @@ char *getLoginName(void) #elif defined(PLATFORM_UNIX) && !defined(PLATFORM_ANDROID) if (login_name == NULL) { - struct passwd *pwd; + char *name = getUnixLoginName(); - if ((pwd = getpwuid(getuid())) == NULL) - login_name = ANONYMOUS_NAME; + if (name != NULL) + login_name = getStringCopy(name); else - login_name = getStringCopy(pwd->pw_name); + login_name = ANONYMOUS_NAME; } #else login_name = ANONYMOUS_NAME; @@ -731,10 +869,10 @@ char *getRealName(void) #elif defined(PLATFORM_UNIX) && !defined(PLATFORM_ANDROID) if (real_name == NULL) { - struct passwd *pwd; + char *name = getUnixRealName(); - if ((pwd = getpwuid(getuid())) != NULL && strlen(pwd->pw_gecos) != 0) - real_name = get_corrected_real_name(pwd->pw_gecos); + if (name != NULL) + real_name = get_corrected_real_name(name); else real_name = ANONYMOUS_NAME; } @@ -1090,7 +1228,7 @@ void GetOptions(int argc, char *argv[], int option_len = strlen(option); if (option_len >= MAX_OPTION_LEN) - Error(ERR_EXIT_HELP, "unrecognized option '%s'", option); + FailWithHelp("unrecognized option '%s'", option); strcpy(option_str, option); // copy argument into buffer option = option_str; @@ -1108,14 +1246,14 @@ void GetOptions(int argc, char *argv[], { *option_arg++ = '\0'; // cut argument from option if (*option_arg == '\0') // no argument after '=' - Error(ERR_EXIT_HELP, "option '%s' has invalid argument", option_str); + FailWithHelp("option '%s' has invalid argument", option_str); } option_len = strlen(option); if (strEqual(option, "-")) { - Error(ERR_EXIT_HELP, "unrecognized option '%s'", option); + FailWithHelp("unrecognized option '%s'", option); } else if (strncmp(option, "-help", option_len) == 0) { @@ -1126,7 +1264,7 @@ void GetOptions(int argc, char *argv[], else if (strncmp(option, "-basepath", option_len) == 0) { if (option_arg == NULL) - Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str); + FailWithHelp("option '%s' requires an argument", option_str); // this should be extended to separate options for ro and rw data options.ro_base_directory = ro_base_path = getStringCopy(option_arg); @@ -1145,7 +1283,7 @@ void GetOptions(int argc, char *argv[], else if (strncmp(option, "-levels", option_len) == 0) { if (option_arg == NULL) - Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str); + FailWithHelp("option '%s' requires an argument", option_str); options.level_directory = getStringCopy(option_arg); if (option_arg == next_option) @@ -1154,7 +1292,7 @@ void GetOptions(int argc, char *argv[], else if (strncmp(option, "-graphics", option_len) == 0) { if (option_arg == NULL) - Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str); + FailWithHelp("option '%s' requires an argument", option_str); options.graphics_directory = getStringCopy(option_arg); if (option_arg == next_option) @@ -1163,7 +1301,7 @@ void GetOptions(int argc, char *argv[], else if (strncmp(option, "-sounds", option_len) == 0) { if (option_arg == NULL) - Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str); + FailWithHelp("option '%s' requires an argument", option_str); options.sounds_directory = getStringCopy(option_arg); if (option_arg == next_option) @@ -1172,7 +1310,7 @@ void GetOptions(int argc, char *argv[], else if (strncmp(option, "-music", option_len) == 0) { if (option_arg == NULL) - Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str); + FailWithHelp("option '%s' requires an argument", option_str); options.music_directory = getStringCopy(option_arg); if (option_arg == next_option) @@ -1216,7 +1354,7 @@ void GetOptions(int argc, char *argv[], else if (strncmp(option, "-execute", option_len) == 0) { if (option_arg == NULL) - Error(ERR_EXIT_HELP, "option '%s' requires an argument", option_str); + FailWithHelp("option '%s' requires an argument", option_str); options.execute_command = getStringCopy(option_arg); if (option_arg == next_option) @@ -1233,7 +1371,7 @@ void GetOptions(int argc, char *argv[], #endif else if (*option == '-') { - Error(ERR_EXIT_HELP, "unrecognized option '%s'", option_str); + FailWithHelp("unrecognized option '%s'", option_str); } else if (options.server_host == NULL) { @@ -1243,125 +1381,16 @@ void GetOptions(int argc, char *argv[], { options.server_port = atoi(*options_left); if (options.server_port < 1024) - Error(ERR_EXIT_HELP, "bad port number '%d'", options.server_port); + FailWithHelp("bad port number '%d'", options.server_port); } else - Error(ERR_EXIT_HELP, "too many arguments"); + FailWithHelp("too many arguments"); options_left++; } } -// ---------------------------------------------------------------------------- -// error handling functions -// ---------------------------------------------------------------------------- - -#define MAX_INTERNAL_ERROR_SIZE 1024 - -// used by SetError() and GetError() to store internal error messages -static char internal_error[MAX_INTERNAL_ERROR_SIZE]; - -void SetError(char *format, ...) -{ - va_list ap; - - va_start(ap, format); - vsnprintf(internal_error, MAX_INTERNAL_ERROR_SIZE, format, ap); - va_end(ap); -} - -char *GetError(void) -{ - return internal_error; -} - -void Error(int mode, char *format, ...) -{ - static boolean last_line_was_separator = FALSE; - char *process_name = ""; - - if (program.log_file[LOG_ERR_ID] == NULL) - return; - -#if defined(PLATFORM_ANDROID) - android_log_prio = (mode & ERR_DEBUG ? ANDROID_LOG_DEBUG : - mode & ERR_INFO ? ANDROID_LOG_INFO : - mode & ERR_WARN ? ANDROID_LOG_WARN : - mode & ERR_EXIT ? ANDROID_LOG_FATAL : - ANDROID_LOG_UNKNOWN); -#endif - - // display debug messages only when running in debug mode - if (mode & ERR_DEBUG && !options.debug) - return; - - // display warnings only when running in verbose mode - if (mode & ERR_WARN && !options.verbose) - return; - - if (mode == ERR_INFO_LINE) - { - if (!last_line_was_separator) - printf_log_line(format, 79); - - last_line_was_separator = TRUE; - - return; - } - - last_line_was_separator = FALSE; - - if (mode & ERR_SOUND_SERVER) - process_name = " sound server"; - else if (mode & ERR_NETWORK_SERVER) - process_name = " network server"; - else if (mode & ERR_NETWORK_CLIENT) - process_name = " network client **"; - - if (format) - { -#if !defined(PLATFORM_ANDROID) - printf_log_nonewline("%s%s: ", program.command_basename, process_name); -#endif - - if (mode & ERR_WARN) - printf_log_nonewline("warning: "); - - if (mode & ERR_EXIT) - printf_log_nonewline("fatal error: "); - - va_list ap; - - va_start(ap, format); - vprintf_log(format, ap); - va_end(ap); - - if ((mode & ERR_EXIT) && !(mode & ERR_FROM_SERVER)) - { - va_start(ap, format); - program.exit_message_function(format, ap); - va_end(ap); - } - } - - if (mode & ERR_HELP) - printf_log("%s: Try option '--help' for more information.", - program.command_basename); - - if (mode & ERR_EXIT) - printf_log("%s%s: aborting", program.command_basename, process_name); - - if (mode & ERR_EXIT) - { - if (mode & ERR_FROM_SERVER) - exit(1); // child process: normal exit - else - program.exit_function(1); // main process: clean up stuff - } -} - - // ---------------------------------------------------------------------------- // checked memory allocation and freeing functions // ---------------------------------------------------------------------------- @@ -1373,7 +1402,7 @@ void *checked_malloc(unsigned int size) ptr = malloc(size); if (ptr == NULL) - Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size); + Fail("cannot allocate %d bytes -- out of memory", size); return ptr; } @@ -1385,7 +1414,7 @@ void *checked_calloc(unsigned int size) ptr = calloc(1, size); if (ptr == NULL) - Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size); + Fail("cannot allocate %d bytes -- out of memory", size); return ptr; } @@ -1395,7 +1424,7 @@ void *checked_realloc(void *ptr, unsigned int size) ptr = realloc(ptr, size); if (ptr == NULL) - Error(ERR_EXIT, "cannot allocate %d bytes -- out of memory", size); + Fail("cannot allocate %d bytes -- out of memory", size); return ptr; } @@ -2255,12 +2284,12 @@ static void dumpList(ListNode *node_first) while (node) { - printf("['%s' (%d)]\n", node->key, - ((struct ListNodeInfo *)node->content)->num_references); + Debug("internal:dumpList", "['%s' (%d)]", node->key, + ((struct ListNodeInfo *)node->content)->num_references); node = node->next; } - printf("[%d nodes]\n", getNumNodes(node_first)); + Debug("internal:dumpList", "[%d nodes]", getNumNodes(node_first)); } #endif @@ -2949,13 +2978,14 @@ struct FileInfo *getFileListFromConfigList(struct ConfigInfo *config_list, num_file_list_entries_found = list_pos + 1; if (num_file_list_entries_found != num_file_list_entries) { - Error(ERR_INFO_LINE, "-"); - Error(ERR_INFO, "inconsistant config list information:"); - Error(ERR_INFO, "- should be: %d (according to 'src/conf_xxx.h')", + Error("---"); + Error("inconsistant config list information:"); + Error("- should be: %d (according to 'src/conf_xxx.h')", num_file_list_entries); - Error(ERR_INFO, "- found to be: %d (according to 'src/conf_xxx.c')", + Error("- found to be: %d (according to 'src/conf_xxx.c')", num_file_list_entries_found); - Error(ERR_EXIT, "please fix"); + + Fail("please fix"); } freeSetupFileHash(ignore_tokens_hash); @@ -3566,14 +3596,14 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info, if (file_list_entry->default_is_cloned && strEqual(basename, UNDEFINED_FILENAME)) { - int error_mode = ERR_WARN; + void (*error_func)(char *, ...) = Warn; // we can get away without sounds and music, but not without graphics if (*listnode == NULL && artwork_info->type == ARTWORK_TYPE_GRAPHICS) - error_mode = ERR_EXIT; + error_func = Fail; - Error(error_mode, "token '%s' was cloned and has no default filename", - file_list_entry->token); + error_func("token '%s' was cloned and has no default filename", + file_list_entry->token); return; } @@ -3590,13 +3620,13 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info, if (filename == NULL) { - int error_mode = ERR_WARN; + void (*error_func)(char *, ...) = Warn; // we can get away without sounds and music, but not without graphics if (*listnode == NULL && artwork_info->type == ARTWORK_TYPE_GRAPHICS) - error_mode = ERR_EXIT; + error_func = Fail; - Error(error_mode, "cannot find default artwork file '%s'", basename); + error_func("cannot find default artwork file '%s'", basename); return; } @@ -3636,13 +3666,13 @@ static void replaceArtworkListEntry(struct ArtworkListInfo *artwork_info, } else { - int error_mode = ERR_WARN; + void (*error_func)(char *, ...) = Warn; // we can get away without sounds and music, but not without graphics if (artwork_info->type == ARTWORK_TYPE_GRAPHICS) - error_mode = ERR_EXIT; + error_func = Fail; - Error(error_mode, "cannot load artwork file '%s'", basename); + error_func("cannot load artwork file '%s'", basename); return; } @@ -3793,7 +3823,7 @@ void NotifyUserAboutErrorFile(void) #if DEBUG -#define DEBUG_PRINT_INIT_TIMESTAMPS FALSE +#define DEBUG_PRINT_INIT_TIMESTAMPS TRUE #define DEBUG_PRINT_INIT_TIMESTAMPS_DEPTH 10 #define DEBUG_NUM_TIMESTAMPS 10 @@ -3841,9 +3871,9 @@ void debug_print_timestamp(int counter_nr, char *message) float timestamp_interval; if (counter_nr < 0) - Error(ERR_EXIT, "debugging: invalid negative counter"); + Fail("debugging: invalid negative counter"); else if (counter_nr >= DEBUG_NUM_TIMESTAMPS) - Error(ERR_EXIT, "debugging: increase DEBUG_NUM_TIMESTAMPS in misc.c"); + Fail("debugging: increase DEBUG_NUM_TIMESTAMPS in misc.c"); #if DEBUG_TIME_IN_MICROSECONDS static double counter[DEBUG_NUM_TIMESTAMPS][2]; @@ -3861,12 +3891,12 @@ void debug_print_timestamp(int counter_nr, char *message) counter[counter_nr][1] = counter[counter_nr][0]; if (message) - Error(ERR_DEBUG, "%s%s%s %.3f %s", - debug_print_timestamp_get_padding(counter_nr * indent_size), - message, - debug_print_timestamp_get_padding(padding_size - strlen(message)), - timestamp_interval / 1000, - unit); + Debug("time:init", "%s%s%s %.3f %s", + debug_print_timestamp_get_padding(counter_nr * indent_size), + message, + debug_print_timestamp_get_padding(padding_size - strlen(message)), + timestamp_interval / 1000, + unit); } #if 0