chiark / gitweb /
[PATCH] add a script that tests the IGNORE rule
[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 static inline int udev_user(int argc, char **argv)
86 {
87         static const char short_options[] = "q:rVh";
88         int option;
89         int retval = -EINVAL;
90         struct udevice dev;
91
92         while (1) {
93                 option = getopt(argc, argv, short_options);
94                 if (option == -1)
95                         break;
96
97                 dbg("option '%c'", option);
98                 switch (option) {
99                 case 'q':
100                         dbg("udev query: %s\n", optarg);
101                         retval = udevdb_open_ro();
102                         if (retval != 0) {
103                                 printf("unable to open udev database\n");
104                                 return -1;
105                         }
106                         retval = udevdb_get_dev(optarg, &dev);
107                         if (retval == 0) {
108                                 printf("%s\n", dev.name);
109                         } else {
110                                 printf("device not found in udev database\n");
111                         }
112                         udevdb_exit();
113                         return retval;
114
115                 case 'r':
116                         printf("%s\n", udev_root);
117                         return 0;
118
119                 case 'V':
120                         printf("udev, version %s\n", UDEV_VERSION);
121                         return 0;
122
123                 case 'h':
124                         retval = 0;
125                 case '?':
126                 default:
127                         goto help;
128                 }
129         }
130
131 help:
132         printf("Usage: [-qrVh]\n"
133                "  -q <path>  query database for the name of the created node\n"
134                "  -r         print udev root\n"
135                "  -V         print udev version\n"
136                "  -h         print this help text\n"
137                "\n");
138
139         return retval;
140 }
141
142 static char *subsystem_blacklist[] = {
143         "net",
144         "scsi_host",
145         "scsi_device",
146         "",
147 };
148
149 static inline int udev_hotplug(int argc, char **argv)
150 {
151         char *action;
152         char *devpath;
153         char *subsystem;
154         int retval = -EINVAL;
155         int i;
156
157         subsystem = argv[1];
158
159         devpath = get_devpath();
160         if (!devpath) {
161                 dbg ("no devpath?");
162                 goto exit;
163         }
164         dbg("looking at '%s'", devpath);
165
166         /* we only care about class devices and block stuff */
167         if (!strstr(devpath, "class") &&
168             !strstr(devpath, "block")) {
169                 dbg("not a block or class device");
170                 goto exit;
171         }
172
173         /* skip blacklisted subsystems */
174         i = 0;
175         while (subsystem_blacklist[i][0] != '\0') {
176                 if (strcmp(subsystem, subsystem_blacklist[i]) == 0) {
177                         dbg("don't care about '%s' devices", subsystem);
178                         goto exit;
179                 }
180                 i++;
181         }
182
183         action = get_action();
184         if (!action) {
185                 dbg ("no action?");
186                 goto exit;
187         }
188
189         /* connect to the system message bus */
190         sysbus_connect();
191
192         /* initialize udev database */
193         retval = udevdb_init(UDEVDB_DEFAULT);
194         if (retval != 0) {
195                 dbg("unable to initialize database");
196                 goto exit_sysbus;
197         }
198
199         /* set up a default signal handler for now */
200         signal(SIGINT, sig_handler);
201         signal(SIGTERM, sig_handler);
202         signal(SIGKILL, sig_handler);
203
204         /* initialize the naming deamon */
205         namedev_init();
206
207         if (strcmp(action, "add") == 0)
208                 retval = udev_add_device(devpath, subsystem);
209
210         else if (strcmp(action, "remove") == 0)
211                 retval = udev_remove_device(devpath, subsystem);
212
213         else {
214                 dbg("unknown action '%s'", action);
215                 retval = -EINVAL;
216         }
217         udevdb_exit();
218
219 exit_sysbus:
220         /* disconnect from the system message bus */
221         sysbus_disconnect();
222
223 exit:
224         if (retval > 0)
225                 retval = 0;
226
227         return -retval;
228 }
229
230 int main(int argc, char **argv, char **envp)
231 {
232         main_argv = argv;
233         main_envp = envp;
234         int retval;
235
236         dbg("version %s", UDEV_VERSION);
237
238         /* initialize our configuration */
239         udev_init_config();
240
241         if (argc == 2 && argv[1][0] != '-') {
242                 dbg("called by hotplug");
243                 retval = udev_hotplug(argc, argv);
244         } else {
245                 dbg("called by user");
246                 retval = udev_user(argc, argv);
247         }
248
249         return retval;
250 }
251
252