[apparmor] [PATCH] Add the ability for the parser to have a basic conf file, that defaults to /etc/apparmor/parser.conf (NOTE option to allow changing this is not provided currently).
John Johansen
john.johansen at canonical.com
Fri Jul 29 01:30:00 UTC 2011
Signed-off-by: John Johansen <john.johansen at canonical.com>
---
parser/apparmor_parser.pod | 16 ++
parser/parser_main.c | 407 +++++++++++++++++++++++++++-----------------
2 files changed, 270 insertions(+), 153 deletions(-)
diff --git a/parser/apparmor_parser.pod b/parser/apparmor_parser.pod
index a7e0add..11d2355 100644
--- a/parser/apparmor_parser.pod
+++ b/parser/apparmor_parser.pod
@@ -199,6 +199,22 @@ Give a quick reference guide.
=back
+=head1 CONFIG FILE
+
+An optional config file /etc/apparmor/parser.conf can be used to specify the
+default options for the parser, which then can be overriden using the command
+line options.
+
+The config file ignores leading whitespace and treats lines that begin with #
+as comments. Config options are specified one per line usign the same format
+as the longform command line options (without the preceeding --).
+
+Eg.
+ #comment
+
+ optimize=no-expr-tree
+ optimize=compress-fast
+
=head1 BUGS
If you find any bugs, please report them at
diff --git a/parser/parser_main.c b/parser/parser_main.c
index e28b2e0..06d3bef 100644
--- a/parser/parser_main.c
+++ b/parser/parser_main.c
@@ -19,6 +19,7 @@
* Ltd.
*/
+#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -304,6 +305,242 @@ static void display_optimize(char *command)
print_flag_table(optflag_table);
}
+
+/* Treat conf file like options passed on command line
+ */
+static int getopt_long_file(FILE *f, const struct option *longopts,
+ char **optarg, int *longindex)
+{
+ static char line[256];
+ char *pos, *opt, *save;
+ int i;
+
+ for (;;) {
+ if (!fgets(line, 256, f))
+ return -1;
+ pos = line;
+ while (isblank(*pos))
+ pos++;
+ if (*pos == '#')
+ continue;
+ opt = strtok_r(pos, " \t\r\n=", &save);
+ /* blank line */
+ if (!opt)
+ continue;
+
+ for (i = 0; longopts[i].name &&
+ strcmp(longopts[i].name, opt) != 0; i++) ;
+ if (!longopts[i].name) {
+ PERROR("%p: unknown option (%s) in config file.\n",
+ progname, opt);
+ /* skip it */
+ continue;
+ }
+ break;
+ }
+
+ if (longindex)
+ *longindex = i;
+
+ if (*save) {
+ int len;
+ while(isblank(*save))
+ save++;
+ len = strlen(save) - 1;
+ if (save[len] == '\n')
+ save[len] = 0;
+ }
+
+ switch (longopts[i].has_arg) {
+ case 0:
+ *optarg = NULL;
+ break;
+ case 1:
+ if (!strlen(save)) {
+ *optarg = NULL;
+ return '?';
+ }
+ *optarg = save;
+ break;
+ case 2:
+ *optarg = save;
+ break;
+ default:
+ PERROR("%p: internal error bad longopt value\n", progname);
+ exit(1);
+ }
+
+ if (longopts[i].flag == NULL)
+ return longopts[i].val;
+ else
+ *longopts[i].flag = longopts[i].val;
+ return 0;
+}
+
+/* process a single argment from getopt_long
+ * Returns: 1 if an action arg, else 0
+ */
+static int process_arg(int c, char *optarg)
+{
+ int count = 0;
+
+ switch (c) {
+ case 0:
+ PERROR("Assert, in getopt_long handling\n");
+ display_usage(progname);
+ exit(0);
+ break;
+ case 'a':
+ count++;
+ option = OPTION_ADD;
+ break;
+ case 'd':
+ debug++;
+ skip_read_cache = 1;
+ break;
+ case 'h':
+ if (!optarg) {
+ display_usage(progname);
+ } else if (strcmp(optarg, "Dump") == 0 ||
+ strcmp(optarg, "dump") == 0 ||
+ strcmp(optarg, "D") == 0) {
+ display_dump(progname);
+ } else if (strcmp(optarg, "Optimize") == 0 ||
+ strcmp(optarg, "optimize") == 0 ||
+ strcmp(optarg, "O") == 0) {
+ display_optimize(progname);
+ } else {
+ PERROR("%s: Invalid --help option %s\n",
+ progname, optarg);
+ exit(1);
+ }
+ exit(0);
+ break;
+ case 'r':
+ count++;
+ option = OPTION_REPLACE;
+ break;
+ case 'R':
+ count++;
+ option = OPTION_REMOVE;
+ skip_cache = 1;
+ break;
+ case 'V':
+ display_version();
+ exit(0);
+ break;
+ case 'I':
+ add_search_dir(optarg);
+ break;
+ case 'b':
+ set_base_dir(optarg);
+ break;
+ case 'B':
+ binary_input = 1;
+ skip_cache = 1;
+ break;
+ case 'C':
+ opt_force_complain = 1;
+ skip_cache = 1;
+ break;
+ case 'N':
+ names_only = 1;
+ skip_cache = 1;
+ break;
+ case 'S':
+ count++;
+ option = OPTION_STDOUT;
+ skip_read_cache = 1;
+ kernel_load = 0;
+ break;
+ case 'o':
+ count++;
+ option = OPTION_OFILE;
+ skip_read_cache = 1;
+ kernel_load = 0;
+ ofile = fopen(optarg, "w");
+ if (!ofile) {
+ PERROR("%s: Could not open file %s\n",
+ progname, optarg);
+ exit(1);
+ }
+ break;
+ case 'f':
+ subdomainbase = strndup(optarg, PATH_MAX);
+ break;
+ case 'D':
+ skip_read_cache = 1;
+ if (!optarg) {
+ dump_vars = 1;
+ } else if (strcmp(optarg, "variables") == 0) {
+ dump_vars = 1;
+ } else if (strcmp(optarg, "expanded-variables") == 0) {
+ dump_expanded_vars = 1;
+ } else if (!handle_flag_table(dumpflag_table, optarg,
+ &dfaflags)) {
+ PERROR("%s: Invalid --Dump option %s\n",
+ progname, optarg);
+ exit(1);
+ }
+ break;
+ case 'O':
+ skip_read_cache = 1;
+
+ if (!handle_flag_table(optflag_table, optarg,
+ &dfaflags)) {
+ PERROR("%s: Invalid --Optimize option %s\n",
+ progname, optarg);
+ exit(1);
+ }
+ break;
+ case 'm':
+ match_string = strdup(optarg);
+ break;
+ case 'q':
+ conf_verbose = 0;
+ conf_quiet = 1;
+ break;
+ case 'v':
+ conf_verbose = 1;
+ conf_quiet = 0;
+ break;
+ case 'n':
+ profile_namespace = strdup(optarg);
+ break;
+ case 'X':
+ read_implies_exec = 1;
+ break;
+ case 'K':
+ skip_cache = 1;
+ break;
+ case 'k':
+ show_cache = 1;
+ break;
+ case 'W':
+ write_cache = 1;
+ break;
+ case 'T':
+ skip_read_cache = 1;
+ break;
+ case 'Q':
+ kernel_load = 0;
+ break;
+ case 'p':
+ count++;
+ kernel_load = 0;
+ skip_cache = 1;
+ preprocess_only = 1;
+ skip_mode_force = 1;
+ break;
+ default:
+ display_usage(progname);
+ exit(0);
+ break;
+ }
+
+ return count;
+}
+
static int process_args(int argc, char *argv[])
{
int c, o;
@@ -312,159 +549,7 @@ static int process_args(int argc, char *argv[])
while ((c = getopt_long(argc, argv, "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWkO:po:", long_options, &o)) != -1)
{
- switch (c) {
- case 0:
- PERROR("Assert, in getopt_long handling\n");
- display_usage(progname);
- exit(0);
- break;
- case 'a':
- count++;
- option = OPTION_ADD;
- break;
- case 'd':
- debug++;
- skip_read_cache = 1;
- break;
- case 'h':
- if (!optarg) {
- display_usage(progname);
- } else if (strcmp(optarg, "Dump") == 0 ||
- strcmp(optarg, "dump") == 0 ||
- strcmp(optarg, "D") == 0) {
- display_dump(progname);
- } else if (strcmp(optarg, "Optimize") == 0 ||
- strcmp(optarg, "optimize") == 0 ||
- strcmp(optarg, "O") == 0) {
- display_optimize(progname);
- } else {
- PERROR("%s: Invalid --help option %s\n",
- progname, optarg);
- exit(1);
- }
- exit(0);
- break;
- case 'r':
- count++;
- option = OPTION_REPLACE;
- break;
- case 'R':
- count++;
- option = OPTION_REMOVE;
- skip_cache = 1;
- break;
- case 'V':
- display_version();
- exit(0);
- break;
- case 'I':
- add_search_dir(optarg);
- break;
- case 'b':
- set_base_dir(optarg);
- break;
- case 'B':
- binary_input = 1;
- skip_cache = 1;
- break;
- case 'C':
- opt_force_complain = 1;
- skip_cache = 1;
- break;
- case 'N':
- names_only = 1;
- skip_cache = 1;
- break;
- case 'S':
- count++;
- option = OPTION_STDOUT;
- skip_read_cache = 1;
- kernel_load = 0;
- break;
- case 'o':
- count++;
- option = OPTION_OFILE;
- skip_read_cache = 1;
- kernel_load = 0;
- ofile = fopen(optarg, "w");
- if (!ofile) {
- PERROR("%s: Could not open file %s\n",
- progname, optarg);
- exit(1);
- }
- break;
- case 'f':
- subdomainbase = strndup(optarg, PATH_MAX);
- break;
- case 'D':
- skip_read_cache = 1;
- if (!optarg) {
- dump_vars = 1;
- } else if (strcmp(optarg, "variables") == 0) {
- dump_vars = 1;
- } else if (strcmp(optarg, "expanded-variables") == 0) {
- dump_expanded_vars = 1;
- } else if (!handle_flag_table(dumpflag_table, optarg,
- &dfaflags)) {
- PERROR("%s: Invalid --Dump option %s\n",
- progname, optarg);
- exit(1);
- }
- break;
- case 'O':
- skip_read_cache = 1;
-
- if (!handle_flag_table(optflag_table, optarg,
- &dfaflags)) {
- PERROR("%s: Invalid --Optimize option %s\n",
- progname, optarg);
- exit(1);
- }
- break;
- case 'm':
- match_string = strdup(optarg);
- break;
- case 'q':
- conf_verbose = 0;
- conf_quiet = 1;
- break;
- case 'v':
- conf_verbose = 1;
- conf_quiet = 0;
- break;
- case 'n':
- profile_namespace = strdup(optarg);
- break;
- case 'X':
- read_implies_exec = 1;
- break;
- case 'K':
- skip_cache = 1;
- break;
- case 'k':
- show_cache = 1;
- break;
- case 'W':
- write_cache = 1;
- break;
- case 'T':
- skip_read_cache = 1;
- break;
- case 'Q':
- kernel_load = 0;
- break;
- case 'p':
- count++;
- kernel_load = 0;
- skip_cache = 1;
- preprocess_only = 1;
- skip_mode_force = 1;
- break;
- default:
- display_usage(progname);
- exit(0);
- break;
- }
+ count += process_arg(c, optarg);
}
if (count > 1) {
@@ -478,6 +563,21 @@ static int process_args(int argc, char *argv[])
return optind;
}
+static int process_config_file(const char *name)
+{
+ char *optarg;
+ FILE *f;
+ int c, o;
+
+ f = fopen(name, "r");
+ if (!f)
+ return 0;
+
+ while ((c = getopt_long_file(f, long_options, &optarg, &o)) != -1)
+ process_arg(c, optarg);
+ return 1;
+}
+
static inline char *try_subdomainfs_mountpoint(const char *mntpnt,
const char *path)
{
@@ -990,6 +1090,7 @@ int main(int argc, char *argv[])
init_base_dir();
+ process_config_file("/etc/apparmor/parser.conf");
optind = process_args(argc, argv);
setlocale(LC_MESSAGES, "");
--
1.7.5.4
More information about the AppArmor
mailing list