+ while(1) {
+ int pid = waitpid(-1, NULL, WNOHANG);
+ if ((pid == -1) || (pid == 0))
+ break;
+ udev_done(pid);
+ }
+}
+
+/* just read everything from the pipe and clear the flag,
+ * the flags was set in the signal handler
+ */
+static void user_sighandler(void)
+{
+ int sig;
+
+ while(1) {
+ int rc = read(pipefds[0], &sig, sizeof(sig));
+ if (rc < 0)
+ break;
+
+ sig_flag = 0;
+ }
+}
+
+static int init_udevd_socket(void)
+{
+ struct sockaddr_un saddr;
+ const int buffersize = 1024 * 1024;
+ socklen_t addrlen;
+ const int feature_on = 1;
+ int retval;
+
+ 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;
+
+ udevd_sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (udevd_sock == -1) {
+ err("error getting socket, %s", strerror(errno));
+ return -1;
+ }
+
+ /* set receive buffersize */
+ setsockopt(udevd_sock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
+
+ /* the bind takes care of ensuring only one copy running */
+ retval = bind(udevd_sock, (struct sockaddr *) &saddr, addrlen);
+ if (retval < 0) {
+ err("bind failed, %s", strerror(errno));
+ close(udevd_sock);
+ return -1;
+ }
+
+ /* enable receiving of the sender credentials */
+ setsockopt(udevd_sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
+
+ return 0;
+}
+
+static int init_uevent_netlink_sock(void)
+{
+ struct sockaddr_nl snl;
+ const int buffersize = 1024 * 1024;
+ int retval;
+
+ memset(&snl, 0x00, sizeof(struct sockaddr_nl));
+ snl.nl_family = AF_NETLINK;
+ snl.nl_pid = getpid();
+ snl.nl_groups = 0xffffffff;
+
+ uevent_netlink_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ if (uevent_netlink_sock == -1) {
+ dbg("error getting socket, %s", strerror(errno));
+ return -1;
+ }
+
+ /* set receive buffersize */
+ setsockopt(uevent_netlink_sock, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
+
+ retval = bind(uevent_netlink_sock, (struct sockaddr *) &snl,
+ sizeof(struct sockaddr_nl));
+ if (retval < 0) {
+ dbg("bind failed, %s", strerror(errno));
+ close(uevent_netlink_sock);
+ uevent_netlink_sock = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[], char *envp[])
+{
+ int maxsockplus;
+ int retval;
+ int fd;
+ struct sigaction act;
+ fd_set readfds;
+ const char *value;
+ int uevent_netlink_active = 0;
+ int daemonize = 0;
+ int i;
+
+ logging_init("udevd");
+ udev_init_config();
+ dbg("version %s", UDEV_VERSION);
+
+ if (getuid() != 0) {
+ err("need to be root, exit");
+ goto exit;
+ }
+
+ for (i = 1 ; i < argc; i++) {
+ char *arg = argv[i];
+ if (strcmp(arg, "--daemon") == 0 || strcmp(arg, "-d") == 0) {
+ info("will daemonize");
+ daemonize = 1;
+ }
+ if (strcmp(arg, "--stop-exec-queue") == 0) {
+ info("will not execute events until START_EXEC_QUEUE is received");
+ stop_exec_q = 1;
+ }
+ }
+ if (daemonize) {
+ pid_t pid;
+
+ pid = fork();
+ switch (pid) {
+ case 0:
+ dbg("damonized fork running");
+ break;
+ case -1:
+ err("fork of daemon failed");
+ goto exit;
+ default:
+ logging_close();
+ exit(0);
+ }
+ }
+
+ /* become session leader */
+ sid = setsid();
+ dbg("our session is %d", sid);
+
+ chdir("/");
+ umask(umask(077) | 022);
+
+ /*set a reasonable scheduling priority for the daemon */
+ setpriority(PRIO_PROCESS, 0, UDEVD_PRIORITY);
+
+ /* Set fds to dev/null */
+ fd = open( "/dev/null", O_RDWR );
+ if (fd >= 0) {
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ if (fd > 2)
+ close(fd);
+ } else
+ err("error opening /dev/null %s", strerror(errno));
+
+ /* setup signal handler pipe */
+ retval = pipe(pipefds);
+ if (retval < 0) {
+ err("error getting pipes: %s", strerror(errno));
+ goto exit;
+ }
+
+ retval = fcntl(pipefds[0], F_SETFL, O_NONBLOCK);
+ if (retval < 0) {
+ err("error fcntl on read pipe: %s", strerror(errno));
+ goto exit;
+ }
+ retval = fcntl(pipefds[0], F_SETFD, FD_CLOEXEC);
+ if (retval < 0)
+ err("error fcntl on read pipe: %s", strerror(errno));
+
+ retval = fcntl(pipefds[1], F_SETFL, O_NONBLOCK);
+ if (retval < 0) {
+ err("error fcntl on write pipe: %s", strerror(errno));
+ goto exit;
+ }
+ retval = fcntl(pipefds[1], F_SETFD, FD_CLOEXEC);
+ if (retval < 0)
+ err("error fcntl on write pipe: %s", strerror(errno));
+
+ /* set signal handlers */
+ memset(&act, 0x00, sizeof(struct sigaction));
+ 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);
+
+ if (init_uevent_netlink_sock() < 0) {
+ dbg("uevent socket not available");
+ }
+
+ if (init_udevd_socket() < 0) {
+ if (errno == EADDRINUSE)
+ dbg("another udevd running, exit");
+ else
+ dbg("error initialising udevd socket: %s", strerror(errno));