From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kay Sievers Date: Mon, 15 Mar 2004 20:28:17 +0000 Subject: [patch] first stupid try for a rule compose gui Message-Id: <20040315202817.GA5653@vrfy.org> MIME-Version: 1 Content-Type: multipart/mixed; boundary="qMm9M+Fa2AknHoGS" List-Id: To: linux-hotplug@vger.kernel.org --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here is a first simple and pretty stupid try to make a simple tool for composing of a udev rule. It reads the udevdb to get all currently handled devices and presents a list, where you can choose the device to compose the rule for. The composed rule is just printed out in a window, nothing else by now. Do we want something like this? Nevermind, I always wanted to know, how this newt thing works :) thanks, Kay --qMm9M+Fa2AknHoGS Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="02-udevruler.patch" diff -Nru a/Makefile b/Makefile --- a/Makefile Mon Mar 15 21:11:57 2004 +++ b/Makefile Mon Mar 15 21:11:57 2004 @@ -36,6 +36,7 @@ INFO = udevinfo TESTER = udevtest STARTER = udevstart +RULER = udevruler VERSION = 021_bk INSTALL_DIR = /usr/local/bin RELEASE_NAME = $(ROOT)-$(VERSION) @@ -175,7 +176,7 @@ CFLAGS += -I$(PWD)/libsysfs -all: $(ROOT) $(SENDER) $(DAEMON) $(INFO) $(TESTER) $(STARTER) +all: $(ROOT) $(SENDER) $(DAEMON) $(INFO) $(TESTER) $(STARTER) $(RULER) @extras="$(EXTRAS)" ; for target in $$extras ; do \ echo $$target ; \ $(MAKE) prefix=$(prefix) \ @@ -294,10 +295,14 @@ $(LD) $(LDFLAGS) -o $@ $(CRT0) udevstart.o $(LIB_OBJS) $(ARCH_LIB_OBJS) $(STRIPCMD) $@ +$(RULER): $(RULER).o $(OBJS) $(HEADERS) $(LIBC) + $(LD) $(LDFLAGS) -o $@ $(CRT0) udevruler.o udev_config.o udevdb.o $(SYSFS) $(TDB) $(LIB_OBJS) $(ARCH_LIB_OBJS) -lnewt + $(STRIPCMD) $@ + clean: -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ | xargs rm -f - -rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(INFO) $(DAEMON) $(SENDER) $(TESTER) $(STARTER) + -rm -f core $(ROOT) $(GEN_HEADERS) $(GEN_CONFIGS) $(INFO) $(DAEMON) $(SENDER) $(TESTER) $(STARTER) $(RULER) $(MAKE) -C klibc clean @extras="$(EXTRAS)" ; for target in $$extras ; do \ echo $$target ; \ diff -Nru a/udevruler.c b/udevruler.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/udevruler.c Mon Mar 15 21:11:57 2004 @@ -0,0 +1,407 @@ +/* + * udevruler.c - simple udev-rule composer + * + * Reads the udev-db to get all currently known devices and + * scans the sysfs device chain for the choosen device to select attributes + * to compose a rule for the udev.rules file to uniquely name this device. + * + * Copyright (C) 2004 Kay Sievers + * + * 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 program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * 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. + * + */ + +#include +#include +#include +#include +#include + +#include "udev.h" +#include "udev_version.h" +#include "udevdb.h" +#include "libsysfs/sysfs.h" +#include "list.h" + +#ifdef LOG +unsigned char logname[LOGNAME_SIZE]; +void log_message(int level, const char *format, ...) +{ + va_list args; + + if (!udev_log) + return; + + va_start(args, format); + vsyslog(level, format, args); + va_end(args); +} +#endif + +static char *dev_blacklist[] = { + "tty", + "pty", + "zero", + "null", + "kmsg", + "rtc", + "timer", + "" +}; + +struct device { + struct list_head list; + char name[NAME_SIZE]; + char devpath[DEVPATH_SIZE]; +}; + +LIST_HEAD(device_list); +int device_count; + +/* callback for database dump */ +static int add_record(char *path, struct udevice *udev) +{ + struct device *dev; + int i = 0; + + while (dev_blacklist[i][0] != '\0') { + if (strncmp(udev->name, dev_blacklist[i], strlen(dev_blacklist[i])) == 0) + goto exit; + i++; + } + + dev = malloc(sizeof(struct device)); + if (dev == NULL) { + printf("error malloc\n"); + exit(2); + } + strfieldcpy(dev->name, udev->name); + strfieldcpy(dev->devpath, path); + list_add_tail(&dev->list, &device_list); + device_count++; + +exit: + return 0; +} + +/* get all devices from udev database */ +static int get_all_devices(void) +{ + int retval; + + device_count = 0; + INIT_LIST_HEAD(&device_list); + + retval = udevdb_open_ro(); + if (retval != 0) { + printf("unable to open udev database\n"); + exit(1); + } + + udevdb_call_foreach(add_record); + udevdb_exit(); + + return 0; +} + +struct attribute { + struct list_head list; + int level; + char key[NAME_SIZE]; +}; + +LIST_HEAD(attribute_list); +int attribute_count; + +static int add_attribute(const char *key, int level) +{ + struct attribute *attr; + + dbg("add attribute '%s'", key); + attr = malloc(sizeof(struct attribute)); + if (attr == NULL) { + printf("error malloc\n"); + exit(2); + } + + strfieldcpy(attr->key, key); + attr->level = level; + list_add_tail(&attr->list, &attribute_list); + attribute_count++; + return 0; +} + +static int add_all_attributes(const char *path, int level) +{ + struct dlist *attributes; + struct sysfs_attribute *attr; + struct sysfs_directory *sysfs_dir; + char value[NAME_SIZE]; + char key[NAME_SIZE]; + int len; + int retval = 0; + + dbg("look at '%s', level %i", path, level); + + sysfs_dir = sysfs_open_directory(path); + if (sysfs_dir == NULL) + return -1; + + attributes = sysfs_get_dir_attributes(sysfs_dir); + if (attributes == NULL) { + retval = -1; + return 0; + } + + dlist_for_each_data(attributes, attr, struct sysfs_attribute) + if (attr->value != NULL) { + dbg("found attribute '%s'", attr->name); + strfieldcpy(value, attr->value); + len = strlen(value); + if (len == 0) + continue; + + /* skip very long attributes */ + if (len > 40) + continue; + + /* remove trailing newline */ + if (value[len-1] == '\n') { + value[len-1] = '\0'; + len--; + } + + /* skip nonprintable values */ + while (len) { + if (!isprint(value[len-1])) + break; + len--; + } + if (len == 0) { + sprintf(key, "SYSFS{%s}=\"%s\"", attr->name, value); + add_attribute(key, level); + } + } + + return 0; +} + +static int get_all_attributes(char *path) +{ + struct sysfs_class_device *class_dev; + struct sysfs_class_device *class_dev_parent; + struct sysfs_attribute *attr; + struct sysfs_device *sysfs_dev; + struct sysfs_device *sysfs_dev_parent; + char key[NAME_SIZE]; + int retval = 0; + int level = 0; + + attribute_count = 0; + INIT_LIST_HEAD(&attribute_list); + + /* get the class dev */ + class_dev = sysfs_open_class_device_path(path); + if (class_dev == NULL) { + dbg("couldn't get the class device"); + return -1; + } + + /* read the 'dev' file for major/minor*/ + attr = sysfs_get_classdev_attr(class_dev, "dev"); + if (attr == NULL) { + dbg("couldn't get the \"dev\" file"); + retval = -1; + goto exit; + } + + sysfs_close_attribute(attr); + + /* open sysfs class device directory and get all attributes */ + if (add_all_attributes(class_dev->path, level) != 0) { + dbg("couldn't open class device directory"); + retval = -1; + goto exit; + } + level++; + + /* get the device link (if parent exists look here) */ + class_dev_parent = sysfs_get_classdev_parent(class_dev); + if (class_dev_parent != NULL) { + //sysfs_close_class_device(class_dev); + class_dev = class_dev_parent; + } + sysfs_dev = sysfs_get_classdev_device(class_dev); + + /* look the device chain upwards */ + while (sysfs_dev != NULL) { + if (sysfs_dev->bus[0] != '\0') { + add_attribute("", level); + sprintf(key, "BUS=\"%s\"", sysfs_dev->bus); + add_attribute(key, level); + sprintf(key, "ID=\"%s\"", sysfs_dev->bus_id); + add_attribute(key, level); + + /* open sysfs device directory and print all attributes */ + add_all_attributes(sysfs_dev->path, level); + } + level++; + + sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev); + if (sysfs_dev_parent == NULL) + break; + + //sysfs_close_device(sysfs_dev); + sysfs_dev = sysfs_dev_parent; + } + sysfs_close_device(sysfs_dev); + +exit: + //sysfs_close_class_device(class_dev); + return retval; +} + + +int main(int argc, char *argv[]) { + newtComponent lbox, run, lattr; + newtComponent quit, form, answer; + newtGrid grid, grid2; + char *devpath; + char roottext[81]; + char path[NAME_SIZE]; + struct device *dev; + + newtInit(); + newtCls(); + + newtWinMessage("udevruler", "Ok", + "This program lets you select a device currently present " + "on the system and you may choose the attributes to uniquely " + "name the device with a udev rule.\n" + "No configuration will be changed, it just prints the rule " + "to place in a udev.rules configuration file. The \"%k\" in the " + "NAME key of the printed rule may be replaced by the name the " + "node should have."); + + init_logging("udevruler"); + udev_init_config(); + get_all_devices(); + + lbox = newtListbox(2, 1, 10, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); + list_for_each_entry(dev, &device_list, list) + newtListboxAppendEntry(lbox, dev->name, (void*) dev->devpath); + + newtPushHelpLine(" / between elements | Use to select a device"); + snprintf(roottext, sizeof(roottext), "simple udev rule composer, version %s, (c) 2004 can't sleep team", UDEV_VERSION); + roottext[sizeof(roottext)-1] = '\0'; + newtDrawRootText(0, 0, roottext); + + form = newtForm(NULL, NULL, 0); + grid = newtCreateGrid(1, 2); + grid2 = newtButtonBar("Select device", &run, "Quit", &quit, NULL); + newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, lbox, 1, 0, 1, 0, NEWT_ANCHOR_TOP, 0); + newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, grid2, 0, 1, 0, 0, NEWT_ANCHOR_TOP, 0); + newtFormAddComponents(form, lbox, run, quit, NULL); + newtGridWrappedWindow(grid,"Choose the device for which to compose a rule"); + newtGridFree(grid, 1); + + while (1) { + struct attribute *attr; + newtComponent ok, back, form2, answer2; + newtGrid grid3, grid4; + int i; + int numitems; + struct attribute **selattr; + + answer = newtRunForm(form); + if (answer == quit) + break; + + devpath = (char *) newtListboxGetCurrent(lbox); + strfieldcpy(path, sysfs_path); + strfieldcat(path, devpath); + dbg("look at sysfs device '%s'", path); + get_all_attributes(path); + + grid3 = newtCreateGrid(1, 2); + form2 = newtForm(NULL, NULL, 0); + grid4 = newtButtonBar("Ok", &ok, "Back", &back, NULL); + + lattr = newtListbox(2, 1, 10, NEWT_FLAG_MULTIPLE | NEWT_FLAG_BORDER | NEWT_FLAG_RETURNEXIT); + list_for_each_entry(attr, &attribute_list, list) + newtListboxAddEntry(lattr, attr->key, (void *) attr); + + newtGridSetField(grid3, 0, 0, NEWT_GRID_COMPONENT, lattr, 0, 0, 0, 1, 0, 0); + newtGridSetField(grid3, 0, 1, NEWT_GRID_SUBGRID, grid4, 0, 1, 0, 0, NEWT_ANCHOR_TOP, 0); + + newtFormAddComponents(form2, lattr, ok, back, NULL); + newtGridWrappedWindow(grid3, "Select one ore more attributes within one section with the space bar"); + newtGridFree(grid3, 1); + + while (1) { + char rule[255]; + int onelevel; + int skipped; + + answer2 = newtRunForm(form2); + if (answer2 == back) + break; + + selattr = (struct attribute **) newtListboxGetSelection(lattr, &numitems); + if (selattr != NULL) { + rule[0] = '\0'; + onelevel = -1; + skipped = 0; + for (i = 0; i < numitems; i++) { + if (selattr[i]->key[0] == '\0') + continue; + + if (onelevel != -1) { + if (onelevel != selattr[i]->level) { + skipped = 1; + continue; + } + } else { + onelevel = selattr[i]->level; + } + + dbg("'%s'\n", selattr[i]->key); + strfieldcat(rule, selattr[i]->key); + strfieldcat(rule, ", "); + } + if (skipped) { + newtWinMessage("error", "Ok", "Please select only attributes within one section"); + continue; + } + + if (strlen(rule) > 200) { + newtWinMessage("error", "Ok", "The line is too long, please select fewer attributes."); + } else { + if (rule[0] == '\0') + continue; + + strfieldcat(rule, "NAME=\"%k\""); + newtWinMessage("the rule to place in config file", "Ok", rule); + } + } + } + + newtPopWindow(); + } + + newtPopWindow(); + newtFormDestroy(form); + newtFinished(); + return 0; +} --qMm9M+Fa2AknHoGS-- ------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel