1/* 2 * Copyright (C) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> 3 * Copyright (C) 2004-2006 Kay Sievers <kay.sievers@vrfy.org> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation version 2 of the License. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 */ 19 20#include <stdlib.h> 21#include <string.h> 22#include <stdio.h> 23#include <stddef.h> 24#include <unistd.h> 25#include <errno.h> 26#include <ctype.h> 27#include <fcntl.h> 28#include <signal.h> 29#include <syslog.h> 30#include <getopt.h> 31 32#include "udev.h" 33#include "udev_rules.h" 34 35 36#ifdef USE_LOG 37void log_message (int priority, const char *format, ...) 38{ 39 va_list args; 40 41 if (priority > udev_log_priority) 42 return; 43 44 va_start(args, format); 45 vprintf(format, args); 46 va_end(args); 47 printf("\n"); 48} 49#endif 50 51static int import_uevent_var(const char *devpath) 52{ 53 char path[PATH_SIZE]; 54 static char value[4096]; /* must stay, used with putenv */ 55 ssize_t size; 56 int fd; 57 char *key; 58 char *next; 59 int rc = -1; 60 61 /* read uevent file */ 62 strlcpy(path, sysfs_path, sizeof(path)); 63 strlcat(path, devpath, sizeof(path)); 64 strlcat(path, "/uevent", sizeof(path)); 65 fd = open(path, O_RDONLY); 66 if (fd < 0) 67 goto out; 68 size = read(fd, value, sizeof(value)); 69 close(fd); 70 if (size < 0) 71 goto out; 72 value[size] = '\0'; 73 74 /* import keys into environment */ 75 key = value; 76 while (key[0] != '\0') { 77 next = strchr(key, '\n'); 78 if (next == NULL) 79 goto out; 80 next[0] = '\0'; 81 info("import into environment: '%s'", key); 82 putenv(key); 83 key = &next[1]; 84 } 85 rc = 0; 86out: 87 return rc; 88} 89 90int main(int argc, char *argv[], char *envp[]) 91{ 92 int force = 0; 93 char *action = "add"; 94 char *subsystem = NULL; 95 char *devpath = NULL; 96 struct udevice *udev; 97 struct sysfs_device *dev; 98 struct udev_rules rules = {}; 99 int retval; 100 int rc = 0; 101 102 static const struct option options[] = { 103 { "action", 1, NULL, 'a' }, 104 { "subsystem", 1, NULL, 's' }, 105 { "force", 0, NULL, 'f' }, 106 { "help", 0, NULL, 'h' }, 107 {} 108 }; 109 110 info("version %s", UDEV_VERSION); 111 udev_config_init(); 112 if (udev_log_priority < LOG_INFO) { 113 char priority[32]; 114 115 udev_log_priority = LOG_INFO; 116 sprintf(priority, "%i", udev_log_priority); 117 setenv("UDEV_LOG", priority, 1); 118 } 119 120 while (1) { 121 int option; 122 123 option = getopt_long(argc, argv, "a:s:fh", options, NULL); 124 if (option == -1) 125 break; 126 127 dbg("option '%c'", option); 128 switch (option) { 129 case 'a': 130 action = optarg; 131 break; 132 case 's': 133 subsystem = optarg; 134 break; 135 case 'f': 136 force = 1; 137 break; 138 case 'h': 139 printf("Usage: udevtest OPTIONS <devpath>\n" 140 " --action=<string> set action string\n" 141 " --subsystem=<string> set subsystem string\n" 142 " --force don't skip node/link creation\n" 143 " --help print this help text\n\n"); 144 exit(0); 145 default: 146 exit(1); 147 } 148 } 149 devpath = argv[optind]; 150 151 if (devpath == NULL) { 152 fprintf(stderr, "devpath parameter missing\n"); 153 rc = 1; 154 goto exit; 155 } 156 157 printf("This program is for debugging only, it does not run any program,\n" 158 "specified by a RUN key. It may show incorrect results, because\n" 159 "some values may be different, or not available at a simulation run.\n" 160 "\n"); 161 162 sysfs_init(); 163 udev_rules_init(&rules, 0); 164 165 /* remove /sys if given */ 166 if (strncmp(devpath, sysfs_path, strlen(sysfs_path)) == 0) 167 devpath = &devpath[strlen(sysfs_path)]; 168 169 dev = sysfs_device_get(devpath); 170 if (dev == NULL) { 171 fprintf(stderr, "unable to open device '%s'\n", devpath); 172 rc = 2; 173 goto exit; 174 } 175 176 udev = udev_device_init(NULL); 177 if (udev == NULL) { 178 fprintf(stderr, "error initializing device\n"); 179 rc = 3; 180 goto exit; 181 } 182 183 if (subsystem != NULL) 184 strlcpy(dev->subsystem, subsystem, sizeof(dev->subsystem)); 185 186 /* override built-in sysfs device */ 187 udev->dev = dev; 188 strlcpy(udev->action, action, sizeof(udev->action)); 189 udev->devt = udev_device_get_devt(udev); 190 191 /* simulate node creation with test flag */ 192 if (!force) 193 udev->test_run = 1; 194 195 setenv("DEVPATH", udev->dev->devpath, 1); 196 setenv("SUBSYSTEM", udev->dev->subsystem, 1); 197 setenv("ACTION", udev->action, 1); 198 import_uevent_var(udev->dev->devpath); 199 200 info("looking at device '%s' from subsystem '%s'", udev->dev->devpath, udev->dev->subsystem); 201 retval = udev_device_event(&rules, udev); 202 if (retval == 0 && !udev->ignore_device && udev_run) { 203 struct name_entry *name_loop; 204 205 list_for_each_entry(name_loop, &udev->run_list, node) { 206 char program[PATH_SIZE]; 207 208 strlcpy(program, name_loop->name, sizeof(program)); 209 udev_rules_apply_format(udev, program, sizeof(program)); 210 info("run: '%s'", program); 211 } 212 } 213 udev_device_cleanup(udev); 214 215exit: 216 udev_rules_cleanup(&rules); 217 sysfs_cleanup(); 218 return rc; 219} 220