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 2014 - 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 server/options.c
24 : *
25 : * This file contains all the functions to manage command line options for
26 : * 'cdpfglserver' program.
27 : */
28 :
29 : #include "server.h"
30 :
31 : static void print_selected_options(options_t *opt);
32 : static void read_from_configuration_file(options_t *opt, gchar *filename);
33 : static void read_from_group_server(options_t *opt, GKeyFile *keyfile, gchar *filename);
34 :
35 : /**
36 : * Frees the options structure if necessary.
37 : * @param opt : the malloc'ed options_t structure
38 : */
39 1 : void free_options_t(options_t *opt)
40 : {
41 :
42 1 : if (opt != NULL)
43 : {
44 1 : free_variable(opt);
45 : }
46 :
47 1 : }
48 :
49 :
50 : /**
51 : * Prints options as selected when invoking the program with -v option
52 : * @param opt the options_t * structure that contains all selected options
53 : * from the command line and that will be used by the program.
54 : */
55 1 : static void print_selected_options(options_t *opt)
56 : {
57 1 : if (opt != NULL)
58 : {
59 1 : fprintf(stdout, _("\n%s options are:\n"), PROGRAM_NAME);
60 :
61 1 : print_string_option(_("Configuration file: %s\n"), opt->configfile);
62 :
63 1 : if (opt->port != 0)
64 : {
65 1 : fprintf(stdout, _("Port number: %d\n"), opt->port);
66 : }
67 : }
68 1 : }
69 :
70 : /**
71 : * creates a buffer containing every selected options ...
72 : * @param opt the options_t * structure that contains all selected options
73 : * from the command line and that will be used by the program.
74 : * @returns options as selected when invoking the program with -v option
75 : * into a newly allocated buffer that may be freed when no longer needed
76 : */
77 0 : gchar *buffer_selected_option(options_t *opt)
78 : {
79 0 : gchar *buf1 = NULL;
80 0 : gchar *buffer = NULL;
81 :
82 0 : if (opt != NULL)
83 : {
84 0 : if (opt->configfile != NULL)
85 : {
86 0 : buffer = g_strdup_printf(_("\n%s options are:\nConfiguration file: %s\n"), PROGRAM_NAME, opt->configfile);
87 : }
88 : else
89 : {
90 0 : buffer = g_strdup_printf(_("\n%s options are:\n"), PROGRAM_NAME);
91 : }
92 :
93 0 : if (opt->port != 0)
94 : {
95 0 : buf1 = g_strdup_printf(_("%sPort number: %d\n"), buffer, opt->port);
96 0 : free_variable(buffer);
97 0 : buffer = buf1;
98 : }
99 : }
100 :
101 0 : return buffer;
102 : }
103 :
104 :
105 : /**
106 : * Reads keys in keyfile if groupname is in that keyfile and fills
107 : * options_t *opt structure accordingly.
108 : * @param[in,out] opt : options_t * structure to store options read from the
109 : * configuration file "filename".
110 : * @param keyfile is the GKeyFile structure that is used by glib to read
111 : * groups and keys from.
112 : * @param filename : the filename of the configuration file to read from
113 : */
114 2 : static void read_from_group_server(options_t *opt, GKeyFile *keyfile, gchar *filename)
115 : {
116 2 : if (opt != NULL && keyfile != NULL && filename != NULL && g_key_file_has_group(keyfile, GN_SERVER) == TRUE)
117 : {
118 : /* Reading the port number if any */
119 2 : opt->port = read_int_from_file(keyfile, filename, GN_SERVER, KN_SERVER_PORT, _("Could not load server port number from file."), SERVER_PORT);
120 : }
121 :
122 2 : read_debug_mode_from_file(keyfile, filename);
123 2 : }
124 :
125 :
126 : /**
127 : * Reads from the configuration file "filename"
128 : * @param[in,out] opt : options_t * structure to store options read from the
129 : * configuration file "filename"
130 : * @param filename : the filename of the configuration file to read from
131 : */
132 3 : static void read_from_configuration_file(options_t *opt, gchar *filename)
133 : {
134 3 : GKeyFile *keyfile = NULL; /** Configuration file parser */
135 3 : GError *error = NULL; /** Glib error handling */
136 :
137 3 : if (filename != NULL)
138 : {
139 2 : if (opt->configfile != NULL)
140 : {
141 1 : free_variable(opt->configfile);
142 : }
143 :
144 2 : opt->configfile = g_strdup(filename);
145 :
146 2 : print_debug(_("Reading configuration from file %s\n"), filename);
147 :
148 2 : keyfile = g_key_file_new();
149 :
150 2 : if (g_key_file_load_from_file(keyfile, filename, G_KEY_FILE_KEEP_COMMENTS, &error))
151 : {
152 2 : read_from_group_server(opt, keyfile, filename);
153 : }
154 0 : else if (error != NULL)
155 : {
156 0 : print_error(__FILE__, __LINE__, _("Failed to open %s configuration file: %s\n"), filename, error->message);
157 0 : error = free_error(error);
158 : }
159 :
160 2 : g_key_file_free(keyfile);
161 : }
162 3 : }
163 :
164 :
165 : /**
166 : * This function parses command line options. It sets the options in this
167 : * order. It means that the value used for an option is the one set in the
168 : * lastest step.
169 : * 0) default values are set into the options_t * structure
170 : * 1) reads the default configuration file if any.
171 : * 2) reads the configuration file mentionned on the command line.
172 : * 3) sets the command line options (except for the list of directories,
173 : * all other values are replaced by thoses in the command line)
174 : * @param argc : number of arguments given on the command line.
175 : * @param argv : an array of strings that contains command line arguments.
176 : * @returns options_t structure malloc'ed and filled upon choosen command
177 : * line's option
178 : */
179 4 : options_t *manage_command_line_options(int argc, char **argv)
180 : {
181 4 : gboolean version = FALSE; /** True if -v was selected on the command line */
182 4 : gint cmdl_debug = -4; /** debug mode as specified on the command line */
183 4 : gchar *configfile = NULL; /** Filename for the configuration file if any */
184 4 : gint port = 0; /** Port number on which to listen */
185 :
186 4 : GOptionEntry entries[] =
187 : {
188 : { "version", 'v', 0, G_OPTION_ARG_NONE, &version, N_("Prints program version."), NULL},
189 : { "debug", 'd', 0, G_OPTION_ARG_INT, &cmdl_debug, N_("Activates (1) or deactivates (0) debug mode."), N_("BOOLEAN")},
190 : { "configuration", 'c', 0, G_OPTION_ARG_STRING, &configfile, N_("Specify an alternative configuration file."), N_("FILENAME")},
191 : { "port", 'p', 0, G_OPTION_ARG_INT, &port, N_("Port NUMBER on which to listen."), N_("NUMBER")},
192 : { NULL }
193 : };
194 :
195 4 : GError *error = NULL;
196 : GOptionContext *context;
197 4 : options_t *opt = NULL; /** Structure to manage program's options */
198 4 : gchar *bugreport = NULL; /** Bug Report message */
199 4 : gchar *summary = NULL; /** Abstract for the program */
200 4 : gchar *defaultconfigfilename = NULL;
201 :
202 4 : bugreport = g_strconcat(_("Please report bugs to: "), PACKAGE_BUGREPORT, NULL);
203 4 : summary = g_strdup(_("This program is monitoring file changes in the filesystem and is hashing\nfiles with SHA256 algorithms from Glib."));
204 4 : context = g_option_context_new("");
205 :
206 4 : set_debug_mode(ENABLE_DEBUG);
207 :
208 4 : set_option_context_options(context, entries, TRUE, bugreport, summary);
209 :
210 4 : if (!g_option_context_parse(context, &argc, &argv, &error))
211 : {
212 0 : g_print(_("[%s, %d] Option parsing failed: %s\n"), __FILE__, __LINE__, error->message);
213 0 : exit(EXIT_FAILURE);
214 : }
215 :
216 : /* 0) Setting default values */
217 :
218 2 : opt = (options_t *) g_malloc0(sizeof(options_t));
219 :
220 2 : opt->configfile = NULL;
221 2 : opt->port = SERVER_PORT;
222 :
223 :
224 : /* 1) Reading options from default configuration file */
225 2 : defaultconfigfilename = get_probable_etc_path(PROGRAM_NAME, "server.conf");
226 2 : read_from_configuration_file(opt, defaultconfigfilename);
227 2 : free_variable(defaultconfigfilename);
228 :
229 2 : opt->version = version; /* only TRUE if -v or --version was invoked */
230 :
231 :
232 : /* 2) Reading the configuration from the configuration file specified
233 : * on the command line
234 : */
235 2 : if (configfile != NULL)
236 : {
237 1 : read_from_configuration_file(opt, configfile);
238 : }
239 :
240 : /* 3) retrieving other options from the command line.
241 : */
242 :
243 2 : set_debug_mode_upon_cmdl(cmdl_debug);
244 :
245 2 : if (port > 1024 && port < 65535)
246 : {
247 0 : opt->port = port;
248 : }
249 :
250 2 : g_option_context_free(context);
251 2 : free_variable(bugreport);
252 2 : free_variable(summary);
253 :
254 2 : return opt;
255 : }
256 :
257 :
258 : /**
259 : * Decides what to do upon command lines options passed to the program
260 : * @param argc : number of arguments given on the command line.
261 : * @param argv : an array of strings that contains command line arguments.
262 : * @returns options_t structure malloc'ed and filled upon choosen command
263 : * line's option (in manage_command_line_options function).
264 : */
265 4 : options_t *do_what_is_needed_from_command_line_options(int argc, char **argv)
266 : {
267 4 : options_t *opt = NULL; /** Structure to manage options from the command line can be freed when no longer needed */
268 :
269 4 : opt = manage_command_line_options(argc, argv);
270 :
271 2 : if (opt != NULL)
272 : {
273 2 : if (opt->version == TRUE)
274 : {
275 1 : print_program_version(PROGRAM_NAME, SERVER_DATE, SERVER_VERSION, SERVER_AUTHORS, SERVER_LICENSE);
276 1 : print_libraries_versions(PROGRAM_NAME);
277 1 : print_selected_options(opt);
278 1 : exit(EXIT_SUCCESS);
279 : }
280 : }
281 :
282 1 : return opt;
283 : }
284 :
285 :
|