|
Lines 39-44
Link Here
|
| 39 |
#include <sys/un.h> |
39 |
#include <sys/un.h> |
| 40 |
#include <sys/sysinfo.h> |
40 |
#include <sys/sysinfo.h> |
| 41 |
#include <sys/stat.h> |
41 |
#include <sys/stat.h> |
|
|
42 |
#include <sys/ioctl.h> |
| 42 |
#include <linux/types.h> |
43 |
#include <linux/types.h> |
| 43 |
#include <linux/netlink.h> |
44 |
#include <linux/netlink.h> |
| 44 |
|
45 |
|
|
Lines 46-68
Link Here
|
| 46 |
#include "udev_libc_wrapper.h" |
47 |
#include "udev_libc_wrapper.h" |
| 47 |
#include "udev.h" |
48 |
#include "udev.h" |
| 48 |
#include "udev_version.h" |
49 |
#include "udev_version.h" |
|
|
50 |
#include "udev_rules.h" |
| 49 |
#include "udev_utils.h" |
51 |
#include "udev_utils.h" |
| 50 |
#include "udevd.h" |
52 |
#include "udevd.h" |
| 51 |
#include "logging.h" |
53 |
#include "logging.h" |
| 52 |
|
54 |
|
| 53 |
/* global variables*/ |
55 |
/* global variables*/ |
|
|
56 |
struct udev_rules rules; |
| 54 |
static int udevd_sock; |
57 |
static int udevd_sock; |
| 55 |
static int uevent_netlink_sock; |
58 |
static int uevent_netlink_sock; |
|
|
59 |
static int inotify_fd; |
| 56 |
static pid_t sid; |
60 |
static pid_t sid; |
| 57 |
|
61 |
|
| 58 |
static int signal_pipe[2] = {-1, -1}; |
62 |
static int signal_pipe[2] = {-1, -1}; |
| 59 |
static volatile int sigchilds_waiting; |
63 |
static volatile int sigchilds_waiting; |
| 60 |
static volatile int run_msg_q; |
64 |
static volatile int run_msg_q; |
| 61 |
static volatile int udev_exit; |
65 |
static volatile int udev_exit; |
|
|
66 |
static volatile int reload_config; |
| 62 |
static int init_phase = 1; |
67 |
static int init_phase = 1; |
| 63 |
static int run_exec_q; |
68 |
static int run_exec_q; |
| 64 |
static int stop_exec_q; |
69 |
static int stop_exec_q; |
| 65 |
static char *udev_bin; |
|
|
| 66 |
static int event_timeout; |
70 |
static int event_timeout; |
| 67 |
static int max_childs; |
71 |
static int max_childs; |
| 68 |
static int max_childs_running; |
72 |
static int max_childs_running; |
|
Lines 75-81
static LIST_HEAD(running_list);
Link Here
|
| 75 |
|
79 |
|
| 76 |
|
80 |
|
| 77 |
#ifdef USE_LOG |
81 |
#ifdef USE_LOG |
| 78 |
void log_message (int priority, const char *format, ...) |
82 |
void log_message(int priority, const char *format, ...) |
| 79 |
{ |
83 |
{ |
| 80 |
va_list args; |
84 |
va_list args; |
| 81 |
|
85 |
|
|
Lines 151-160
static void msg_queue_insert(struct ueve
Link Here
|
| 151 |
return; |
155 |
return; |
| 152 |
} |
156 |
} |
| 153 |
|
157 |
|
| 154 |
/* forks event and removes event from run queue when finished */ |
158 |
static void asmlinkage udev_event_sig_handler(int signum) |
|
|
159 |
{ |
| 160 |
if (signum == SIGALRM) |
| 161 |
exit(1); |
| 162 |
} |
| 163 |
|
| 164 |
static int udev_event_process(struct uevent_msg *msg) |
| 165 |
{ |
| 166 |
struct sigaction act; |
| 167 |
struct udevice udev; |
| 168 |
struct name_entry *name_loop; |
| 169 |
int i; |
| 170 |
int retval; |
| 171 |
|
| 172 |
/* set signal handlers */ |
| 173 |
memset(&act, 0x00, sizeof(act)); |
| 174 |
act.sa_handler = (void (*)(int)) udev_event_sig_handler; |
| 175 |
sigemptyset (&act.sa_mask); |
| 176 |
act.sa_flags = 0; |
| 177 |
sigaction(SIGALRM, &act, NULL); |
| 178 |
|
| 179 |
/* trigger timeout to prevent hanging processes */ |
| 180 |
alarm(UDEV_ALARM_TIMEOUT); |
| 181 |
|
| 182 |
/* reconstruct env from message */ |
| 183 |
for (i = 0; msg->envp[i]; i++) |
| 184 |
putenv(msg->envp[i]); |
| 185 |
|
| 186 |
udev_init_device(&udev, msg->devpath, msg->subsystem, msg->action); |
| 187 |
retval = udev_process_event(&rules, &udev); |
| 188 |
|
| 189 |
/* run programs collected by RUN-key*/ |
| 190 |
if (!retval) { |
| 191 |
list_for_each_entry(name_loop, &udev.run_list, node) { |
| 192 |
if (strncmp(name_loop->name, "socket:", strlen("socket:")) == 0) |
| 193 |
pass_env_to_socket(&name_loop->name[strlen("socket:")], msg->devpath, msg->action); |
| 194 |
else |
| 195 |
run_program(name_loop->name, udev.subsystem, NULL, 0, NULL, (udev_log_priority >= LOG_INFO)); |
| 196 |
} |
| 197 |
} |
| 198 |
|
| 199 |
udev_cleanup_device(&udev); |
| 200 |
|
| 201 |
return 0; |
| 202 |
} |
| 203 |
|
| 204 |
/* runs event and removes event from run queue when finished */ |
| 155 |
static void udev_event_run(struct uevent_msg *msg) |
205 |
static void udev_event_run(struct uevent_msg *msg) |
| 156 |
{ |
206 |
{ |
| 157 |
char *const argv[] = { "udev", msg->subsystem, NULL }; |
|
|
| 158 |
pid_t pid; |
207 |
pid_t pid; |
| 159 |
struct sysinfo info; |
208 |
struct sysinfo info; |
| 160 |
|
209 |
|
|
Lines 162-175
static void udev_event_run(struct uevent
Link Here
|
| 162 |
switch (pid) { |
211 |
switch (pid) { |
| 163 |
case 0: |
212 |
case 0: |
| 164 |
/* child */ |
213 |
/* child */ |
| 165 |
if (uevent_netlink_sock != -1) |
214 |
if (uevent_netlink_sock > 0) |
| 166 |
close(uevent_netlink_sock); |
215 |
close(uevent_netlink_sock); |
|
|
216 |
if (inotify_fd > 0) |
| 217 |
close(inotify_fd); |
| 167 |
close(udevd_sock); |
218 |
close(udevd_sock); |
|
|
219 |
close(signal_pipe[READ_END]); |
| 220 |
close(signal_pipe[WRITE_END]); |
| 168 |
logging_close(); |
221 |
logging_close(); |
|
|
222 |
|
| 223 |
logging_init("udevd-event"); |
| 169 |
setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY); |
224 |
setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY); |
| 170 |
execve(udev_bin, argv, msg->envp); |
225 |
udev_event_process(msg); |
| 171 |
err("exec of child failed"); |
226 |
info("seq %llu finished", msg->seqnum); |
| 172 |
_exit(1); |
227 |
|
|
|
228 |
logging_close(); |
| 229 |
exit(0); |
| 173 |
case -1: |
230 |
case -1: |
| 174 |
err("fork of child failed"); |
231 |
err("fork of child failed"); |
| 175 |
msg_queue_delete(msg); |
232 |
msg_queue_delete(msg); |
|
Lines 420-428
recheck:
Link Here
|
| 420 |
if (msg_age >= timeout) { |
477 |
if (msg_age >= timeout) { |
| 421 |
msg_move_exec(loop_msg); |
478 |
msg_move_exec(loop_msg); |
| 422 |
goto recheck; |
479 |
goto recheck; |
| 423 |
} else { |
480 |
} else |
| 424 |
break; |
481 |
break; |
| 425 |
} |
|
|
| 426 |
} |
482 |
} |
| 427 |
|
483 |
|
| 428 |
msg_dump_queue(); |
484 |
msg_dump_queue(); |
|
Lines 566-571
static struct uevent_msg *get_udevd_msg(
Link Here
|
| 566 |
info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval); |
622 |
info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval); |
| 567 |
max_childs = *intval; |
623 |
max_childs = *intval; |
| 568 |
break; |
624 |
break; |
|
|
625 |
case UDEVD_RELOAD_RULES: |
| 626 |
info("udevd message (RELOAD_RULES) received"); |
| 627 |
reload_config = 1; |
| 628 |
break; |
| 569 |
default: |
629 |
default: |
| 570 |
dbg("unknown message type"); |
630 |
dbg("unknown message type"); |
| 571 |
} |
631 |
} |
|
Lines 639-644
static void asmlinkage sig_handler(int s
Link Here
|
| 639 |
/* set flag, then write to pipe if needed */ |
699 |
/* set flag, then write to pipe if needed */ |
| 640 |
sigchilds_waiting = 1; |
700 |
sigchilds_waiting = 1; |
| 641 |
break; |
701 |
break; |
|
|
702 |
case SIGHUP: |
| 703 |
reload_config = 1; |
| 704 |
break; |
| 642 |
} |
705 |
} |
| 643 |
|
706 |
|
| 644 |
/* write to pipe, which will wakeup select() in our mainloop */ |
707 |
/* write to pipe, which will wakeup select() in our mainloop */ |
|
Lines 837-853
int main(int argc, char *argv[], char *e
Link Here
|
| 837 |
err("error fcntl on read pipe: %s", strerror(errno)); |
900 |
err("error fcntl on read pipe: %s", strerror(errno)); |
| 838 |
goto exit; |
901 |
goto exit; |
| 839 |
} |
902 |
} |
| 840 |
retval = fcntl(signal_pipe[READ_END], F_SETFD, FD_CLOEXEC); |
|
|
| 841 |
if (retval < 0) |
| 842 |
err("error fcntl on read pipe: %s", strerror(errno)); |
| 843 |
retval = fcntl(signal_pipe[WRITE_END], F_SETFL, O_NONBLOCK); |
903 |
retval = fcntl(signal_pipe[WRITE_END], F_SETFL, O_NONBLOCK); |
| 844 |
if (retval < 0) { |
904 |
if (retval < 0) { |
| 845 |
err("error fcntl on write pipe: %s", strerror(errno)); |
905 |
err("error fcntl on write pipe: %s", strerror(errno)); |
| 846 |
goto exit; |
906 |
goto exit; |
| 847 |
} |
907 |
} |
| 848 |
retval = fcntl(signal_pipe[WRITE_END], F_SETFD, FD_CLOEXEC); |
|
|
| 849 |
if (retval < 0) |
| 850 |
err("error fcntl on write pipe: %s", strerror(errno)); |
| 851 |
|
908 |
|
| 852 |
/* set signal handlers */ |
909 |
/* set signal handlers */ |
| 853 |
memset(&act, 0x00, sizeof(struct sigaction)); |
910 |
memset(&act, 0x00, sizeof(struct sigaction)); |
|
Lines 860-883
int main(int argc, char *argv[], char *e
Link Here
|
| 860 |
sigaction(SIGCHLD, &act, NULL); |
917 |
sigaction(SIGCHLD, &act, NULL); |
| 861 |
sigaction(SIGHUP, &act, NULL); |
918 |
sigaction(SIGHUP, &act, NULL); |
| 862 |
|
919 |
|
|
|
920 |
/* parse the rules and keep it in memory */ |
| 921 |
udev_rules_init(&rules, 0, 1); |
| 922 |
|
| 863 |
if (init_udevd_socket() < 0) { |
923 |
if (init_udevd_socket() < 0) { |
| 864 |
if (errno == EADDRINUSE) |
924 |
if (errno == EADDRINUSE) |
| 865 |
dbg("another udevd running, exit"); |
925 |
dbg("another udevd running, exit"); |
| 866 |
else |
926 |
else |
| 867 |
dbg("error initialising udevd socket: %s", strerror(errno)); |
927 |
dbg("error initialising udevd socket: %s", strerror(errno)); |
| 868 |
|
|
|
| 869 |
goto exit; |
928 |
goto exit; |
| 870 |
} |
929 |
} |
| 871 |
|
930 |
|
| 872 |
if (init_uevent_netlink_sock() < 0) |
931 |
if (init_uevent_netlink_sock() < 0) |
| 873 |
info("uevent socket not available"); |
932 |
err("uevent socket not available"); |
| 874 |
|
933 |
|
| 875 |
/* override of forked udev binary, used for testing */ |
934 |
/* watch rules directory */ |
| 876 |
udev_bin = getenv("UDEV_BIN"); |
935 |
inotify_fd = inotify_init(); |
| 877 |
if (udev_bin != NULL) |
936 |
if (inotify_fd > 0) |
| 878 |
info("udev binary is set to '%s'", udev_bin); |
937 |
inotify_add_watch(inotify_fd, udev_rules_filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); |
| 879 |
else |
|
|
| 880 |
udev_bin = UDEV_BIN; |
| 881 |
|
938 |
|
| 882 |
/* init of expected_seqnum value */ |
939 |
/* init of expected_seqnum value */ |
| 883 |
value = getenv("UDEVD_EXPECTED_SEQNUM"); |
940 |
value = getenv("UDEVD_EXPECTED_SEQNUM"); |
|
Lines 910-915
int main(int argc, char *argv[], char *e
Link Here
|
| 910 |
max_childs_running = UDEVD_MAX_CHILDS_RUNNING; |
967 |
max_childs_running = UDEVD_MAX_CHILDS_RUNNING; |
| 911 |
info("initialize max_childs_running to %u", max_childs_running); |
968 |
info("initialize max_childs_running to %u", max_childs_running); |
| 912 |
|
969 |
|
|
|
970 |
/* clear environment for forked event processes */ |
| 971 |
clearenv(); |
| 972 |
|
| 913 |
/* export log_priority , as called programs may want to follow that setting */ |
973 |
/* export log_priority , as called programs may want to follow that setting */ |
| 914 |
sprintf(log, "UDEV_LOG=%i", udev_log_priority); |
974 |
sprintf(log, "UDEV_LOG=%i", udev_log_priority); |
| 915 |
putenv(log); |
975 |
putenv(log); |
|
Lines 923-930
int main(int argc, char *argv[], char *e
Link Here
|
| 923 |
FD_SET(udevd_sock, &readfds); |
983 |
FD_SET(udevd_sock, &readfds); |
| 924 |
if (uevent_netlink_sock > 0) |
984 |
if (uevent_netlink_sock > 0) |
| 925 |
FD_SET(uevent_netlink_sock, &readfds); |
985 |
FD_SET(uevent_netlink_sock, &readfds); |
|
|
986 |
if (inotify_fd > 0) |
| 987 |
FD_SET(inotify_fd, &readfds); |
| 926 |
|
988 |
|
| 927 |
fdcount = select(UDEV_MAX(udevd_sock, uevent_netlink_sock)+1, &readfds, NULL, NULL, NULL); |
989 |
fdcount = select(UDEV_MAX(uevent_netlink_sock, inotify_fd)+1, &readfds, NULL, NULL, NULL); |
| 928 |
if (fdcount < 0) { |
990 |
if (fdcount < 0) { |
| 929 |
if (errno != EINTR) |
991 |
if (errno != EINTR) |
| 930 |
dbg("error in select: %s", strerror(errno)); |
992 |
dbg("error in select: %s", strerror(errno)); |
|
Lines 964-969
int main(int argc, char *argv[], char *e
Link Here
|
| 964 |
read(signal_pipe[READ_END], &buf, sizeof(buf)); |
1026 |
read(signal_pipe[READ_END], &buf, sizeof(buf)); |
| 965 |
} |
1027 |
} |
| 966 |
|
1028 |
|
|
|
1029 |
/* rules directory inotify watch */ |
| 1030 |
if (inotify_fd > 0 && FD_ISSET(inotify_fd, &readfds)) { |
| 1031 |
int nbytes; |
| 1032 |
|
| 1033 |
/* discard all possible events, we can just reload the config */ |
| 1034 |
if ((ioctl(inotify_fd, FIONREAD, &nbytes) == 0) && nbytes) { |
| 1035 |
char *buf; |
| 1036 |
|
| 1037 |
reload_config = 1; |
| 1038 |
buf = malloc(nbytes); |
| 1039 |
if (!buf) { |
| 1040 |
err("error getting buffer for inotify, disable watching"); |
| 1041 |
close(inotify_fd); |
| 1042 |
inotify_fd = -1; |
| 1043 |
} |
| 1044 |
read(inotify_fd, buf, nbytes); |
| 1045 |
free(buf); |
| 1046 |
} |
| 1047 |
} |
| 1048 |
|
| 1049 |
/* rules changed, set by inotify or a signal*/ |
| 1050 |
if (reload_config) { |
| 1051 |
reload_config = 0; |
| 1052 |
udev_rules_close(&rules); |
| 1053 |
udev_rules_init(&rules, 0, 1); |
| 1054 |
} |
| 1055 |
|
| 967 |
/* forked child have returned */ |
1056 |
/* forked child have returned */ |
| 968 |
if (sigchilds_waiting) { |
1057 |
if (sigchilds_waiting) { |
| 969 |
sigchilds_waiting = 0; |
1058 |
sigchilds_waiting = 0; |
|
Lines 989-994
int main(int argc, char *argv[], char *e
Link Here
|
| 989 |
} |
1078 |
} |
| 990 |
|
1079 |
|
| 991 |
exit: |
1080 |
exit: |
|
|
1081 |
udev_rules_close(&rules); |
| 1082 |
|
| 992 |
if (signal_pipe[READ_END] > 0) |
1083 |
if (signal_pipe[READ_END] > 0) |
| 993 |
close(signal_pipe[READ_END]); |
1084 |
close(signal_pipe[READ_END]); |
| 994 |
if (signal_pipe[WRITE_END] > 0) |
1085 |
if (signal_pipe[WRITE_END] > 0) |
|
Lines 996-1001
exit:
Link Here
|
| 996 |
|
1087 |
|
| 997 |
if (udevd_sock > 0) |
1088 |
if (udevd_sock > 0) |
| 998 |
close(udevd_sock); |
1089 |
close(udevd_sock); |
|
|
1090 |
if (inotify_fd > 0) |
| 1091 |
close(inotify_fd); |
| 999 |
if (uevent_netlink_sock > 0) |
1092 |
if (uevent_netlink_sock > 0) |
| 1000 |
close(uevent_netlink_sock); |
1093 |
close(uevent_netlink_sock); |
| 1001 |
|
1094 |
|