static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_TAIL, ARG_NEW_ID128, ARG_HEADER }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version" , no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "follow", no_argument, NULL, 'f' }, { "output", required_argument, NULL, 'o' }, { "all", no_argument, NULL, 'a' }, { "lines", required_argument, NULL, 'n' }, { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, { "local", no_argument, NULL, 'l' }, { "this-boot", no_argument, NULL, 'b' }, { "directory", required_argument, NULL, 'D' }, { "header", no_argument, NULL, ARG_HEADER }, { NULL, 0, NULL, 0 } }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hfo:an:qlbD:", options, NULL)) >= 0) { switch (c) { case 'h': help(); return 0; case ARG_VERSION: puts(PACKAGE_STRING); puts(DISTRIBUTION); puts(SYSTEMD_FEATURES); return 0; case ARG_NO_PAGER: arg_no_pager = true; break; case 'f': arg_follow = true; break; case 'o': arg_output = output_mode_from_string(optarg); if (arg_output < 0) { log_error("Unknown output '%s'.", optarg); return -EINVAL; } break; case 'a': arg_show_all = true; break; case 'n': r = safe_atoi(optarg, &arg_lines); if (r < 0 || arg_lines < 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } break; case ARG_NO_TAIL: arg_no_tail = true; break; case ARG_NEW_ID128: arg_new_id128 = true; break; case 'q': arg_quiet = true; break; case 'l': arg_local = true; break; case 'b': arg_this_boot = true; break; case 'D': arg_directory = optarg; break; case ARG_HEADER: arg_print_header = true; break; case '?': return -EINVAL; default: log_error("Unknown option code %c", c); return -EINVAL; } } if (arg_follow && !arg_no_tail && arg_lines < 0) arg_lines = 10; return 1; }
static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_NO_TAIL, ARG_NEW_ID128, ARG_ROOT, ARG_HEADER, ARG_FULL, ARG_SETUP_KEYS, ARG_INTERVAL, ARG_VERIFY, ARG_VERIFY_KEY, ARG_DISK_USAGE, ARG_SINCE, ARG_UNTIL, ARG_USER_UNIT, ARG_LIST_CATALOG, ARG_DUMP_CATALOG, ARG_UPDATE_CATALOG }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version" , no_argument, NULL, ARG_VERSION }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, { "pager-end", no_argument, NULL, 'e' }, { "follow", no_argument, NULL, 'f' }, { "output", required_argument, NULL, 'o' }, { "all", no_argument, NULL, 'a' }, { "full", no_argument, NULL, ARG_FULL }, { "lines", optional_argument, NULL, 'n' }, { "no-tail", no_argument, NULL, ARG_NO_TAIL }, { "new-id128", no_argument, NULL, ARG_NEW_ID128 }, { "quiet", no_argument, NULL, 'q' }, { "merge", no_argument, NULL, 'm' }, { "this-boot", no_argument, NULL, 'b' }, { "directory", required_argument, NULL, 'D' }, { "root", required_argument, NULL, ARG_ROOT }, { "header", no_argument, NULL, ARG_HEADER }, { "priority", required_argument, NULL, 'p' }, { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS }, { "interval", required_argument, NULL, ARG_INTERVAL }, { "verify", no_argument, NULL, ARG_VERIFY }, { "verify-key", required_argument, NULL, ARG_VERIFY_KEY }, { "disk-usage", no_argument, NULL, ARG_DISK_USAGE }, { "cursor", required_argument, NULL, 'c' }, { "since", required_argument, NULL, ARG_SINCE }, { "until", required_argument, NULL, ARG_UNTIL }, { "unit", required_argument, NULL, 'u' }, { "user-unit", required_argument, NULL, ARG_USER_UNIT }, { "field", required_argument, NULL, 'F' }, { "catalog", no_argument, NULL, 'x' }, { "list-catalog", no_argument, NULL, ARG_LIST_CATALOG }, { "dump-catalog", no_argument, NULL, ARG_DUMP_CATALOG }, { "update-catalog",no_argument, NULL, ARG_UPDATE_CATALOG }, { "reverse", no_argument, NULL, 'r' }, { NULL, 0, NULL, 0 } }; int c, r; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "hefo:an::qmbD:p:c:u:F:xr", options, NULL)) >= 0) { switch (c) { case 'h': help(); return 0; case ARG_VERSION: puts(PACKAGE_STRING); puts(SYSTEMD_FEATURES); return 0; case ARG_NO_PAGER: arg_no_pager = true; break; case 'e': arg_pager_end = true; if (arg_lines < 0) arg_lines = 1000; break; case 'f': arg_follow = true; break; case 'o': arg_output = output_mode_from_string(optarg); if (arg_output < 0) { log_error("Unknown output format '%s'.", optarg); return -EINVAL; } if (arg_output == OUTPUT_EXPORT || arg_output == OUTPUT_JSON || arg_output == OUTPUT_JSON_PRETTY || arg_output == OUTPUT_JSON_SSE || arg_output == OUTPUT_CAT) arg_quiet = true; break; case ARG_FULL: arg_full = true; break; case 'a': arg_all = true; break; case 'n': if (optarg) { r = safe_atoi(optarg, &arg_lines); if (r < 0 || arg_lines < 0) { log_error("Failed to parse lines '%s'", optarg); return -EINVAL; } } else { int n; /* Hmm, no argument? Maybe the next * word on the command line is * supposed to be the argument? Let's * see if there is one, and is * parsable as a positive * integer... */ if (optind < argc && safe_atoi(argv[optind], &n) >= 0 && n >= 0) { arg_lines = n; optind++; } else arg_lines = 10; } break; case ARG_NO_TAIL: arg_no_tail = true; break; case ARG_NEW_ID128: arg_action = ACTION_NEW_ID128; break; case 'q': arg_quiet = true; break; case 'm': arg_merge = true; break; case 'b': arg_this_boot = true; break; case 'D': arg_directory = optarg; break; case ARG_ROOT: arg_root = optarg; break; case 'c': arg_cursor = optarg; break; case ARG_HEADER: arg_action = ACTION_PRINT_HEADER; break; case ARG_VERIFY: arg_action = ACTION_VERIFY; break; case ARG_DISK_USAGE: arg_action = ACTION_DISK_USAGE; break; #ifdef HAVE_GCRYPT case ARG_SETUP_KEYS: arg_action = ACTION_SETUP_KEYS; break; case ARG_VERIFY_KEY: arg_action = ACTION_VERIFY; arg_verify_key = optarg; arg_merge = false; break; case ARG_INTERVAL: r = parse_sec(optarg, &arg_interval); if (r < 0 || arg_interval <= 0) { log_error("Failed to parse sealing key change interval: %s", optarg); return -EINVAL; } break; #else case ARG_SETUP_KEYS: case ARG_VERIFY_KEY: case ARG_INTERVAL: log_error("Forward-secure sealing not available."); return -ENOTSUP; #endif case 'p': { const char *dots; dots = strstr(optarg, ".."); if (dots) { char *a; int from, to, i; /* a range */ a = strndup(optarg, dots - optarg); if (!a) return log_oom(); from = log_level_from_string(a); to = log_level_from_string(dots + 2); free(a); if (from < 0 || to < 0) { log_error("Failed to parse log level range %s", optarg); return -EINVAL; } arg_priorities = 0; if (from < to) { for (i = from; i <= to; i++) arg_priorities |= 1 << i; } else { for (i = to; i <= from; i++) arg_priorities |= 1 << i; } } else { int p, i; p = log_level_from_string(optarg); if (p < 0) { log_error("Unknown log level %s", optarg); return -EINVAL; } arg_priorities = 0; for (i = 0; i <= p; i++) arg_priorities |= 1 << i; } break; } case ARG_SINCE: r = parse_timestamp(optarg, &arg_since); if (r < 0) { log_error("Failed to parse timestamp: %s", optarg); return -EINVAL; } arg_since_set = true; break; case ARG_UNTIL: r = parse_timestamp(optarg, &arg_until); if (r < 0) { log_error("Failed to parse timestamp: %s", optarg); return -EINVAL; } arg_until_set = true; break; case 'u': r = strv_extend(&arg_system_units, optarg); if (r < 0) return log_oom(); break; case ARG_USER_UNIT: r = strv_extend(&arg_user_units, optarg); if (r < 0) return log_oom(); break; case '?': return -EINVAL; case 'F': arg_field = optarg; break; case 'x': arg_catalog = true; break; case ARG_LIST_CATALOG: arg_action = ACTION_LIST_CATALOG; break; case ARG_DUMP_CATALOG: arg_action = ACTION_DUMP_CATALOG; break; case ARG_UPDATE_CATALOG: arg_action = ACTION_UPDATE_CATALOG; break; case 'r': arg_reverse = true; break; default: log_error("Unknown option code %c", c); return -EINVAL; } } if (arg_follow && !arg_no_tail && arg_lines < 0) arg_lines = 10; if (arg_since_set && arg_until_set && arg_since > arg_until) { log_error("--since= must be before --until=."); return -EINVAL; } if (arg_cursor && arg_since_set) { log_error("Please specify either --since= or --cursor=, not both."); return -EINVAL; } if (arg_follow && arg_reverse) { log_error("Please specify either --reverse= or --follow=, not both."); return -EINVAL; } return 1; }