2 * User options handling code of libcaptive
3 * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "captive/options.h" /* self */
23 #include <glib/gmessages.h>
24 #include "captive/macros.h"
25 #include <glib/gstrfuncs.h>
31 #define DEFAULT_SYSLOG_FACILITY LOG_DAEMON
34 void captive_options_init(struct captive_options *options)
36 g_return_if_fail(options!=NULL);
38 CAPTIVE_MEMZERO(options);
39 options->filesystem.type=CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY;
40 options->rwmode=CAPTIVE_OPTION_RWMODE_BLIND;
41 options->media=CAPTIVE_OPTION_MEDIA_DISK;
42 options->debug_messages=FALSE;
43 options->load_module=NULL;
44 options->sandbox=FALSE;
45 options->syslog_facility=-1;
49 void captive_options_copy(struct captive_options *dest,const struct captive_options *src)
51 GList *load_module_node;
53 g_return_if_fail(dest!=NULL);
54 g_return_if_fail(src!=NULL);
55 g_return_if_fail(dest!=src);
57 memcpy(dest,src,sizeof(*dest));
59 captive_options_module_copy(&dest->filesystem,&src->filesystem);
60 if (dest->image_iochannel)
61 g_io_channel_ref(dest->image_iochannel);
63 dest->load_module=NULL;
64 for (load_module_node=src->load_module;load_module_node;load_module_node=load_module_node->next) {
65 struct captive_options_module *options_module_src=load_module_node->data;
66 struct captive_options_module *options_module_dest;
68 captive_new(options_module_dest);
69 captive_options_module_copy(options_module_dest,options_module_src);
70 dest->load_module=g_list_append(dest->load_module,options_module_dest);
73 if (src->sandbox_server_argv) {
76 for (sp=src->sandbox_server_argv;*sp;sp++) {
77 if (sp>src->sandbox_server_argv)
78 g_assert(*sp>=sp[-1]);
80 dest->sandbox_server_argv=g_memdup(src->sandbox_server_argv,
81 (sp==src->sandbox_server_argv ? (char *)(sp+1) : sp[-1]+strlen(sp[-1])+1) - (char *)src->sandbox_server_argv);
82 /* Really update the pointers inside the copied array block. :-) */
83 for (sp=src->sandbox_server_argv;*sp;sp++) {
84 dest->sandbox_server_argv[sp-src->sandbox_server_argv]=(gpointer)((char *)dest->sandbox_server_argv
85 +(src->sandbox_server_argv[sp-src->sandbox_server_argv]-(char *)src->sandbox_server_argv));
89 if (src->sandbox_server_ior)
90 dest->sandbox_server_ior=g_strdup(src->sandbox_server_ior);
92 if (src->bug_pathname)
93 dest->bug_pathname=g_strdup(src->bug_pathname);
97 void captive_options_free(struct captive_options *options)
99 g_return_if_fail(options!=NULL);
101 captive_options_module_free(&options->filesystem);
102 if (options->image_iochannel)
103 g_io_channel_unref(options->image_iochannel);
105 while (options->load_module) {
106 captive_options_module_free(options->load_module->data);
107 options->load_module=g_list_delete_link(options->load_module,options->load_module); /* also frees 'options->load_module->data' */
110 g_free(options->sandbox_server_argv);
111 g_free(options->sandbox_server_ior);
112 g_free(options->bug_pathname);
116 static gchar *captive_popt_optarg;
119 static void arg_filesystem(void)
123 captive_options_module_free(&captive_options->filesystem);
124 errbool=captive_options_module_load(&captive_options->filesystem,captive_popt_optarg);
125 g_assert(errbool==TRUE);
128 static void arg_load_module(void)
130 struct captive_options_module *options_module;
133 captive_new(options_module);
134 errbool=captive_options_module_load(options_module,captive_popt_optarg);
135 g_assert(errbool==TRUE);
137 captive_options->load_module=g_list_append(captive_options->load_module,options_module);
140 static void arg_ro(void)
142 captive_options->rwmode=CAPTIVE_OPTION_RWMODE_RO;
144 static void arg_blind(void)
146 captive_options->rwmode=CAPTIVE_OPTION_RWMODE_BLIND;
148 static void arg_rw(void)
150 captive_options->rwmode=CAPTIVE_OPTION_RWMODE_RW;
153 static void arg_cdrom(void)
155 captive_options->media=CAPTIVE_OPTION_MEDIA_CDROM;
157 static void arg_disk(void)
159 captive_options->media=CAPTIVE_OPTION_MEDIA_DISK;
162 static void arg_debug_messages(void)
164 captive_options->debug_messages=TRUE;
167 static void sandbox_args_clear(void)
169 free(captive_options->sandbox_server_argv);
170 captive_options->sandbox_server_argv=NULL;
172 g_free(captive_options->sandbox_server_ior);
173 captive_options->sandbox_server_ior=NULL;
175 captive_options->sandbox=FALSE;
178 static void arg_sandbox_server(void)
183 sandbox_args_clear();
185 /* 'argcPtr' is forbidden to be NULL at least by popt of rpm-3.0.6. */
186 errint=poptParseArgvString(
187 captive_popt_optarg, /* s */
188 &trash_argc, /* argcPtr */
189 (const char ***)&captive_options->sandbox_server_argv); /* argvPtr */
192 captive_options->sandbox=TRUE;
195 static void arg_sandbox_server_ior(void)
197 sandbox_args_clear();
199 captive_options->sandbox_server_ior=g_strdup(captive_popt_optarg);
200 captive_options->sandbox=TRUE;
203 static void arg_no_sandbox(void)
205 sandbox_args_clear();
208 static void arg_bug_pathname(void)
210 g_free(captive_options->bug_pathname);
211 captive_options->bug_pathname=g_strdup(captive_popt_optarg);
214 /* Do not: #define SYSLOG_NAMES 1
215 * to enable <syslog.h>/facilitynames[] as such array is global (non-static)
216 * and it is likely it would conflict with facilitynames[] defined elsewhere
217 * (such as even conflicts by libcaptive.so).
219 static const struct syslog_facility {
222 } syslog_facility[]={
224 { "authpriv", LOG_AUTHPRIV },
227 { "cron" , LOG_CRON },
230 { "daemon" , LOG_DAEMON },
236 { "kern" , LOG_KERN },
242 { "mail" , LOG_MAIL },
245 { "news" , LOG_NEWS },
248 { "syslog" , LOG_SYSLOG },
251 { "user" , LOG_USER },
254 { "uucp" , LOG_UUCP },
257 { "local0" , LOG_LOCAL0 },
260 { "local1" , LOG_LOCAL1 },
263 { "local2" , LOG_LOCAL2 },
266 { "local3" , LOG_LOCAL3 },
269 { "local4" , LOG_LOCAL4 },
272 { "local5" , LOG_LOCAL5 },
275 { "local6" , LOG_LOCAL6 },
278 { "local7" , LOG_LOCAL7 },
282 static void arg_syslog(void)
284 captive_options->syslog_facility=DEFAULT_SYSLOG_FACILITY;
287 static int arg_syslog_facility_value;
289 static void arg_syslog_facility(void)
291 const struct syslog_facility *facility;
295 for (facility=syslog_facility;facility<syslog_facility+G_N_ELEMENTS(syslog_facility);facility++)
296 if (!strcmp(captive_popt_optarg,facility->name)) {
297 arg_syslog_facility_value=facility->value;
301 gstring=g_string_new(captive_printf_alloca(_("Unknown '--syslog' facility '%s'; known:"),captive_popt_optarg));
302 for (facility=syslog_facility;facility<syslog_facility+G_N_ELEMENTS(syslog_facility);facility++) {
303 gstring=g_string_append_c(gstring,' ');
304 gstring=g_string_append(gstring,facility->name);
306 gs=g_string_free(gstring,
307 FALSE); /* free_segment */
313 static void captive_popt_callback
314 (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data);
316 const struct poptOption captive_popt[]={
317 { argInfo:POPT_ARG_INTL_DOMAIN,arg:(void *)PACKAGE },
318 { argInfo:POPT_ARG_CALLBACK|POPT_CBFLAG_PRE|POPT_CBFLAG_POST,arg:(void *)captive_popt_callback },
319 #define POPT_OFFSET 2
320 #define CAPTIVE_POPT(longname,argInfoP,argP,descripP,argDescripP) \
322 longName: (longname), \
324 argInfo: (argInfoP), \
327 descrip: (descripP), \
328 argDescrip: (argDescripP), \
330 #define CAPTIVE_POPT_STRING(longname,descripP,argDescripP) \
331 CAPTIVE_POPT(longname,POPT_ARG_STRING,&captive_popt_optarg,descripP,argDescripP)
332 #define CAPTIVE_POPT_NONE(longname,descripP) \
333 CAPTIVE_POPT(longname,POPT_ARG_NONE ,NULL ,descripP,NULL )
335 CAPTIVE_POPT_STRING("filesystem" ,N_("Pathname to .sys or .so filesystem module file"),N_("pathname")),
336 CAPTIVE_POPT_STRING("load-module" ,N_("Pathname to any W32 module to load w/o initialization"),N_("pathname")),
337 CAPTIVE_POPT_NONE( "ro" ,N_("Read/write mode: Any write access will be forbidden")),
338 CAPTIVE_POPT_NONE( "blind" ,N_("Read/write mode: All writes are just simulated in memory (default)")),
339 CAPTIVE_POPT_NONE( "rw" ,N_("Read/write mode: Write directly to the image file/device")),
340 CAPTIVE_POPT_NONE( "cdrom" ,N_("Media type: CD-ROM")),
341 CAPTIVE_POPT_NONE( "disk" ,N_("Media type: Disk (default)")),
342 CAPTIVE_POPT_NONE( "debug-messages" ,N_("Turn on debugging messages")),
343 CAPTIVE_POPT_STRING("sandbox-server" ,N_("Pathname to 'captive-sandbox-server', turns on sandboxing"),N_("pathname")),
344 CAPTIVE_POPT_STRING("sandbox-server-ior",N_("CORBA IOR of 'captive-sandbox-server', turns on sandboxing"),N_("IOR")),
345 CAPTIVE_POPT_NONE( "no-sandbox" ,N_("Turn off sandboxing feature")),
346 CAPTIVE_POPT_STRING("bug-pathname" ,N_("Pathname to strftime(3) for .captivebug.xml.gz bugreports"),N_("pathname")),
347 /* Do not: POPT_ARGFLAG_OPTIONAL
348 * as it always eats one argument unless it is at end of argv[].
350 CAPTIVE_POPT_NONE( "syslog" ,N_("Messages sent to syslog(3) instead of stderr")),
351 CAPTIVE_POPT_STRING("syslog-facility" ,N_("openlog(3) facility for --syslog"),N_("facility")),
353 #undef CAPTIVE_POPT_NONE
354 #undef CAPTIVE_POPT_STRING
359 static const struct poptOption captive_popt_standalone[]={
360 CAPTIVE_POPT_INCLUDE,
366 static void (*const popt_func_table[])(void)={
376 arg_sandbox_server_ior,
384 /* poptCallbackType captive_popt_callback */
385 static void captive_popt_callback
386 (poptContext con,enum poptCallbackReason reason,const struct poptOption *opt,const char *arg,const void *data)
391 case POPT_CALLBACK_REASON_PRE:
392 arg_syslog_facility_value=-1;
395 case POPT_CALLBACK_REASON_OPTION:
396 funci=(opt-(captive_popt+POPT_OFFSET));
397 g_return_if_fail(funci>=0);
398 g_return_if_fail(funci<(gint)G_N_ELEMENTS(popt_func_table));
399 if (popt_func_table[funci])
400 (*popt_func_table[funci])();
401 free(captive_popt_optarg);
404 case POPT_CALLBACK_REASON_POST:
405 if (captive_options->syslog_facility!=-1 && arg_syslog_facility_value!=-1)
406 captive_options->syslog_facility=arg_syslog_facility_value;
410 default: g_assert_not_reached();
413 captive_popt_optarg=NULL; /* sanity */
417 gboolean captive_options_parse(struct captive_options *options,const gchar *captive_args)
420 int captive_args_argc;
421 const char **captive_args_argv=NULL;
425 g_return_val_if_fail(options!=NULL,FALSE);
426 g_return_val_if_fail(captive_args!=NULL,FALSE);
428 g_assert(captive_options==NULL);
429 captive_options=options;
431 errint=poptParseArgvString(captive_args,&captive_args_argc,&captive_args_argv);
433 g_warning("argument parsing args error: %s",captive_args);
436 context=poptGetContext(
438 captive_args_argc,captive_args_argv, /* argc,argv */
439 captive_popt_standalone, /* options */
440 POPT_CONTEXT_KEEP_FIRST);
442 g_warning("argument recognization args error: %s",captive_args);
445 errint=poptReadDefaultConfig(context,
448 g_warning("argument recognization args error: %s",captive_args);
449 goto args_err_context;
451 errint=poptGetNextOpt(context);
453 g_warning("some non-callbacked argument reached: %s",captive_args);
454 goto args_err_context;
456 if (poptPeekArg(context)) {
457 g_warning("some non-option argument reached: %s",captive_args);
458 goto args_err_context;
460 r=TRUE; /* success */
462 poptFreeContext(context);
464 free(captive_args_argv); /* may be NULL here */
467 captive_options=NULL;
471 g_assert(captive_options!=NULL);
472 captive_options=NULL;