diff options
| -rw-r--r-- | src/disp.c | 79 |
1 files changed, 72 insertions, 7 deletions
@@ -1,12 +1,76 @@ +#include <assert.h> #include <dlfcn.h> #include <limits.h> -#include <string.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> -#include <assert.h> +#include <string.h> +#include <sys/stat.h> +#include <errno.h> #include "disp.h" +void +/* Internals of strbuild. */ +__strbuild(char *buf, int size, + const char *file, int line, + const char *fmt, ...) +{ + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + if (len < 0) + { + fprintf(stderr, "%s:%d: ", file, line); + perror(""); + exit(EXIT_FAILURE); + } + if (len >= size) + { + fprintf(stderr, "%s:%d: error: not enough space, " + "have %d, need at least %d\n", + file, line, + size, len + 1); + exit(EXIT_FAILURE); + } + + va_start(ap, fmt); + len = vsnprintf(buf, size, fmt, ap); + va_end(ap); + + assert(len >= 0); +} + +/* Safely create a formatted string and write it to BUF. BUF shall be a buffer + * of size at least SIZE. BUF can be stack-allocated. If the formatting cannot + * be performed, exit(3) is called. This function is not meant to be called + * directly: the macro strbuild should be used. The code is adapted from the + * make_message function of the vsnprintf(3) manual page, section "examples". */ +#define strbuild(buf, fmt, ...) \ + __strbuild(buf, sizeof(buf), __FILE__, __LINE__, fmt, __VA_ARGS__) + +#define strbuild_with_size(buf, size, fmt, ...) \ + __strbuild(buf, size, __FILE__, __LINE__, fmt, __VA_ARGS__) + +int +file_exists(const char *path) +{ + struct stat statbuf __attribute__((unused)); + int rc = stat(path, &statbuf); + if (rc == 0) + return 1; + else if ((rc == -1) && (errno == ENOENT)) + return 0; + fprintf(stderr, "stat: \"%s\": ", path); + perror(""); + exit(EXIT_FAILURE); +} + + static void * load_generic_symbol(struct disp *disp, char *base_name) { @@ -57,12 +121,13 @@ load_symbols(struct disp *disp) struct disp * get_disp(char *disp_name) { - /* displays are shared libraries */ char so_path[128]; - strcpy(so_path, CALCULER_PREFIX); - strcat(so_path, "/lib/calculer/lib"); - strcat(so_path, disp_name); - strcat(so_path, ".so"); + /* local lookup, useful while developing */ + strbuild(so_path, "./lib%s.so", disp_name); + + if (!file_exists(so_path)) + strbuild(so_path, "%s/lib/calculer/lib%s.so", CALCULER_PREFIX, disp_name); + struct disp *disp = malloc(sizeof(*disp)); disp->so_path = strdup(so_path); disp->name = disp_name; |
