chiark / gitweb /
Prep v234: Apply missing upstream fixes in src/basic (1/6)
[elogind.git] / src / basic / verbs.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2014 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <getopt.h>
22 #include <stdbool.h>
23 #include <stddef.h>
24
25 #include "log.h"
26 #include "macro.h"
27 #include "string-util.h"
28 #include "verbs.h"
29 #include "virt.h"
30
31 int dispatch_verb(int argc, char *argv[], const Verb verbs[], void *userdata) {
32         const Verb *verb;
33         const char *name;
34         unsigned i;
35         int left;
36
37         assert(verbs);
38         assert(verbs[0].dispatch);
39         assert(argc >= 0);
40         assert(argv);
41         assert(argc >= optind);
42
43         left = argc - optind;
44         name = argv[optind];
45
46         for (i = 0;; i++) {
47                 bool found;
48
49                 /* At the end of the list? */
50                 if (!verbs[i].dispatch) {
51                         if (name)
52                                 log_error("Unknown operation %s.", name);
53                         else
54                                 log_error("Requires operation parameter.");
55                         return -EINVAL;
56                 }
57
58                 if (name)
59                         found = streq(name, verbs[i].verb);
60                 else
61                         found = !!(verbs[i].flags & VERB_DEFAULT);
62
63                 if (found) {
64                         verb = &verbs[i];
65                         break;
66                 }
67         }
68
69         assert(verb);
70
71         if (!name)
72                 left = 1;
73
74         if (verb->min_args != VERB_ANY &&
75             (unsigned) left < verb->min_args) {
76                 log_error("Too few arguments.");
77                 return -EINVAL;
78         }
79
80         if (verb->max_args != VERB_ANY &&
81             (unsigned) left > verb->max_args) {
82                 log_error("Too many arguments.");
83                 return -EINVAL;
84         }
85
86         if ((verb->flags & VERB_NOCHROOT) && running_in_chroot() > 0) {
87                 log_info("Running in chroot, ignoring request.");
88                 return 0;
89         }
90
91         if (name)
92                 return verb->dispatch(left, argv + optind, userdata);
93         else {
94                 char* fake[2] = {
95                         (char*) verb->verb,
96                         NULL
97                 };
98
99                 return verb->dispatch(1, fake, userdata);
100         }
101 }