[systemd-devel] [RFC] xyzctl-common

Peeters Simon peeters.simon at gmail.com
Sat Nov 16 10:41:13 PST 2013


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
        };

        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?


Simon


More information about the systemd-devel mailing list