common.c 3.74 KB
Newer Older
1 2 3 4
#include "common.h"

#include <stdio.h>
#include <stdlib.h>
5
#include <stdarg.h>
6 7
#include <string.h>
#include <strings.h>
8
#include <assert.h>
9 10 11 12 13 14 15 16

//

/**
 * Returns the index of the given value in the given array of values.
 * Returns -1 if the value could not be found among the allowed values.
 */
int
17 18 19
find_value_index (
	const char * restrict strval, const char * restrict values [], int nvals
) {
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
	for (int i = 0; i < nvals; i++) {
		if (strcasecmp (values [i], strval) == 0) {
			return i;
		}
	}

	return -1;
}

//

/**
 * Reports an error and terminates the program. This function implements the
 * slow path of check_error(). It prints the given error message and exits with
 * an error code indicating a generic error.
 */
void
37 38 39 40 41
die_with_error (const char * restrict format, va_list args) {
	fprintf (stderr, AGENT_NAME ": error: ");
	vfprintf (stderr, format, args);
	fprintf (stderr, "\n");

42 43 44 45 46 47 48 49 50 51 52
	exit (ERROR_GENERIC);
}


/**
 * Reports a standard library error and terminates the program. This function
 * implements the slow path of check_std_error(). It prints the given error
 * message along with the error message provided by the standard library and
 * exits with an error code indicating failure in standard library call.
 */
void
53
die_with_std_error (int errnum, const char * restrict format, va_list args) {
54
	char * cause = strerror (errnum);
55 56 57 58 59 60
	fprintf (stderr, AGENT_NAME ": std-error: %s\n", cause);

	fprintf (stderr, AGENT_NAME ": ");
	vfprintf (stderr, format, args);
	fprintf (stderr, "\n");

61 62 63
	exit (ERROR_STD);
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
// ****************************************************************************
// STRING UTILS SECTION
// ****************************************************************************

size_t
substr_count(const char * string, const char * restrict substr) {
	size_t count = 0;
	for(const char * token = string; (token = strstr(token, substr)) != NULL; ++token)
	{
		++count;
	}
	return (count);
}

char **
split_string(char * string, const char * restrict separator, size_t * tkns) {
	size_t tokens = substr_count(string, separator) + 1;
	assert(tokens > 0);
	char ** arr = malloc(tokens * sizeof(char *));
	arr[0] = strtok(string, separator);

	for(size_t i = 1; i < tokens; ++i)
		arr[i] = strtok(NULL, separator);

	*tkns = tokens;
	return (arr);
}
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

#ifdef MINGW

/**
 * Obtains an error message for the given error code.
 * Allocates a new string that has to be released by the caller.
 */
static char *
__get_error_message (const DWORD msg_id) {
	LPVOID msg_buffer = NULL;
	size_t size = FormatMessageA (
		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, msg_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &msg_buffer, 0, NULL
	);

	if (size != 0 && msg_buffer != NULL) {
		char * message = strdup (msg_buffer);
		LocalFree (msg_buffer);
		return message;

	} else {
		static const char * msg_format = "unknown error (%d)";
		size_t msg_length = strlen (msg_format) + ((sizeof(DWORD) * 8) / 3) + 1;
		char * message = (char *) malloc (msg_length);
		if (message != NULL) {
			snprintf (message, msg_length, msg_format, msg_id);
		}

		return message;
	}
}


/**
 * Reports a windows error and terminates the program. This function
 * implements the slow path of check_win_error(). It prints the given error
 * message along with the error message provided by windows and
 * exits with an error code indicating failure in standard library call.
 */
void
131 132 133
die_with_win_error (DWORD errnum, const char * restrict format, va_list args) {
	const char * restrict cause = __get_error_message (errnum);
	fprintf (stderr, AGENT_NAME ": std-error: %s\n", cause);
134 135 136 137
	if (cause != NULL) {
		free (cause);
	}

138 139 140 141
	fprintf (stderr, AGENT_NAME ": ");
	vfprintf (stderr, format, args);
	fprintf (stderr, "\n");

142 143 144 145
	exit (ERROR_STD);
}

#endif /* MINGW */