/* * udev_multiplex.c directory multiplexer * * Copyright (C) 2004 Greg Kroah-Hartman * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation version 2 of the License. */ /* * This essentially emulates the following shell script logic in C: * DIR="/etc/dev.d" * export DEVNAME="whatever_dev_name_udev_just_gave" * for I in "${DIR}/$DEVNAME/"*.dev "${DIR}/$1/"*.dev "${DIR}/default/"*.dev ; do * if [ -f $I ]; then $I $1 ; fi * done * exit 1; */ #include #include #include #include #include #include #include #include #include "udev.h" #include "udev_libc_wrapper.h" #include "udev_utils.h" #include "logging.h" static int run_program(struct udevice *udev, const char *filename) { pid_t pid; int fd; dbg("running %s", filename); pid = fork(); switch (pid) { case 0: /* child */ fd = open("/dev/null", O_RDWR); if ( fd >= 0) { dup2(fd, STDOUT_FILENO); dup2(fd, STDIN_FILENO); dup2(fd, STDERR_FILENO); } close(fd); execl(filename, filename, udev->subsystem, NULL); dbg("exec of child failed"); _exit(1); case -1: dbg("fork of child failed"); break; return -1; default: waitpid(pid, NULL, 0); } return 0; } /* * runs files in these directories in order: * / * subsystem/ * default/ */ void udev_multiplex_directory(struct udevice *udev, const char *basedir, const char *suffix) { char dirname[PATH_SIZE]; /* chop the device name up into pieces based on '/' */ if (udev->name[0] != '\0') { char devname[PATH_SIZE]; char *temp; strlcpy(devname, udev->name, sizeof(devname)); temp = strchr(devname, '/'); while (temp != NULL) { temp[0] = '\0'; /* don't call the subsystem directory here */ if (strcmp(devname, udev->subsystem) != 0) { snprintf(dirname, sizeof(dirname), "%s/%s", basedir, devname); dirname[sizeof(dirname)-1] = '\0'; call_foreach_file(run_program, udev, dirname, suffix); } temp[0] = '/'; ++temp; temp = strchr(temp, '/'); } } if (udev->name[0] != '\0') { snprintf(dirname, sizeof(dirname), "%s/%s", basedir, udev->name); dirname[sizeof(dirname)-1] = '\0'; call_foreach_file(run_program, udev, dirname, suffix); } if (udev->subsystem[0] != '\0') { snprintf(dirname, sizeof(dirname), "%s/%s", basedir, udev->subsystem); dirname[sizeof(dirname)-1] = '\0'; call_foreach_file(run_program, udev, dirname, suffix); } snprintf(dirname, sizeof(dirname), "%s/default", basedir); dirname[sizeof(dirname)-1] = '\0'; call_foreach_file(run_program, udev, dirname, suffix); }