dss-0.1.3.
[dss.git] / string.c
index ac9c336..60c53d5 100644 (file)
--- a/string.c
+++ b/string.c
@@ -1,5 +1,11 @@
+/*
+ * Copyright (C) 2004-2009 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <stdarg.h>
 #include <assert.h>
 #include <limits.h>
 #include <unistd.h>
 
 
-#include "cmdline.h"
 #include "gcc-compat.h"
 #include "log.h"
 #include "error.h"
 #include "string.h"
 
-__noreturn void clean_exit(int status);
-
 /**
  * Write a message to a dynamically allocated string.
  *
@@ -71,7 +74,7 @@ __must_check __malloc void *dss_realloc(void *p, size_t size)
        if (!(p = realloc(p, size))) {
                DSS_EMERG_LOG("realloc failed (size = %zu), aborting\n",
                        size);
-               clean_exit(EXIT_FAILURE);
+               exit(EXIT_FAILURE);
        }
        return p;
 }
@@ -96,7 +99,7 @@ __must_check __malloc void *dss_malloc(size_t size)
        if (!p) {
                DSS_EMERG_LOG("malloc failed (size = %zu),  aborting\n",
                        size);
-               clean_exit(EXIT_FAILURE);
+               exit(EXIT_FAILURE);
        }
        return p;
 }
@@ -142,7 +145,7 @@ __must_check __malloc char *dss_strdup(const char *s)
        if ((ret = strdup(s? s: "")))
                return ret;
        DSS_EMERG_LOG("strdup failed, aborting\n");
-       clean_exit(EXIT_FAILURE);
+       exit(EXIT_FAILURE);
 }
 
 /**
@@ -166,12 +169,6 @@ __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...)
        return msg;
 }
 
-__printf_1_2 void make_err_msg(const char* fmt,...)
-{
-       free(dss_error_txt);
-       VSPRINTF(fmt, dss_error_txt);
-}
-
 /**
  * Get the home directory of the current user.
  *
@@ -201,22 +198,14 @@ int dss_atoi64(const char *str, int64_t *value)
 
        errno = 0; /* To distinguish success/failure after call */
        tmp = strtoll(str, &endptr, 10);
-       if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN)) {
-               make_err_msg("%s", str);
+       if (errno == ERANGE && (tmp == LLONG_MAX || tmp == LLONG_MIN))
                return -E_ATOI_OVERFLOW;
-       }
-       if (errno != 0 && tmp == 0) { /* other error */
-               make_err_msg("%s", str);
+       if (errno != 0 && tmp == 0) /* other error */
                return -E_STRTOLL;
-       }
-       if (endptr == str) {
-               make_err_msg("%s", str);
+       if (endptr == str)
                return -E_ATOI_NO_DIGITS;
-       }
-       if (*endptr != '\0') { /* Further characters after number */
-               make_err_msg("%s", str);
+       if (*endptr != '\0') /* Further characters after number */
                return -E_ATOI_JUNK_AT_END;
-       }
        *value = tmp;
        return 1;
 }
@@ -236,3 +225,52 @@ __must_check __malloc char *dss_logname(void)
        return dss_strdup(pw? pw->pw_name : "unknown_user");
 }
 
+/**
+ * Split string and return pointers to its parts.
+ *
+ * \param args The string to be split.
+ * \param argv_ptr Pointer to the list of substrings.
+ * \param delim Delimiter.
+ *
+ * This function modifies \a args by replacing each occurance of \a delim by
+ * zero. A \p NULL-terminated array of pointers to char* is allocated dynamically
+ * and these pointers are initialized to point to the broken-up substrings
+ * within \a args. A pointer to this array is returned via \a argv_ptr.
+ *
+ * \return The number of substrings found in \a args.
+ */
+__must_check unsigned split_args(char *args, char *** const argv_ptr, const char *delim)
+{
+       char *p = args;
+       char **argv;
+       size_t n = 0, i, j;
+
+       p = args + strspn(args, delim);
+       for (;;) {
+               i = strcspn(p, delim);
+               if (!i)
+                       break;
+               p += i;
+               n++;
+               p += strspn(p, delim);
+       }
+       *argv_ptr = dss_malloc((n + 1) * sizeof(char *));
+       argv = *argv_ptr;
+       i = 0;
+       p = args + strspn(args, delim);
+       while (p) {
+               argv[i] = p;
+               j = strcspn(p, delim);
+               if (!j)
+                       break;
+               p += strcspn(p, delim);
+               if (*p) {
+                       *p = '\0';
+                       p++;
+                       p += strspn(p, delim);
+               }
+               i++;
+       }
+       argv[n] = NULL;
+       return n;
+}