From: greg@kroah.com Date: Thu, 17 Jul 2003 08:24:51 +0000 (-0700) Subject: [PATCH] Initial namedev parsing of config files X-Git-Tag: 002~19 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=2232cac825e4f8b53273d16154309278cf639e3c [PATCH] Initial namedev parsing of config files .permission parsing works, .config needs more work. --- diff --git a/Makefile b/Makefile index 4e0ca6b3c..0013d0679 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,8 @@ $(ARCH_LIB_OBJS) : $(MAKE) -C klibc OBJS = udev.o \ - logging.o + logging.o \ + namedev.o # header files automatically generated diff --git a/list.h b/list.h new file mode 100644 index 000000000..07d474888 --- /dev/null +++ b/list.h @@ -0,0 +1,444 @@ +/* + * Copied from the Linux kernel source tree, version 2.6.0-test1. + * + * Licensed under the GPL v2 as per the whole kernel source tree. + * + * Ripped out the rcu stuff, as it's not needed. + */ + +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +//#include +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +//#include +static inline void prefetch(const void *x) {;} + +//#include + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + prefetch(pos->member.prev); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member), \ + prefetch(pos->member.prev)) + + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) + +static __inline__ int hlist_unhashed(struct hlist_node *h) +{ + return !h->pprev; +} + +static __inline__ int hlist_empty(struct hlist_head *h) +{ + return !h->first; +} + +static __inline__ void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static __inline__ void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +static __inline__ void hlist_del_init(struct hlist_node *n) +{ + if (n->pprev) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +static __inline__ void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + +/* next must be != NULL */ +static __inline__ void hlist_add_before(struct hlist_node *n, struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static __inline__ void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + *(next->pprev) = n; + n->next = next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +/* Cannot easily do prefetch unfortunately */ +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ + pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; n = pos ? pos->next : 0, pos; \ + pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +#endif diff --git a/namedev.c b/namedev.c new file mode 100644 index 000000000..ee122cf07 --- /dev/null +++ b/namedev.c @@ -0,0 +1,345 @@ +/* + * namedev.c + * + * Userspace devfs + * + * Copyright (C) 2003 Greg Kroah-Hartman + * + * + * 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 +#include +#include + +#include "list.h" +#include "udev.h" +#include "udev_version.h" +#include "namedev.h" + +#define TYPE_LABEL "LABEL" +#define TYPE_NUMBER "NUMBER" +#define TYPE_TOPOLOGY "TOPOLOGY" +#define TYPE_REPLACE "REPLACE" + +enum config_type { + KERNEL_NAME = 0, /* must be 0 to let memset() default to this value */ + LABEL = 1, + NUMBER = 2, + TOPOLOGY = 3, + REPLACE = 4, +}; + +#define BUS_SIZE 30 +#define FILE_SIZE 50 +#define VALUE_SIZE 100 +#define ID_SIZE 50 +#define PLACE_SIZE 50 +#define NAME_SIZE 100 +#define OWNER_SIZE 30 +#define GROUP_SIZE 30 + + +struct config_device { + struct list_head node; + + enum config_type type; + + char bus[BUS_SIZE]; + char sysfs_file[FILE_SIZE]; + char sysfs_value[VALUE_SIZE]; + char id[ID_SIZE]; + char place[PLACE_SIZE]; + char kernel_name[NAME_SIZE]; + + /* what to set the device to */ + int mode; + char name[NAME_SIZE]; + char owner[OWNER_SIZE]; + char group[GROUP_SIZE]; +}; + + +static LIST_HEAD(config_device_list); + +#define copy_var(a, b, var) \ + if (b->var) \ + b->var = a->var; + +#define copy_string(a, b, var) \ + if (strlen(b->var)) \ + strcpy(b->var, a->var); + +static int add_dev(struct config_device *new_dev) +{ + struct list_head *tmp; + struct config_device *tmp_dev; + + /* loop through the whole list of devices to see if we already have + * this one... */ + list_for_each(tmp, &config_device_list) { + struct config_device *dev = list_entry(tmp, struct config_device, node); + if (strcmp(dev->name, new_dev->name) == 0) { + /* the same, copy the new info into this structure */ + copy_var(new_dev, dev, type); + copy_var(new_dev, dev, mode); + copy_string(new_dev, dev, bus); + copy_string(new_dev, dev, sysfs_file); + copy_string(new_dev, dev, sysfs_value); + copy_string(new_dev, dev, id); + copy_string(new_dev, dev, place); + copy_string(new_dev, dev, kernel_name); + copy_string(new_dev, dev, owner); + copy_string(new_dev, dev, group); + return 0; + } + } + + /* not found, lets create a new structure, and add it to the list */ + tmp_dev = malloc(sizeof(*tmp_dev)); + if (!tmp_dev) + return -ENOMEM; + memcpy(tmp_dev, new_dev, sizeof(*tmp_dev)); + list_add(&tmp_dev->node, &config_device_list); + return 0; +} + +static int get_value(const char *left, char **orig_string, char **ret_string) +{ + char *temp; + char *string = *orig_string; + + /* eat any whitespace */ + while (isspace(*string)) + ++string; + + /* split based on '=' */ + temp = strsep(&string, "="); + if (strcasecmp(temp, left) == 0) { + /* got it, now strip off the '"' */ + while (isspace(*string)) + ++string; + if (*string == '"') + ++string; + temp = strsep(&string, "\""); + *ret_string = temp; + *orig_string = string; + return 0; + } + return -ENODEV; +} + + +static int namedev_init_config(void) +{ + char filename[255]; + char line[255]; + char *temp; + char *temp2; + char *temp3; + FILE *fd; + int retval = 0; + struct config_device dev; + + strcpy(filename, NAMEDEV_CONFIG_ROOT NAMEDEV_CONFIG_FILE); + dbg("opening %s to read as permissions config", filename); + fd = fopen(filename, "r"); + if (fd == NULL) { + dbg("Can't open %s", filename); + return -ENODEV; + } + + /* loop through the whole file */ + while (1) { + /* get a line */ + temp = fgets(line, sizeof(line), fd); + if (temp == NULL) + break; + + dbg("read %s", temp); + + /* eat the whitespace at the beginning of the line */ + while (isspace(*temp)) + ++temp; + + /* no more line? */ + if (*temp == 0x00) + continue; + + /* see if this is a comment */ + if (*temp == COMMENT_CHARACTER) + continue; + + memset(&dev, 0x00, sizeof(dev)); + + /* parse the line */ + temp2 = strsep(&temp, ","); + if (strcasecmp(temp2, TYPE_LABEL) == 0) { + /* label type */ + dev.type = LABEL; + + /* BUS="bus" */ + retval = get_value("BUS", &temp, &temp3); + if (retval) + continue; + strcpy(dev.bus, temp3); + dbg("LABEL name = %s, bus = %s", dev.name, dev.bus); + } + + if (strcasecmp(temp2, TYPE_NUMBER) == 0) { + /* number type */ + dev.type = NUMBER; + + /* BUS="bus" */ + retval = get_value("BUS", &temp, &temp3); + if (retval) + continue; + strcpy(dev.bus, temp3); + dbg("NUMBER name = %s, bus = %s", dev.name, dev.bus); + } + + if (strcasecmp(temp2, TYPE_TOPOLOGY) == 0) { + /* number type */ + dev.type = TOPOLOGY; + + /* BUS="bus" */ + retval = get_value("BUS", &temp, &temp3); + if (retval) + continue; + strcpy(dev.bus, temp3); + dbg("TOPOLOGY name = %s, bus = %s", dev.name, dev.bus); + } + + if (strcasecmp(temp2, TYPE_REPLACE) == 0) { + /* number type */ + dev.type = REPLACE; + + /* KERNEL="kernel_name" */ + retval = get_value("KERNEL", &temp, &temp3); + if (retval) + continue; + strcpy(dev.kernel_name, temp3); + + /* NAME="new_name" */ + temp2 = strsep(&temp, ","); + retval = get_value("NAME", &temp, &temp3); + if (retval) + continue; + strcpy(dev.name, temp3); + dbg("REPLACE name = %s, kernel_name = %s", dev.name, dev.kernel_name); + } + + retval = add_dev(&dev); + if (retval) { + dbg("add_dev returned with error %d", retval); + goto exit; + } + } + +exit: + fclose(fd); + return retval; +} + + +static int namedev_init_permissions(void) +{ + char filename[255]; + char line[255]; + char *temp; + char *temp2; + FILE *fd; + int retval = 0; + struct config_device dev; + + strcpy(filename, NAMEDEV_CONFIG_ROOT NAMEDEV_CONFIG_PERMISSION_FILE); + dbg("opening %s to read as permissions config", filename); + fd = fopen(filename, "r"); + if (fd == NULL) { + dbg("Can't open %s", filename); + return -ENODEV; + } + + /* loop through the whole file */ + while (1) { + /* get a line */ + temp = fgets(line, sizeof(line), fd); + if (temp == NULL) + break; + + dbg("read %s", temp); + + /* eat the whitespace at the beginning of the line */ + while (isspace(*temp)) + ++temp; + + /* no more line? */ + if (*temp == 0x00) + continue; + + /* see if this is a comment */ + if (*temp == COMMENT_CHARACTER) + continue; + + memset(&dev, 0x00, sizeof(dev)); + + /* parse the line */ + temp2 = strsep(&temp, ":"); + strncpy(dev.name, temp2, sizeof(dev.name)); + + temp2 = strsep(&temp, ":"); + strncpy(dev.owner, temp2, sizeof(dev.owner)); + + temp2 = strsep(&temp, ":"); + strncpy(dev.group, temp2, sizeof(dev.owner)); + + dev.mode = strtol(temp, NULL, 8); + + dbg("name = %s, owner = %s, group = %s, mode = %x", dev.name, dev.owner, dev.group, dev.mode); + retval = add_dev(&dev); + if (retval) { + dbg("add_dev returned with error %d", retval); + goto exit; + } + } + +exit: + fclose(fd); + return retval; +} + + + +int namedev_init(void) +{ + int retval; + + retval = namedev_init_config(); + if (retval) + return retval; + + retval = namedev_init_permissions(); + if (retval) + return retval; + + return retval; +} + diff --git a/namedev.config b/namedev.config new file mode 100644 index 000000000..a26562342 --- /dev/null +++ b/namedev.config @@ -0,0 +1,21 @@ +# USB Epson printer to be called lp_epson +LABEL, BUS="usb", serial="HXOLL0012202323480", NAME="lp_epson" + +# USB HP printer to be called lp_hp +LABEL, BUS="usb", serial="W09090207101241330", NAME="lp_hp" + +# sound card with PCI bus id 00:0b.0 to be the first sound card +NUMBER, BUS="pci", id="00:0b.0", NAME="dsp" + +# sound card with PCI bus id 00:07.1 to be the second sound card +NUMBER, BUS="pci", id="00:07.1", NAME="dsp1" + +# USB mouse plugged into the third port of the first hub to be called mouse0 +TOPOLOGY, BUS="usb", place="1.3", NAME="mouse0" + +# USB tablet plugged into the second port of the second hub to be called mouse1 +TOPOLOGY, BUS="usb", place="2.2", NAME="mouse1" + +# ttyUSB1 should always be called visor +REPLACE, KERNEL="ttyUSB1", NAME="visor" + diff --git a/namedev.h b/namedev.h new file mode 100644 index 000000000..0089b4d24 --- /dev/null +++ b/namedev.h @@ -0,0 +1,34 @@ +/* + * namedev.h + * + * Userspace devfs + * + * Copyright (C) 2003 Greg Kroah-Hartman + * + * 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. + * + */ + +#ifndef NAMEDEV_H +#define NAMEDEV_H + +/* namedev config files */ +#define COMMENT_CHARACTER '#' +#define NAMEDEV_CONFIG_ROOT "/home/greg/src/udev/" +#define NAMEDEV_CONFIG_PERMISSION_FILE "namedev.permissions" +#define NAMEDEV_CONFIG_FILE "namedev.config" + +extern int namedev_init(void); + +#endif diff --git a/namedev.permissions b/namedev.permissions new file mode 100644 index 000000000..6148a15e4 --- /dev/null +++ b/namedev.permissions @@ -0,0 +1,4 @@ +#name:user:group:mode +ttyUSB0:root:uucp:0666 +ttyUSB1:root:uucp:0666 + diff --git a/udev.c b/udev.c index de6b6565f..bf170d165 100644 --- a/udev.c +++ b/udev.c @@ -30,6 +30,7 @@ #include "udev.h" #include "udev_version.h" +#include "namedev.h" static char *get_action(void) @@ -262,6 +263,8 @@ int main(int argc, char *argv[]) goto exit; } + namedev_init(); + /* sleep for a second or two to give the kernel a chance to * create the dev file */ diff --git a/udev.h b/udev.h index f4f4f11f2..fb35cad49 100644 --- a/udev.h +++ b/udev.h @@ -49,8 +49,6 @@ /* Binaries that udev calls to do stuff */ #define MKNOD "/bin/mknod" - - extern int log_message (int level, const char *format, ...);