cfparser: filename params, with tilde expansion
authorMarko Kreen <markokr@gmail.com>
Wed, 10 Nov 2010 15:44:41 +0000 (17:44 +0200)
committerMarko Kreen <markokr@gmail.com>
Wed, 10 Nov 2010 15:44:41 +0000 (17:44 +0200)
Patch by Asko Tiidumaa, applied with minor modifications.

usual/cfparser.c
usual/cfparser.h

index 480686ce13c050162edb3522bd3cf87df0ca29f8..fdbd2fe0d4f533640299d2a409a3a88b9c235fa9 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <ctype.h>
 #include <string.h>
+#include <pwd.h>
 
 #include <usual/fileutil.h>
 #include <usual/logging.h>
@@ -246,6 +247,66 @@ bool cf_set_str(void *dst, const char *value)
        return true;
 }
 
+bool cf_set_filename(void *dst, const char *value)
+{
+       char **dst_p = dst;
+       char *tmp, *home, *p;
+       int v_len, usr_len, home_len;
+       struct passwd *pw;
+
+       /* do we need to do tilde expansion */
+       if (value[0] != '~')
+               return cf_set_str(dst, value);
+
+       /* find username end */
+       v_len = strlen(value);
+       if ((p = memchr(value, '/', v_len)) == NULL)
+               usr_len = v_len - 1;
+       else
+               usr_len = (p - value) - 1;
+
+       if (usr_len) {
+               p = malloc(usr_len + 1);
+               if (!p)
+                       return false;
+               memcpy(p, value + 1, usr_len);
+               p[usr_len] = 0;
+               pw = getpwnam(p);
+               free(p);
+               if (!pw)
+                       goto fail;
+               home = pw->pw_dir;
+       } else {
+               home = getenv("HOME");
+               if (!home) {
+                       pw = getpwuid(getuid());
+                       if (!pw)
+                               goto fail;
+                       home = pw->pw_dir;
+               }
+       }
+       if (!home)
+               goto fail;
+
+       home_len = strlen(home);
+       tmp = malloc(v_len - usr_len + home_len);
+       if (!tmp)
+               return false;
+       memcpy(tmp, home, home_len);
+       memcpy(tmp + home_len, value + usr_len + 1, v_len - usr_len - 1);
+       tmp[v_len - usr_len + home_len] = 0;
+
+       log_debug("expanded '%s' -> '%s'", value, tmp);
+
+       if (*dst_p)
+               free(*dst_p);
+       *dst_p = tmp;
+       return true;
+fail:
+       log_error("cannot to expand filename: %s", value);
+       return false;
+}
+
 bool cf_set_time_usec(void *dst, const char *value)
 {
        usec_t *ptr = dst;
index 33d34175851ede1c06e6d372cc5ff3f6bdddad0d..1c1631b0e87fb51e1b39cbcb335e0cb56132a2e5 100644 (file)
@@ -95,6 +95,8 @@ struct CfSect {
 
 /** Setter for string */
 bool cf_set_str(void *dst, const char *value);
+/** Setter for filename */
+bool cf_set_filename(void *dst, const char *value);
 /** Setter for int */
 bool cf_set_int(void *dst, const char *value);
 /** Setter for time-usec */
@@ -111,6 +113,9 @@ bool cf_set_time_double(void *dst, const char *value);
 /** String with offset relative to struct referenced in CF_REL_BASE */
 #define CF_REL_STR(x) cf_set_str, CF_VAL_REL, offsetof(CF_REL_BASE, x)
 
+/** Filename with offset relative to struct referenced in CF_REL_BASE */
+#define CF_REL_FILENAME(x) cf_set_filename, CF_VAL_REL, offsetof(CF_REL_BASE, x)
+
 /** Integer offset relative to struct referenced in CF_REL_BASE */
 #define CF_REL_BOOL(x) cf_set_int, CF_VAL_REL, offsetof(CF_REL_BASE, x)
 
@@ -126,6 +131,9 @@ bool cf_set_time_double(void *dst, const char *value);
 /** String with absolute pointer */
 #define CF_ABS_STR(x) cf_set_str, CF_VAL_ABS, (uintptr_t)&(x)
 
+/** Filename with absolute pointer */
+#define CF_ABS_FILENAME(x) cf_set_filename, CF_VAL_ABS, (uintptr_t)&(x)
+
 /** Bool with absolute pointer */
 #define CF_ABS_BOOL(x) cf_set_int, CF_VAL_ABS, (uintptr_t)&(x)