[systemd-devel] [RFC] xyzctl-common
Peeters Simon
peeters.simon at gmail.com
Sat Nov 16 17:05:48 PST 2013
2013/11/16 Zbigniew Jędrzejewski-Szmek <zbyszek at in.waw.pl>:
> On Sat, Nov 16, 2013 at 07:41:13PM +0100, Peeters Simon wrote:
>> hello all,
>>
>> During the sd_bus porting I noted that the *ctl tools (and
>> systemd-analyze) contain a lot of common boilerplate code.
>>
>> So the basic idea is to split this boilerplate out into
>> xyzctl-common.[ch] so that f.ex the bottom hostnamectl.c would look
>> like:
>>
>> ...
>> static void help(void ) {...}
>>
>> enum {
>> ARG_TRANSIENT = 0x100,
>> ARG_STATIC,
>> ARG_PRETTY,
>> };
>>
>> static int parse_arg(int option, const char* arg) {
>> assert(option >= 0);
>>
>> switch (option) {
>> case ARG_TRANSIENT:
>> arg_transient = true;
>> break;
>>
>> case ARG_PRETTY:
>> arg_pretty = true;
>> break;
>>
>> case ARG_STATIC:
>> arg_static = true;
>> break;
>>
>> default:
>> return -EINVAL;
>> }
>>
>> return 1;
>> }
>>
>> int main(int argc, char *argv[]) {
>>
>> static const struct option options[] = {
>> { "transient", no_argument, NULL, ARG_TRANSIENT },
>> { "static", no_argument, NULL, ARG_STATIC },
>> { "pretty", no_argument, NULL, ARG_PRETTY },
>> {}
>> };
>> static const xyzctl_verb verbs[] = {
>> { "status", LESS, 1, show_status, XYZCTL_USE_PAGER },
>> { "set-hostname", EQUAL, 2, set_hostname, XYZCTL_USE_POLKIT },
>> { "set-icon-name", EQUAL, 2, set_icon_name, XYZCTL_USE_POLKIT },
>> { "set-chassis", EQUAL, 2, set_chassis, XYZCTL_USE_POLKIT },
>> {}
>> };
>> static const xyzctl_tool hostnamectl = {
>> &help,
>> &parse_arg,
>> XYZCTL_NO_USER,
>> options,
>> verbs
>> };
>>
>> return xyzctl_main(&hostnamectl, argc, argv);
>> }
>>
>> it would use or-able flags to controll common functionality, i currently have:
>> enum verb_flags {
>> XYZCTL_NO_BUS = 1,
>> The execution of the verb does not require a bus connection.
>> The system will try to connect to the bus, but will ignore any errors,
>> and pass a NULL bus.
>> XYZCTL_USE_PAGER = 2,
>> Open a pager unless the user passes --no-pager
>> XYZCTL_USE_POLKIT = 4,
>> Starts the polkit agent unless the user passes --no-ask-password
>> XYZCTL_LOOP_ARGS = 8,
>> Executes the verb once for each argument.
>> This is usefull where
>> $ xyzctl verb a b c
>> is the same as
>> $ xyzctl verb a
>> $ xyzctl verb b
>> $ xyzctl verb c
> I think that we do some sorting on the arguments and other operations
> which mean that the behaviour for multiple args isn't usually
> *exactly* the same as for one repeated. What exactly does this
> flag mean?
what it does exactly:
instead of calling
verb.dispatch(bus, argv_left, argc_left)
it does:
for (int i = 1; i < argc_left; i++)
verb.dispatch(bus, (char *[]){argv_left[0], argv_left[i]}, 2);
an example use for it would be loginctl kill-session
In the beginning I tought this would be nice to have, but I am fine
with dropping this.
>> };
>>
>> enum tool_flags {
>> XYZCTL_NO_REMOTE = 1,
>> Do not allow the use of --host=HOST to connect to a remote host
>> XYZCTL_NO_MACHINE = 2,
>> Do not allow the use of --machine=CONTAINER to connect to a container
>> XYZCTL_NO_USER = 4,
>> Do not allow connection to the user bus by using --user
>> XYZCTL_CONNECT_SYSTEMD = 8,
>> connect directly to systemd's private socket.
>> }
>>
>>
>> As a proof of concept I ported hostnemctl and loginctl resulting in +-
>> 360 lines less code
>>
>>
>> Does anybody have any comments on the basic idea and/or the proposed interface?
>
> If it makes things shorter, without making them much more complicated,
> then it's probably a good idea. Can you post the full patch for
> loginctl and hostnamectl?
I will do this tomorow.
on the calling side things get a lot simpler, the other side (the code
in xyzctl-common.c) is slightly more complex because it has to
dynamicly construct the options array for getopt_long, but I think it
is within reason.
More information about the systemd-devel
mailing list