chiark / gitweb /
libudev: rename libudev-utils.c libudev-util.c
[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
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include <unistd.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <getopt.h>
27
28 #include "udev.h"
29
30 static int debug;
31
32 static void log_fn(struct udev *udev, int priority,
33                    const char *file, int line, const char *fn,
34                    const char *format, va_list args)
35 {
36         if (debug) {
37                 fprintf(stderr, "%s: ", fn);
38                 vfprintf(stderr, format, args);
39         } else {
40                 vsyslog(priority, format, args);
41         }
42 }
43
44 struct command {
45         const char *name;
46         int (*cmd)(struct udev *udev, int argc, char *argv[]);
47         const char *help;
48         int debug;
49 };
50
51 static const struct command cmds[];
52
53 static int version(struct udev *udev, int argc, char *argv[])
54 {
55         printf("%s\n", VERSION);
56         return 0;
57 }
58
59 static int help(struct udev *udev, int argc, char *argv[])
60 {
61         const struct command *cmd;
62
63         printf("Usage: udevadm [--help] [--version] [--debug] COMMAND [COMMAND OPTIONS]\n");
64         for (cmd = cmds; cmd->name != NULL; cmd++)
65                 if (cmd->help != NULL)
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         },
107         {
108                 .name = "help",
109                 .cmd = help,
110         },
111         {}
112 };
113
114 static int run_command(struct udev *udev, const struct command *cmd, int argc, char *argv[])
115 {
116         if (cmd->debug) {
117                 debug = 1;
118                 if (udev_get_log_priority(udev) < LOG_INFO)
119                         udev_set_log_priority(udev, LOG_INFO);
120         }
121         info(udev, "calling: %s\n", cmd->name);
122         return cmd->cmd(udev, argc, argv);
123 }
124
125 int main(int argc, char *argv[])
126 {
127         struct udev *udev;
128         static const struct option options[] = {
129                 { "debug", 0, NULL, 'd' },
130                 { "help", 0, NULL, 'h' },
131                 { "version", 0, NULL, 'V' },
132                 {}
133         };
134         const char *command;
135         int i;
136         const char *pos;
137         int rc = 1;
138
139         udev = udev_new();
140         if (udev == NULL)
141                 goto out;
142
143         logging_init("udevadm");
144         udev_set_log_fn(udev, log_fn);
145         sysfs_init();
146
147         /* see if we are a compat link, this will be removed in a future release */
148         command = argv[0];
149         pos = strrchr(command, '/');
150         if (pos != NULL)
151                 command = &pos[1];
152
153         /* the trailing part of the binary or link name is the command */
154         if (strncmp(command, "udev", 4) == 0)
155                 command = &command[4];
156
157         for (i = 0; cmds[i].cmd != NULL; i++) {
158                 if (strcmp(cmds[i].name, command) == 0) {
159                         char path[128];
160                         char prog[512];
161                         ssize_t len;
162
163                         snprintf(path, sizeof(path), "/proc/%lu/exe", (unsigned long) getppid());
164                         len = readlink(path, prog, sizeof(prog));
165                         if (len > 0) {
166                                 prog[len] = '\0';
167                                 fprintf(stderr, "the program '%s' called '%s', it should use 'udevadm %s <options>', "
168                                        "this will stop working in a future release\n", prog, argv[0], command);
169                                 err(udev, "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                         }
172                         rc = run_command(udev, &cmds[i], argc, argv);
173                         goto out;
174                 }
175         }
176
177         while (1) {
178                 int option;
179
180                 option = getopt_long(argc, argv, "+dhV", options, NULL);
181                 if (option == -1)
182                         break;
183
184                 switch (option) {
185                 case 'd':
186                         debug = 1;
187                         if (udev_get_log_priority(udev) < LOG_INFO)
188                                 udev_set_log_priority(udev, LOG_INFO);
189                         break;
190                 case 'h':
191                         rc = help(udev, argc, argv);
192                         goto out;
193                 case 'V':
194                         rc = version(udev, argc, argv);
195                         goto out;
196                 default:
197                         goto out;
198                 }
199         }
200         command = argv[optind];
201
202         if (command != NULL)
203                 for (i = 0; cmds[i].cmd != NULL; i++) {
204                         if (strcmp(cmds[i].name, command) == 0) {
205                                 optind++;
206                                 rc = run_command(udev, &cmds[i], argc, argv);
207                                 goto out;
208                         }
209                 }
210
211         fprintf(stderr, "missing or unknown command\n\n");
212         help(udev, argc, argv);
213         rc = 2;
214 out:
215         sysfs_cleanup();
216         udev_unref(udev);
217         logging_close();
218         return rc;
219 }