chiark / gitweb /
e4f24205467c2286730c6ae7dc5c44f714bee4d5
[elogind.git] / udev / udevadm.c
1 /*
2  * Copyright (C) 2007-2008 Kay Sievers <kay.sievers@vrfy.org>
3  *
4  *      This program is free software; you can redistribute it and/or modify it
5  *      under the terms of the GNU General Public License as published by the
6  *      Free Software Foundation version 2 of the License.
7  * 
8  *      This program is distributed in the hope that it will be useful, but
9  *      WITHOUT ANY WARRANTY; without even the implied warranty of
10  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  *      General Public License for more details.
12  * 
13  *      You should have received a copy of the GNU General Public License along
14  *      with this program; if not, write to the Free Software Foundation, Inc.,
15  *      51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16  *
17  */
18
19 #include "config.h"
20
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <getopt.h>
28
29 #include "udev.h"
30
31 static int debug;
32
33 static void log_fn(struct udev *udev, int priority,
34                    const char *file, int line, const char *fn,
35                    const char *format, va_list args)
36 {
37         if (debug) {
38                 fprintf(stderr, "%s: ", fn);
39                 vfprintf(stderr, format, args);
40         } else {
41                 vsyslog(priority, format, args);
42         }
43 }
44
45 struct command {
46         const char *name;
47         int (*cmd)(struct udev *udev, int argc, char *argv[]);
48         const char *help;
49         int debug;
50 };
51
52 static const struct command cmds[];
53
54 static int version(struct udev *udev, int argc, char *argv[])
55 {
56         printf("%s\n", VERSION);
57         return 0;
58 }
59
60 static int help(struct udev *udev, int argc, char *argv[])
61 {
62         const struct command *cmd;
63
64         printf("Usage: udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n");
65         for (cmd = cmds; cmd->name != NULL; cmd++)
66                 printf("  %-12s %s\n", cmd->name, cmd->help);
67         printf("\n");
68         return 0;
69 }
70
71 static const struct command cmds[] = {
72         {
73                 .name = "info",
74                 .cmd = udevadm_info,
75                 .help = "query sysfs or the udev database",
76         },
77         {
78                 .name = "trigger",
79                 .cmd = udevadm_trigger,
80                 .help = "request events from the kernel",
81         },
82         {
83                 .name = "settle",
84                 .cmd = udevadm_settle, "",
85                 .help = "wait for the event queue to finish",
86         },
87         {
88                 .name = "control",
89                 .cmd = udevadm_control,
90                 .help = "control the udev daemon",
91         },
92         {
93                 .name = "monitor",
94                 .cmd = udevadm_monitor,
95                 .help = "listen to kernel and udev events",
96         },
97         {
98                 .name = "test",
99                 .cmd = udevadm_test,
100                 .help = "simulation run",
101                 .debug = 1,
102         },
103         {
104                 .name = "version",
105                 .cmd = version,
106                 .help = "print the version number",
107         },
108         {
109                 .name = "help",
110                 .cmd = help,
111                 .help = "print this help text",
112         },
113         {}
114 };
115
116 static int run_command(struct udev *udev, const struct command *cmd, int argc, char *argv[])
117 {
118         if (cmd->debug) {
119                 debug = 1;
120                 if (udev_get_log_priority(udev) < LOG_INFO)
121                         udev_set_log_priority(udev, LOG_INFO);
122         }
123         info(udev, "calling: %s\n", cmd->name);
124         return cmd->cmd(udev, argc, argv);
125 }
126
127 int main(int argc, char *argv[])
128 {
129         struct udev *udev;
130         static const struct option options[] = {
131                 { "debug", 0, NULL, 'd' },
132                 { "help", 0, NULL, 'h' },
133                 { "version", 0, NULL, 'V' },
134                 {}
135         };
136         const char *command;
137         int i;
138         const char *pos;
139         int rc = 1;
140
141         udev = udev_new();
142         if (udev == NULL)
143                 goto out;
144
145         logging_init("udevadm");
146         udev_set_log_fn(udev, log_fn);
147         sysfs_init();
148
149         /* see if we are a compat link, this will be removed in a future release */
150         command = argv[0];
151         pos = strrchr(command, '/');
152         if (pos != NULL)
153                 command = &pos[1];
154
155         /* the trailing part of the binary or link name is the command */
156         if (strncmp(command, "udev", 4) == 0)
157                 command = &command[4];
158
159         for (i = 0; cmds[i].cmd != NULL; i++) {
160                 if (strcmp(cmds[i].name, command) == 0) {
161                         char path[128];
162                         char prog[512];
163                         ssize_t len;
164
165                         snprintf(path, sizeof(path), "/proc/%lu/exe", (unsigned long) getppid());
166                         len = readlink(path, prog, sizeof(prog));
167                         if (len > 0) {
168                                 prog[len] = '\0';
169                                 fprintf(stderr, "the program '%s' called '%s', it should use 'udevadm %s <options>', "
170                                        "this will stop working in a future release\n", prog, argv[0], command);
171                                 info(udev, "the program '%s' called '%s', it should use 'udevadm %s <options>', "
172                                      "this will stop working in a future release\n", prog, argv[0], command);
173                         }
174                         rc = run_command(udev, &cmds[i], argc, argv);
175                         goto out;
176                 }
177         }
178
179         while (1) {
180                 int option;
181
182                 option = getopt_long(argc, argv, "+dhV", options, NULL);
183                 if (option == -1)
184                         break;
185
186                 switch (option) {
187                 case 'd':
188                         debug = 1;
189                         if (udev_get_log_priority(udev) < LOG_INFO)
190                                 udev_set_log_priority(udev, LOG_INFO);
191                         break;
192                 case 'h':
193                         rc = help(udev, argc, argv);
194                         goto out;
195                 case 'V':
196                         rc = version(udev, argc, argv);
197                         goto out;
198                 default:
199                         goto out;
200                 }
201         }
202         command = argv[optind];
203
204         if (command != NULL)
205                 for (i = 0; cmds[i].cmd != NULL; i++) {
206                         if (strcmp(cmds[i].name, command) == 0) {
207                                 optind++;
208                                 rc = run_command(udev, &cmds[i], argc, argv);
209                                 goto out;
210                         }
211                 }
212
213         fprintf(stderr, "unknown command, try udevadm help\n\n");
214         rc = 2;
215 out:
216         sysfs_cleanup();
217         udev_unref(udev);
218         logging_close();
219         return rc;
220 }