author | Olivier Brunel
<jjk@jjacky.com> 2015-02-27 17:43:10 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2015-04-04 12:47:35 UTC |
parent | 3a792d19d71db7f9401c387717fb588d0975d152 |
doc/aa-incmdline.pod | +51 | -0 |
package/modes | +1 | -0 |
package/targets.mak | +2 | -0 |
src/utils/aa-incmdline.c | +153 | -0 |
src/utils/deps-exe/aa-incmdline | +2 | -0 |
diff --git a/doc/aa-incmdline.pod b/doc/aa-incmdline.pod new file mode 100644 index 0000000..3a730d9 --- /dev/null +++ b/doc/aa-incmdline.pod @@ -0,0 +1,51 @@ +=head1 NAME + +aa-incmdline - Helper to parse kernel command line + +=head1 SYNOPSIS + +B<aa-incmdline> [B<-q>] [B<-f> I<FILE>] [B<-r>] [B<-s>] I<NAME> + +=head1 OPTIONS + +=over + +=item B<-f, --file> I<FILE> + +Read command line from I<FILE> instead of I</proc/cmdline> + +=item B<-h, --help> + +Show help screen and exit. + +=item B<-q, --quiet> + +Do not print value (if any) on stdout + +=item B<-r, --required> + +Ignore argument (i.e. exit 3) if no value was specified. + +=item B<-s, --safe>[=I<C>] + +Ignore argument (i.e. exit 3) if it contains I<C> (defaults to I</>). + +=item B<-V, --version> + +Show version information and exit. + +=back + +=head1 DESCRIPTION + +B<aa-incmdline>(1) is a small helper to parse arguments from the kernel command +line. It will read I</proc/cmdline> (or I<FILE> specified with B<--file>) and +look for an argument I<NAME>. If reading the file fails, it exits 2. If no +I<NAME> was specified, it exits 1. + +If there's no such argument on the command line, or B<--safe> was used and the +argument's value contains I<C>, or there's no value and B<--required> was used, +it exits 3; Else it exits 0. + +If the argument had a value specified it will be printed on stdout unless +B<--quiet> was used. diff --git a/package/modes b/package/modes index e0181ef..5c37527 100644 --- a/package/modes +++ b/package/modes @@ -1,6 +1,7 @@ aa-chroot 0755 aa-echo 0755 aa-enable 0755 +aa-incmdline 0755 aa-kill 0755 aa-mount 0755 aa-pivot 0755 diff --git a/package/targets.mak b/package/targets.mak index 4596999..6511818 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -6,6 +6,7 @@ aa-stop LIBEXEC_TARGETS := \ aa-chroot \ aa-echo \ +aa-incmdline \ aa-kill \ aa-mount \ aa-pivot \ @@ -20,6 +21,7 @@ anopa.1 \ aa-chroot.1 \ aa-echo.1 \ aa-enable.1 \ +aa-incmdline.1 \ aa-kill.1 \ aa-mount.1 \ aa-pivot.1 \ diff --git a/src/utils/aa-incmdline.c b/src/utils/aa-incmdline.c new file mode 100644 index 0000000..a28d268 --- /dev/null +++ b/src/utils/aa-incmdline.c @@ -0,0 +1,153 @@ + +#include <getopt.h> +#include <skalibs/djbunix.h> +#include <skalibs/stralloc.h> +#include <skalibs/bytestr.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <anopa/common.h> + +const char *PROG; + +static void +dieusage (int rc) +{ + aa_die_usage (rc, "[OPTION] NAME", + " -f, --file FILE Use FILE instead of /proc/cmdline\n" + " -q, --quiet Don't write value (if any) to stdout\n" + " -s, --safe[=C] Ignore argument if value contain C (default: '/')\n" + " -r, --required Ignore argument if no value specified\n" + " -h, --help Show this help screen and exit\n" + " -V, --version Show version information and exit\n" + ); +} + +int +main (int argc, char * const argv[]) +{ + PROG = "aa-incmdline"; + stralloc sa = STRALLOC_ZERO; + const char *file = "/proc/cmdline"; + int quiet = 0; + int req = 0; + char safe = '\0'; + int len_arg; + int start; + int i; + + for (;;) + { + struct option longopts[] = { + { "file", no_argument, NULL, 'f' }, + { "help", no_argument, NULL, 'h' }, + { "quiet", no_argument, NULL, 'q' }, + { "required", no_argument, NULL, 'r' }, + { "safe", optional_argument, NULL, 's' }, + { "version", no_argument, NULL, 'V' }, + { NULL, 0, 0, 0 } + }; + int c; + + c = getopt_long (argc, argv, "f:hqrs::V", longopts, NULL); + if (c == -1) + break; + switch (c) + { + case 'f': + file = optarg; + break; + + case 'h': + dieusage (0); + + case 'q': + quiet = 1; + break; + + case 'r': + req = 1; + break; + + case 's': + if (!optarg) + safe = '/'; + else if (!*optarg || optarg[1]) + dieusage (1); + else + safe = *optarg; + break; + + case 'V': + aa_die_version (); + + default: + dieusage (1); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + dieusage (1); + + if (!openslurpclose (&sa, file)) + strerr_diefu2sys (2, "read ", file); + + len_arg = strlen (argv[0]); + for (start = i = 0; i < sa.len; ++i) + { + if (sa.s[i] == '=' || sa.s[i] == ' ' || sa.s[i] == '\t' + || sa.s[i] == '\n' || sa.s[i] == '\0') + { + int found = (i - start == len_arg && !str_diffn (sa.s + start, argv[0], len_arg)); + int len; + + if (sa.s[i] != '=') + { + if (found) + return (req) ? 3 : 0; + start = ++i; + goto next; + } + else if (found && quiet && !safe) + return (req) ? 3 : 0; + + start = ++i; + if (sa.s[start] != '"') + for (len = 0; + start + len < sa.len + && sa.s[start + len] != ' ' && sa.s[start + len] != '\t'; + ++len) + ; + else + { + ++start; + len = byte_chr (sa.s + start, sa.len - start, '"'); + } + + if (found) + { + if (len == sa.len - start) + --len; + if (safe && byte_chr (sa.s + start, len, safe) < len) + return 3; + if (req && len == 0) + return 3; + else if (!quiet) + { + buffer_putnoflush (buffer_1small, sa.s + start, len); + buffer_putsflush (buffer_1small, "\n"); + } + return 0; + } + + start += len; + i = ++start; +next: + while (i < sa.len && (sa.s[i] == ' ' || sa.s[i] == '\t')) + start = ++i; + } + } + + return 3; +} diff --git a/src/utils/deps-exe/aa-incmdline b/src/utils/deps-exe/aa-incmdline new file mode 100644 index 0000000..30987b4 --- /dev/null +++ b/src/utils/deps-exe/aa-incmdline @@ -0,0 +1,2 @@ +${LIBANOPA} +-lskarnet