devd. A daemon that hooks into the kernel's /dev/devctl to produce

arbitrary commands when devices come and go in the device tree (which is
different than the /dev directory).

This is an initial version.  Much of the planned power isn't here.
Instead of doing the full matching, we always run /etc/devd-generic.
/etc/devd.generic will go away at some point, I think.

I'm committing it in this early state so I can start getting feedback
from early adapters.

Approved by: re
This commit is contained in:
Warner Losh 2002-10-20 22:15:17 +00:00
parent be36629d5c
commit e530e0446b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=105573
9 changed files with 852 additions and 0 deletions

16
sbin/devd/Makefile Normal file
View File

@ -0,0 +1,16 @@
# $FreeBSD$
PROG= devd
SRCS= devd.c token.l parse.y y.tab.h
MAN= devd.8
WARNS?= 5
DPADD= ${LIBL}
LDADD= -ll
YFLAGS+=-v
CFLAGS+=-I. -I${.CURDIR}
CLEANFILES= y.output
.include <bsd.prog.mk>

26
sbin/devd/devd-generic Normal file
View File

@ -0,0 +1,26 @@
#!/bin/sh
#
# $FreeBSD$
#
# Script called by devd(8) whenever a device appears or disappears.
#
# XXX this is a temporary hack that will go away soon
dev="$1"
startstop="$2"
driver="${dev%%[0-9]*}"
unit="${dev##*[^0-9]}"
if [ -z "$driver" -o -z "$unit" ]; then
echo "cannot parse device \"$dev\"" 1>&2
exit 1
fi
case "$driver" in
an|ar|awi|bge|cm|cnw|cs|dc|de|ed|el|em|ep|ex|fe|fxp|gem|gx|hme|ie|lge|lnc|my| \
nge|pcn|ray|rl|sf|sis|sk|sn|snc|ste|ti|tl|tx|txp|vr|vx|wb|wi|xe|xl)
# An ethernet interface; call pccard_ether to do the real work
/etc/pccard_ether "$dev" "$startstop"
;;
esac

88
sbin/devd/devd.8 Normal file
View File

@ -0,0 +1,88 @@
.\"
.\" Copyright (c) 2002 M. Warner Losh.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd October 17, 2002
.Dt DEVD 8
.Os
.Sh NAME
.Nm devd
.Nd "Device state change daemon"
.Sh SYNOPSIS
.Nm
.Op Fl d
.Sh DESCRIPTION
The
.Nm
daemon provides a way to have userland programs run when certain
kernel events happen.
.Pp
The following options are accepted.
.Bl -tag -width indent
.It Fl d
Enable debugging messages and run in the foreground instead of
becoming a daemon.
.El
.Sh IMPLEMENTATION NOTES
.Nm
is a system daemon.
It runs in the background all the time.
When ever a device is added to or removed from the device tree, devd
will cause a certain action to take place.
In addition, when a device that is not matched enters the system, devd
will also perform an action.
.Pp
.Nm
hooks into the
.Xr devctl 4
device driver.
This device driver has hooks into the device configuration system.
When nodes are added or deleted from the tree, this device will
deliver information about the even to
.Nm .
Once
.Nm
has parsed the message, it will search its action list for that kind
of event, and perform the action with the highest matching value.
For most mundane uses, the default handlers are adequate.
However, for more advanced users, the power is present to tweak every
aspect of what happens.
.Pp
.Nm reads /etc/devd.conf, and that drives the rest of the process.
While the format of this file is described in
.Xr devd.conf 5
some basics are covered here.
In the options section, one can define multiple directories to search
for config files.
All files in each of these directories are parsed.
These files are intended to be installed by third party vendors that
wish to hook into the devd system without modifying the user's other
config files.
.Sh SEE ALSO
.Xr devctl 4 ,
.Xr devd.conf 5
.Sh AUTHORS
.An M. Warner Losh

223
sbin/devd/devd.c Normal file
View File

@ -0,0 +1,223 @@
/*-
* Copyright (c) 2002 M. Warner Losh.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* DEVD control daemon.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <err.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "devd.h"
#define CF "/etc/devd.conf"
extern FILE *yyin;
extern int lineno;
int dflag;
int romeo_must_die = 0;
struct file_list_head dirlist = TAILQ_HEAD_INITIALIZER(dirlist);
static void event_loop(void);
static void parse(void);
static void parse_config_file(const char *fn);
static void parse_files_in_dir(const char *dirname);
static void reset_config(void);
static void usage(void);
void
add_directory(const char *dir)
{
struct file_list *elm;
elm = malloc(sizeof(*elm));
elm->path = strdup(dir);
TAILQ_INSERT_TAIL(&dirlist, elm, fl_link);
}
static void
reset_config(void)
{
struct file_list *flp;
TAILQ_FOREACH(flp, &dirlist, fl_link) {
free(flp->path);
free(flp);
}
}
static void
parse_config_file(const char *fn)
{
if (dflag)
printf("Parsing %s\n", fn);
yyin = fopen(fn, "r");
if (yyin == NULL)
err(1, "Cannot open config file %s", fn);
if (yyparse() != 0)
errx(1, "Cannot parse %s at line %d", fn, lineno);
fclose(yyin);
}
static void
parse_files_in_dir(const char *dirname)
{
DIR *dirp;
struct dirent *dp;
char path[PATH_MAX];
if (dflag)
printf("Parsing files in %s\n", dirname);
dirp = opendir(dirname);
if (dirp == NULL)
return;
readdir(dirp); /* Skip . */
readdir(dirp); /* Skip .. */
while ((dp = readdir(dirp)) != NULL) {
if (strcmp(dp->d_name + dp->d_namlen - 5, ".conf") == 0) {
snprintf(path, sizeof(path), "%s/%s",
dirname, dp->d_name);
parse_config_file(path);
}
}
}
static void
parse(void)
{
struct file_list *flp;
parse_config_file(CF);
TAILQ_FOREACH(flp, &dirlist, fl_link) {
parse_files_in_dir(flp->path);
}
}
static void
process_event(const char *buffer)
{
char type;
char cmd[1024];
char *sp;
// Ignore unknown devices for now.
if (*buffer == '?')
return;
type = *buffer++;
sp = strchr(buffer, ' ');
if (sp == NULL)
return; /* Can't happen? */
*sp = '\0';
snprintf(cmd, sizeof(cmd), "/etc/devd-generic %s %s", buffer,
type == '+' ? "start" : "stop");
if (dflag)
printf("Trying '%s'\n", cmd);
system(cmd);
}
static void
event_loop(void)
{
int rv;
int fd;
char buffer[1024 + 1]; /* XXX */
fd = open("/dev/devctl", O_RDONLY); /* XXX */
if (fd == -1)
err(1, "Can't open devctl");
if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0)
err(1, "Can't set close-on-exec flag");
while (1) {
if (romeo_must_die)
break;
rv = read(fd, buffer, sizeof(buffer) - 1);
if (rv > 0) {
buffer[rv] = '\0';
while (buffer[--rv] == '\n')
buffer[rv] = '\0';
process_event(buffer);
} else if (rv < 0) {
if (errno != EINTR)
break;
} else {
/* EOF */
break;
}
}
close(fd);
}
static void
gensighand(int foo __unused)
{
romeo_must_die++;
}
static void
usage()
{
fprintf(stderr, "usage: %s [-d]", getprogname());
exit(1);
}
int
main(int argc, char **argv)
{
int ch;
while ((ch = getopt(argc, argv, "d")) != -1) {
switch (ch) {
case 'd':
dflag++;
break;
default:
usage();
}
}
reset_config();
parse();
if (!dflag)
daemon(0, 0);
event_loop();
signal(SIGHUP, gensighand);
signal(SIGINT, gensighand);
signal(SIGTERM, gensighand);
return (0);
}

92
sbin/devd/devd.conf Normal file
View File

@ -0,0 +1,92 @@
// $FreeBSD$
//
// Refer to devd.conf(5) and devd(8) man pages for the details on how to
// run and configure devd.
//
// NB: All regular expressions have an implicit ^$ around them.
options {
// Each directory directive adds a directory the list of directories
// that we scan for files. Files are read-in in the order that they
// are returned from readdir(3). The rule-sets are combined to
// create a DFA that's used to match events to actions.
directory "/etc/devd";
directory "/usr/local/etc/devd";
pid-file "/var/run/devd.pid";
// Setup some shorthand for regex that we use later in the file.
set ethernet-nic-regex
"(an|ar|aue|awi|bge|cm|cnw|cs|cue|dc|de|ed|el|em|ep|ex|\
fe|fxp|gem|gx|hme|ie|kue|lge|lnc|my|nge|pcn|ray|rl|\
sf|sis|sk|sn|snc|ste|ti|tl|tx|txp|vr|vx|wb|wi|xe|xl)[0-9]+";
set scsi-controller-regex
"(adv|advw|aic|aha|ahb|ahc|ahd|bt|ct|iir|isp|mly|mpt|ncv|nsp|\
stg|sym|wds)[0-9]+";
};
// Note that the attach/detach with the highest value wins, so that one can
// override these general rules.
// NB: device-name is shorthand for 'match device-name'
//
// For ethernet like devices, the default is to run dhclient. Due to
// a historical accident, the name of this script it called pccard_ether
//
attach 0 {
device-name "$ethernet-nic-regex";
action "/etc/pccard_ether $device-name start";
};
detach 0 {
device-name "$ethernet-nic-regex";
action "/etc/pccard_ether $device-name stop";
};
// An entry like this might be in a different file, but is included here
// as an example of how to override things. Normally 'ed20' would match
// the above attach/detach stuff, but the value of 100 makes it
// ed20 is hard wired to 1.2.3.4
attach 100 {
device-name "ed20";
action "ifconfig $device-name inet 1.2.3.4 netmask 0xffff0000";
};
detach 100 {
device-name "ed20";
};
//
// Rescan scsi device-names on attach, but not detach.
//
attach 0 {
device-name "$scsi-controller-regex";
action "camcontrol rescan all";
};
// Don't even try to second guess what to do about drivers that don't
// match here. Instead, pass it off to a smart script to deal.
nomatch 0 {
action "/usr/local/bin/smart-loader $pnpinfo $location $bus";
};
// The following might be an example of something that a vendor might
// install if you were to add their device. This might reside in
// /usr/local/etc/devd/deqna.conf. A deqna is, in this hypothetical
// example, a pccard ethernet-like device. Students of history may
// know other devices by this name, and will get the in-jokes in this
// entry.
nomatch 10 {
match "bus" "pccard[0-9]+";
match "manufacturer" "0x1234";
match "product" "0x2323";
action "kldload if_deqna";
};
attach 10 {
device-name "^deqna[0-9]+";
action "/etc/pccard_ether $device-name start";
};
detach 10 {
device-name "^deqna[0-9]+";
action "/etc/pccard_ether $device-name stop";
};

133
sbin/devd/devd.conf.5 Normal file
View File

@ -0,0 +1,133 @@
.\"
.\" Copyright (c) 2002 M. Warner Losh
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.\" The section on comments was taken from named.conf.5, which has the
.\" following copyright:
.\" Copyright (c) 1999-2000 by Internet Software Consortium
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
.\" ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
.\" CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
.\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
.\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
.\" SOFTWARE.
.Dd October 17, 2002
.Dt DEVD.CONF 5
.Os
.Sh NAME
.Nm devd.conf
.Nd configuration file for
.Xr devdd 8
.Sh OVERVIEW
.Ss General Syntax
A
.Xr devd 8
configuration consists of two general features, statements
and comments.
All statements end with a semicolon.
Many statements can contain substatements, which are each also
terminated with a semicolon.
.Pp
The following statements are supported:
.Bl -tag -width 0n
.It Ic options
specifies various options and parameters for the operation of
.Xr devd 8 .
.It Ic attach
specifies various matching criteria and actions to perform when
a newly attached device matches said criteria.
.It Ic detach
specifies various matching criteria and actions to perform when
a newly attached device matches said criteria.
.It Ic nomatch
specifies various matching criteria and actions to perform when
no device driver currently loaded in the kernel claims a (new)
device.
.El
.Pp
Statements may occur in any order in the config file, and may be
repated as often as required.
Further details on the syntax and meaning of each statement, and their
substatements is explained below.
.Pp
Comments may appear anywhere that whitespace may appear in a BIND
configuration file. To appeal to programmers of all kinds, they can
be written in C, C++, or shell/perl constructs.
.Pp
C-style comments start with the two characters
.Li /*
(slash, star) and end with
.Li */
(star, slash).
Because they are completely delimited with these characters,
they can be used to comment only a portion of a line or to span
multiple lines.
.Pp
C-style comments cannot be nested. For example, the following is
not valid because the entire comment ends with the first
.Li */ :
.Bd -literal -offset indent
/* This is the start of a comment.
This is still part of the comment.
/* This is an incorrect attempt at nesting a comment. */
This is no longer in any comment. */
.Ed
.Pp
C++-style comments start with the two characters
.Li //
(slash, slash) and continue to the end of the physical line.
They cannot be continued across multiple physical lines; to have
one logical comment span multiple lines, each line must use the
.Li //
pair. For example:
.Bd -literal -offset indent
// This is the start of a comment. The next line
// is a new comment, even though it is logically
// part of the previous comment.
.Ed
.Pp
.Em WARNING :
you cannot use the
.Li ;
(semicolon) character to start a comment such as you would in a zone
file. The semicolon indicates the end of a configuration statement,
so whatever follows it will be interpreted as the start of the next
statement.
.Sh FILES
.Bl -tag -width 0n -compact
.It Pa /etc/devd.conf
The
.Nm devd
configuration file.
.El
.Sh SEE ALSO
.Xr devd 8

48
sbin/devd/devd.h Normal file
View File

@ -0,0 +1,48 @@
/*-
* DEVD (Device action daemon)
*
* Copyright (c) 2002 M. Warner Losh <imp@freebsd.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/queue.h>
int yylex(void);
void yyerror(const char *s);
int yyparse(void);
void add_directory(const char *);
struct file_list
{
char *path;
TAILQ_ENTRY(file_list) fl_link;
};
TAILQ_HEAD(file_list_head, file_list);
extern struct file_list_head dirlist;

137
sbin/devd/parse.y Normal file
View File

@ -0,0 +1,137 @@
%{
/*-
* DEVD (Device action daemon)
*
* Copyright (c) 2002 M. Warner Losh <imp@freebsd.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "devd.h"
#include <stdio.h>
%}
%union {
char *str;
int i;
}
%token SEMICOLON BEGINBLOCK ENDBLOCK COMMA
%token <i> NUMBER
%token <str> STRING
%token <str> ID
%token OPTIONS SET DIRECTORY PID_FILE DEVICE_NAME ACTION MATCH
%token ATTACH DETACH NOMATCH
%type <str> id
%type <i> number
%type <str> string
%%
config_file
: config_list
;
config_list
: config
| config_list config
;
config
: option_block
| attach_block
| detach_block
| nomatch_block
;
option_block
: OPTIONS BEGINBLOCK options ENDBLOCK SEMICOLON
;
options
: option
| options option
option
: directory_option
| pid_file_option
| set_option
;
directory_option
: DIRECTORY string SEMICOLON { add_directory($2); }
;
pid_file_option
: PID_FILE string SEMICOLON
;
set_option
: SET id string SEMICOLON
;
attach_block
: ATTACH number BEGINBLOCK match_or_action_list ENDBLOCK SEMICOLON
;
detach_block
: DETACH number BEGINBLOCK match_or_action_list ENDBLOCK SEMICOLON
;
nomatch_block
: NOMATCH number BEGINBLOCK match_or_action_list ENDBLOCK SEMICOLON
;
match_or_action_list
: match_or_action
| match_or_action_list match_or_action
;
match_or_action
: match
| action
;
match
: MATCH string string SEMICOLON
| DEVICE_NAME string SEMICOLON
;
action
: ACTION string SEMICOLON
;
number
: NUMBER { $$ = $1; }
string
: STRING { $$ = $1; }
id
: ID { $$ = $1; }
%%

89
sbin/devd/token.l Normal file
View File

@ -0,0 +1,89 @@
%{
/*-
* DEVD (Device action daemon)
*
* Copyright (c) 2002 M. Warner Losh <imp@freebsd.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include "devd.h"
#include "y.tab.h"
int lineno = 1;
#define YY_NO_UNPUT
%}
%%
[ \t]+ ;
\n lineno++;
; { return SEMICOLON; }
\/\/.*$ ;
\/\*(.|\n)*\*\/ ;
\{ { return BEGINBLOCK; }
\} { return ENDBLOCK; }
[0-9]+ { yylval.i = atoi(yytext); return NUMBER; }
\"[^"]+\" {
int len = strlen(yytext) - 2;
if ((yylval.str = (char *) malloc(len + 1)) == NULL)
goto out;
memcpy(yylval.str, yytext + 1, len);
yylval.str[len] = '\0';
out:;
return STRING;
}
options { return OPTIONS; }
set { return SET; }
directory { return DIRECTORY; }
pid-file { return PID_FILE; }
attach { return ATTACH; }
detach { return DETACH; }
device-name { return DEVICE_NAME; }
action { return ACTION; }
match { return MATCH; }
nomatch { return NOMATCH; }
[A-Za-z][A-Za-z0-9-]* {
int len = strlen(yytext);
if ((yylval.str = (char *) malloc(len + 1)) == NULL)
goto out2;
memcpy(yylval.str, yytext + 1, len);
yylval.str[len] = '\0';
out2:;
return ID;
}
%%
void
yyerror(const char *s)
{
syslog(LOG_ERR, "line %d: %s%s %s.\n", lineno, yytext, yytext?":":"", s);
}