chiark / gitweb /
[PATCH] if using glibc, link dynamically, as no one like 500Kb udev binaries...
[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 inline int udev_hotplug(int argc, char **argv)
143 {
144         char *action;
145         char *devpath;
146         char *subsystem;
147         int retval = -EINVAL;
148
149         subsystem = argv[1];
150
151         devpath = get_devpath();
152         if (!devpath) {
153                 dbg ("no devpath?");
154                 goto exit;
155         }
156         dbg("looking at '%s'", devpath);
157
158         /* we only care about class devices and block stuff */
159         if (!strstr(devpath, "class") &&
160             !strstr(devpath, "block")) {
161                 dbg("not a block or class device");
162                 goto exit;
163         }
164
165         /* but we don't care about net class devices */
166         if (strcmp(subsystem, "net") == 0) {
167                 dbg("don't care about net devices");
168                 goto exit;
169         }
170
171         action = get_action();
172         if (!action) {
173                 dbg ("no action?");
174                 goto exit;
175         }
176
177         /* connect to the system message bus */
178         sysbus_connect();
179
180         /* initialize udev database */
181         retval = udevdb_init(UDEVDB_DEFAULT);
182         if (retval != 0) {
183                 dbg("unable to initialize database");
184                 goto exit_sysbus;
185         }
186
187         /* set up a default signal handler for now */
188         signal(SIGINT, sig_handler);
189         signal(SIGTERM, sig_handler);
190         signal(SIGKILL, sig_handler);
191
192         /* initialize the naming deamon */
193         namedev_init();
194
195         if (strcmp(action, "add") == 0)
196                 retval = udev_add_device(devpath, subsystem);
197
198         else if (strcmp(action, "remove") == 0)
199                 retval = udev_remove_device(devpath, subsystem);
200
201         else {
202                 dbg("unknown action '%s'", action);
203                 retval = -EINVAL;
204         }
205         udevdb_exit();
206
207 exit_sysbus:
208         /* disconnect from the system message bus */
209         sysbus_disconnect();
210
211 exit:
212         return retval;
213 }
214
215 int main(int argc, char **argv, char **envp)
216 {
217         main_argv = argv;
218         main_envp = envp;
219         int retval;
220
221         dbg("version %s", UDEV_VERSION);
222
223         /* initialize our configuration */
224         udev_init_config();
225
226         if (argc == 2 && argv[1][0] != '-') {
227                 dbg("called by hotplug");
228                 retval = udev_hotplug(argc, argv);
229         } else {
230                 dbg("called by user");
231                 retval = udev_user(argc, argv);
232         }
233
234         return retval;
235 }
236
237