/* ** CONF: Configuration option / file handling module ** Copyright (C) 2002 Michael W. Shaffer ** ** 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 (see the file COPYING). 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 #include "getopt.h" #include "list.h" #include "hash.h" #include "config_file.h" #include "ssync.h" #include "conf.h" extern char *conf_path_default; static struct hash_table conf; char * get_config_string (char *key) { struct datum d; struct datum *dd; if (!key) return NULL; memset (&d, 0, sizeof (struct datum)); d.key = key; d.ksize = strlen (key); dd = hash_table_search (&conf, &d); if (!dd) return NULL; return (dd->val); } long get_config_long (char *key) { long lval = 0; char *val = NULL; val = get_config_string (key); if (!val) return (0); if ((strlen (val) > 2) && (val[0] == '0') && (val[1] == 'x')) { lval = (int) strtoul (val, NULL, 16); } else { lval = (int) strtoul (val, NULL, 10); } return lval; } double get_config_double (char *key) { char *val = NULL; val = get_config_string (key); if (!val) return ((double) 0); return strtod (val, NULL); } void config_write (int fd) { int i = 0; struct datum *d = NULL; struct list_item *curr = NULL; char msg[256]; for (i = 0 ; i < conf.size ; i++) { for (curr = conf.tbl[i].head ; curr ; curr = curr->next) { d = (struct datum *) curr->data; if (d) { memset (msg, 0, sizeof (msg)); snprintf (msg, (sizeof (msg) - 1), "%s: %s\n", (char *) d->key, (char *) d->val); write (fd, msg, strlen (msg)); } } } return; } enum options { o_help = 0, o_interval, o_work_file, o_src_path, o_dst_path, o_priority, o_no_detach, o_no_sync_data, o_no_sync_time, o_no_sync_meta, o_update_only, o_test, o_pid_path, o_log_mode, o_log_path, o_log_ident, o_log_level, o_conf_path }; static struct option long_options[] = { { "help", 0, 0, 'h' }, { "interval", 1, 0, 'i' }, { "work-file", 1, 0, 'w' }, { "src-path", 1, 0, 'f' }, { "dst-path", 1, 0, 't' }, { "priority", 1, 0, 'n' }, { "no-detach", 0, 0, 'F' }, { "no-sync-data", 0, 0, 'D' }, { "no-sync-time", 0, 0, 'T' }, { "no-sync-meta", 0, 0, 'M' }, { "update-only", 0, 0, 'U' }, { "test", 0, 0, 'X' }, { "pid-path", 1, 0, 'p' }, { "log-mode", 1, 0, 'm' }, { "log-path", 1, 0, 'l' }, { "log-ident", 1, 0, 's' }, { "log-level", 1, 0, 'v' }, { "conf-path", 1, 0, 'c' }, { 0, 0, 0, 0 } }; static void parse_command_line (int argc, char **argv, struct hash_table *conf) { int c = '\0'; int optind = 0; struct datum d; if (!((argc > 0) && argv && conf)) return; opterr = 0; memset (&d, 0, sizeof (struct datum)); d.key = "conf-path"; d.ksize = strlen ("conf-path"); d.val = conf_path_default; d.vsize = strlen (conf_path_default); hash_table_insert (conf, &d); while (1) { memset (&d, 0, sizeof (struct datum)); c = getopt_long (argc, argv, "hi:w:f:t:n:FDTMUXp:m:l:s:v:c:", long_options, &optind); if (c == -1) goto EXIT; switch (c) { case 'h': print_usage (argv[0], 2); exit (0); break; case 'i': d.key = (char *) long_options[o_interval].name; d.ksize = strlen (long_options[o_interval].name); d.val = optarg; break; case 'w': d.key = (char *) long_options[o_work_file].name; d.ksize = strlen (long_options[o_work_file].name); d.val = optarg; break; case 'f': d.key = (char *) long_options[o_src_path].name; d.ksize = strlen (long_options[o_src_path].name); d.val = optarg; break; case 't': d.key = (char *) long_options[o_dst_path].name; d.ksize = strlen (long_options[o_dst_path].name); d.val = optarg; break; case 'n': d.key = (char *) long_options[o_priority].name; d.ksize = strlen (long_options[o_priority].name); d.val = optarg; break; case 'F': d.key = (char *) long_options[o_no_detach].name; d.ksize = strlen (long_options[o_no_detach].name); d.val = "yes"; break; case 'D': d.key = (char *) long_options[o_no_sync_data].name; d.ksize = strlen (long_options[o_no_sync_data].name); d.val = "yes"; break; case 'T': d.key = (char *) long_options[o_no_sync_time].name; d.ksize = strlen (long_options[o_no_sync_time].name); d.val = "yes"; break; case 'M': d.key = (char *) long_options[o_no_sync_meta].name; d.ksize = strlen (long_options[o_no_sync_meta].name); d.val = "yes"; break; case 'U': d.key = (char *) long_options[o_update_only].name; d.ksize = strlen (long_options[o_update_only].name); d.val = "yes"; break; case 'X': d.key = (char *) long_options[o_test].name; d.ksize = strlen (long_options[o_test].name); d.val = "yes"; break; case 'p': d.key = (char *) long_options[o_pid_path].name; d.ksize = strlen (long_options[o_pid_path].name); d.val = optarg; break; case 'm': d.key = (char *) long_options[o_log_mode].name; d.ksize = strlen (long_options[o_log_mode].name); d.val = optarg; break; case 'l': d.key = (char *) long_options[o_log_path].name; d.ksize = strlen (long_options[o_log_path].name); d.val = optarg; break; case 's': d.key = (char *) long_options[o_log_ident].name; d.ksize = strlen (long_options[o_log_ident].name); d.val = optarg; break; case 'v': d.key = (char *) long_options[o_log_level].name; d.ksize = strlen (long_options[o_log_level].name); d.val = optarg; break; case 'c': d.key = (char *) long_options[o_conf_path].name; d.ksize = strlen (long_options[o_conf_path].name); d.val = optarg; break; default: print_usage (argv[0], 2); exit (0); break; } if (d.key && d.ksize > 0) { d.vsize = strlen (d.val); hash_table_insert (conf, &d); } } EXIT: return; } void config_load (int argc, char **argv) { memset (&conf, 0, sizeof (struct hash_table)); conf.size = 32; hash_table_init (&conf); parse_command_line (argc, argv, &conf); parse_config_file (get_config_string ("conf-path"), &conf); return; } void config_free (void) { hash_table_free (&conf); return; } void print_usage (char *name, int fd) { char msg[4096]; if (!name || (fd < 0)) goto EXIT; memset (msg, 0, sizeof (msg)); snprintf (msg, (sizeof (msg) - 1), " \n" " ssync version %s \n" " \n" " Usage: \n" " \n" " %s [OPTIONS] \n" " \n" " Option Argument Comment \n" " ----------------------------------------------------------------------\n" " -h | --help display this message \n" " -c | --conf-path PATH alternative config file \n" " -i | --interval NUM seconds between runs \n" " -w | --work-file PATH file containing work list\n" " -f | --src-path PATH source path \n" " -t | --dst-path PATH destination path \n" " -n | --priority (-20 - +20) scheduling priority \n" " -F | --no-detach no detach from terminal \n" " -D | --no-sync-data no sync data in files \n" " -T | --no-sync-time no sync atime / mtime \n" " -M | --no-sync-meta no sync uid / gid / mode \n" " -U | --update-only only if source is newer \n" " -X | --test don't modify anything \n" " -p | --pid-path PATH path for pid file \n" " -m | --log-mode (file|syslog|stderr) path for log file \n" " -l | --log-path PATH path for log file \n" " -s | --log-ident STRING ident string for syslog \n" " -v | --log-level (0 - 5) verboseness \n" " \n", SSYNC_VERSION, name); write (fd, msg, strlen (msg)); EXIT: return; }