/* * Guillaume Cottenceau (gc@mandrakesoft.com) * * Copyright 2000 MandrakeSoft * * This software may be freely redistributed under the terms of the GNU * public license. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* * Portions from Erik Troan (ewt@redhat.com), * * Copyright 1996 Red Hat Software * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "init.h" #include "udev.h" #include "common.h" /* * This need to safe symbols import */ #define fatal(m) init_fatal(m) #define warn(m) init_warn(m) /* defined in init.c */ extern int cooperate_mode; extern char * const env[]; static pid_t udevd_pid; static void spawn_wait(char * const command[], const char *message) { int status = 0; if (waitpid(spawn(command), &status, 0) < 0 || !(WIFEXITED(status))) { warn(message); } } static void spawn_silent(char * const command[]) { int fd = 0; pid_t pid = fork(); if (pid < 0) fatal(command[0]); else if (pid == 0) { fd = open("/dev/null", O_WRONLY, 0666); if (fd >= 0) { dup2(fd, 1); dup2(fd, 2); close(fd); } execve(command[0], &command[1], env); perror(command[0]); exit(1); } if (waitpid(pid, &fd, 0) >= 0) { fd = WIFEXITED(fd); } } void udev_start(void) { /* See make-initrd v0.8.x @ /data/lib/initrd/modules/050-udev for more details */ static char* const udevd[] = {"/sbin/udevd", "udevd", "--resolve-names=never", NULL}; static char* const priority[] = {"/sbin/udevadm", "udevadm", "control", "--log-priority=info", NULL}; static char* const startup[] = {"/sbin/udevadm", "udevadm", "control", "--property=STARTUP=1", NULL}; static char* const reload[] = {"/sbin/udevadm", "udevadm", "control", "--reload-rules", NULL}; static char* const subsys[] = {"/sbin/udevadm", "udevadm", "trigger", "--type=subsystems", "--action=add", NULL}; static char* const devices[] = {"/sbin/udevadm", "udevadm", "trigger", "--type=devices", "--action=add", NULL}; if (mkdirs_dev(".udev", ".udev/db", NULL) < 0) fatal("/dev/.udev/db"); if (cooperate_mode) { if (mkdir_dev(".udev/queue") < 0) fatal("cannot create /dev/.udev/queue"); /* No more to do in lazy initialization mode */ return; } printf("Spawning udevd... "); udevd_pid = spawn(udevd); spawn_wait(priority, "udev_priority"); spawn_wait(startup, "udev_startup"); spawn_silent(reload); if (mkdir_dev(".udev/queue") < 0) fatal("cannot create /dev/.udev/queue"); spawn_silent(subsys); spawn_silent(devices); udev_settle(); printf("done\n"); } void udev_settle(void) { /* See make-initrd v0.8.x @ /data/lib/initrd/modules/080-loop for more details */ static char* const settle[] = {"/sbin/udevadm", "udevadm", "settle", "--timeout=5", NULL}; spawn_wait(settle, "udev_settle"); } void udev_stop(void) { int fd, n = 0; /* This code moved from init.c/main() for compatibility */ udev_settle(); if (!cooperate_mode) { kill(udevd_pid, 9); if (waitpid(udevd_pid, &n, 0) >= 0) n = WIFEXITED(n); } nuke_dir("/dev/.udev/queue"); fd = open("/.udev_version", O_RDONLY, 0); if (fd >= 0) { char buf[32]; n = read(fd, buf, sizeof(buf)); close(fd); fd = creat("/dev/.initramfs/udev_version", 0); if (fd < 0) fatal("/dev/.initramfs/udev_version"); else { n = write(fd, buf, n); close(fd); } } }