2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-29 13:28:19 +00:00

parser: update option parsing so --config-file does not have to be first

Requiring --config-file to be first in the option list is not user
friendly fix the option parsing so that --config-file can be specified
anywhere in the option list.

This also fixes a bug where even when the --config-file option is
first the option parsing fails because the detection logic is broken
for some option cases.

PR: https://gitlab.com/apparmor/apparmor/merge_requests/175
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2018-08-19 02:13:21 -07:00
parent 9a8e7e58d2
commit af1818c053
2 changed files with 30 additions and 30 deletions

View File

@ -359,9 +359,8 @@ profiles.
=item --config-file =item --config-file
Specify the config file to use instead of Specify the config file to use instead of
/etc/apparmor/parser.conf. This option must be the first option /etc/apparmor/parser.conf. This option will be processed early before
specified when invoking the parser, otherwise the parser will abort regular options regardless of the order it is specified in.
with an error.
=item --print-config-file =item --print-config-file

View File

@ -59,6 +59,8 @@
#define PRIVILEGED_OPS (kernel_load) #define PRIVILEGED_OPS (kernel_load)
#define UNPRIVILEGED_OPS (!(PRIVILEGED_OPS)) #define UNPRIVILEGED_OPS (!(PRIVILEGED_OPS))
#define EARLY_ARG_CONFIG_FILE 141
const char *parser_title = "AppArmor parser"; const char *parser_title = "AppArmor parser";
const char *parser_copyright = "Copyright (C) 1999-2008 Novell Inc.\nCopyright 2009-2018 Canonical Ltd."; const char *parser_copyright = "Copyright (C) 1999-2008 Novell Inc.\nCopyright 2009-2018 Canonical Ltd.";
@ -161,7 +163,7 @@ struct option long_options[] = {
{"kernel-features", 1, 0, 138}, /* no short option */ {"kernel-features", 1, 0, 138}, /* no short option */
{"compile-features", 1, 0, 139}, /* no short option */ {"compile-features", 1, 0, 139}, /* no short option */
{"print-config-file", 0, 0, 140}, /* no short option */ {"print-config-file", 0, 0, 140}, /* no short option */
{"config-file", 1, 0, 141}, /* early option, no short option */ {"config-file", 1, 0, EARLY_ARG_CONFIG_FILE}, /* early option, no short option */
{NULL, 0, 0, 0}, {NULL, 0, 0, 0},
}; };
@ -219,7 +221,7 @@ static void display_usage(const char *command)
"--max-jobs n Hard cap on --jobs. Default 8*cpus\n" "--max-jobs n Hard cap on --jobs. Default 8*cpus\n"
"--abort-on-error Abort processing of profiles on first error\n" "--abort-on-error Abort processing of profiles on first error\n"
"--skip-bad-cache-rebuild Do not try rebuilding the cache if it is rejected by the kernel\n" "--skip-bad-cache-rebuild Do not try rebuilding the cache if it is rejected by the kernel\n"
"--config-file n Specify the parser config file location, Must be the first option.\n" "--config-file n Specify the parser config file location, processed early before other options.\n"
"--print-config Print config file location\n" "--print-config Print config file location\n"
"--warn n Enable warnings (see --help=warn)\n" "--warn n Enable warnings (see --help=warn)\n"
,command); ,command);
@ -388,10 +390,19 @@ static long process_jobs_arg(const char *arg, const char *val) {
} }
bool early_arg(int c) {
switch(c) {
case EARLY_ARG_CONFIG_FILE:
return true;
}
return false;
}
/* process a single argment from getopt_long /* process a single argment from getopt_long
* Returns: 1 if an action arg, else 0 * Returns: 1 if an action arg, else 0
*/ */
static int process_arg(int c, char *optarg, int config_count) static int process_arg(int c, char *optarg)
{ {
int count = 0; int count = 0;
@ -639,16 +650,11 @@ static int process_arg(int c, char *optarg, int config_count)
kernel_load = 0; kernel_load = 0;
print_cache_dir = true; print_cache_dir = true;
break; break;
case 141: case EARLY_ARG_CONFIG_FILE:
if (optind - config_count != 1) { config_file = strdup(optarg);
PERROR("%s: --config-file=%s must be the first option specified\n", progname, optarg); if (!config_file) {
PERROR("%s: %m", progname);
exit(1); exit(1);
} else {
config_file = strdup(optarg);
if (!config_file) {
PERROR("%s: %m", progname);
exit(1);
}
} }
break; break;
case 140: case 140:
@ -663,24 +669,18 @@ static int process_arg(int c, char *optarg, int config_count)
return count; return count;
} }
static int process_early_args(int argc, char *argv[]) static void process_early_args(int argc, char *argv[])
{ {
int c, o, count = 1; int c, o;
if (argc <= 1) while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1)
return 1;
if (strcmp("--config-file", argv[1]) == 0)
count = 2;
else if (strncmp("--config-file=", argv[1], 14) != 0)
return 1;
if ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1)
{ {
process_arg(c, optarg, count); if (early_arg(c))
process_arg(c, optarg);
} }
PDEBUG("optind = %d argc = %d\n", optind, argc); /* reset args, so we are ready for a second pass */
return optind; optind = 1;
} }
static int process_args(int argc, char *argv[]) static int process_args(int argc, char *argv[])
@ -692,7 +692,8 @@ static int process_args(int argc, char *argv[])
opterr = 1; opterr = 1;
while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1) while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1)
{ {
count += process_arg(c, optarg, 0); if (!early_arg(c))
count += process_arg(c, optarg);
} }
if (count > 1) { if (count > 1) {
@ -718,7 +719,7 @@ static int process_config_file(const char *name)
} }
while ((c = getopt_long_file(f, long_options, &optarg, &o)) != -1) while ((c = getopt_long_file(f, long_options, &optarg, &o)) != -1)
process_arg(c, optarg, 0); process_arg(c, optarg);
return 1; return 1;
} }