Make it easier to print the help for select options.
[adu.git] / adu.c
diff --git a/adu.c b/adu.c
index 07248e99a592e6466cb7f42abeb9d45fbeab905f..8ce7317cdd207719f924523a0d7aa5ca32fcf288 100644 (file)
--- a/adu.c
+++ b/adu.c
@@ -1,6 +1,8 @@
 #include "adu.h"
 #include <dirent.h> /* readdir() */
 #include <pwd.h>
+#include "format.h"
+#include "select.h"
 
 #include "gcc-compat.h"
 #include "cmdline.h"
@@ -18,6 +20,9 @@ static int signum;
 /** Command line and config file options. */
 struct gengetopt_args_info conf;
 
+/** Options passed to --select-options. */
+struct select_args_info select_conf;
+
 /** The number of different uids found so far. */
 uint32_t num_uids = 0;
 
@@ -48,12 +53,6 @@ static inline int ui_admissible(struct user_info *ui)
  */
 struct osl_table *dir_table = NULL;
 
-/**
- * The array of all uid ranges that were given at the command line.
- */
-struct uid_range *admissible_uids;
-
-
 /**
  * Compare the size of two directories
  *
@@ -142,6 +141,15 @@ static struct osl_table_description dir_table_desc = {
        .column_descriptions = dir_table_cols,
 };
 
+/*
+ * The columns of the per-user tables.
+ *
+ * Adu tracks disk usage on a per-user basis. For each user, a user table is
+ * being created. The rows of the user table have three columns: The directory
+ * number that may be resolved to the path using the directory table, the
+ * number of bytes and the number of files in that directory owned by the given
+ * user.
+ */
 static struct osl_column_description user_table_cols[] = {
        [UT_DIR_NUM] = {
                .storage_type = OSL_MAPPED_STORAGE,
@@ -363,24 +371,25 @@ static uint32_t double_hash(uint32_t uid, uint32_t probe_num)
                % uid_hash_table_size;
 }
 
-static int uid_is_admissible(uint32_t uid)
+static int uid_is_admissible(uint32_t uid, struct uid_range *urs)
 {
-       int i;
-
-       for (i = 0; i < conf.uid_given; i++) {
-               struct uid_range *ur = admissible_uids + i;
+       struct uid_range *ur;
+       int ret = 1;
 
+       if (!urs) /* empty array means all uids are allowed */
+               return 1;
+       FOR_EACH_UID_RANGE(ur, urs)
                if (ur->low <= uid && ur->high >= uid)
-                       break;
-       }
-       i = !conf.uid_given || i < conf.uid_given;
+                       goto out;
+       ret = 0;
+out:
        DEBUG_LOG("uid %u is %sadmissible\n", (unsigned)uid,
-               i? "" : "not ");
-       return i;
+               ret? "" : "not ");
+       return ret;
 }
 
-int search_uid(uint32_t uid, enum search_uid_flags flags,
-               struct user_info **ui_ptr)
+int search_uid(uint32_t uid, struct uid_range *urs,
+               enum search_uid_flags flags, struct user_info **ui_ptr)
 {
        uint32_t p;
 
@@ -393,7 +402,7 @@ int search_uid(uint32_t uid, enum search_uid_flags flags,
                                return -E_BAD_UID;
                        ui->uid = uid;
                        ui->flags |= UI_FL_SLOT_USED;
-                       if (!uid_is_admissible(uid))
+                       if (!uid_is_admissible(uid, urs))
                                return 0;
                        ui->flags |= UI_FL_ADMISSIBLE;
                        ret = open_user_table(ui, flags & CREATE_USER_TABLE);
@@ -440,9 +449,6 @@ int open_dir_table(int create)
 
 static int check_args(void)
 {
-       int i, ret;
-
-
        if (conf.create_given && !conf.base_dir_given)
                return -E_SYNTAX;
 
@@ -459,19 +465,35 @@ static int check_args(void)
                        conf.base_dir_arg[len] = '\0';
                }
        }
-       if (!conf.uid_given)
-               return 0;
-       admissible_uids = adu_malloc(conf.uid_given * sizeof(*admissible_uids));
-       for (i = 0; i < conf.uid_given; i++) {
-               ret = parse_uid_range(conf.uid_arg[i], admissible_uids + i);
-               if (ret < 0)
-                       goto err;
-       }
        return 1;
-err:
-       free(admissible_uids);
-       admissible_uids = NULL;
-       return ret;
+}
+
+static int print_complete_help_and_die(void)
+{
+       const char **line;
+       select_cmdline_parser_init(&select_conf);
+
+       if (conf.help_given)
+               line = gengetopt_args_info_help;
+       else
+               line = gengetopt_args_info_detailed_help;
+
+       printf("adu command line options:\n");
+       printf("=========================\n");
+       for (; *line; line++)
+               printf("%s\n", *line);
+       if (conf.help_given)
+               line = select_args_info_help;
+       else
+               line  = select_args_info_detailed_help;
+       printf("select options:\n");
+       printf("===============\n");
+       for (; *line; line++)
+               printf("%s\n", *line);
+       printf("interactive commands:\n");
+       printf("=====================\n");
+       print_interactive_help();
+       exit(EXIT_FAILURE);
 }
 
 int main(int argc, char **argv)
@@ -480,12 +502,21 @@ int main(int argc, char **argv)
        struct cmdline_parser_params params = {
                .override = 0,
                .initialize = 1,
-               .check_required = 1,
-               .check_ambiguity = 1,
-               .print_errors = 1
+               .check_required = 0,
+               .check_ambiguity = 0,
+               .print_errors = 0
        };
+       /* ignore errors and print complete help if --help was given */
+       cmdline_parser_ext(argc, argv, &conf, &params);
+       if (conf.help_given || conf.detailed_help_given)
+               print_complete_help_and_die();
+       params.check_required = 1;
+       params.check_ambiguity = 1;
+       params.print_errors = 1;
+       ret = cmdline_parser_ext(argc, argv, &conf, &params);
+       if (ret)
+               exit(EXIT_FAILURE);
 
-       cmdline_parser_ext(argc, argv, &conf, &params); /* aborts on errors */
        ret = check_args();
        if (ret < 0)
                goto out;
@@ -502,7 +533,6 @@ int main(int argc, char **argv)
        if (ret < 0)
                goto out;
 out:
-       free(admissible_uids);
        if (ret < 0) {
                ERROR_LOG("%s\n", adu_strerror(-ret));
                return -EXIT_FAILURE;