diff options
-rw-r--r-- | src/lib/Makefile.am | 4 | ||||
-rw-r--r-- | src/lib/config_file.c | 213 | ||||
-rw-r--r-- | src/lib/config_file.h | 36 | ||||
-rw-r--r-- | src/lib/misc.c | 27 | ||||
-rw-r--r-- | src/lib/misc.h | 7 | ||||
-rw-r--r-- | src/plugins/file.c | 33 |
6 files changed, 311 insertions, 9 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 3badb67..955007e 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,6 +1,6 @@ lib_LTLIBRARIES = libproxy.la -libproxy_la_SOURCES = misc.c ip.c url.c pac.c dhcp.c dns.c slp.c wpad.c proxy_factory.c \ - misc.h ip.h url.h pac.h dhcp.h dns.h slp.h wpad.h proxy_factory.h proxy.h +libproxy_la_SOURCES = misc.c ip.c url.c pac.c dhcp.c dns.c slp.c wpad.c proxy_factory.c config_file.c \ + misc.h ip.h url.h pac.h dhcp.h dns.h slp.h wpad.h proxy_factory.h proxy.h config_file.h libproxy_la_CFLAGS = -Wall libproxy_la_LDFLAGS = -lm diff --git a/src/lib/config_file.c b/src/lib/config_file.c new file mode 100644 index 0000000..b19756a --- /dev/null +++ b/src/lib/config_file.c @@ -0,0 +1,213 @@ +/******************************************************************************* + * libproxy - A library for proxy configuration + * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ******************************************************************************/ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> + +#include "misc.h" +#include "config_file.h" + +struct _pxConfigFileSection { + char *name; + char **keys; + char **vals; +}; +typedef struct _pxConfigFileSection pxConfigFileSection; + +struct _pxConfigFile { + char *filename; + time_t mtime; + pxConfigFileSection **sections; +}; + +pxConfigFile * +px_config_file_new(char *filename) +{ + // Open the file and stat it + struct stat st; + int fd = open(filename, O_RDONLY); + if (fd < 0) return NULL; + fstat(fd, &st); + + // Allocate our structure; get mtime and filename + pxConfigFile *self = px_malloc0(sizeof(pxConfigFile)); + self->mtime = st.st_mtime; + self->filename = px_strdup(filename); + + // Add one section (PX_CONFIG_FILE_DEFAULT_SECTION) + self->sections = px_malloc0(sizeof(pxConfigFileSection *) * 2); + self->sections[0] = px_malloc0(sizeof(pxConfigFileSection)); + self->sections[0]->name = px_strdup(PX_CONFIG_FILE_DEFAULT_SECTION); + pxConfigFileSection *current = self->sections[0]; + + // Parse our file + for (char *line=NULL ; (line = px_readline(fd)) ; px_free(line)) + { + // Strip + char *tmp = px_strstrip(line); + px_free(line); line = tmp; + + // Check for comment and/or empty line + if (*line == '#' || !strcmp(line, "")) continue; + + // If we have a new section + if (*line == '[' || line[strlen(line)-1] == ']') + { + // Get just the section name + memmove(line, line+1, strlen(line)-1); + line[strlen(line)-2] = '\0'; + + // Check for each section... + for (int i=0 ; self->sections[i] ; i++) + { + // If we found the section already, set it as current and move on + if (!strcmp(self->sections[i]->name, line)) + { + current = self->sections[i]; + break; + } + + // If the section wasn't found, add a new section + if (!self->sections[i+1]) + { + // Create new section + current = px_malloc0(sizeof(pxConfigFileSection)); + current->name = px_strdup(line); + + // Add section to the end + pxConfigFileSection **sections = self->sections; + self->sections = px_malloc0(sizeof(pxConfigFileSection *) * (i+3)); + memcpy(self->sections, sections, sizeof(pxConfigFileSection) * (i+1)); + self->sections[i+1] = current; + px_free(sections); + + break; + } + } + continue; + } + + // If this is a key/val line, get the key/val. + if ((tmp = strchr(line, '=')) && tmp[1]) + { + // If this is our first key/val, create a new array + if (!current->keys || !current->vals) + { + // Add key + current->keys = px_malloc0(sizeof(char *) * 2); + current->keys[0] = px_strndup(line, tmp - line); + current->keys[1] = NULL; + + // Add val + current->vals = px_malloc0(sizeof(char *) * 2); + current->vals[0] = px_strdup(tmp+1); + current->vals[1] = NULL; + } + + // If this is not our first key/val, tack it on the end + else + { + for (int i=0 ; current->keys[i] ; i++) + { + if (!current->keys[i+1]) + { + // Add val + char **vals = px_malloc0(sizeof(char *) * (i+3)); + memcpy(vals, current->vals, sizeof(char *) * (i+1)); + vals[i+1] = px_strstrip(tmp+1); + px_free(current->vals); current->vals = vals; + + // Add key + *tmp = '\0'; + char **keys = px_malloc0(sizeof(char *) * (i+3)); + memcpy(keys, current->keys, sizeof(char *) * (i+1)); + keys[i+1] = px_strstrip(line); + px_free(current->keys); current->keys = keys; + + break; + } + } + } + continue; + } + } + + close(fd); + return self; +} + +bool +px_config_file_is_stale(pxConfigFile *self) +{ + struct stat st; + return (!stat(self->filename, &st) && st.st_mtime > self->mtime); +} + +char ** +px_config_file_get_sections(pxConfigFile *self) +{ + int count; + for (count=0 ; self->sections[count] ; count++); + char **output = px_malloc0(sizeof(char *) * ++count); + for (count=0 ; self->sections[count] ; count++) + output[count] = px_strdup(self->sections[count]->name); + return output; +} + +char ** +px_config_file_get_keys(pxConfigFile *self, char *section) +{ + for (int i=0 ; self->sections[i] ; i++) + { + if (!strcmp(self->sections[i]->name, section)) + return px_strdupv((const char **) self->sections[i]->keys); + } + + return NULL; +} + +char * +px_config_file_get_value(pxConfigFile *self, char *section, char *key) +{ + for (int i=0 ; self->sections[i] ; i++) + if (!strcmp(self->sections[i]->name, section)) + for (int j=0 ; self->sections[i]->keys && self->sections[i]->keys[j] ; j++) + if (!strcmp(self->sections[i]->keys[j], key)) + return px_strdup(self->sections[i]->vals[j]); + + return NULL; +} + +void +px_config_file_free(pxConfigFile *self) +{ + for (int i=0 ; self->sections[i] ; i++) + { + px_free(self->sections[i]->name); + px_strfreev(self->sections[i]->keys); + px_strfreev(self->sections[i]->vals); + px_free(self->sections[i]); + } + px_free(self); +} + + diff --git a/src/lib/config_file.h b/src/lib/config_file.h new file mode 100644 index 0000000..bcdb781 --- /dev/null +++ b/src/lib/config_file.h @@ -0,0 +1,36 @@ +/******************************************************************************* + * libproxy - A library for proxy configuration + * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ******************************************************************************/ + +#ifndef CONFIG_FILE_H_ +#define CONFIG_FILE_H_ + +#include <stdbool.h> + +#define PX_CONFIG_FILE_DEFAULT_SECTION "__DEFAULT__" + +typedef struct _pxConfigFile pxConfigFile; + +pxConfigFile *px_config_file_new (char *filename); +bool px_config_file_is_stale (pxConfigFile *self); +char **px_config_file_get_sections(pxConfigFile *self); +char **px_config_file_get_keys (pxConfigFile *self, char *section); +char *px_config_file_get_value (pxConfigFile *self, char *section, char *key); +void px_config_file_free (pxConfigFile *self); + +#endif /*CONFIG_FILE_H_*/ diff --git a/src/lib/misc.c b/src/lib/misc.c index 02ff678..9095db1 100644 --- a/src/lib/misc.c +++ b/src/lib/misc.c @@ -80,6 +80,26 @@ px_strdup(const char *s) } /** + * Duplicates a string vector + * @sv String vector to duplicate + * @return Newly allocated string vector (free w/ px_strfreev()) + */ +char ** +px_strdupv(const char **sv) +{ + int count; + + if (!sv) return NULL; + for (count=0 ; sv[count] ; count++); + + char **output = px_malloc0(sizeof(char *) * ++count); + for (int i=0 ; sv[i] ; i++) + output[i] = px_strdup(sv[i]); + + return output; +} + +/** * Concatenates two or more strings into a newly allocated string * @s The first string to concatenate. * @... Subsequent strings. The last argument must be NULL. @@ -200,13 +220,14 @@ px_readline(int fd) char c; // Receive a single character, check for newline or EOF - if (read(fd, &c, 1) != 1 || c == '\n') break; + if (read(fd, &c, 1) != 1) return buffer; + if (c == '\n') return buffer ? buffer : px_strdup(""); // Allocate new buffer if we need if (i % 1024 == 1) { char *tmp = buffer; - buffer = px_malloc0(1024+i); + buffer = px_malloc0(1024 * i + 1); if (tmp) { strcpy(buffer, tmp); px_free(tmp); } } @@ -243,7 +264,7 @@ px_strrstrip(char *string) for (int i=0 ; string[i] ; i++) if (!isspace(string[i])) tmp = string + i; - *tmp = '\0'; + tmp[1] = '\0'; return string; } diff --git a/src/lib/misc.h b/src/lib/misc.h index cab466c..e09b1ed 100644 --- a/src/lib/misc.h +++ b/src/lib/misc.h @@ -51,6 +51,13 @@ char *px_strndup(const char *s, size_t n); char *px_strdup(const char *s); /** + * Duplicates a string vector + * @sv String vector to duplicate + * @return Newly allocated string vector (free w/ px_strfreev()) + */ +char **px_strdupv(const char **sv); + +/** * Concatenates two or more strings into a newly allocated string * @s The first string to concatenate. * @... Subsequent strings. The last argument must be NULL. diff --git a/src/plugins/file.c b/src/plugins/file.c index 2551e4f..54c4689 100644 --- a/src/plugins/file.c +++ b/src/plugins/file.c @@ -22,21 +22,44 @@ #include <misc.h> #include <proxy_factory.h> +#include <config_file.h> -pxConfig *get_config_from_file(char *filename) +pxConfig *get_config_from_file(pxProxyFactory *self, char *misc, char *filename) { - return NULL; + pxConfigFile *cf = px_proxy_factory_misc_get(self, misc); + if (!cf || px_config_file_is_stale(cf)) + { + if (cf) px_config_file_free(cf); + cf = px_config_file_new(filename); + } + + if (!cf) return NULL; + + pxConfig *config = px_malloc0(sizeof(pxConfig)); + config->url = px_config_file_get_value(cf, PX_CONFIG_FILE_DEFAULT_SECTION, "proxy"); + config->ignore = px_config_file_get_value(cf, PX_CONFIG_FILE_DEFAULT_SECTION, "ignore"); + if (!config->url) + config->url = px_strdup("wpad://"); + if (!config->ignore) + config->ignore = px_strdup(""); + + return config; } pxConfig *system_get_config_cb(pxProxyFactory *self) { - return get_config_from_file("/etc/proxy.conf"); + return get_config_from_file(self, "file_system", "/etc/proxy.conf"); } pxConfig *user_get_config_cb(pxProxyFactory *self) { - return get_config_from_file("~/.proxy.conf"); + char *tmp = getenv("HOME"); + if (!tmp) return NULL; + char *filename = px_strcat(tmp, "/", ".proxy.conf", NULL); + pxConfig *config = get_config_from_file(self, "file_user", filename); + px_free(filename); + return config; } bool on_proxy_factory_instantiate(pxProxyFactory *self) @@ -53,4 +76,6 @@ void on_proxy_factory_destantiate(pxProxyFactory *self) { px_proxy_factory_config_del(self, "file_system"); px_proxy_factory_config_del(self, "file_user"); + px_config_file_free(px_proxy_factory_misc_get(self, "file_system")); + px_config_file_free(px_proxy_factory_misc_get(self, "file_user")); } |