X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udevtrigger.c;h=d4b10d06ab461516ae62e7ae8566144bf1209b03;hp=cebc518c432c73bb601f5a2a01fb6d2ebcf2108a;hb=0654a21c78caf312fa612059725d1b47c78e7802;hpb=52434fb98b2e8920e8e254d87ecfff2789ebd6b7 diff --git a/udevtrigger.c b/udevtrigger.c index cebc518c4..d4b10d06a 100644 --- a/udevtrigger.c +++ b/udevtrigger.c @@ -70,7 +70,7 @@ static int device_list_insert(const char *path) char devpath[PATH_SIZE]; struct stat statbuf; - dbg("add '%s'" , path); + dbg("add '%s'\n" , path); /* we only have a device, if we have an uevent file */ strlcpy(filename, path, sizeof(filename)); @@ -110,17 +110,17 @@ static void trigger_uevent(const char *devpath, const char *action) fd = open(filename, O_WRONLY); if (fd < 0) { - dbg("error on opening %s: %s", filename, strerror(errno)); + dbg("error on opening %s: %s\n", filename, strerror(errno)); return; } if (write(fd, action, strlen(action)) < 0) - info("error writing '%s' to '%s': %s", action, filename, strerror(errno)); + info("error writing '%s' to '%s': %s\n", action, filename, strerror(errno)); close(fd); } -static int pass_to_socket(const char *devpath, const char *action) +static int pass_to_socket(const char *devpath, const char *action, const char *env) { struct udevice udev; struct name_entry *name_loop; @@ -133,6 +133,9 @@ static int pass_to_socket(const char *devpath, const char *action) int len; int err = 0; + if (verbose) + printf("%s\n", devpath); + udev_device_init(&udev); udev_db_get_device(&udev, devpath); @@ -140,6 +143,12 @@ static int pass_to_socket(const char *devpath, const char *action) bufpos = snprintf(buf, sizeof(buf)-1, "%s@%s", action, devpath); bufpos++; + /* add cookie */ + if (env != NULL) { + bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "%s", env); + bufpos++; + } + /* add standard keys */ bufpos += snprintf(&buf[bufpos], sizeof(buf)-1, "DEVPATH=%s", devpath); bufpos++; @@ -227,7 +236,7 @@ static int pass_to_socket(const char *devpath, const char *action) return err; } -static void exec_list(const char *action) +static void exec_list(const char *action, const char *env) { struct name_entry *loop_device; struct name_entry *tmp_device; @@ -236,7 +245,7 @@ static void exec_list(const char *action) if (delay_device(loop_device->name)) continue; if (sock >= 0) - pass_to_socket(loop_device->name, action); + pass_to_socket(loop_device->name, action, env); else trigger_uevent(loop_device->name, action); list_del(&loop_device->node); @@ -246,7 +255,7 @@ static void exec_list(const char *action) /* trigger remaining delayed devices */ list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) { if (sock >= 0) - pass_to_socket(loop_device->name, action); + pass_to_socket(loop_device->name, action, env); else trigger_uevent(loop_device->name, action); list_del(&loop_device->node); @@ -555,6 +564,7 @@ int udevtrigger(int argc, char *argv[], char *envp[]) const char *sockpath = NULL; int option; const char *action = "add"; + const char *env = NULL; static const struct option options[] = { { "verbose", 0, NULL, 'v' }, { "dry-run", 0, NULL, 'n' }, @@ -566,16 +576,17 @@ int udevtrigger(int argc, char *argv[], char *envp[]) { "subsystem-nomatch", 1, NULL, 'S' }, { "attr-match", 1, NULL, 'a' }, { "attr-nomatch", 1, NULL, 'A' }, + { "env", 1, NULL, 'e' }, {} }; logging_init("udevtrigger"); udev_config_init(); - dbg("version %s", UDEV_VERSION); + dbg("version %s\n", UDEV_VERSION); sysfs_init(); while (1) { - option = getopt_long(argc, argv, "vnFo:hc:s:S:a:A:", options, NULL); + option = getopt_long(argc, argv, "vnFo:hce::s:S:a:A:", options, NULL); if (option == -1) break; @@ -595,6 +606,10 @@ int udevtrigger(int argc, char *argv[], char *envp[]) case 'c': action = optarg; break; + case 'e': + if (strchr(optarg, '=') != NULL) + env = optarg; + break; case 's': name_list_add(&filter_subsystem_match_list, optarg, 0); break; @@ -613,6 +628,8 @@ int udevtrigger(int argc, char *argv[], char *envp[]) " --dry-run do not actually trigger the events\n" " --retry-failed trigger only the events which have been\n" " marked as failed during a previous run\n" + " --socket= pass events to socket instead of triggering kernel events\n" + " --env== pass an additional key (works only with --socket=)\n" " --subsystem-match= trigger devices from a matching subystem\n" " --subsystem-nomatch= exclude devices from a matching subystem\n" " --attr-match=]> trigger devices with a matching sysfs\n" @@ -628,17 +645,32 @@ int udevtrigger(int argc, char *argv[], char *envp[]) } if (sockpath != NULL) { + struct stat stats; + sock = socket(AF_LOCAL, SOCK_DGRAM, 0); memset(&saddr, 0x00, sizeof(struct sockaddr_un)); saddr.sun_family = AF_LOCAL; - /* abstract namespace only */ - strlcpy(&saddr.sun_path[1], sockpath, sizeof(saddr.sun_path)-1); - saddrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1; + if (sockpath[0] == '@') { + /* abstract namespace socket requested */ + strlcpy(&saddr.sun_path[1], &sockpath[1], sizeof(saddr.sun_path)-1); + saddrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); + } else if (stat(sockpath, &stats) == 0 && S_ISSOCK(stats.st_mode)) { + /* existing socket file */ + strlcpy(saddr.sun_path, sockpath, sizeof(saddr.sun_path)); + saddrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path); + } else { + /* no socket file, assume abstract namespace socket */ + strlcpy(&saddr.sun_path[1], sockpath, sizeof(saddr.sun_path)-1); + saddrlen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&saddr.sun_path[1]); + } + } else if (env != NULL) { + fprintf(stderr, "error: --env= only valid with --socket= option\n"); + goto exit; } if (failed) { scan_failed(); - exec_list(action); + exec_list(action, env); } else { char base[PATH_SIZE]; struct stat statbuf; @@ -648,12 +680,12 @@ int udevtrigger(int argc, char *argv[], char *envp[]) strlcat(base, "/subsystem", sizeof(base)); if (stat(base, &statbuf) == 0) { scan_subsystem("subsystem", SCAN_SUBSYSTEM); - exec_list(action); + exec_list(action, env); scan_subsystem("subsystem", SCAN_DEVICES); - exec_list(action); + exec_list(action, env); } else { scan_subsystem("bus", SCAN_SUBSYSTEM); - exec_list(action); + exec_list(action, env); scan_subsystem("bus", SCAN_DEVICES); scan_class(); @@ -662,7 +694,7 @@ int udevtrigger(int argc, char *argv[], char *envp[]) strlcat(base, "/class/block", sizeof(base)); if (stat(base, &statbuf) != 0) scan_block(); - exec_list(action); + exec_list(action, env); } }