Line data Source code
1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 : /*
3 : * options.c
4 : * This file is part of "Sauvegarde" project.
5 : *
6 : * (C) Copyright 2015 - 2016 Olivier Delhomme
7 : * e-mail : olivier.delhomme@free.fr
8 : *
9 : * "Sauvegarde" is free software: you can redistribute it and/or modify
10 : * it under the terms of the GNU General Public License as published by
11 : * the Free Software Foundation, either version 3 of the License, or
12 : * (at your option) any later version.
13 : *
14 : * "Sauvegarde" is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with "Sauvegarde". If not, see <http://www.gnu.org/licenses/>
21 : */
22 : /**
23 : * @file restore/options.c
24 : *
25 : * This file contains all the functions to manage command line options for
26 : * 'cdpfglrestore' program.
27 : */
28 :
29 : #include "restore.h"
30 :
31 : static void print_selected_options(options_t *opt);
32 : static void read_from_group_all(GKeyFile *keyfile, gchar *filename);
33 : static void read_from_group_server(options_t *opt, GKeyFile *keyfile, gchar *filename);
34 : static options_t *manage_command_line_options(int argc, char **argv);
35 :
36 :
37 : /**
38 : * Prints options as selected when invoking the program with -v option
39 : * @param opt the options_t * structure that contains all selected options
40 : * from the command line and that will be used by the program.
41 : */
42 1 : static void print_selected_options(options_t *opt)
43 : {
44 1 : if (opt != NULL)
45 : {
46 1 : fprintf(stdout, _("\n%s options are:\n"), PROGRAM_NAME);
47 1 : print_string_option(_("Configuration file: %s\n"), opt->configfile);
48 1 : print_string_option(_("server's IP address: %s\n"), opt->ip);
49 1 : fprintf(stdout, _("server's port number: %d\n"), opt->port);
50 : }
51 1 : }
52 :
53 :
54 : /**
55 : * Reads keys in keyfile if group GN_ALL is in that keyfile.
56 : * @param keyfile is the GKeyFile structure that is used by glib to read
57 : * groups and keys from.
58 : * @param filename : the filename of the configuration file to read from
59 : */
60 : static void read_from_group_all(GKeyFile *keyfile, gchar *filename)
61 : {
62 16 : read_debug_mode_from_file(keyfile, filename);
63 : }
64 :
65 :
66 : /**
67 : * Reads keys in keyfile if groupname is in that keyfile and fills
68 : * options_t *opt structure accordingly.
69 : * @param[in,out] opt : options_t * structure to store options read from the
70 : * configuration file "filename".
71 : * @param keyfile is the GKeyFile structure that is used by glib to read
72 : * groups and keys from.
73 : * @param filename : the filename of the configuration file to read from
74 : */
75 16 : static void read_from_group_server(options_t *opt, GKeyFile *keyfile, gchar *filename)
76 : {
77 16 : gint port = 0;
78 :
79 16 : if (opt != NULL && keyfile != NULL && filename != NULL && g_key_file_has_group(keyfile, GN_SERVER) == TRUE)
80 : {
81 : /* Reading the port number if any */
82 16 : port = read_int_from_file(keyfile, filename, GN_SERVER, KN_SERVER_PORT, _("Could not load server port number from file."), SERVER_PORT);
83 :
84 16 : if (port > 1024 && port < 65535)
85 : {
86 16 : opt->port = port;
87 : }
88 :
89 : /* Reading IP address of server's host if any */
90 16 : opt->ip = read_string_from_file(keyfile, filename, GN_SERVER, KN_SERVER_IP, _("Could not load cache database name"));
91 : }
92 16 : }
93 :
94 :
95 : /**
96 : * Reads from the configuration file "filename" and fills the options_t *
97 : * opt structure.
98 : * @param[in,out] opt : options_t * structure to store options read from
99 : * the configuration file "filename"
100 : * @param filename : the filename of the configuration file to read from
101 : */
102 25 : static void read_from_configuration_file(options_t *opt, gchar *filename)
103 : {
104 25 : GKeyFile *keyfile = NULL; /** Configuration file parser */
105 25 : GError *error = NULL; /** Glib error handling */
106 :
107 25 : if (filename != NULL)
108 : {
109 :
110 16 : if (opt->configfile != NULL)
111 : {
112 4 : free_variable(opt->configfile);
113 : }
114 16 : opt->configfile = g_strdup(filename);
115 :
116 16 : print_debug(_("Reading configuration from file %s\n"), filename);
117 :
118 16 : keyfile = g_key_file_new();
119 :
120 16 : if (g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_KEEP_COMMENTS, &error))
121 : {
122 : read_from_group_all(keyfile, filename);
123 16 : read_from_group_server(opt, keyfile, filename);
124 : }
125 0 : else if (error != NULL)
126 : {
127 0 : print_error(__FILE__, __LINE__, _("Failed to open %s configuration file: %s\n"), filename, error->message);
128 0 : error = free_error(error);
129 : }
130 :
131 16 : g_key_file_free(keyfile);
132 : }
133 25 : }
134 :
135 :
136 : /**
137 : * This function parses command line options. It sets the options in this
138 : * order. It means that the value used for an option is the one set in the
139 : * lastest step.
140 : * 0) default values are set into the options_t * structure
141 : * 1) reads the default configuration file if any.
142 : * 2) reads the configuration file mentionned on the command line.
143 : * 3) sets the command line options (except for the list of directories,
144 : * all other values are replaced by thoses in the command line)
145 : * @param argc : number of arguments given on the command line.
146 : * @param argv : an array of strings that contains command line arguments.
147 : * @returns options_t structure malloc'ed and filled upon choosen command
148 : * line's option
149 : */
150 15 : static options_t *manage_command_line_options(int argc, char **argv)
151 : {
152 15 : gboolean version = FALSE; /** True if -v was selected on the command line */
153 15 : gint debug = -4; /** 0 == FALSE and other values == TRUE */
154 15 : gchar *configfile = NULL; /** filename for the configuration file if any */
155 15 : gchar *ip = NULL; /** IP address where is located server's program */
156 15 : gint port = 0; /** Port number on which to send things to the server */
157 15 : gchar *list = NULL; /** Should contain a filename or a directory to filter out */
158 15 : gchar *restore = NULL; /** Must contain a filename or a directory name to be restored */
159 15 : gchar *date = NULL; /** date at which we want to restore a file or directory */
160 15 : gchar *where = NULL; /** Contains the directory where to restore a file / directory */
161 15 : gchar *afterdate = NULL; /** afterdate: we want to restore a file that has its mtime after this date */
162 15 : gchar *beforedate = NULL; /** beforedate: we want to restore a file that has its mtime before this date */
163 :
164 15 : GOptionEntry entries[] =
165 : {
166 : { "version", 'v', 0, G_OPTION_ARG_NONE, &version, N_("Prints program version."), NULL},
167 : { "list", 'l', 0, G_OPTION_ARG_FILENAME, &list, N_("Gives a list of saved files that correspond to the given REGEX."), "REGEX"},
168 : { "restore", 'r', 0, G_OPTION_ARG_FILENAME, &restore, N_("Restores requested filename (REGEX) (by default latest version)."), "REGEX"},
169 : { "date", 't', 0, G_OPTION_ARG_STRING, &date, N_("Restores the selected file at that specific DATE (YYYY-MM-DD HH:MM:SS format)."), "DATE"},
170 : { "after", 'a', 0, G_OPTION_ARG_STRING, &afterdate, N_("Restores the selected file with mtime after DATE (YYYY-MM-DD HH:MM:SS format)."), "DATE"},
171 : { "before", 'b', 0, G_OPTION_ARG_STRING, &beforedate, N_("Restores the selected file with mtime before DATE (YYYY-MM-DD HH:MM:SS format)."), "DATE"},
172 : { "debug", 'd', 0, G_OPTION_ARG_INT, &debug, N_("Activates (1) or desactivates (0) debug mode."), N_("BOOLEAN")},
173 : { "configuration", 'c', 0, G_OPTION_ARG_STRING, &configfile, N_("Specify an alternative configuration file."), N_("FILENAME")},
174 : { "where", 'w', 0, G_OPTION_ARG_STRING, &where, N_("Specify a DIRECTORY where to restore a file."), N_("DIRECTORY")},
175 : { "ip", 'i', 0, G_OPTION_ARG_STRING, &ip, N_("IP address where server program is."), "IP"},
176 : { "port", 'p', 0, G_OPTION_ARG_INT, &port, N_("Port NUMBER on which server program is listening."), N_("NUMBER")},
177 : { NULL }
178 : };
179 :
180 15 : GError *error = NULL;
181 : GOptionContext *context;
182 15 : options_t *opt = NULL; /** Structure to manage program's options */
183 15 : gchar *bugreport = NULL; /** Bug Report message */
184 15 : gchar *summary = NULL; /** Abstract for the program */
185 15 : gchar *defaultconfigfilename = NULL;
186 :
187 15 : bugreport = g_strconcat(_("Please report bugs to: "), PACKAGE_BUGREPORT, NULL);
188 15 : summary = g_strdup(_("This program is restoring files from cdpfglserver's server.\n"));
189 15 : context = g_option_context_new("");
190 :
191 15 : set_debug_mode(ENABLE_DEBUG);
192 :
193 15 : set_option_context_options(context, entries, TRUE, bugreport, summary);
194 :
195 15 : if (!g_option_context_parse(context, &argc, &argv, &error))
196 : {
197 0 : g_print(_("Option parsing failed: %s\n"), error->message);
198 0 : exit(EXIT_FAILURE);
199 : }
200 :
201 : /* 0) Setting default values */
202 :
203 13 : opt = (options_t *) g_malloc0(sizeof(options_t));
204 :
205 13 : opt->configfile = NULL;
206 13 : opt->list = NULL;
207 13 : opt->restore = NULL;
208 13 : opt->ip = g_strdup("localhost");
209 13 : opt->port = SERVER_PORT;
210 13 : opt->where = NULL;
211 :
212 :
213 : /* 1) Reading options from default configuration file
214 : * note: restore option will never be read into the configuration
215 : * file.
216 : */
217 13 : defaultconfigfilename = get_probable_etc_path(PROGRAM_NAME, "restore.conf");
218 13 : read_from_configuration_file(opt, defaultconfigfilename);
219 13 : defaultconfigfilename = free_variable(defaultconfigfilename);
220 :
221 :
222 : /* 2) Reading the configuration from the configuration file specified
223 : * on the command line (if any).
224 : * note: same note than 1) applies here too.
225 : */
226 13 : if (configfile != NULL)
227 : {
228 12 : read_from_configuration_file(opt, configfile);
229 : }
230 :
231 :
232 : /* 3) retrieving other options from the command line.
233 : */
234 13 : set_debug_mode_upon_cmdl(debug);
235 13 : opt->version = version; /* only TRUE if -v or --version was invoked */
236 :
237 13 : if (date != NULL)
238 : {
239 0 : opt->date = g_strdup(date);
240 : }
241 :
242 13 : if (afterdate != NULL)
243 : {
244 2 : opt->afterdate = g_strdup(afterdate);
245 : }
246 :
247 13 : if (beforedate != NULL)
248 : {
249 1 : opt->beforedate = g_strdup(beforedate);
250 : }
251 :
252 13 : if (list != NULL)
253 : {
254 4 : opt->list = g_strdup(list);
255 : }
256 :
257 13 : if (restore != NULL)
258 : {
259 8 : opt->restore = g_strdup(restore);
260 : }
261 :
262 13 : if (ip != NULL)
263 : {
264 0 : free_variable(opt->ip);
265 0 : opt->ip = g_strdup(ip);
266 : }
267 :
268 13 : if (port > 1024 && port < 65535)
269 : {
270 0 : opt->port = port;
271 : }
272 :
273 13 : if (where != NULL)
274 : {
275 8 : opt->where = g_strdup(where);
276 : }
277 :
278 13 : g_option_context_free(context);
279 13 : free_variable(ip);
280 13 : free_variable(bugreport);
281 13 : free_variable(summary);
282 13 : free_variable(list);
283 13 : free_variable(restore);
284 13 : free_variable(date);
285 13 : free_variable(afterdate);
286 13 : free_variable(beforedate);
287 13 : free_variable(where);
288 :
289 13 : return opt;
290 : }
291 :
292 :
293 : /**
294 : * Decides what to do upon command lines options passed to the program
295 : * @param argc : number of arguments given on the command line.
296 : * @param argv : an array of strings that contains command line arguments.
297 : * @returns options_t structure malloc'ed and filled upon choosen command
298 : * line's option (in manage_command_line_options function).
299 : */
300 15 : options_t *do_what_is_needed_from_command_line_options(int argc, char **argv)
301 : {
302 15 : options_t *opt = NULL; /** Structure to manage options from the command line can be freed when no longer needed */
303 :
304 15 : opt = manage_command_line_options(argc, argv);
305 :
306 13 : if (opt != NULL)
307 : {
308 13 : if (opt->version == TRUE)
309 : {
310 1 : print_program_version(PROGRAM_NAME, RESTORE_DATE, RESTORE_VERSION, RESTORE_AUTHORS, RESTORE_LICENSE);
311 1 : print_libraries_versions(PROGRAM_NAME);
312 1 : print_selected_options(opt);
313 1 : exit(EXIT_SUCCESS);
314 : }
315 : }
316 :
317 12 : return opt;
318 : }
319 :
320 :
321 : /**
322 : * Frees the option structure
323 : * @param opt is the structure to be freed
324 : */
325 12 : void free_options_t(options_t *opt)
326 : {
327 12 : if (opt != NULL)
328 : {
329 12 : free_variable(opt->list);
330 12 : free_variable(opt->restore);
331 12 : free_variable(opt->date);
332 12 : free_variable(opt->configfile);
333 12 : free_variable(opt->ip);
334 12 : free_variable(opt);
335 : }
336 12 : }
|