+ } else {
+ strcat(pos, udev->program_result);
+ dbg("substitute result string '%s'", udev->program_result);
+ }
+ break;
+ case 's':
+ if (attr != NULL) {
+ tmpattr = find_sysfs_attribute(class_dev, sysfs_device, attr);
+ if (tmpattr == NULL) {
+ dbg("sysfa attribute '%s' not found", attr);
+ break;
+ }
+ strcpy(pos, tmpattr->value);
+ dbg("substitute sysfs value '%s'", tmpattr->value);
+ } else {
+ dbg("missing attribute");
+ }
+ break;
+ case '%':
+ strcat(pos, "%");
+ break;
+ default:
+ dbg("unknown substitution type '%%%c'", c);
+ break;
+ }
+ strcat(pos, tail);
+ }
+}
+
+/*
+ * Note, we can have multiple files for different busses in here due
+ * to the mess that USB has for its device tree...
+ */
+static struct bus_file {
+ char *bus;
+ char *file;
+} bus_files[] = {
+ { .bus = "scsi", .file = "vendor" },
+ { .bus = "usb", .file = "idVendor" },
+ { .bus = "usb", .file = "iInterface" },
+ { .bus = "usb-serial", .file = "detach_state" },
+ { .bus = "ide", .file = "detach_state" },
+ { .bus = "pci", .file = "vendor" },
+ {}
+};
+
+#define SECONDS_TO_WAIT_FOR_FILE 10
+static void wait_for_device_to_initialize(struct sysfs_device *sysfs_device)
+{
+ /* sleep until we see the file for this specific bus type show up this
+ * is needed because we can easily out-run the kernel in looking for
+ * these files before the paticular subsystem has created them in the
+ * sysfs tree properly.
+ *
+ * And people thought that the /sbin/hotplug event system was going to
+ * be slow, poo on you for arguing that before even testing it...
+ */
+ struct bus_file *b = &bus_files[0];
+ struct sysfs_attribute *tmpattr;
+ int found = 0;
+ int loop = SECONDS_TO_WAIT_FOR_FILE;
+
+ while (1) {
+ if (b->bus == NULL) {
+ if (!found)