# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-# Set this to make use of syslog
+# Set this to make use of syslog.
USE_LOG = true
-# Set this to ad development debug messages
+# Set this to compile-in development debug messages. Pass UDEV_LOG="debug"
+# to the executed binary or set the value in the udev configuration file to
+# let udev print the debug messages to syslog.
DEBUG = false
# Set this to include Security-Enhanced Linux support.
USE_SELINUX = false
-# Set this to comile with the local version of klibc instead of glibc.
+# Set this to comile with klibc instead of glibc.
USE_KLIBC = false
# Set this to create statically linked binaries.
@echo \#define UDEV_CONFIG_DIR \"$(configdir)\" >> $@
@echo \#define UDEV_CONFIG_FILE \"$(configdir)/udev.conf\" >> $@
@echo \#define UDEV_RULES_FILE \"$(configdir)/rules.d\" >> $@
- @echo \#define UDEV_LOG_DEFAULT \"yes\" >> $@
@echo \#define UDEV_BIN \"$(DESTDIR)$(sbindir)/udev\" >> $@
@echo \#define UDEVD_BIN \"$(DESTDIR)$(sbindir)/udevd\" >> $@
+udev 057
+========
+We support log priority levels now. The value udev_log in udev.conf is used
+to determine what is printed to syslog. This makes it possible to
+run a version with compiled-in debug messages in a production environment
+which is sometimes needed to find a bug.
+It is still possible to supress the inclusion of _any_ syslog usage with
+USE_LOG=false to create the smallest possible binaries if needed.
+The configured udev_log value can be overridden with the environment variable
+UDEV_LOG.
+
udev 056
========
Possible use of a system-wide klibc:
# udev.conf
-# The main config file for udev
#
-# This file can be used to override some of udev's default values
-# for where it looks for files, and where it places device nodes.
-
-# udev_root - where in the filesystem to place the device nodes
+# Where in the filesystem to place the device nodes
udev_root="@udevdir@"
-# udev_db - The name and location of the udev database.
+# The name and location of the udev database.
udev_db="@udevdir@/.udevdb"
-# udev_rules - The name and location of the udev rules file
+# The name and location of the udev rules file(s).
udev_rules="@configdir@/rules.d"
-# udev_log - set to "yes" if you want logging, else "no"
-udev_log="yes"
+# The syslog(3) priority: "err", "info", or the numerical value.
+udev_log="err"
#ifndef LOGGING_H
#define LOGGING_H
+#define err(format, arg...) do { } while (0)
#define info(format, arg...) do { } while (0)
#define dbg(format, arg...) do { } while (0)
#define logging_init(foo) do { } while (0)
#include <unistd.h>
#include <syslog.h>
+#undef err
+#define err(format, arg...) \
+ do { \
+ log_message(LOG_INFO ,"%s: " format ,__FILE__ ,## arg); \
+ } while (0)
+
#undef info
#define info(format, arg...) \
do { \
- log_message(LOG_INFO , format , ## arg); \
+ log_message(LOG_INFO ,"%s: " format ,__FILE__ ,## arg); \
} while (0)
#ifdef DEBUG
#undef dbg
#define dbg(format, arg...) \
do { \
- log_message(LOG_DEBUG , "%s: " format , __FUNCTION__ , ## arg); \
+ log_message(LOG_DEBUG ,"%s: " format ,__FUNCTION__ ,## arg); \
} while (0)
#endif
-extern void log_message(int level, const char *format, ...)
+extern void log_message(int priority, const char *format, ...)
__attribute__ ((format (printf, 2, 3)));
#undef logging_init
.SH NAME
udev \- Linux configurable dynamic device naming support
.SH SYNOPSIS
-.BI udev " hotplug-subsystem"
+.BI udev
.SH "DESCRIPTION"
.B udev
provides a dynamic device directory containing only the files for actually
.IR /etc/udev/rules.d/ .
.TP
.B udev_log
-The switch to enable/disable logging of udev information
+The logging priority which can be set to
+.IR "err " , "info "
+or the corresponding numerical
+.BR syslog (3)
+value.
The default value is
-.IR yes .
+.IR err .
.P
.RI "A sample " udev.conf " file might look like this:
.sp
.nf
-# udev_root - where to place the device nodes in the filesystem
-udev_root="/udev"
+# Where in the filesystem to place the device nodes
+udev_root="@udevdir@"
-# udev_db - The name and location of the udev database
-udev_db="/udev/.udevdb"
+# The name and location of the udev database.
+udev_db="@udevdir@/.udevdb"
-# udev_rules - The name of the udev rules file or directory to look
- for files with the suffix .rules
-udev_rules="/etc/udev/rules.d/"
+# The name and location of the udev rules file(s).
+udev_rules="@configdir@/rules.d"
-# udev_log - set to "yes" if you want logging, else "no"
-udev_log="yes"
+# The syslog(3) priority: "err", "info", or the numerical value.
+udev_log="err"
.fi
.P
The rules for device naming are read from the files located in the
.B last_rule
will be the last rule applied. No later rules will have any effect.
.sp
-.B OPTIONS
.B ignore_device
will ignore this device. No node will be created.
.sp
# multiple USB webcams with symlinks to be called webcam0, webcam1, ...
BUS=="usb", SYSFS{model}=="XV3", NAME=="video%n", SYMLINK="webcam%n"
-
-# grouping of optical drives from multiple kernel subsystems
-KERNEL=="sr*", NAME="%k", SYMLINK="cdrom%e"
-KERNEL=="scd*", NAME="%k", SYMLINK="cdrom%e"
-KERNEL=="pcd*", NAME="%k", SYMLINK="cdrom%e"
-KERNEL=="hd[a-z]", PROGRAM=="/bin/cat /proc/ide/%k/media", RESULT=="cdrom",
- NAME="%k", SYMLINK="cdrom%e"
.fi
.P
A number of different fields in the above configuration files support a simple
.br
In addition to the hotplug environment variables,
.B UDEV_LOG
-is set if udev is configured to use the syslog facility. Executed programs may
-want to follow that setting.
+is set and contains the numerical priority value, if udev is configured to use
+.BR syslog (3).
+Executed programs may want to follow that setting.
.B DEVNAME
is exported to make the name of the created node, or the name the network
device is renamed to, available to the executed program. The programs in every
.B udev
config file.
.TP
+.B UDEV_LOG
+Overrides the log priority specified in the config file.
+.TP
.B UDEV_NO_DEVD
The default behavior of
.B udev
.PP
.B Web resources:
.nf
-.I http://linux\-hotplug.sourceforge.net/
.I http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
+.I http://linux\-hotplug.sourceforge.net/
.fi
.SH AUTHORS
.B udev
#include "udev_rules.h"
#include "logging.h"
-
#ifdef USE_LOG
-void log_message(int level, const char *format, ...)
+void log_message(int priority, const char *format, ...)
{
va_list args;
- if (!udev_log)
+ if (priority > udev_log_priority)
return;
va_start(args, format);
- vsyslog(level, format, args);
+ vsyslog(priority, format, args);
va_end(args);
}
#endif
}
logging_init("udev");
- dbg("version %s", UDEV_VERSION);
-
udev_init_config();
+ dbg("version %s", UDEV_VERSION);
/* set signal handlers */
memset(&act, 0x00, sizeof(act));
- act.sa_handler = (void (*) (int))sig_handler;
+ act.sa_handler = (void (*)(int)) sig_handler;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
udev_init_device(&udev, devpath, subsystem);
if (!action || !subsystem || !devpath) {
- dbg("action, subsystem or devpath missing");
+ err("action, subsystem or devpath missing");
goto hotplug;
}
/* export logging flag, as called scripts may want to do the same as udev */
- if (udev_log)
- setenv("UDEV_LOG", "1", 1);
+ if (udev_log_priority) {
+ char priority[32];
+
+ sprintf(priority, "%i", udev_log_priority);
+ setenv("UDEV_LOG", priority, 1);
+ }
if (udev.type == DEV_BLOCK || udev.type == DEV_CLASS || udev.type == DEV_NET) {
if (strcmp(action, "add") == 0) {
path[sizeof(path)-1] = '\0';
class_dev = wait_class_device_open(path);
if (class_dev == NULL) {
- dbg ("open class device failed");
+ dbg("open class device failed");
goto hotplug;
}
dbg("opened class_dev->name='%s'", class_dev->name);
extern char udev_db_path[PATH_SIZE];
extern char udev_config_filename[PATH_SIZE];
extern char udev_rules_filename[PATH_SIZE];
-extern int udev_log;
+extern int udev_log_priority;
extern int udev_dev_d;
extern int udev_hotplug_d;
/* preserve node with already correct numbers, to not change the inode number */
if (((stats.st_mode & S_IFMT) == S_IFBLK || (stats.st_mode & S_IFMT) == S_IFCHR) &&
(stats.st_rdev == devt)) {
- dbg("preserve file '%s', cause it has correct dev_t", file);
+ info("preserve file '%s', cause it has correct dev_t", file);
selinux_setfilecon(file, udev->kernel_name, stats.st_mode);
goto perms;
}
retval = mknod(file, mode, devt);
selinux_resetfscreatecon();
if (retval != 0) {
- dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
+ err("mknod(%s, %#o, %u, %u) failed with error '%s'",
file, mode, major(devt), minor(devt), strerror(errno));
goto exit;
}
struct ifreq ifr;
int retval;
- dbg("changing net interface name from '%s' to '%s'", udev->kernel_name, udev->name);
+ info("changing net interface name from '%s' to '%s'", udev->kernel_name, udev->name);
if (udev->test_run)
return 0;
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
+#include <syslog.h>
#include "libsysfs/sysfs/libsysfs.h"
#include "udev_libc_wrapper.h"
#include "udev_utils.h"
#include "udev_version.h"
#include "logging.h"
-#include "udev_rules.h"
/* global variables */
char sysfs_path[PATH_SIZE];
char udev_root[PATH_SIZE];
char udev_db_path[PATH_SIZE];
-char udev_rules_filename[PATH_SIZE];
char udev_config_filename[PATH_SIZE];
-int udev_log;
+char udev_rules_filename[PATH_SIZE];
+int udev_log_priority;
int udev_dev_d;
int udev_hotplug_d;
-
static int string_is_true(const char *str)
{
if (strcasecmp(str, "true") == 0)
return 0;
}
+static int log_priority(const char *priority)
+{
+ char *endptr;
+ int prio;
+
+ prio = strtol(priority, &endptr, 10);
+ if (endptr[0] == '\0')
+ return prio;
+ if (strncasecmp(priority, "err", 3) == 0)
+ return LOG_ERR;
+ if (strcasecmp(priority, "info") == 0)
+ return LOG_INFO;
+ if (strcasecmp(priority, "debug") == 0)
+ return LOG_DEBUG;
+ if (string_is_true(priority))
+ return LOG_ERR;
+
+ return 0;
+}
+
static int get_key(char **line, char **key, char **value)
{
char *linepos;
return 0;
}
-static void init_variables(void)
-{
- const char *env;
-
- /* If any config values are specified, they will override these values. */
- strcpy(udev_root, UDEV_ROOT);
- strcpy(udev_db_path, UDEV_DB);
- strcpy(udev_config_filename, UDEV_CONFIG_FILE);
- strcpy(udev_rules_filename, UDEV_RULES_FILE);
-
- udev_log = string_is_true(UDEV_LOG_DEFAULT);
-
- udev_dev_d = 1;
- env = getenv("UDEV_NO_DEVD");
- if (env && string_is_true(env))
- udev_dev_d = 0;
-
- udev_hotplug_d = 1;
- env = getenv("UDEV_NO_HOTPLUGD");
- if (env && string_is_true(env))
- udev_hotplug_d = 0;
-}
-
static int parse_config_file(void)
{
char line[LINE_SIZE];
int retval = 0;
if (file_map(udev_config_filename, &buf, &bufsize) != 0) {
- dbg("can't open '%s' as config file", udev_config_filename);
+ err("can't open '%s' as config file", udev_config_filename);
return -ENODEV;
}
- dbg("reading '%s' as config file", udev_config_filename);
/* loop through the whole file */
lineno = 0;
lineno++;
if (count >= sizeof(line)) {
- info("line too long, conf line skipped %s, line %d",
- udev_config_filename, lineno);
+ err("line too long, conf line skipped %s, line %d", udev_config_filename, lineno);
continue;
}
continue;
strlcpy(line, bufline, count);
- dbg("read '%s'", line);
linepos = line;
retval = get_key(&linepos, &variable, &value);
if (retval != 0) {
- info("error parsing %s, line %d:%d", udev_config_filename, lineno, (int) (linepos-line));
+ err("error parsing %s, line %d:%d", udev_config_filename, lineno, (int) (linepos-line));
continue;
}
- dbg("variable='%s', value='%s'", variable, value);
-
if (strcasecmp(variable, "udev_root") == 0) {
strlcpy(udev_root, value, sizeof(udev_root));
no_trailing_slash(udev_root);
}
if (strcasecmp(variable, "udev_log") == 0) {
- udev_log = string_is_true(value);
+ udev_log_priority = log_priority(value);
continue;
}
}
void udev_init_config(void)
{
- const char *config;
+ const char *env;
- init_variables();
+ strcpy(udev_root, UDEV_ROOT);
+ strcpy(udev_db_path, UDEV_DB);
+ strcpy(udev_config_filename, UDEV_CONFIG_FILE);
+ strcpy(udev_rules_filename, UDEV_RULES_FILE);
+ udev_log_priority = LOG_ERR;
+ udev_dev_d = 1;
+ udev_hotplug_d = 1;
sysfs_get_mnt_path(sysfs_path, sizeof(sysfs_path));
- config = getenv("UDEV_CONFIG_FILE");
- if (config != NULL)
- strlcpy(udev_config_filename, config, sizeof(udev_config_filename));
+ env = getenv("UDEV_NO_DEVD");
+ if (env && string_is_true(env))
+ udev_dev_d = 0;
+
+ env = getenv("UDEV_NO_HOTPLUGD");
+ if (env && string_is_true(env))
+ udev_hotplug_d = 0;
+
+ env = getenv("UDEV_CONFIG_FILE");
+ if (env) {
+ strlcpy(udev_config_filename, env, sizeof(udev_config_filename));
+ no_trailing_slash(udev_config_filename);
+ }
parse_config_file();
+
+ env = getenv("UDEV_LOG");
+ if (env)
+ udev_log_priority = log_priority(env);
+
dbg("sysfs_path='%s'", sysfs_path);
+ dbg("UDEV_CONFIG_FILE='%s'", udev_config_filename);
dbg("udev_root='%s'", udev_root);
- dbg("udev_config_filename='%s'", udev_config_filename);
- dbg("udev_db_path='%s'", udev_db_path);
- dbg("udev_rules_filename='%s'", udev_rules_filename);
- dbg("udev_log=%d", udev_log);
+ dbg("udev_db='%s'", udev_db_path);
+ dbg("udev_rules='%s'", udev_rules_filename);
+ dbg("udev_log=%d", udev_log_priority);
}
f = fopen(filename, "w");
if (f == NULL) {
- dbg("unable to create db file '%s'", filename);
+ err("unable to create db file '%s'", filename);
return -1;
}
dbg("storing data for device '%s' in '%s'", udev->devpath, filename);
size_t count;
if (file_map(filename, &buf, &bufsize) != 0) {
- dbg("unable to read db file '%s'", filename);
+ err("unable to read db file '%s'", filename);
return -1;
}
dir = opendir(udev_db_path);
if (dir == NULL) {
- dbg("unable to udev db '%s'", udev_db_path);
+ err("unable to open udev_db '%s'", udev_db_path);
return -1;
}
dbg("looking at '%s'", filename);
if (file_map(filename, &buf, &bufsize) != 0) {
- dbg("unable to read db file '%s'", filename);
+ err("unable to read db file '%s'", filename);
continue;
}
dir = opendir(udev_db_path);
if (dir == NULL) {
- dbg("unable to udev db '%s'", udev_db_path);
+ err("unable to open udev_db '%s'", udev_db_path);
return -1;
}
dbg("looking at '%s'", filename);
if (file_map(filename, &buf, &bufsize) != 0) {
- dbg("unable to read db file '%s'", filename);
+ err("unable to read db file '%s'", filename);
continue;
}
if (temp == NULL)
return -ENODEV;
strlcpy(udev->name, &temp[1], sizeof(udev->name));
- dbg("'%s' not found in database, falling back on default name", udev->name);
+ info("'%s' not found in database, falling back on default name", udev->name);
}
/* use full path to the environment */
if (*str[0] == '{') {
pos = strchr(*str, '}');
if (pos == NULL) {
- dbg("missing closing brace for format");
+ err("missing closing brace for format");
return NULL;
}
pos[0] = '\0';
dbg("format length=%i", num);
return num;
} else {
- dbg("format parsing error '%s'", *str);
+ err("format parsing error '%s'", *str);
}
}
return -1;
cpos++;
}
if (i > 0) {
- dbg("requested part of result string not found");
+ err("requested part of result string not found");
break;
}
strlcpy(temp2, cpos, sizeof(temp2));
}
tmpattr = find_sysfs_attribute(class_dev, sysfs_device, attr);
if (tmpattr == NULL) {
- dbg("sysfa attribute '%s' not found", attr);
+ dbg("sysfs attribute '%s' not found", attr);
break;
}
/* strip trailing whitespace of matching value */
dbg("substitute udev_root '%s'", udev_root);
break;
default:
- dbg("unknown substitution type '%%%c'", c);
+ err("unknown substitution type '%%%c'", c);
break;
}
/* truncate to specified length */
retval = pipe(fds);
if (retval != 0) {
- dbg("pipe failed");
+ err("pipe failed");
return -1;
}
info(KEY_PROGRAM " execution of '%s' failed", path);
exit(1);
case -1:
- dbg("fork failed");
+ err("fork of '%s' failed", path);
return -1;
default:
/* parent reads from fds[0] */
i += count;
if (i >= len-1) {
- dbg("result len %d too short", len);
+ err("result len %d too short", len);
retval = -1;
break;
}
}
if (count < 0) {
- dbg("read failed with '%s'", strerror(errno));
+ err("read failed with '%s'", strerror(errno));
retval = -1;
}
next = strchr(temp, ' ');
while (next) {
next[0] = '\0';
- dbg("add symlink '%s'", pos);
+ info("add symlink '%s'", pos);
name_list_add(&udev->symlink_list, pos, 0);
pos = &next[1];
next = strchr(pos, ' ');
}
- dbg("add symlink '%s'", pos);
+ info("add symlink '%s'", pos);
name_list_add(&udev->symlink_list, pos, 0);
}
if (udev->name[0] == '\0') {
/* no rule matched, so we use the kernel name */
strlcpy(udev->name, udev->kernel_name, sizeof(udev->name));
- dbg("no rule found, use kernel name '%s'", udev->name);
+ info("no rule found, use kernel name '%s'", udev->name);
}
if (udev->tmp_node[0] != '\0') {
attr++;
pos = strchr(attr, '}');
if (pos == NULL) {
- dbg("missing closing brace for format");
+ err("missing closing brace for format");
return NULL;
}
pos[0] = '\0';
struct udev_rule rule;
if (file_map(filename, &buf, &bufsize) != 0) {
- dbg("can't open '%s' as rules file", filename);
+ err("can't open '%s' as rules file", filename);
return -1;
}
dbg("reading '%s' as rules file", filename);
struct key_pair *pair;
if (rule.sysfs_pair_count >= KEY_SYSFS_PAIRS_MAX) {
- dbg("skip rule, to many " KEY_SYSFS " keys in a single rule");
+ err("skip rule, to many " KEY_SYSFS " keys in a single rule");
goto error;
}
pair = &rule.sysfs_pair[rule.sysfs_pair_count];
attr = get_key_attribute(key + sizeof(KEY_SYSFS)-1);
if (attr == NULL) {
- dbg("error parsing " KEY_SYSFS " attribute");
+ err("error parsing " KEY_SYSFS " attribute");
goto error;
}
strlcpy(pair->name, attr, sizeof(pair->name));
struct key_pair *pair;
if (rule.env_pair_count >= KEY_ENV_PAIRS_MAX) {
- dbg("skip rule, to many " KEY_ENV " keys in a single rule");
+ err("skip rule, to many " KEY_ENV " keys in a single rule");
goto error;
}
pair = &rule.env_pair[rule.env_pair_count];
attr = get_key_attribute(key + sizeof(KEY_ENV)-1);
if (attr == NULL) {
- dbg("error parsing " KEY_ENV " attribute");
+ err("error parsing " KEY_ENV " attribute");
continue;
}
strlcpy(pair->name, attr, sizeof(pair->name));
continue;
}
- dbg("unknown key '%s'", key);
+ err("unknown key '%s'", key);
goto error;
}
/* simple plausibility checks for given keys */
if ((rule.sysfs_pair[0].name[0] == '\0') ^
(rule.sysfs_pair[0].value[0] == '\0')) {
- info("inconsistency in " KEY_SYSFS " key");
+ err("inconsistency in " KEY_SYSFS " key");
goto error;
}
if ((rule.result[0] != '\0') && (program_given == 0)) {
- info(KEY_RESULT " is only useful when "
- KEY_PROGRAM " is called in any rule before");
+ info(KEY_RESULT " is only useful when " KEY_PROGRAM " is called in any rule before");
goto error;
}
dbg("add_config_dev returned with error %d", retval);
continue;
error:
- info("parse error %s, line %d:%d, rule skipped",
+ err("parse error %s, line %d:%d, rule skipped",
filename, lineno, (int) (linepos - line));
}
}
.SH NAME
udevd, udevdsend \- udev event serializer daemon and udev event sender
.SH SYNOPSIS
-.BI udevsend " hotplug-subsystem"
+.BI udevsend
.SH "DESCRIPTION"
.B udevd
allows the serialization of
char *udev_bin;
#ifdef USE_LOG
-void log_message (int level, const char *format, ...)
+void log_message (int priority, const char *format, ...)
{
- va_list args;
+ va_list args;
+
+ if (priority > udev_log_priority)
+ return;
va_start(args, format);
- vsyslog(level, format, args);
+ vsyslog(priority, format, args);
va_end(args);
}
#endif
-#define msg_dump(msg) \
- dbg("msg_dump: sequence %llu, '%s', '%s', '%s'", \
- msg->seqnum, msg->action, msg->devpath, msg->subsystem);
-
static void msg_dump_queue(void)
{
#ifdef DEBUG
break;
if (loop_msg->seqnum == msg->seqnum) {
- dbg("ignoring duplicate message seq %llu", msg->seqnum);
+ info("ignoring duplicate message seq %llu", msg->seqnum);
return;
}
}
setpriority(PRIO_PROCESS, 0, UDEV_PRIORITY);
execve(udev_bin, argv, msg->envp);
- dbg("exec of child failed");
+ err("exec of child failed");
_exit(1);
break;
case -1:
- dbg("fork of child failed");
+ err("fork of child failed");
run_queue_delete(msg);
break;
default:
cred = (struct ucred *) CMSG_DATA(cmsg);
if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
- dbg("no sender credentials received, message ignored");
+ info("no sender credentials received, message ignored");
return NULL;
}
if (cred->uid != 0) {
- dbg("sender uid=%i, message ignored", cred->uid);
+ info("sender uid=%i, message ignored", cred->uid);
return NULL;
}
if (strncmp(usend_msg.magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
- dbg("message magic '%s' doesn't match, ignore it", usend_msg.magic);
+ info("message magic '%s' doesn't match, ignore it", usend_msg.magic);
return NULL;
}
udevsendsock = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (udevsendsock == -1) {
- dbg("error getting socket, %s", strerror(errno));
+ err("error getting socket, %s", strerror(errno));
return -1;
}
/* the bind takes care of ensuring only one copy running */
retval = bind(udevsendsock, (struct sockaddr *) &saddr, addrlen);
if (retval < 0) {
- dbg("bind failed, %s", strerror(errno));
+ err("bind failed, %s", strerror(errno));
close(udevsendsock);
return -1;
}
const char *udevd_expected_seqnum;
logging_init("udevd");
+ udev_init_config();
dbg("version %s", UDEV_VERSION);
if (getuid() != 0) {
- dbg("need to be root, exit");
+ err("need to be root, exit");
goto exit;
}
dbg("damonized fork running");
break;
case -1:
- dbg("fork of daemon failed");
+ err("fork of daemon failed");
goto exit;
default:
logging_close();
if (fd > 2)
close(fd);
} else
- dbg("error opening /dev/null %s", strerror(errno));
+ err("error opening /dev/null %s", strerror(errno));
/* setup signal handler pipe */
retval = pipe(pipefds);
if (retval < 0) {
- dbg("error getting pipes: %s", strerror(errno));
+ err("error getting pipes: %s", strerror(errno));
goto exit;
}
retval = fcntl(pipefds[0], F_SETFL, O_NONBLOCK);
if (retval < 0) {
- dbg("error fcntl on read pipe: %s", strerror(errno));
+ err("error fcntl on read pipe: %s", strerror(errno));
goto exit;
}
retval = fcntl(pipefds[0], F_SETFD, FD_CLOEXEC);
if (retval < 0)
- dbg("error fcntl on read pipe: %s", strerror(errno));
+ err("error fcntl on read pipe: %s", strerror(errno));
retval = fcntl(pipefds[1], F_SETFL, O_NONBLOCK);
if (retval < 0) {
- dbg("error fcntl on write pipe: %s", strerror(errno));
+ err("error fcntl on write pipe: %s", strerror(errno));
goto exit;
}
retval = fcntl(pipefds[1], F_SETFD, FD_CLOEXEC);
if (retval < 0)
- dbg("error fcntl on write pipe: %s", strerror(errno));
+ err("error fcntl on write pipe: %s", strerror(errno));
/* set signal handlers */
memset(&act, 0x00, sizeof(struct sigaction));
- act.sa_handler = (void (*) (int))sig_handler;
+ act.sa_handler = (void (*)(int)) sig_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
sigaction(SIGINT, &act, NULL);
/* possible override of udev binary, used for testing */
udev_bin = getenv("UDEV_BIN");
if (udev_bin != NULL)
- dbg("udev binary is set to '%s'", udev_bin);
+ info("udev binary is set to '%s'", udev_bin);
else
udev_bin = UDEV_BIN;
udevd_expected_seqnum = getenv("UDEVD_EXPECTED_SEQNUM");
if (udevd_expected_seqnum != NULL) {
expected_seqnum = strtoull(udevd_expected_seqnum, NULL, 10);
- dbg("initialize expected_seqnum to %llu", expected_seqnum);
+ info("initialize expected_seqnum to %llu", expected_seqnum);
}
/* get current time to provide shorter timeout on startup */
#ifdef USE_LOG
-void log_message (int level, const char *format, ...)
+void log_message (int priority, const char *format, ...)
{
va_list args;
+ if (priority > udev_log_priority)
+ return;
+
va_start(args, format);
- vsyslog(level, format, args);
+ vsyslog(priority, format, args);
va_end(args);
}
#endif
static int sock = -1;
#ifdef USE_LOG
-void log_message (int level, const char *format, ...)
+void log_message (int priority, const char *format, ...)
{
- va_list args;
+ va_list args;
+
+ if (priority > udev_log_priority)
+ return;
va_start(args, format);
- vsyslog(level, format, args);
+ vsyslog(priority, format, args);
va_end(args);
}
#endif
/* daemon with empty environment */
close(sock);
execve(UDEVD_BIN, argv, envp);
- dbg("exec of daemon failed");
+ err("exec of daemon failed");
_exit(1);
case -1:
- dbg("fork of daemon failed");
+ err("fork of daemon failed");
return -1;
default:
exit(0);
}
break;
case -1:
- dbg("fork of helper failed");
+ err("fork of helper failed");
return -1;
default:
waitpid(pid, NULL, 0);
case 0:
/* child */
execv(UDEV_BIN, argv);
- dbg("exec of child failed");
+ err("exec of udev child failed");
_exit(1);
break;
case -1:
- dbg("fork of child failed");
+ err("fork of udev child failed");
break;
default:
waitpid(pid, NULL, 0);
const char *subsystem = NULL;
logging_init("udevsend");
+#ifdef USE_LOG
+ udev_init_config();
+#endif
dbg("version %s", UDEV_VERSION);
sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (sock == -1) {
- dbg("error getting socket");
+ err("error getting socket");
goto fallback;
}
}
if (bufpos + keylen >= HOTPLUG_BUFFER_SIZE-1) {
- dbg("environment buffer too small, probably not called by the kernel");
+ err("environment buffer too small, probably not called by the kernel");
continue;
}
}
if (errno != ECONNREFUSED) {
- dbg("error sending message (%s)", strerror(errno));
+ err("error sending message (%s)", strerror(errno));
goto fallback;
}
if (!started_daemon) {
- dbg("try to start udevd daemon");
+ info("try to start udevd daemon");
retval = start_daemon();
if (retval) {
dbg("error starting daemon");
}
fallback:
- info("unable to connect to event daemon, try to call udev directly");
+ err("unable to connect to event daemon, try to call udev directly");
run_udev(subsystem);
exit:
#include "libsysfs/sysfs/libsysfs.h"
#include "udev_libc_wrapper.h"
#include "udev.h"
+#include "udev_version.h"
#include "logging.h"
#include "udev_rules.h"
#include "udev_utils.h"
#include "list.h"
#ifdef USE_LOG
-void log_message(int level, const char *format, ...)
+void log_message(int priority, const char *format, ...)
{
+ va_list args;
+
+ if (priority > udev_log_priority)
+ return;
+
+ va_start(args, format);
+ vsyslog(priority, format, args);
+ va_end(args);
}
#endif
{
struct sigaction act;
+ logging_init("udev");
udev_init_config();
+ /* disable all logging if not explicitely requested */
+ if (getenv("UDEV_LOG") == NULL)
+ udev_log_priority = 0;
+ dbg("version %s", UDEV_VERSION);
/* set signal handlers */
memset(&act, 0x00, sizeof(act));
udev_scan_block();
udev_scan_class();
+ logging_close();
return 0;
}
udevtest \- simulates a udev run to test the configured rules
.SH SYNOPSIS
.B udevtest
-.IR "sysfs_device_path " [ subsystem ]
+.I sysfs_device_path subsystem
.SH "DESCRIPTION"
.B udevtest
simulates a
#include <errno.h>
#include <ctype.h>
#include <signal.h>
+#include <syslog.h>
#include "libsysfs/sysfs/libsysfs.h"
#include "udev.h"
#ifdef USE_LOG
-void log_message (int level, const char *format, ...)
+void log_message (int priority, const char *format, ...)
{
va_list args;
+ if (priority > udev_log_priority)
+ return;
+
va_start(args, format);
vprintf(format, args);
va_end(args);
info("version %s", UDEV_VERSION);
- if (argc < 2 || argc > 3) {
- info("Usage: udevtest <devpath> [subsystem]");
+ if (argc != 3) {
+ info("Usage: udevtest <devpath> <subsystem>");
return 1;
}
/* initialize our configuration */
udev_init_config();
+ if (udev_log_priority < LOG_INFO)
+ udev_log_priority = LOG_INFO;
/* remove sysfs_path if given */
if (strncmp(argv[1], sysfs_path, strlen(sysfs_path)) == 0)