]>
Commit | Line | Data |
---|---|---|
f0083e3d | 1 | /* |
e8d569b4 | 2 | * Copyright (C) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> |
27b77df4 | 3 | * Copyright (C) 2004-2006 Kay Sievers <kay.sievers@vrfy.org> |
f0083e3d GKH |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation version 2 of the License. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but | |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
27b77df4 | 16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
f0083e3d GKH |
17 | * |
18 | */ | |
19 | ||
c81b35c0 KS |
20 | #include <stdio.h> |
21 | #include <stddef.h> | |
f0083e3d GKH |
22 | #include <stdlib.h> |
23 | #include <string.h> | |
c449b25e | 24 | #include <fcntl.h> |
e8baccca | 25 | #include <ctype.h> |
c81b35c0 | 26 | #include <errno.h> |
d12ecb53 | 27 | #include <signal.h> |
1ceba936 | 28 | #include <unistd.h> |
27f877e6 | 29 | #include <syslog.h> |
85511f02 | 30 | |
f0083e3d | 31 | #include "udev.h" |
e5e322bc | 32 | #include "udev_rules.h" |
eef7c9a3 | 33 | #include "udev_selinux.h" |
f0083e3d | 34 | |
6c18b1fb | 35 | #ifdef USE_LOG |
6b493a20 | 36 | void log_message(int priority, const char *format, ...) |
51a8bb2f | 37 | { |
e964c2c0 | 38 | va_list args; |
d026a35d | 39 | |
6b493a20 | 40 | if (priority > udev_log_priority) |
d026a35d GKH |
41 | return; |
42 | ||
43 | va_start(args, format); | |
6b493a20 | 44 | vsyslog(priority, format, args); |
d026a35d | 45 | va_end(args); |
51a8bb2f | 46 | } |
d026a35d | 47 | #endif |
51a8bb2f | 48 | |
e5a5b54a | 49 | static void asmlinkage sig_handler(int signum) |
d12ecb53 | 50 | { |
d12ecb53 | 51 | switch (signum) { |
7e89a569 | 52 | case SIGALRM: |
2b41e68a | 53 | exit(1); |
d12ecb53 MB |
54 | case SIGINT: |
55 | case SIGTERM: | |
d12ecb53 | 56 | exit(20 + signum); |
d12ecb53 MB |
57 | } |
58 | } | |
59 | ||
aee380b6 | 60 | int main(int argc, char *argv[], char *envp[]) |
f4dc8d11 | 61 | { |
1aa1e248 KS |
62 | struct sysfs_device *dev; |
63 | struct udevice *udev; | |
64 | const char *maj, *min; | |
8bd41f36 | 65 | struct udev_rules rules; |
8544c9ad KS |
66 | const char *action; |
67 | const char *devpath; | |
68 | const char *subsystem; | |
03cfa139 | 69 | struct sigaction act; |
3f9f8de4 | 70 | int devnull; |
8544c9ad | 71 | int retval = -EINVAL; |
f4dc8d11 | 72 | |
51737eb8 KS |
73 | if (argc == 2 && strcmp(argv[1], "-V") == 0) { |
74 | printf("%s\n", UDEV_VERSION); | |
75 | exit(0); | |
76 | } | |
77 | ||
e3396a2d | 78 | /* set std fd's to /dev/null, /sbin/hotplug forks us, we don't have them at all */ |
3f9f8de4 KS |
79 | devnull = open("/dev/null", O_RDWR); |
80 | if (devnull >= 0) { | |
81 | if (devnull != STDIN_FILENO) | |
82 | dup2(devnull, STDIN_FILENO); | |
83 | if (devnull != STDOUT_FILENO) | |
84 | dup2(devnull, STDOUT_FILENO); | |
85 | if (devnull != STDERR_FILENO) | |
86 | dup2(devnull, STDERR_FILENO); | |
87 | if (devnull > STDERR_FILENO) | |
88 | close(devnull); | |
89 | } | |
90 | ||
7257cb18 | 91 | logging_init("udev"); |
3f9f8de4 | 92 | if (devnull < 0) |
e3396a2d | 93 | err("open /dev/null failed: %s", strerror(errno)); |
1aa1e248 | 94 | udev_config_init(); |
eef7c9a3 | 95 | selinux_init(); |
6b493a20 | 96 | dbg("version %s", UDEV_VERSION); |
af815f88 | 97 | |
47bf9196 | 98 | /* set signal handlers */ |
18ebc430 | 99 | memset(&act, 0x00, sizeof(act)); |
6b493a20 | 100 | act.sa_handler = (void (*)(int)) sig_handler; |
f8911dbb | 101 | sigemptyset (&act.sa_mask); |
5a73b25f | 102 | act.sa_flags = 0; |
7e89a569 | 103 | sigaction(SIGALRM, &act, NULL); |
f8911dbb KS |
104 | sigaction(SIGINT, &act, NULL); |
105 | sigaction(SIGTERM, &act, NULL); | |
3fd52a76 | 106 | |
2af003fe | 107 | /* trigger timeout to prevent hanging processes */ |
8815afa1 | 108 | alarm(UDEV_ALARM_TIMEOUT); |
7e89a569 | 109 | |
7e0bd584 KS |
110 | action = getenv("ACTION"); |
111 | devpath = getenv("DEVPATH"); | |
112 | subsystem = getenv("SUBSYSTEM"); | |
113 | /* older kernels passed the SUBSYSTEM only as argument */ | |
1aa1e248 | 114 | if (subsystem == NULL && argc == 2) |
7e0bd584 | 115 | subsystem = argv[1]; |
7e0bd584 | 116 | |
1aa1e248 | 117 | if (action == NULL || subsystem == NULL || devpath == NULL) { |
6b493a20 | 118 | err("action, subsystem or devpath missing"); |
c07669bd | 119 | goto exit; |
c449b25e | 120 | } |
f0713480 | 121 | |
8ab44e3f | 122 | /* export log_priority , as called programs may want to do the same as udev */ |
6b493a20 KS |
123 | if (udev_log_priority) { |
124 | char priority[32]; | |
125 | ||
126 | sprintf(priority, "%i", udev_log_priority); | |
127 | setenv("UDEV_LOG", priority, 1); | |
128 | } | |
c449b25e | 129 | |
1aa1e248 | 130 | sysfs_init(); |
287814b2 | 131 | udev_rules_init(&rules, 0); |
821d0ec8 | 132 | |
1aa1e248 KS |
133 | dev = sysfs_device_get(devpath); |
134 | if (dev == NULL) { | |
135 | info("unable to open '%s'", devpath); | |
136 | goto fail; | |
137 | } | |
138 | ||
31de3a2b | 139 | udev = udev_device_init(NULL); |
1aa1e248 KS |
140 | if (udev == NULL) |
141 | goto fail; | |
142 | ||
143 | /* override built-in sysfs device */ | |
144 | udev->dev = dev; | |
145 | strlcpy(udev->action, action, sizeof(udev->action)); | |
146 | ||
147 | /* get dev_t from environment, which is needed for "remove" to work, "add" works also from sysfs */ | |
148 | maj = getenv("MAJOR"); | |
149 | min = getenv("MINOR"); | |
150 | if (maj != NULL && min != NULL) | |
151 | udev->devt = makedev(atoi(maj), atoi(min)); | |
152 | else | |
153 | udev->devt = udev_device_get_devt(udev); | |
154 | ||
155 | retval = udev_device_event(&rules, udev); | |
2a94c877 | 156 | |
37854ffc | 157 | if (retval == 0 && !udev->ignore_device && udev_run) { |
c07669bd KS |
158 | struct name_entry *name_loop; |
159 | ||
160 | dbg("executing run list"); | |
1aa1e248 | 161 | list_for_each_entry(name_loop, &udev->run_list, node) { |
d455b008 KS |
162 | if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0) |
163 | pass_env_to_socket(&name_loop->name[strlen("socket:")], devpath, action); | |
f5f0c34f AB |
164 | else { |
165 | char program[PATH_SIZE]; | |
166 | ||
167 | strlcpy(program, name_loop->name, sizeof(program)); | |
a9bd2ed8 | 168 | udev_rules_apply_format(udev, program, sizeof(program)); |
f5f0c34f AB |
169 | run_program(program, udev->dev->subsystem, NULL, 0, NULL, (udev_log_priority >= LOG_INFO)); |
170 | } | |
d455b008 | 171 | } |
c07669bd | 172 | } |
d07557b9 | 173 | |
1aa1e248 KS |
174 | udev_device_cleanup(udev); |
175 | fail: | |
176 | udev_rules_cleanup(&rules); | |
177 | sysfs_cleanup(); | |
456cb387 | 178 | selinux_exit(); |
fb39f056 | 179 | |
d27d8d6a | 180 | exit: |
7257cb18 | 181 | logging_close(); |
37854ffc KS |
182 | if (retval != 0) |
183 | return 1; | |
184 | return 0; | |
f0083e3d | 185 | } |