From 59b05c8bc31982a8b3b1012cb84601cfb4216bf6 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Tue, 1 Jan 2008 20:19:31 -0500 Subject: [PATCH] Update the log settings (path, enabled, etc) on each file reload. Fixed print_fmt() to be thread safe. Cleanups. Added misc.[ch]. --- src/Makefile.am | 2 +- src/commands.c | 204 +++++++++------------------------------------ src/commands.h | 6 +- src/common.h | 4 - src/misc.c | 167 +++++++++++++++++++++++++++++++++++++ src/{pinentry.h => misc.h} | 18 ++-- src/pinentry.c | 4 +- src/pinentry.h | 1 - src/pwmd.c | 62 +++++++------- src/xml.c | 131 ++++++++++++----------------- src/xml.h | 5 +- 11 files changed, 309 insertions(+), 295 deletions(-) create mode 100644 src/misc.c copy src/{pinentry.h => misc.h} (63%) diff --git a/src/Makefile.am b/src/Makefile.am index 2d382c03..c752081d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ bin_PROGRAMS = pwmd pwmd_SOURCES = pwmd.c pwmd.h xml.c xml.h pwmd_error.c pwmd_error.h commands.c \ - commands.h common.h cache.c cache.h gettext.h + commands.h common.h cache.c cache.h gettext.h misc.c misc.h pwmd_LDFLAGS = @XML_LIBS@ @GLIB_LIBS@ @LIBGCRYPT_LIBS@ @GPG_ERROR_LIBS@ pwmd_CFLAGS = -DLOCALEDIR=\"${prefix}/share/locale\" @XML_CPPFLAGS@ @GLIB_CFLAGS@ \ @LIBGCRYPT_CFLAGS@ @LIBASSUAN_PTH_CFLAGS@ @GPG_ERROR_CFLAGS@ diff --git a/src/commands.c b/src/commands.c index 857d54c7..dfd89d7c 100644 --- a/src/commands.c +++ b/src/commands.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -47,6 +46,7 @@ #include "pwmd_error.h" #include "cache.h" +#include "misc.h" #include "commands.h" static void *z_alloc(void *data, unsigned items, unsigned size) @@ -95,7 +95,7 @@ static gboolean encrypt_xml(gcry_cipher_hd_t gh, void *outbuf, gsize outsize, return TRUE; } -gpg_error_t decrypt_xml(gcry_cipher_hd_t gh, void *outbuf, gsize outsize, +static gpg_error_t decrypt_xml(gcry_cipher_hd_t gh, void *outbuf, gsize outsize, void *inbuf, gsize insize) { gpg_error_t rc; @@ -118,36 +118,6 @@ static gpg_error_t parse_xml(assuan_context_t ctx) return 0; } -gboolean valid_filename(const gchar *filename) -{ - const gchar *p; - - if (!filename || !*filename) - return FALSE; - - for (p = filename; *p; p++) { - if (g_ascii_isalnum(*p) == FALSE && *p != '-' && *p != '_' && *p != '.') - return FALSE; - } - - return TRUE; -} - -gint open_file(const gchar *filename, struct stat *st) -{ - gint fd; - - if ((fd = open(filename, O_RDONLY)) == -1) - return -1; - - if (stat(filename, st) == -1) { - close(fd); - return -1; - } - - return fd; -} - void unlock_file_mutex(struct client_s *client) { pth_mutex_t *m; @@ -249,17 +219,6 @@ static void cleanup_client(struct client_s *client) CACHE_UNLOCK; } -static gchar *print_fmt(const char *fmt, ...) -{ - va_list ap; - static gchar buf[ASSUAN_LINELENGTH] = {0}; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - return buf; -} - gboolean do_decompress(assuan_context_t ctx, gpointer in, gint insize, gpointer *out, glong *outsize, gint *error) { @@ -269,6 +228,7 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gint insize, gz_header h; gchar buf[17]; gpg_error_t rc; + gchar str[ASSUAN_LINELENGTH]; z.zalloc = z_alloc; z.zfree = z_free; @@ -338,7 +298,7 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gint insize, if (ctx) { rc = assuan_write_status(ctx, "DECOMPRESS", - print_fmt("%i %i", z.total_out, insize)); + print_fmt(str, sizeof(str), "%i %i", z.total_out, insize)); if (rc) { ret = rc; @@ -359,7 +319,7 @@ gboolean do_decompress(assuan_context_t ctx, gpointer in, gint insize, if (ctx) { rc = assuan_write_status(ctx, "DECOMPRESS", - print_fmt("%i %i", z.total_out, insize)); + print_fmt(str, sizeof(str), "%i %i", z.total_out, insize)); if (rc) { ret = rc; @@ -669,6 +629,7 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, gchar buf[17]; gint cmd = Z_NO_FLUSH; gpg_error_t rc; + gchar str[ASSUAN_LINELENGTH]; z.zalloc = z_alloc; z.zfree = z_free; @@ -735,7 +696,7 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, if (ctx) { rc = assuan_write_status(ctx, "COMPRESS", - print_fmt("%i %i", z.total_in, size)); + print_fmt(str, sizeof(str), "%i %i", z.total_in, size)); if (rc) { ret = rc; @@ -759,7 +720,7 @@ gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, if (ctx) { rc = assuan_write_status(ctx, "COMPRESS", - print_fmt("%i %i", z.total_in, size)); + print_fmt(str, sizeof(str), "%i %i", z.total_in, size)); if (rc) { ret = rc; @@ -794,6 +755,7 @@ gpg_error_t do_xml_encrypt(struct client_s *client, gcry_cipher_hd_t gh, guint iter_progress = 0, n_iter = 0, xiter = 0; gchar tmp[FILENAME_MAX]; file_header_t file_header; + gchar str[ASSUAN_LINELENGTH]; if (iter == -1) { /* @@ -851,8 +813,8 @@ gpg_error_t do_xml_encrypt(struct client_s *client, gcry_cipher_hd_t gh, while (xiter < file_header.iter) { if (client && iter_progress > 0 && xiter >= iter_progress) { if (!(xiter % iter_progress)) { - error = assuan_write_status(client->ctx, "ENCRYPT", print_fmt("%i", - ++n_iter * iter_progress)); + error = assuan_write_status(client->ctx, "ENCRYPT", + print_fmt(str, sizeof(str), "%i", ++n_iter * iter_progress)); if (error) { gcry_free(inbuf); @@ -900,7 +862,7 @@ gpg_error_t do_xml_encrypt(struct client_s *client, gcry_cipher_hd_t gh, if (client && iter_progress && file_header.iter >= iter_progress) { error = assuan_write_status(client->ctx, "ENCRYPT", - print_fmt("%i", file_header.iter)); + print_fmt(str, sizeof(str), "%i", file_header.iter)); if (error) { gcry_free(inbuf); @@ -1136,24 +1098,6 @@ done: return save_command_finalize(ctx, shakey, cached); } -static gboolean contains_whitespace(const gchar *str) -{ - const gchar *p = str; - gunichar c; - glong len; - - len = g_utf8_strlen(p++, -1) -1; - - while (len--) { - c = g_utf8_get_char(p++); - - if (g_unichar_isspace(c)) - return TRUE; - } - - return FALSE; -} - static int delete_command(assuan_context_t ctx, char *line) { struct client_s *client = assuan_get_pointer(ctx); @@ -1365,83 +1309,23 @@ static int get_command(assuan_context_t ctx, char *line) return send_error(ctx, error); } -static gchar *element_path_to_req(const gchar *account, xmlChar *path) -{ - xmlChar *p = path; - gint n; - gchar *buf; - - if (!p) - return NULL; - - for (n = 0; *p && n < 3; p++) { - if (*p == '/') - n++; - } - - if (strstr((gchar *)p, "text()") != NULL) - p[xmlStrlen(p) - 7] = 0; - - for (n = 0; p[n]; n++) { - if (p[n] == '/') - p[n] = '\t'; - } - - buf = g_strdup_printf("%s\t%s", account, p); - p = (xmlChar *)buf + strlen(buf) - 1; - - while (isspace(*p)) - *p-- = 0; - - return buf; -} - -gboolean strv_printf(gchar ***array, const gchar *fmt, ...) -{ - gchar **a; - va_list ap; - gchar *buf; - gint len = *array ? g_strv_length(*array) : 0; - gint ret; - - if (!fmt) - return FALSE; - - if ((a = g_realloc(*array, (len + 2) * sizeof(gchar *))) == NULL) - return FALSE; - - va_start(ap, fmt); - ret = g_vasprintf(&buf, fmt, ap); - va_end(ap); - - if (ret == -1) - return FALSE; - - a[len++] = buf; - a[len] = NULL; - *array = a; - return TRUE; -} - -struct realpath_s { - gchar *account; -}; - static xmlNodePtr realpath_elements_cb(xmlNodePtr node, gchar **req, gpg_error_t *error, void *data) { - struct realpath_s *rp = data; + gchar *account = *(gchar **)data; - if (rp->account) - g_free(rp->account); + if (account) + g_free(account); - rp->account = g_strdup(req[0]); + account = g_strdup(req[0]); - if (!rp->account) { + if (!account) { *error = gpg_error_from_errno(ENOMEM); + *(gchar **)data = NULL; return NULL; } + *(gchar **)data = account; return node; } @@ -1454,8 +1338,8 @@ static int realpath_command(assuan_context_t ctx, char *line) gchar *result, *t; gint i; xmlNodePtr n; - struct realpath_s *rp; GString *string; + gchar *rp_account = NULL; error = file_modified(client); @@ -1481,39 +1365,30 @@ static int realpath_command(assuan_context_t ctx, char *line) return send_error(ctx, error); } - rp = g_malloc(sizeof(struct realpath_s)); - - if (!rp) { - g_strfreev(req); - return send_syserror(ctx, ENOMEM); - } - - rp->account = g_strdup(req[0]); + rp_account = g_strdup(req[0]); - if (!rp->account) { + if (!rp_account) { g_strfreev(req); return send_syserror(ctx, ENOMEM); } if (req[1]) { n = find_elements(client->doc, n->children, req+1, &error, - NULL, realpath_elements_cb, NULL, FALSE, 0, rp); + NULL, realpath_elements_cb, NULL, FALSE, 0, &rp_account); if (!n) { - g_free(rp->account); - g_free(rp); + g_free(rp_account); g_strfreev(req); return send_error(ctx, error); } } p = xmlGetNodePath(n); - result = element_path_to_req(rp->account, p); + result = element_path_to_req(rp_account, p); if (!result) { g_free(result); - g_free(rp->account); - g_free(rp); + g_free(rp_account); g_strfreev(req); xmlFree(p); return send_syserror(ctx, ENOMEM); @@ -1521,8 +1396,7 @@ static int realpath_command(assuan_context_t ctx, char *line) string = g_string_new(result); g_free(result); - g_free(rp->account); - g_free(rp); + g_free(rp_account); g_strfreev(req); xmlFree(p); i = 0; @@ -1540,9 +1414,6 @@ again: return send_error(ctx, error); } -/* - * This could be faster especially when finding "target" attributes. - */ static int list_command(assuan_context_t ctx, char *line) { struct client_s *client = assuan_get_pointer(ctx); @@ -2146,14 +2017,15 @@ gpg_error_t send_cache_status(assuan_context_t ctx) { gchar *tmp; struct client_s *client = assuan_get_pointer(ctx); + gchar buf[ASSUAN_LINELENGTH]; CACHE_LOCK(client->ctx); - tmp = print_fmt("%i %i", + tmp = print_fmt(buf, sizeof(buf), "%i %i", cache_file_count(), (cache_size / sizeof(file_cache_t)) - cache_file_count()); CACHE_UNLOCK; - return assuan_write_status(ctx, "CACHE", tmp); + return assuan_write_status(ctx, "CACHE", buf); } static int clearcache_command(assuan_context_t ctx, char *line) @@ -2379,8 +2251,8 @@ static int option_handler(assuan_context_t ctx, const gchar *name, gpg_error_t register_commands(assuan_context_t ctx) { static struct { - const char *name; - int (*handler)(assuan_context_t, char *line); + const gchar *name; + gint (*handler)(assuan_context_t, gchar *line); } table[] = { { "OPEN", open_command }, { "SAVE", save_command }, @@ -2399,7 +2271,7 @@ gpg_error_t register_commands(assuan_context_t ctx) { "OUTPUT", NULL }, { NULL, NULL } }; - int i, rc; + gint i, rc; for (i=0; table[i].name; i++) { rc = assuan_register_command (ctx, table[i].name, table[i].handler); @@ -2409,10 +2281,12 @@ gpg_error_t register_commands(assuan_context_t ctx) } rc = assuan_register_bye_notify(ctx, cleanup_assuan); + if (rc) return rc; rc = assuan_register_option_handler(ctx, option_handler); + if (rc) return rc; @@ -2435,6 +2309,7 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, gint fd, struct stat st, glong outsize = 0; gpg_error_t error; file_header_t file_header; + gchar str[ASSUAN_LINELENGTH]; if (!ctx) { error = gcry_cipher_open(&gh, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0); @@ -2576,8 +2451,8 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, gint fd, struct stat st, while (iter < file_header.iter) { if (ctx && iter_progress > 0 && iter >= iter_progress) { if (!(iter % iter_progress)) { - error = assuan_write_status(ctx, "DECRYPT", print_fmt("%i", - ++n_iter * iter_progress)); + error = assuan_write_status(ctx, "DECRYPT", + print_fmt(str, sizeof(str), "%i", ++n_iter * iter_progress)); if (error) { gcry_free(inbuf); @@ -2620,7 +2495,8 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, gint fd, struct stat st, } if (ctx && iter_progress && file_header.iter >= iter_progress) { - error = assuan_write_status(ctx, "DECRYPT", print_fmt("%i", file_header.iter)); + error = assuan_write_status(ctx, "DECRYPT", + print_fmt(str, sizeof(str), "%i", file_header.iter)); if (error) { gcry_free(inbuf); diff --git a/src/commands.h b/src/commands.h index a711a10d..6576e927 100644 --- a/src/commands.h +++ b/src/commands.h @@ -19,9 +19,6 @@ #ifndef COMMANDS_H #define COMMANDS_H -#define _ASSUAN_ONLY_GPG_ERRORS 1 -#include - gboolean disable_list_and_dump; gpg_error_t register_commands(assuan_context_t ctx); @@ -32,5 +29,8 @@ gpg_error_t try_xml_decrypt(assuan_context_t ctx, gint fd, struct stat st, void command_finalize(assuan_context_t ctx, gint error); void unlock_file_mutex(struct client_s *client); gpg_error_t read_file_header(const gchar *filename, file_header_t *fh); +gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, + gint size, gpointer *out, glong *outsize, gint *error); +gboolean valid_filename(const gchar *filename); #endif diff --git a/src/common.h b/src/common.h index 4eed37e6..2ddaad7e 100644 --- a/src/common.h +++ b/src/common.h @@ -129,10 +129,6 @@ gint get_key_file_integer(const gchar *section, const gchar *what); gboolean get_key_file_boolean(const gchar *section, const gchar *what); gchar *get_key_file_string(const gchar *section, const gchar *what); gchar *expand_homedir(gchar *str); -gboolean strv_printf(gchar ***array, const gchar *fmt, ...); -gboolean valid_filename(const gchar *filename); -gboolean do_compress(assuan_context_t ctx, gint level, gpointer data, - gint size, gpointer *out, glong *outsize, gint *error); void free_client(struct client_s *client); #endif diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 00000000..f997c765 --- /dev/null +++ b/src/misc.c @@ -0,0 +1,167 @@ +/* vim:tw=78:ts=8:sw=4:set ft=c: */ +/* + Copyright (C) 2006-2008 Ben Kibbey + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "misc.h" + +gboolean strv_printf(gchar ***array, const gchar *fmt, ...) +{ + gchar **a; + va_list ap; + gchar *buf; + gint len = *array ? g_strv_length(*array) : 0; + gint ret; + + if (!fmt) + return FALSE; + + if ((a = g_realloc(*array, (len + 2) * sizeof(gchar *))) == NULL) + return FALSE; + + va_start(ap, fmt); + ret = g_vasprintf(&buf, fmt, ap); + va_end(ap); + + if (ret == -1) + return FALSE; + + a[len++] = buf; + a[len] = NULL; + *array = a; + return TRUE; +} + +gchar **strvcatv(gchar **dst, gchar **src) +{ + gchar **p; + gint i; + gchar **d; + + if (!src) + return NULL; + + d = g_strdupv(dst); + + if (!d) + return NULL; + + i = g_strv_length(d); + + for (p = src; *p; p++) { + gchar **pa; + + pa = g_realloc(d, (i + 2) * sizeof(gchar *)); + + if (!pa) { + g_strfreev(d); + return NULL; + } + + d = pa; + d[i] = g_strdup(*p); + + if (!d[i]) { + g_strfreev(d); + return NULL; + } + + d[++i] = NULL; + } + + return d; +} + +gboolean valid_filename(const gchar *filename) +{ + const gchar *p; + + if (!filename || !*filename) + return FALSE; + + for (p = filename; *p; p++) { + if (g_ascii_isalnum(*p) == FALSE && *p != '-' && *p != '_' && *p != '.') + return FALSE; + } + + return TRUE; +} + +gint open_file(const gchar *filename, struct stat *st) +{ + gint fd; + + if ((fd = open(filename, O_RDONLY)) == -1) + return -1; + + if (stat(filename, st) == -1) { + close(fd); + return -1; + } + + return fd; +} + +gchar *print_fmt(gchar *buf, gsize len, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + g_vsnprintf(buf, len, fmt, ap); + va_end(ap); + return buf; +} + +gboolean contains_whitespace(const gchar *str) +{ + const gchar *p = str; + gunichar c; + glong len; + + len = g_utf8_strlen(p++, -1) -1; + + while (len--) { + c = g_utf8_get_char(p++); + + if (g_unichar_isspace(c)) + return TRUE; + } + + return FALSE; +} + +gchar *expand_homedir(gchar *str) +{ + gchar *p = str; + + if (*p++ == '~') + return g_strdup_printf("%s%s", g_get_home_dir(), p); + + return g_strdup(str); +} diff --git a/src/pinentry.h b/src/misc.h similarity index 63% copy from src/pinentry.h copy to src/misc.h index 6e493c5b..d3f92e8c 100644 --- a/src/pinentry.h +++ b/src/misc.h @@ -1,6 +1,6 @@ /* vim:tw=78:ts=8:sw=4:set ft=c: */ /* - Copyright (C) 2007-2008 Ben Kibbey + Copyright (C) 2006-2008 Ben Kibbey This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,13 +16,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef PINENTRY_H -#define PINENTRY_H +#ifndef MISC_H +#define MISC_H -gpg_error_t pinentry_fork(assuan_context_t ctx); -void cleanup_pinentry(struct pinentry_s *pin); -void set_pinentry_defaults(struct pinentry_s *pin); -gpg_error_t pinentry_getpin(struct pinentry_s *pin, gchar **result); -void free_client_list(); +gboolean strv_printf(gchar ***array, const gchar *fmt, ...); +gchar **strvcatv(gchar **dst, gchar **src); +gboolean valid_filename(const gchar *filename); +gint open_file(const gchar *filename, struct stat *st); +gchar *print_fmt(gchar *buf, gsize len, const char *fmt, ...); +gchar *expand_homedir(gchar *str); +gboolean contains_whitespace(const gchar *str); #endif diff --git a/src/pinentry.c b/src/pinentry.c index 0fb30644..29b2d91e 100644 --- a/src/pinentry.c +++ b/src/pinentry.c @@ -23,9 +23,6 @@ #include #include -#define _ASSUAN_ONLY_GPG_ERRORS 1 -#include - #ifdef HAVE_CONFIG_H #include #endif @@ -40,6 +37,7 @@ typedef struct { void *buf; } membuf_t; +void free_client_list(); static gpg_error_t set_pinentry_strings(struct pinentry_s *pin, int which); static int mem_realloc_cb(void *data, const void *buffer, size_t len) diff --git a/src/pinentry.h b/src/pinentry.h index 6e493c5b..e3dbc115 100644 --- a/src/pinentry.h +++ b/src/pinentry.h @@ -23,6 +23,5 @@ gpg_error_t pinentry_fork(assuan_context_t ctx); void cleanup_pinentry(struct pinentry_s *pin); void set_pinentry_defaults(struct pinentry_s *pin); gpg_error_t pinentry_getpin(struct pinentry_s *pin, gchar **result); -void free_client_list(); #endif diff --git a/src/pwmd.c b/src/pwmd.c index 8b3586c7..32b9499d 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -62,6 +62,7 @@ #include "commands.h" #include "pwmd_error.h" #include "cache.h" +#include "misc.h" #include "pwmd.h" static void clear_rcfile_key() @@ -481,6 +482,36 @@ fail: return NULL; } +static void setup_logging(GKeyFile *kf) +{ + gboolean n = g_key_file_get_boolean(kf, "global", "enable_logging", NULL); + + if (n == TRUE) { + gchar *p = g_key_file_get_string(kf, "global", "log_path", NULL); + + if (*p == '~') { + gchar buf[PATH_MAX]; + + p++; + snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--); + g_free(p); + + if (logfile) + g_free(logfile); + + logfile = g_strdup(buf); + } + else { + if (logfile) + g_free(logfile); + + logfile = p; + } + } + + log_syslog = g_key_file_get_boolean(kf, "global", "syslog", NULL); +} + /* * Make sure all settings are set to either the specified setting or a * default. @@ -555,6 +586,8 @@ static void set_rcfile_defaults(GKeyFile *kf) if (g_key_file_has_key(kf, "global", "enable_pinentry", NULL) == FALSE) g_key_file_set_boolean(kf, "global", "enable_pinentry", TRUE); #endif + + setup_logging(kf); } static GKeyFile *parse_rcfile(int cmdline) @@ -904,16 +937,6 @@ gboolean get_key_file_boolean(const gchar *section, const gchar *what) return val; } -gchar *expand_homedir(gchar *str) -{ - gchar *p = str; - - if (*p++ == '~') - return g_strdup_printf("%s%s", g_get_home_dir(), p); - - return g_strdup(str); -} - static gboolean _getline(const gchar *file, gchar **result) { FILE *fp; @@ -1633,24 +1656,7 @@ int main(int argc, char *argv[]) errx(EXIT_FAILURE, N_("cache size must be in multiples of %li"), page_size); } - if (g_key_file_has_key(keyfileh, "global", "log_path", NULL) == TRUE) { - if (g_key_file_has_key(keyfileh, "global", "enable_logging", NULL) == TRUE) { - n = g_key_file_get_boolean(keyfileh, "global", "enable_logging", NULL); - - if (n == TRUE) { - p = g_key_file_get_string(keyfileh, "global", "log_path", NULL); - - if (*p == '~') { - p++; - snprintf(buf, sizeof(buf), "%s%s", g_get_home_dir(), p--); - g_free(p); - logfile = g_strdup(buf); - } - else - logfile = p; - } - } - } + setup_logging(keyfileh); if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE) cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL); diff --git a/src/xml.c b/src/xml.c index e1b1c2e3..951f6067 100644 --- a/src/xml.c +++ b/src/xml.c @@ -33,10 +33,12 @@ #endif #include "pwmd_error.h" +#include "misc.h" #include "xml.h" void log_write(const gchar *fmt, ...); -gboolean strv_printf(gchar ***array, const gchar *fmt, ...); +static xmlNodePtr find_element(xmlNodePtr node, gchar *element, xmlNodePtr stop); +static xmlChar *node_has_attribute(xmlNodePtr n, xmlChar *attr); gboolean is_literal_element_str(gchar *element) { @@ -144,11 +146,11 @@ xmlChar *new_document() { xmlChar *buf; const xmlChar *line = (xmlChar *) - "\n" - "\n" - "\n" - "]>\n" + "" + "" + "" + "]>" ""; buf = gcry_calloc(1, xmlStrlen(line) + 1); @@ -156,7 +158,8 @@ xmlChar *new_document() } /* - * The "target" attribute is ignored here. + * Lists root account element names. If there's a target attribute both + * literal and non-literal element names will be added. */ gpg_error_t list_accounts(xmlDocPtr doc, GString **result) { @@ -274,46 +277,10 @@ gchar **split_input_line(gchar *str, gchar *delim, gint n) return g_strsplit(str, delim, n); } -static gchar **append_element_path(gchar **dst, gchar **src) -{ - gchar **p; - gint i; - gchar **d; - - if (!src) - return NULL; - - d = g_strdupv(dst); - - if (!d) - return NULL; - - i = g_strv_length(d); - - for (p = src; *p; p++) { - gchar **pa; - - pa = g_realloc(d, (i + 2) * sizeof(gchar *)); - - if (!pa) { - g_strfreev(d); - return NULL; - } - - d = pa; - d[i] = g_strdup(*p); - - if (!d[i]) { - g_strfreev(d); - return NULL; - } - - d[++i] = NULL; - } - - return d; -} - +/* + * Prevents a sibling element past the current element path with the same + * element name. + */ static xmlNodePtr find_stop_node(xmlNodePtr node) { xmlNodePtr n; @@ -522,7 +489,7 @@ xmlNodePtr find_account(xmlDocPtr doc, gchar ***req, gpg_error_t *error, #endif tmp = *req; - tmp = append_element_path(nreq, tmp+1); + tmp = strvcatv(nreq, tmp+1); g_strfreev(nreq); if (!tmp) { @@ -540,7 +507,7 @@ xmlNodePtr find_account(xmlDocPtr doc, gchar ***req, gpg_error_t *error, } nreq = *req; - nreq = append_element_path(tmp, nreq+1); + nreq = strvcatv(tmp, nreq+1); g_strfreev(tmp); if (!nreq) { @@ -570,7 +537,7 @@ xmlNodePtr find_account(xmlDocPtr doc, gchar ***req, gpg_error_t *error, return NULL; } -xmlNodePtr find_sibling(xmlNodePtr node, gchar *element, xmlNodePtr stop) +static xmlNodePtr find_element(xmlNodePtr node, gchar *element, xmlNodePtr stop) { xmlNodePtr n; @@ -591,16 +558,8 @@ xmlNodePtr find_sibling(xmlNodePtr node, gchar *element, xmlNodePtr stop) return NULL; } -xmlNodePtr find_element(xmlNodePtr node, gchar *element, xmlNodePtr stop) -{ - if (!node || !element) - return NULL; - - return find_sibling(node, element, stop); -} - // FIXME: return xmlNodeGetContent(a->children). -xmlChar *node_has_attribute(xmlNodePtr n, xmlChar *attr) +static xmlChar *node_has_attribute(xmlNodePtr n, xmlChar *attr) { xmlAttrPtr a = xmlHasProp(n, attr); @@ -712,7 +671,7 @@ xmlNodePtr find_elements(xmlDocPtr doc, xmlNodePtr node, if (found_fn) found_fn(n, nreq, error, data); - nnreq = append_element_path(nreq+1, p+1); + nnreq = strvcatv(nreq+1, p+1); g_strfreev(nreq); // FIXME ENOMEM @@ -755,24 +714,6 @@ xmlNodePtr find_elements(xmlDocPtr doc, xmlNodePtr node, return n; } -gboolean node_has_child_element(xmlNodePtr node) -{ - xmlNodePtr n; - - if (!node) - return FALSE; - - for (n = node; n; n = n->next) { - if (n->type == XML_ELEMENT_NODE) - return TRUE; - - if (n->children) - return node_has_child_element(n->children); - } - - return FALSE; -} - static gboolean update_element_list(struct element_list_s *elements) { gchar *line; @@ -935,7 +876,8 @@ gpg_error_t create_path_list(xmlDocPtr doc, struct element_list_s *elements, * * If any req_orig element contains no target the element should be prefixed with * the literal character. Not really crucial if the client isn't human - * because sub-nodes/sub-elements are prefixed when needed. + * because child elements are prefixed for the current path. But may + * be confusing if editing by hand. */ elements->prefix = g_strjoinv("\t", req_orig); @@ -964,3 +906,34 @@ fail: g_strfreev(req); return rc; } + +gchar *element_path_to_req(const gchar *account, xmlChar *path) +{ + xmlChar *p = path; + gint n; + gchar *buf; + + if (!p) + return NULL; + + for (n = 0; *p && n < 3; p++) { + if (*p == '/') + n++; + } + + if (strstr((gchar *)p, "text()") != NULL) + p[xmlStrlen(p) - 7] = 0; + + for (n = 0; p[n]; n++) { + if (p[n] == '/') + p[n] = '\t'; + } + + buf = g_strdup_printf("%s\t%s", account, p); + p = (xmlChar *)buf + strlen(buf) - 1; + + while (isspace(*p)) + *p-- = 0; + + return buf; +} diff --git a/src/xml.h b/src/xml.h index da73b2e8..99b12fec 100644 --- a/src/xml.h +++ b/src/xml.h @@ -45,7 +45,6 @@ xmlNodePtr find_elements(xmlDocPtr doc, xmlNodePtr node, xmlNodePtr (*found_fn)(xmlNodePtr, gchar **, gpg_error_t *, void *), xmlNodePtr (*not_found_fn)(xmlNodePtr, gchar **, gpg_error_t *, void *), gboolean is_list_command, gint recursion_depth, void *data); -xmlNodePtr find_element(xmlNodePtr node, gchar *element, xmlNodePtr stop); xmlNodePtr find_account(xmlDocPtr doc, gchar ***req, gpg_error_t *error, gboolean *target, gint recursion_depth); xmlNodePtr create_elements_cb(xmlNodePtr node, gchar **elements, @@ -54,12 +53,10 @@ xmlNodePtr create_target_elements_cb(xmlNodePtr node, gchar **elements, gpg_error_t *error, void *data); gboolean is_literal_element(gchar **element); gboolean is_literal_element_str(gchar *element); -xmlChar *node_has_attribute(xmlNodePtr n, xmlChar *attr); -gboolean node_has_child_element(xmlNodePtr node); -gint sort_element_list(gconstpointer a, gconstpointer b); gboolean valid_element_path(gchar **path, gboolean has_value); xmlNodePtr find_text_node(xmlNodePtr node); gpg_error_t create_path_list(xmlDocPtr doc, struct element_list_s *elements, gchar *path); +gchar *element_path_to_req(const gchar *account, xmlChar *path); #endif -- 2.11.4.GIT