X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=string.c;h=9fffad13f3586796c2f66d66b884375f71c6570e;hb=refs%2Fheads%2Fpu;hp=f98b199b569856d7e6df624eaf6cb1cd7ff5802e;hpb=f484411f1a48386975f55d1273750ca3c926aa9a;p=paraslash.git diff --git a/string.c b/string.c index f98b199b..56f1443f 100644 --- a/string.c +++ b/string.c @@ -43,6 +43,62 @@ __must_check void *arr_realloc(void *ptr, size_t nmemb, size_t size) return ptr; } +/** + * Allocate an array, abort on failure or bugs. + * + * \param nmemb See \ref arr_realloc(). + * \param size See \ref arr_realloc(). + * + * Like \ref arr_realloc(), this aborts on invalid arguments, integer overflow + * and allocation errors. + * + * \return A pointer to newly allocated memory which is suitably aligned for + * any kind of variable. + * + * \sa See \ref arr_realloc(). + */ +__must_check __malloc void *arr_alloc(size_t nmemb, size_t size) +{ + return arr_realloc(NULL, nmemb, size); +} + +/** + * Allocate and initialize an array, abort on failure or bugs. + * + * \param nmemb See \ref arr_realloc(). + * \param size See \ref arr_realloc(). + * + * This calls \ref arr_alloc() and zeroes-out the array. + * + * \return See \ref arr_alloc(). + */ +__must_check __malloc void *arr_zalloc(size_t nmemb, size_t size) +{ + void *ptr = arr_alloc(nmemb, size); + + /* + * This multiplication can not overflow because the above call to \ref + * arr_alloc() aborts on overflow. + */ + memset(ptr, 0, nmemb * size); + return ptr; +} + +/** + * Allocate and initialize memory. + * + * \param size The desired new size. + * + * \return A pointer to the allocated and zeroed-out memory, which is suitably + * aligned for any kind of variable. + * + * \sa \ref alloc(), calloc(3). + */ +__must_check void *zalloc(size_t size) +{ + return arr_zalloc(1, size); +} + /** * Paraslash's version of realloc(). * @@ -76,34 +132,7 @@ __must_check void *para_realloc(void *p, size_t size) */ __must_check __malloc void *alloc(size_t size) { - void *p; - - assert(size); - p = malloc(size); - if (!p) { - PARA_EMERG_LOG("malloc failed (size = %zu), aborting\n", - size); - exit(EXIT_FAILURE); - } - return p; -} - -/** - * Allocate and initialize memory. - * - * \param size The desired new size. - * - * \return A pointer to the allocated and zeroed-out memory, which is suitably - * aligned for any kind of variable. - * - * \sa \ref alloc(), calloc(3). - */ -__must_check __malloc void *zalloc(size_t size) -{ - void *ret = alloc(size); - - memset(ret, 0, size); - return ret; + return arr_alloc(1, size); } /** @@ -279,15 +308,33 @@ __must_check __malloc char *para_logname(void) } /** - * Get the home directory of the current user. + * Return the expansion of $HOME/.paraslash. + * + * If the environment variable HOME is unset or empty, the function prints an + * error message and aborts. Otherwise, on the first call the memory for the + * string is allocated and a pointer to this memory location is returned. + * Subsequent calls return a pointer to the memory that was allocated during + * the first call. * - * \return A dynamically allocated string that must be freed by the caller. If - * the home directory could not be found, this function returns "/tmp". + * \return A pointer to a C string, allocated on the heap. Callers should make + * sure that free() is only called once. + * + * \sa getenv(3), getuid(2). */ -__must_check __malloc char *para_homedir(void) +__malloc char *get_confdir(void) { - struct passwd *pw = getpwuid(getuid()); - return para_strdup(pw? pw->pw_dir : "/tmp"); + static char *dot_para; + const char *home; + + if (dot_para) + return dot_para; + home = getenv("HOME"); + if (!home || !*home) { + PARA_EMERG_LOG("fatal: HOME is unset or empty"); + exit(EXIT_FAILURE); + } + dot_para = make_message("%s/.paraslash", home); + return dot_para; } /** @@ -570,37 +617,6 @@ int para_atoi32(const char *str, int32_t *value) return 1; } -static inline int loglevel_equal(const char *arg, const char * const ll) -{ - return !strncasecmp(arg, ll, strlen(ll)); -} - -/** - * Compute the loglevel number from its name. - * - * \param txt The name of the loglevel (debug, info, ...). - * - * \return The numeric representation of the loglevel name. - */ -int get_loglevel_by_name(const char *txt) -{ - if (loglevel_equal(txt, "debug")) - return LL_DEBUG; - if (loglevel_equal(txt, "info")) - return LL_INFO; - if (loglevel_equal(txt, "notice")) - return LL_NOTICE; - if (loglevel_equal(txt, "warning")) - return LL_WARNING; - if (loglevel_equal(txt, "error")) - return LL_ERROR; - if (loglevel_equal(txt, "crit")) - return LL_CRIT; - if (loglevel_equal(txt, "emerg")) - return LL_EMERG; - return -E_BAD_LL; -} - static int get_next_word(const char *buf, const char *delim, char **word) { enum line_state_flags {LSF_HAVE_WORD = 1, LSF_BACKSLASH = 2, @@ -741,13 +757,11 @@ void free_argv(char **argv) static int create_argv_offset(int offset, const char *buf, const char *delim, char ***result) { - char *word, **argv = alloc((offset + 1) * sizeof(char *)); + char *word, **argv = arr_zalloc(offset + 1, sizeof(char *)); const char *p; int i, ret; - for (i = 0; i < offset; i++) - argv[i] = NULL; - for (p = buf; p && *p; p += ret, i++) { + for (p = buf, i = offset; p && *p; p += ret, i++) { ret = get_next_word(p, delim, &word); if (ret < 0) goto err; @@ -808,27 +822,6 @@ int create_shifted_argv(const char *buf, const char *delim, char ***result) return create_argv_offset(1, buf, delim, result); } -/** - * Find out if the given string is contained in the arg vector. - * - * \param arg The string to look for. - * \param argv The array to search. - * - * \return The first index whose value equals \a arg, or \p -E_ARG_NOT_FOUND if - * arg was not found in \a argv. - */ -int find_arg(const char *arg, char **argv) -{ - int i; - - if (!argv) - return -E_ARG_NOT_FOUND; - for (i = 0; argv[i]; i++) - if (strcmp(arg, argv[i]) == 0) - return i; - return -E_ARG_NOT_FOUND; -} - /** * Compile a regular expression. * @@ -1029,7 +1022,7 @@ __must_check int strwidth(const char *s, size_t *result) return -ERRNO_TO_PARA_ERROR(errno); if (num_wchars == 0) return 0; - dest = alloc((num_wchars + 1) * sizeof(*dest)); + dest = arr_alloc(num_wchars + 1, sizeof(*dest)); src = s; memset(&state, 0, sizeof(state)); num_wchars = mbsrtowcs(dest, &src, num_wchars, &state); @@ -1084,7 +1077,7 @@ __must_check int sanitize_str(const char *src, size_t max_width, num_wchars = mbsrtowcs(NULL, &src, 0, &state); if (num_wchars == (size_t)-1) return -ERRNO_TO_PARA_ERROR(errno); - wcs = alloc((num_wchars + 1) * sizeof(*wcs)); + wcs = arr_alloc(num_wchars + 1, sizeof(*wcs)); memset(&state, 0, sizeof(state)); num_wchars = mbsrtowcs(wcs, &src, num_wchars + 1, &state); assert(num_wchars != (size_t)-1);