From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: [patch] first stupid try for a rule compose gui
Date: Mon, 15 Mar 2004 20:28:17 +0000 [thread overview]
Message-ID: <20040315202817.GA5653@vrfy.org> (raw)
[-- Attachment #1: Type: text/plain, Size: 417 bytes --]
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
[-- Attachment #2: 02-udevruler.patch --]
[-- Type: text/plain, Size: 11827 bytes --]
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 <kay.sievers@vrfy.org>
+ *
+ * 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 <newt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#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(" <Tab>/<Alt-Tab> between elements | Use <Enter> 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;
+}
next reply other threads:[~2004-03-15 20:28 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-03-15 20:28 Kay Sievers [this message]
2004-03-18 2:55 ` [patch] first stupid try for a rule compose gui Kay Sievers
2004-03-23 18:46 ` Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040315202817.GA5653@vrfy.org \
--to=kay.sievers@vrfy.org \
--cc=linux-hotplug@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).