Completely rebuild the commandline processing.
authorlace <>
Mon, 26 Dec 2005 16:44:34 +0000 (16:44 +0000)
committerlace <>
Mon, 26 Dec 2005 16:44:34 +0000 (16:44 +0000)
 - It should now mostly match the original LUFS mount.captive(8) behavior.

src/client/fuse/main.c

index b805c71..c018808 100644 (file)
@@ -118,15 +118,30 @@ struct fuse *capfuse_fuse;
 
 int main(int argc,char **argv)
 {
-poptContext context;
-int errint;
-int rest_argc,i;
+poptContext context=NULL;      /* Valid if: opt_o; '= NULL' to shut up GCC. */
+int rest_argc;
 const char **rest_argv,**csp;
 struct captive_options options;
+int capfuse_argc;
 const char **capfuse_argv;
 const char *program_name=argv[0];
 const char *sandbox_server_argv0=G_STRINGIFY(LIBEXECDIR) "/captive-sandbox-server";
-const char *image_filename;
+const char *image_filename=NULL;
+gboolean opt_n=FALSE;
+gboolean opt_v=FALSE;
+const char *opt_o=NULL;
+const char *mountpoint=NULL;
+char **argv_sp;
+int opt_o_argc;        /* Valid if: opt_o */
+const char **opt_o_argv=NULL;  /* Valid if: opt_o */
+
+#if 0
+{
+char **sp;
+       for (sp=argv;*sp;sp++)
+               fprintf(stderr,"argv: \"%s\"\n",*sp);
+}
+#endif
 
        g_log_set_always_fatal(~(0
                        |G_LOG_LEVEL_MESSAGE
@@ -136,6 +151,74 @@ const char *image_filename;
 
        captive_standalone_init();
 
+       argv_sp=argv+1;
+       if (*argv_sp && (*argv_sp)[0]!='-')
+               image_filename=*argv_sp++;
+       if (*argv_sp && (*argv_sp)[0]!='-')
+               mountpoint=*argv_sp++;
+       if (*argv_sp && !strcmp(*argv_sp,"-n")) {
+               opt_n=TRUE;
+               argv_sp++;
+               }
+       if (*argv_sp && !strcmp(*argv_sp,"-v")) {
+               opt_v=TRUE;
+               argv_sp++;
+               }
+       if (argv_sp[0] && argv_sp[1] && !strcmp(argv_sp[0],"-o")) {
+               argv_sp++;
+               opt_o=*argv_sp++;
+               }
+       if (*argv_sp) {
+               /* Lethal path but still give chance for "--help" etc. */
+               /* Do not: POPT_CONTEXT_POSIXMEHARDER
+                * as mount(8) puts there first un-pre-dashed "ro"/"rw" etc. */
+               if ((context=poptGetContext(
+                               PACKAGE,        /* name */
+                               argc,(/*en-const*/const char **)argv,   /* argc,argv */
+                               popt_table,     /* options */
+                               0)))    /* flags; && !POPT_CONTEXT_KEEP_FIRST */
+                       while (0<=poptGetNextOpt(context));
+               g_error(_("Excessive argument: %s"),*argv_sp);
+               }
+
+       if (opt_o) {
+char *opt_o_spaced=(char */* de-const; length is not changed */)captive_strdup_alloca(opt_o);
+char *s,quote;
+
+               quote=0;
+               for (s=opt_o_spaced;*s;s++) {
+                       /* Be compatible with: poptParseArgvString()
+                        * which also does not differentiate '"' and "'" */
+                       if (*s=='\\' && s[1]) {
+                               s++;
+                               continue;
+                               }
+                       if (quote) {
+                               if (*s==quote)
+                                       quote=0;
+                               continue;
+                               }
+                       switch (*s) {
+                               case '"':
+                               case '\'':
+                                       quote=*s;
+                                       continue;
+                               case ',':
+                                       *s=' ';
+                                       continue;
+                               }
+                       }
+               if (poptParseArgvString(opt_o_spaced,&opt_o_argc,&opt_o_argv))
+                       g_error(_("Error splitting arguments of the space-reparsed '-o': %s"),opt_o_spaced);
+               /* Pre-dash "ro"/"rw" to let libcaptive to be aware of the mode. */
+               for (csp=opt_o_argv;*csp;csp++) {
+                       if (!strcmp(*csp,"ro"))
+                               *csp="--ro";
+                       if (!strcmp(*csp,"rw"))
+                               *csp="--rw";
+                       }
+               }
+
        captive_options_init(&options);
        captive_options=&options;       /* for parsing by 'CAPTIVE_POPT_INCLUDE' */
 
@@ -154,55 +237,32 @@ const char *image_filename;
 
        options.syslog_facility=DEFAULT_SYSLOG_FACILITY;
 
-       context=poptGetContext(
-                       PACKAGE,        /* name */
-                       argc,(/*en-const*/const char **)argv,   /* argc,argv */
-                       popt_table,     /* options */
-                       POPT_CONTEXT_POSIXMEHARDER);    /* flags; && !POPT_CONTEXT_KEEP_FIRST */
-       if (context==NULL) {
-               g_error(_("Error parsing command-line arguments"));
-               return EXIT_FAILURE;
-               }
-       errint=poptReadDefaultConfig(context,
-                       TRUE);  /* useEnv */
-       if (errint!=0)
-               g_warning(_("Error reading default popt configuration"));
-       errint=poptGetNextOpt(context);
-       if (errint!=-1) {
-               g_error(_("Error parsing (dash-prefixed) command-line argument"));
-               return EXIT_FAILURE;
+       if (opt_o) {
+               /* Do not: POPT_CONTEXT_POSIXMEHARDER
+                * as mount(8) puts there first un-pre-dashed "ro"/"rw" etc. */
+               if (!(context=poptGetContext(
+                               PACKAGE,        /* name */
+                               opt_o_argc,opt_o_argv,  /* argc,argv */
+                               popt_table,     /* options */
+                               POPT_CONTEXT_KEEP_FIRST)))      /* flags */
+                       g_error(_("Error parsing command-line arguments from pre-parsed '-o': %s"),opt_o);
+               if (poptReadDefaultConfig(context,
+                               TRUE))  /* useEnv */
+                       g_warning(_("Error reading default popt configuration"));
+               while (0<=poptGetNextOpt(context));
+               rest_argv=poptGetArgs(context);
                }
-       rest_argv=poptGetArgs(context);
-       for (csp=rest_argv,rest_argc=0;csp && *csp;csp++)
+       else
+               rest_argv=NULL;
+       rest_argc=0;
+       for (csp=rest_argv;csp && *csp;csp++)
                rest_argc++;
 
-       /* Override the (default) Captive options with mount(8) supplied "-o" argument. */
-       /* rest_argv[0] is the device now. */
-       /* rest_argv[1] is the mountpoint now. */
-       if (rest_argc>=4 && !strcmp(rest_argv[2],"-o")) {
-const char *cs=rest_argv[3];
-
-               while (cs&&*cs) {
-                       if ((!strncmp(cs,"ro",2) || !strncmp(cs,"rw",2)) && (cs[2]==',' || !cs[2])) {
-                               if (!strncmp(cs,"ro",2))
-                                       options.rwmode=CAPTIVE_OPTION_RWMODE_RO;
-                               if (!strncmp(cs,"rw",2))
-                                       options.rwmode=CAPTIVE_OPTION_RWMODE_RW;
-                               }
-                       if ((cs=strchr(cs,',')))
-                               cs++;
-                       }
-               }
+       if (!image_filename || !mountpoint)
+               g_error(_("File/device disk image pathname and mountpoint command-line arguments required"));
 
        /* image_iochannel */
-       if (rest_argc<1) {
-               g_error(_("File/device disk image pathname command-line argument required"));
-               return EXIT_FAILURE;
-               }
        g_assert(options.image_iochannel==NULL);
-       image_filename=rest_argv[0];
-       rest_argc--;
-       rest_argv++;
        if (!(options.image_iochannel=g_io_channel_new_file(
                        image_filename, /* filename */
                        (options.rwmode==CAPTIVE_OPTION_RWMODE_RW ? "r+" : "r"),        /* mode */
@@ -251,29 +311,36 @@ struct captive_options_module *options_module;
        captive_options_free(&options);
 
        /* Simulate argv[0] there as it got cut by popt. */
-       captive_newn_alloca(capfuse_argv,1+rest_argc+1+2);
-       capfuse_argv[0]=argv[0];
-       memcpy(capfuse_argv+1,rest_argv,sizeof(*rest_argv)*(rest_argc+1));
-
-       for (i=1;capfuse_argv[i];i++) {
-               if (strcmp(capfuse_argv[i],"-o"))
-                       continue;
-               capfuse_argv[i+1]=captive_printf_alloca("fsname=%s" LIBFUSE_ADDONS  ",%s",image_filename,capfuse_argv[i+1]);
-               break;
-               }
-       if (!capfuse_argv[i]) {
-               capfuse_argv[i  ]="-o";
-               capfuse_argv[i+1]=captive_printf_alloca("fsname=%s" LIBFUSE_ADDONS,image_filename);
-               capfuse_argv[i+2]=NULL;
-               }
+       capfuse_argc=4+2*rest_argc;
+       captive_newn_alloca(capfuse_argv,capfuse_argc+1);
+       csp=capfuse_argv;
+       *csp++=argv[0];
+       *csp++=mountpoint;
+       *csp++="-o";
+       *csp++=captive_printf_alloca("fsname=%s" LIBFUSE_ADDONS ",%s",
+                       image_filename,(options.rwmode==CAPTIVE_OPTION_RWMODE_RO ? "ro" : "rw"));
+       if (rest_argv)
+               while (*rest_argv) {
+                       *csp++="-o";
+                       *csp++=*rest_argv++;
+                       }
+       *csp=NULL;
+#if 0
+{
+const char **csp;
+       for (csp=capfuse_argv;*csp;csp++)
+               fprintf(stderr,"capfuse_argv: \"%s\"\n",*csp);
+}
+#endif
 
        /* FIXFUSE: fuse_main()/fuse_main_real() would be enough for Captive fuse but
         * the public interface of fuse_main() is too broken.
         */
-       capfuse_run(1+rest_argc,capfuse_argv);
+       capfuse_run(capfuse_argc,capfuse_argv);
 
        /* 'rest_argv' gets cleared by 'poptFreeContext(context);' below */
-       poptFreeContext(context);
+       if (opt_o)
+               poptFreeContext(context);
 
        if (capfuse_captive_vfs_object) {
                g_object_unref(capfuse_captive_vfs_object);