chiark / gitweb /
[PATCH] udev - drop all methods :)
[elogind.git] / udev.c
1 /*
2  * udev.c
3  *
4  * Userspace devfs
5  *
6  * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
7  *
8  *
9  *      This program is free software; you can redistribute it and/or modify it
10  *      under the terms of the GNU General Public License as published by the
11  *      Free Software Foundation version 2 of the License.
12  * 
13  *      This program is distributed in the hope that it will be useful, but
14  *      WITHOUT ANY WARRANTY; without even the implied warranty of
15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *      General Public License for more details.
17  * 
18  *      You should have received a copy of the GNU General Public License along
19  *      with this program; if not, write to the Free Software Foundation, Inc.,
20  *      675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <signal.h>
32 #include <stdarg.h>
33
34 #include "udev.h"
35 #include "udev_version.h"
36 #include "udev_dbus.h"
37 #include "namedev.h"
38 #include "udevdb.h"
39 #include "libsysfs/libsysfs.h"
40
41 /* global variables */
42 char **main_argv;
43 char **main_envp;
44
45 static void sig_handler(int signum)
46 {
47         dbg("caught signal %d", signum);
48         switch (signum) {
49                 case SIGINT:
50                 case SIGTERM:
51                 case SIGKILL:
52                         sysbus_disconnect();
53                         udevdb_exit();
54                         exit(20 + signum);
55                         break;
56                 default:
57                         dbg("unhandled signal");
58         }
59 }
60
61 static inline char *get_action(void)
62 {
63         char *action;
64
65         action = getenv("ACTION");
66         return action;
67 }
68
69 static inline char *get_devpath(void)
70 {
71         char *devpath;
72
73         devpath = getenv("DEVPATH");
74         return devpath;
75 }
76
77 static inline char *get_seqnum(void)
78 {
79         char *seqnum;
80
81         seqnum = getenv("SEQNUM");
82         return seqnum;
83 }
84
85 enum query_type {
86         NONE,
87         NAME,
88         SYMLINK,
89         OWNER,
90         GROUP
91 };
92
93 static inline int udev_user(int argc, char **argv)
94 {
95         static const char short_options[] = "p:q:rVh";
96         int option;
97         int retval = -EINVAL;
98         struct udevice dev;
99         int root = 0;
100         enum query_type query = NONE;
101         char result[NAME_SIZE] = "";
102         char path[NAME_SIZE] = "";
103
104         /* get command line options */
105         while (1) {
106                 option = getopt(argc, argv, short_options);
107                 if (option == -1)
108                         break;
109
110                 dbg("option '%c'", option);
111                 switch (option) {
112                 case 'p':
113                         dbg("udev path: %s\n", optarg);
114                         strfieldcpy(path, optarg);
115                         break;
116
117                 case 'q':
118                         dbg("udev query: %s\n", optarg);
119
120                         if (strcmp(optarg, "name") == 0) {
121                                 query = NAME;
122                                 break;
123                         }
124
125                         if (strcmp(optarg, "symlink") == 0) {
126                                 query = SYMLINK;
127                                 break;
128                         }
129
130                         if (strcmp(optarg, "owner") == 0) {
131                                 query = OWNER;
132                                 break;
133                         }
134
135                         if (strcmp(optarg, "group") == 0) {
136                                 query = GROUP;
137                                 break;
138                         }
139
140                         printf("unknown query type\n");
141                         return -EINVAL;
142
143                 case 'r':
144                         root = 1;
145                         break;
146
147                 case 'V':
148                         printf("udev, version %s\n", UDEV_VERSION);
149                         return 0;
150
151                 case 'h':
152                         retval = 0;
153                 case '?':
154                 default:
155                         goto help;
156                 }
157         }
158
159         /* process options */
160         if (query != NONE) {
161                 if (path[0] == '\0') {
162                         printf("query needs device path specified\n");
163                         return -EINVAL;
164                 }
165
166                 retval = udevdb_open_ro();
167                 if (retval != 0) {
168                         printf("unable to open udev database\n");
169                         return -EACCES;
170                 }
171                 retval = udevdb_get_dev(path, &dev);
172                 if (retval == 0) {
173                         switch(query) {
174                         case NAME:
175                                 if (root)
176                                 strfieldcpy(result, udev_root);
177                                 strncat(result, dev.name, sizeof(result));
178                                 break;
179
180                         case SYMLINK:
181                                 strfieldcpy(result, dev.symlink);
182                                 break;
183
184                         case GROUP:
185                                 strfieldcpy(result, dev.group);
186                                 break;
187
188                         case OWNER:
189                                 strfieldcpy(result, dev.owner);
190                                 break;
191
192                         default:
193                                 break;
194                         }
195                         printf("%s\n", result);
196                 } else {
197                         printf("device not found in udev database\n");
198                 }
199                 udevdb_exit();
200                 return retval;
201         }
202
203         if (root) {
204                 printf("%s\n", udev_root);
205                 return 0;
206         }
207
208 help:
209         printf("Usage: [-qrVh]\n"
210                "  -q <name>  query database for the specified value\n"
211                "  -p <path>  device path used for query\n"
212                "  -r         print udev root\n"
213                "  -V         print udev version\n"
214                "  -h         print this help text\n"
215                "\n");
216         return retval;
217 }
218
219 static char *subsystem_blacklist[] = {
220         "net",
221         "scsi_host",
222         "scsi_device",
223         "",
224 };
225
226 static inline int udev_hotplug(int argc, char **argv)
227 {
228         char *action;
229         char *devpath;
230         char *subsystem;
231         int retval = -EINVAL;
232         int i;
233
234         subsystem = argv[1];
235
236         devpath = get_devpath();
237         if (!devpath) {
238                 dbg ("no devpath?");
239                 goto exit;
240         }
241         dbg("looking at '%s'", devpath);
242
243         /* we only care about class devices and block stuff */
244         if (!strstr(devpath, "class") &&
245             !strstr(devpath, "block")) {
246                 dbg("not a block or class device");
247                 goto exit;
248         }
249
250         /* skip blacklisted subsystems */
251         i = 0;
252         while (subsystem_blacklist[i][0] != '\0') {
253                 if (strcmp(subsystem, subsystem_blacklist[i]) == 0) {
254                         dbg("don't care about '%s' devices", subsystem);
255                         goto exit;
256                 }
257                 i++;
258         }
259
260         action = get_action();
261         if (!action) {
262                 dbg ("no action?");
263                 goto exit;
264         }
265
266         /* connect to the system message bus */
267         sysbus_connect();
268
269         /* initialize udev database */
270         retval = udevdb_init(UDEVDB_DEFAULT);
271         if (retval != 0) {
272                 dbg("unable to initialize database");
273                 goto exit_sysbus;
274         }
275
276         /* set up a default signal handler for now */
277         signal(SIGINT, sig_handler);
278         signal(SIGTERM, sig_handler);
279         signal(SIGKILL, sig_handler);
280
281         /* initialize the naming deamon */
282         namedev_init();
283
284         if (strcmp(action, "add") == 0)
285                 retval = udev_add_device(devpath, subsystem);
286
287         else if (strcmp(action, "remove") == 0)
288                 retval = udev_remove_device(devpath, subsystem);
289
290         else {
291                 dbg("unknown action '%s'", action);
292                 retval = -EINVAL;
293         }
294         udevdb_exit();
295
296 exit_sysbus:
297         /* disconnect from the system message bus */
298         sysbus_disconnect();
299
300 exit:
301         if (retval > 0)
302                 retval = 0;
303
304         return -retval;
305 }
306
307 int main(int argc, char **argv, char **envp)
308 {
309         int retval;
310         main_argv = argv;
311         main_envp = envp;
312
313         dbg("version %s", UDEV_VERSION);
314
315         /* initialize our configuration */
316         udev_init_config();
317
318         if (argc == 2 && argv[1][0] != '-') {
319                 dbg("called by hotplug");
320                 retval = udev_hotplug(argc, argv);
321         } else {
322                 dbg("called by user");
323                 retval = udev_user(argc, argv);
324         }
325
326         return retval;
327 }
328
329