+ int maxsockplus;
+ struct sockaddr_un saddr;
+ socklen_t addrlen;
+ int retval, fd;
+ const int feature_on = 1;
+ struct sigaction act;
+ fd_set readfds;
+
+ logging_init("udevd");
+ dbg("version %s", UDEV_VERSION);
+
+ if (getuid() != 0) {
+ dbg("need to be root, exit");
+ _exit(1);
+ }
+
+ /* make sure we don't lock any path */
+ chdir("/");
+ umask(umask(077) | 022);
+
+ /* Set fds to dev/null */
+ fd = open( "/dev/null", O_RDWR );
+ if ( fd < 0 ) {
+ dbg("error opening /dev/null %s", strerror(errno));
+ exit(1);
+ }
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ if (fd > 2)
+ close(fd);
+
+ /* become session leader */
+ setsid();
+
+ /* setup signal handler pipe */
+ retval = pipe(pipefds);
+ if (retval < 0) {
+ dbg("error getting pipes: %s", strerror(errno));
+ exit(1);
+ }
+
+ retval = fcntl(pipefds[0], F_SETFL, O_NONBLOCK);
+ if (retval < 0) {
+ dbg("error fcntl on read pipe: %s", strerror(errno));
+ exit(1);
+ }
+ retval = fcntl(pipefds[0], F_SETFD, FD_CLOEXEC);
+ if (retval < 0) {
+ dbg("error fcntl on read pipe: %s", strerror(errno));
+ exit(1);
+ }
+
+ retval = fcntl(pipefds[1], F_SETFL, O_NONBLOCK);
+ if (retval < 0) {
+ dbg("error fcntl on write pipe: %s", strerror(errno));
+ exit(1);
+ }
+ retval = fcntl(pipefds[1], F_SETFD, FD_CLOEXEC);
+ if (retval < 0) {
+ dbg("error fcntl on write pipe: %s", strerror(errno));
+ exit(1);
+ }
+
+ /* set signal handlers */
+ act.sa_handler = (void (*) (int))sig_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGALRM, &act, NULL);
+ sigaction(SIGCHLD, &act, NULL);
+
+ memset(&saddr, 0x00, sizeof(saddr));
+ saddr.sun_family = AF_LOCAL;
+ /* use abstract namespace for socket path */
+ strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
+ addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
+
+ udevsendsock = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (udevsendsock == -1) {
+ dbg("error getting socket, exit");
+ exit(1);
+ }
+
+ /* the bind takes care of ensuring only one copy running */
+ retval = bind(udevsendsock, (struct sockaddr *) &saddr, addrlen);
+ if (retval < 0) {
+ dbg("bind failed, exit");
+ goto exit;
+ }
+
+ /* enable receiving of the sender credentials */
+ setsockopt(udevsendsock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
+
+ /* possible override of udev binary, used for testing */
+ udev_bin = getenv("UDEV_BIN");
+ if (udev_bin != NULL)
+ dbg("udev binary is set to '%s'", udev_bin);
+ else
+ udev_bin = UDEV_BIN;
+
+ FD_ZERO(&readfds);
+ FD_SET(udevsendsock, &readfds);
+ FD_SET(pipefds[0], &readfds);
+ maxsockplus = udevsendsock+1;
+ while (1) {
+ fd_set workreadfds = readfds;
+ retval = select(maxsockplus, &workreadfds, NULL, NULL, NULL);
+
+ if (retval < 0) {
+ if (errno != EINTR)
+ dbg("error in select: %s", strerror(errno));
+ continue;
+ }
+
+ if (FD_ISSET(udevsendsock, &workreadfds))
+ handle_udevsend_msg(udevsendsock);
+
+ if (FD_ISSET(pipefds[0], &workreadfds))
+ user_sighandler();
+
+ if (sigchilds_waiting) {
+ sigchilds_waiting = 0;
+ reap_sigchilds();
+ }
+
+ if (run_msg_q) {
+ run_msg_q = 0;
+ msg_queue_manager();
+ }
+
+ if (run_exec_q) {
+ /* clean up running_list before calling exec_queue_manager() */
+ if (sigchilds_waiting) {
+ sigchilds_waiting = 0;
+ reap_sigchilds();
+ }
+
+ run_exec_q = 0;
+ exec_queue_manager();
+ }
+ }
+exit:
+ close(udevsendsock);
+ logging_close();
+ return 1;