+ while (1) {
+ option = getopt_long(argc, argv, "dDthV", options, NULL);
+ if (option == -1)
+ break;
+
+ switch (option) {
+ case 'd':
+ daemonize = 1;
+ break;
+ case 't':
+ debug_trace = 1;
+ break;
+ case 'D':
+ debug = 1;
+ if (udev_log_priority < LOG_INFO)
+ udev_log_priority = LOG_INFO;
+ break;
+ case 'h':
+ printf("Usage: udevd [--help] [--daemon] [--debug-trace] [--debug] [--version]\n");
+ goto exit;
+ case 'V':
+ printf("%s\n", UDEV_VERSION);
+ goto exit;
+ default:
+ goto exit;
+ }
+ }
+
+ if (getuid() != 0) {
+ fprintf(stderr, "root privileges required\n");
+ err("root privileges required\n");
+ goto exit;
+ }
+
+ /* make sure std{in,out,err} fd's are in a sane state */
+ fd = open("/dev/null", O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open /dev/null\n");
+ err("cannot open /dev/null\n");
+ }
+ if (fd > STDIN_FILENO)
+ dup2(fd, STDIN_FILENO);
+ if (write(STDOUT_FILENO, 0, 0) < 0)
+ dup2(fd, STDOUT_FILENO);
+ if (write(STDERR_FILENO, 0, 0) < 0)
+ dup2(fd, STDERR_FILENO);
+
+ /* init sockets to receive events */
+ if (init_udevd_socket() < 0) {
+ if (errno == EADDRINUSE) {
+ fprintf(stderr, "another udev daemon already running\n");
+ err("another udev daemon already running\n");
+ rc = 1;
+ } else {
+ fprintf(stderr, "error initializing udevd socket\n");
+ err("error initializing udevd socket\n");
+ rc = 2;
+ }
+ goto exit;
+ }
+
+ if (init_uevent_netlink_sock() < 0) {
+ fprintf(stderr, "error initializing netlink socket\n");
+ err("error initializing netlink socket\n");
+ rc = 3;
+ goto exit;
+ }
+
+ /* setup signal handler pipe */
+ retval = pipe(signal_pipe);
+ if (retval < 0) {
+ err("error getting pipes: %s\n", strerror(errno));
+ goto exit;
+ }
+
+ retval = fcntl(signal_pipe[READ_END], F_GETFL, 0);
+ if (retval < 0) {
+ err("error fcntl on read pipe: %s\n", strerror(errno));
+ goto exit;
+ }
+ retval = fcntl(signal_pipe[READ_END], F_SETFL, retval | O_NONBLOCK);
+ if (retval < 0) {
+ err("error fcntl on read pipe: %s\n", strerror(errno));
+ goto exit;
+ }
+
+ retval = fcntl(signal_pipe[WRITE_END], F_GETFL, 0);
+ if (retval < 0) {
+ err("error fcntl on write pipe: %s\n", strerror(errno));
+ goto exit;
+ }
+ retval = fcntl(signal_pipe[WRITE_END], F_SETFL, retval | O_NONBLOCK);
+ if (retval < 0) {
+ err("error fcntl on write pipe: %s\n", strerror(errno));
+ goto exit;
+ }
+
+ /* parse the rules and keep them in memory */
+ sysfs_init();
+ udev_rules_init(&rules, 1);
+
+ export_initial_seqnum();
+
+ if (daemonize) {
+ pid_t pid;
+
+ pid = fork();
+ switch (pid) {
+ case 0:
+ dbg("daemonized fork running\n");
+ break;
+ case -1:
+ err("fork of daemon failed: %s\n", strerror(errno));
+ rc = 4;
+ goto exit;
+ default:
+ dbg("child [%u] running, parent exits\n", pid);
+ rc = 0;
+ goto exit;
+ }
+ }
+
+ /* redirect std{out,err} fd's */
+ if (!debug)
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > STDERR_FILENO)
+ close(fd);
+
+ /* set scheduling priority for the daemon */
+ setpriority(PRIO_PROCESS, 0, UDEVD_PRIORITY);
+
+ chdir("/");
+ umask(022);
+
+ /* become session leader */
+ sid = setsid();
+ dbg("our session is %d\n", sid);
+
+ /* OOM_DISABLE == -17 */
+ fd = open("/proc/self/oom_adj", O_RDWR);
+ if (fd < 0)
+ err("error disabling OOM: %s\n", strerror(errno));
+ else {
+ write(fd, "-17", 3);
+ close(fd);
+ }
+
+ fd = open("/dev/kmsg", O_WRONLY);
+ if (fd > 0) {
+ const char *str = "<6>udevd version " UDEV_VERSION " started\n";
+
+ write(fd, str, strlen(str));
+ close(fd);
+ }
+
+ /* set signal handlers */
+ memset(&act, 0x00, sizeof(struct sigaction));
+ act.sa_handler = (void (*)(int)) sig_handler;
+ sigemptyset(&act.sa_mask);