[Glibc-bsd-commits] r2930 - in trunk/freebsd-utils/debian: . patches
Aurelien Jarno
aurel32 at alioth.debian.org
Sat Jan 16 11:05:31 UTC 2010
Author: aurel32
Date: 2010-01-16 11:05:29 +0000 (Sat, 16 Jan 2010)
New Revision: 2930
Added:
trunk/freebsd-utils/debian/patches/000_acpiconf_sources.diff
trunk/freebsd-utils/debian/patches/000_devd_sources.diff
trunk/freebsd-utils/debian/patches/022_devd.diff
trunk/freebsd-utils/debian/patches/023_acpiconf.diff
Modified:
trunk/freebsd-utils/debian/changelog
trunk/freebsd-utils/debian/copyright
trunk/freebsd-utils/debian/freebsd-utils.install
trunk/freebsd-utils/debian/freebsd-utils.manpages
trunk/freebsd-utils/debian/patches/series
trunk/freebsd-utils/debian/rules
Log:
* Add acpiconf and devd binaries, patch by Werner Koch.
Modified: trunk/freebsd-utils/debian/changelog
===================================================================
--- trunk/freebsd-utils/debian/changelog 2010-01-15 15:23:31 UTC (rev 2929)
+++ trunk/freebsd-utils/debian/changelog 2010-01-16 11:05:29 UTC (rev 2930)
@@ -1,3 +1,9 @@
+freebsd-utils (8.0-3) UNRELEASED; urgency=low
+
+ * Add acpiconf and devd binaries, patch by Werner Koch.
+
+ -- Aurelien Jarno <aurel32 at debian.org> Sat, 16 Jan 2010 10:51:34 +0100
+
freebsd-utils (8.0-2) unstable; urgency=low
* freebsd-utils.init: fix quoting, and use a symbolic links instead
Modified: trunk/freebsd-utils/debian/copyright
===================================================================
--- trunk/freebsd-utils/debian/copyright 2010-01-15 15:23:31 UTC (rev 2929)
+++ trunk/freebsd-utils/debian/copyright 2010-01-16 11:05:29 UTC (rev 2930)
@@ -2767,3 +2767,82 @@
Polytechnic Institute of Grenoble and University Joseph Fourier.
The research unit in Software, Systems, Networks (LSR) is member of IMAG.
+ --
+
+ Copyright (c) 2002-2003 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.
+
+ --
+
+ Copyright (c) 1999 Mitsuru IWASAKI <iwasaki at 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.
+
+ --
+
+ Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
+ 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
+ in this position and unchanged.
+ 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.
+ 3. 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 ``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 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.
Modified: trunk/freebsd-utils/debian/freebsd-utils.install
===================================================================
--- trunk/freebsd-utils/debian/freebsd-utils.install 2010-01-15 15:23:31 UTC (rev 2929)
+++ trunk/freebsd-utils/debian/freebsd-utils.install 2010-01-16 11:05:29 UTC (rev 2930)
@@ -25,3 +25,7 @@
sbin/mount_reiserfs/mount_reiserfs /sbin
sbin/mount_udf/mount_udf /sbin
sbin/mount_unionfs/mount_unionfs /sbin
+sbin/devd/devd /sbin
+
+usr.sbin/acpi/acpiconf/acpiconf /usr/sbin
+
Modified: trunk/freebsd-utils/debian/freebsd-utils.manpages
===================================================================
--- trunk/freebsd-utils/debian/freebsd-utils.manpages 2010-01-15 15:23:31 UTC (rev 2929)
+++ trunk/freebsd-utils/debian/freebsd-utils.manpages 2010-01-16 11:05:29 UTC (rev 2930)
@@ -19,4 +19,8 @@
sbin/swapon/swapon.8
sbin/sysctl/sysctl.8
sbin/umount/umount.8
+sbin/devd/devd.8
+sbin/devd/devd.conf.5
+usr.sbin/acpi/acpiconf/acpiconf.8
+
Added: trunk/freebsd-utils/debian/patches/000_acpiconf_sources.diff
===================================================================
--- trunk/freebsd-utils/debian/patches/000_acpiconf_sources.diff (rev 0)
+++ trunk/freebsd-utils/debian/patches/000_acpiconf_sources.diff 2010-01-16 11:05:29 UTC (rev 2930)
@@ -0,0 +1,342 @@
+# This patch should be removed when a new tarball is created
+
+diff -Nurd a/usr.sbin/acpi/acpiconf/acpiconf.8 b/usr.sbin/acpi/acpiconf/acpiconf.8
+--- a/usr.sbin/acpi/acpiconf/acpiconf.8 1970-01-01 01:00:00.000000000 +0100
++++ b/usr.sbin/acpi/acpiconf/acpiconf.8 2005-02-09 19:07:17.000000000 +0100
+@@ -0,0 +1,92 @@
++.\"-
++.\" Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
++.\" 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
++.\" in this position and unchanged.
++.\" 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.
++.\" 3. 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 ``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 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 August 16, 2004
++.Dt ACPICONF 8
++.Os
++.Sh NAME
++.Nm acpiconf
++.Nd control ACPI power management
++.Sh SYNOPSIS
++.Nm
++.Op Fl h
++.Op Fl i Ar batt
++.Op Fl s Ar type
++.Sh DESCRIPTION
++The
++.Nm
++utility allows the user control of the ACPI power management
++functions.
++The following command-line options are recognized:
++.Bl -tag -width ".Fl s Ar type"
++.It Fl h
++Displays a summary of available options.
++.It Fl i Ar batt
++Get design information about the specified battery.
++.It Fl s Ar type
++Enters the specified sleep mode.
++Recognized types are
++.Cm 1
++(only the CPU clock is stopped),
++.Cm 2
++(not implemented on most systems but similar to S1),
++.Cm 3
++(the CPU context is lost and memory context is preserved),
++.Cm 4
++(the CPU context is lost and memory context is stored to disk)
++and
++.Cm 5
++(soft off).
++Sleep states may also be given as S1, S2, etc.
++The supported states depend on BIOS implementation, including ACPI
++byte code (AML).
++If the
++.Pa /etc/rc.suspend
++and
++.Pa /etc/rc.resume
++scripts are executable, they will be run before and after entering
++the given sleep state.
++.El
++.Sh SEE ALSO
++.Xr acpi 4 ,
++.Xr acpidump 8 ,
++.Xr apm 8
++.Sh HISTORY
++The
++.Nm
++utility appeared in
++.Fx 5.0 .
++.Sh AUTHORS
++.An -nosplit
++The
++.Nm
++utility was written by
++.An Mitsuru Iwasaki Aq iwasaki at FreeBSD.org .
++This manual page was written by
++.An Dag-Erling Sm\(/orgrav Aq des at FreeBSD.org .
+diff -Nurd a/usr.sbin/acpi/acpiconf/acpiconf.c b/usr.sbin/acpi/acpiconf/acpiconf.c
+--- a/usr.sbin/acpi/acpiconf/acpiconf.c 1970-01-01 01:00:00.000000000 +0100
++++ b/usr.sbin/acpi/acpiconf/acpiconf.c 2009-06-05 20:50:45.000000000 +0200
+@@ -0,0 +1,228 @@
++/*-
++ * Copyright (c) 1999 Mitsuru IWASAKI <iwasaki at 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.
++ *
++ * $Id: acpiconf.c,v 1.5 2000/08/08 14:12:19 iwasaki Exp $
++ * $FreeBSD$
++ */
++
++#include <sys/param.h>
++
++#include <err.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <sys/ioctl.h>
++#include <sysexits.h>
++#include <unistd.h>
++
++#include <dev/acpica/acpiio.h>
++
++#include <contrib/dev/acpica/include/acpi.h>
++
++#define ACPIDEV "/dev/acpi"
++
++static int acpifd;
++
++static void
++acpi_init(void)
++{
++ acpifd = open(ACPIDEV, O_RDWR);
++ if (acpifd == -1)
++ acpifd = open(ACPIDEV, O_RDONLY);
++ if (acpifd == -1)
++ err(EX_OSFILE, ACPIDEV);
++}
++
++/* Prepare to sleep and then wait for the signal that sleeping can occur. */
++static void
++acpi_sleep(int sleep_type)
++{
++ int ret;
++
++ /* Notify OS that we want to sleep. devd(8) gets this notify. */
++ ret = ioctl(acpifd, ACPIIO_REQSLPSTATE, &sleep_type);
++ if (ret != 0)
++ err(EX_IOERR, "request sleep type (%d) failed", sleep_type);
++}
++
++/* Ack or abort a pending suspend request. */
++static void
++acpi_sleep_ack(int err_val)
++{
++ int ret;
++
++ ret = ioctl(acpifd, ACPIIO_ACKSLPSTATE, &err_val);
++ if (ret != 0)
++ err(EX_IOERR, "ack sleep type failed");
++}
++
++/* should be a acpi define, but doesn't appear to be */
++#define UNKNOWN_CAP 0xffffffff
++#define UNKNOWN_VOLTAGE 0xffffffff
++
++static int
++acpi_battinfo(int num)
++{
++ union acpi_battery_ioctl_arg battio;
++ const char *pwr_units;
++ int hours, min;
++
++ if (num < 0 || num > 64)
++ err(EX_USAGE, "invalid battery %d", num);
++
++ /* Print battery design information. */
++ battio.unit = num;
++ if (ioctl(acpifd, ACPIIO_BATT_GET_BIF, &battio) == -1)
++ err(EX_IOERR, "get battery info (%d) failed", num);
++ if (battio.bif.units == 0)
++ pwr_units = "mW";
++ else
++ pwr_units = "mA";
++
++ if (battio.bif.dcap == UNKNOWN_CAP)
++ printf("Design capacity:\tunknown\n");
++ else
++ printf("Design capacity:\t%d %sh\n", battio.bif.dcap,
++ pwr_units);
++ if (battio.bif.lfcap == UNKNOWN_CAP)
++ printf("Last full capacity:\tunknown\n");
++ else
++ printf("Last full capacity:\t%d %sh\n", battio.bif.lfcap,
++ pwr_units);
++ printf("Technology:\t\t%s\n", battio.bif.btech == 0 ?
++ "primary (non-rechargeable)" : "secondary (rechargeable)");
++ if (battio.bif.dvol == UNKNOWN_CAP)
++ printf("Design voltage:\t\tunknown\n");
++ else
++ printf("Design voltage:\t\t%d mV\n", battio.bif.dvol);
++ printf("Capacity (warn):\t%d %sh\n", battio.bif.wcap, pwr_units);
++ printf("Capacity (low):\t\t%d %sh\n", battio.bif.lcap, pwr_units);
++ printf("Low/warn granularity:\t%d %sh\n", battio.bif.gra1, pwr_units);
++ printf("Warn/full granularity:\t%d %sh\n", battio.bif.gra2, pwr_units);
++ printf("Model number:\t\t%s\n", battio.bif.model);
++ printf("Serial number:\t\t%s\n", battio.bif.serial);
++ printf("Type:\t\t\t%s\n", battio.bif.type);
++ printf("OEM info:\t\t%s\n", battio.bif.oeminfo);
++
++ /* Print current battery state information. */
++ battio.unit = num;
++ if (ioctl(acpifd, ACPIIO_BATT_GET_BATTINFO, &battio) == -1)
++ err(EX_IOERR, "get battery user info (%d) failed", num);
++ if (battio.battinfo.state != ACPI_BATT_STAT_NOT_PRESENT) {
++ printf("State:\t\t\t");
++ if (battio.battinfo.state == 0)
++ printf("high ");
++ if (battio.battinfo.state & ACPI_BATT_STAT_CRITICAL)
++ printf("critical ");
++ if (battio.battinfo.state & ACPI_BATT_STAT_DISCHARG)
++ printf("discharging ");
++ if (battio.battinfo.state & ACPI_BATT_STAT_CHARGING)
++ printf("charging ");
++ printf("\n");
++ if (battio.battinfo.cap == -1)
++ printf("Remaining capacity:\tunknown\n");
++ else
++ printf("Remaining capacity:\t%d%%\n",
++ battio.battinfo.cap);
++ if (battio.battinfo.min == -1)
++ printf("Remaining time:\t\tunknown\n");
++ else {
++ hours = battio.battinfo.min / 60;
++ min = battio.battinfo.min % 60;
++ printf("Remaining time:\t\t%d:%02d\n", hours, min);
++ }
++ if (battio.battinfo.rate == -1)
++ printf("Present rate:\t\tunknown\n");
++ else
++ printf("Present rate:\t\t%d %s\n",
++ battio.battinfo.rate, pwr_units);
++ } else
++ printf("State:\t\t\tnot present\n");
++
++ /* Print battery voltage information. */
++ battio.unit = num;
++ if (ioctl(acpifd, ACPIIO_BATT_GET_BST, &battio) == -1)
++ err(EX_IOERR, "get battery status (%d) failed", num);
++ if (battio.bst.state != ACPI_BATT_STAT_NOT_PRESENT) {
++ if (battio.bst.volt == UNKNOWN_VOLTAGE)
++ printf("Voltage:\t\tunknown\n");
++ else
++ printf("Voltage:\t\t%d mV\n", battio.bst.volt);
++ }
++
++ return (0);
++}
++
++static void
++usage(const char* prog)
++{
++ printf("usage: %s [-h] [-i batt] [-k ack] [-s 1-4]\n", prog);
++ exit(0);
++}
++
++int
++main(int argc, char *argv[])
++{
++ char c, *prog;
++ int sleep_type;
++
++ prog = argv[0];
++ if (argc < 2)
++ usage(prog);
++ /* NOTREACHED */
++
++ sleep_type = -1;
++ acpi_init();
++ while ((c = getopt(argc, argv, "hi:k:s:")) != -1) {
++ switch (c) {
++ case 'i':
++ acpi_battinfo(atoi(optarg));
++ break;
++ case 'k':
++ acpi_sleep_ack(atoi(optarg));
++ break;
++ case 's':
++ if (optarg[0] == 'S')
++ sleep_type = optarg[1] - '0';
++ else
++ sleep_type = optarg[0] - '0';
++ if (sleep_type < 1 || sleep_type > 4)
++ errx(EX_USAGE, "invalid sleep type (%d)",
++ sleep_type);
++ break;
++ case 'h':
++ default:
++ usage(prog);
++ /* NOTREACHED */
++ }
++ }
++ argc -= optind;
++ argv += optind;
++
++ if (sleep_type != -1)
++ acpi_sleep(sleep_type);
++
++ close(acpifd);
++ exit (0);
++}
+diff -Nurd a/usr.sbin/acpi/acpiconf/Makefile b/usr.sbin/acpi/acpiconf/Makefile
+--- a/usr.sbin/acpi/acpiconf/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ b/usr.sbin/acpi/acpiconf/Makefile 2004-11-13 02:54:22.000000000 +0100
+@@ -0,0 +1,8 @@
++# $Id: Makefile,v 1.2 2000/07/14 18:16:25 iwasaki Exp $
++# $FreeBSD$
++
++PROG= acpiconf
++MAN= acpiconf.8
++WARNS?= 6
++
++.include <bsd.prog.mk>
Added: trunk/freebsd-utils/debian/patches/000_devd_sources.diff
===================================================================
--- trunk/freebsd-utils/debian/patches/000_devd_sources.diff (rev 0)
+++ trunk/freebsd-utils/debian/patches/000_devd_sources.diff 2010-01-16 11:05:29 UTC (rev 2930)
@@ -0,0 +1,2157 @@
+# This patch should be removed when a new tarball is created
+
+diff -Nurd a/sbin/devd/devd.8 b/sbin/devd/devd.8
+--- a/sbin/devd/devd.8 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/devd.8 2006-09-18 00:49:26.000000000 +0200
+@@ -0,0 +1,147 @@
++.\"
++.\" 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 November 24, 2005
++.Dt DEVD 8
++.Os
++.Sh NAME
++.Nm devd
++.Nd "device state change daemon"
++.Sh SYNOPSIS
++.Nm
++.Op Fl Ddn
++.Op Fl f Ar file
++.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 ".Fl f Ar file"
++.It Fl D
++Enable debugging messages.
++.It Fl d
++Run in the foreground instead of becoming a daemon.
++.It Fl f Ar file
++Use configuration file
++.Ar file
++instead of the default
++.Pa /etc/devd.conf .
++If option
++.Fl f
++is specified more than once, the last file specified is used.
++.It Fl n
++Do not process all pending events before becoming a daemon.
++Instead, call daemon right away.
++.El
++.Sh IMPLEMENTATION NOTES
++The
++.Nm
++utility
++is a system daemon that runs in the background all the time.
++Whenever a device is added to or removed from the device tree,
++.Nm
++will execute actions specified in
++.Xr devd.conf 5 .
++For example,
++.Nm
++might execute
++.Xr dhclient 8
++when an Ethernet adapter is added to the system, and kill the
++.Xr dhclient 8
++instance when the same adapter is removed.
++Another example would be for
++.Nm
++to use a table to locate and load via
++.Xr kldload 8
++the proper driver for an unrecognized device that is added to the system.
++.Pp
++The
++.Nm
++utility
++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 event 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
++The
++.Nm
++utility
++reads
++.Pa /etc/devd.conf
++or the alternate configuration file specified with a
++.Fl f
++option and uses that file to drive 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
++.Ic options
++section, one can define multiple directories to search
++for config files.
++All files in these directories whose names match the pattern
++.Pa *.conf
++are parsed.
++These files are intended to be installed by third party vendors that
++wish to hook into the
++.Nm
++system without modifying the user's other
++config files.
++.Pp
++All messages that
++.Nm
++receives are forwarded to the
++.Ux
++domain socket at
++.Pa /var/run/devd.pipe .
++.Sh FILES
++.Bl -tag -width ".Pa /var/run/devd.pipe" -compact
++.It Pa /etc/devd.conf
++The default
++.Nm
++configuration file.
++.It Pa /var/run/devd.pipe
++The socket used by
++.Nm
++to communicate with its clients.
++.El
++.Sh SEE ALSO
++.Xr devctl 4 ,
++.Xr devd.conf 5
++.Sh AUTHORS
++.An M. Warner Losh
+diff -Nurd a/sbin/devd/devd.cc b/sbin/devd/devd.cc
+--- a/sbin/devd/devd.cc 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/devd.cc 2008-12-14 12:48:51.000000000 +0100
+@@ -0,0 +1,965 @@
++/*-
++ * Copyright (c) 2002-2003 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.
++ */
++
++// TODO list:
++// o devd.conf and devd man pages need a lot of help:
++// - devd needs to document the unix domain socket
++// - devd.conf needs more details on the supported statements.
++
++#include <sys/cdefs.h>
++__FBSDID("$FreeBSD$");
++
++#include <sys/param.h>
++#include <sys/socket.h>
++#include <sys/stat.h>
++#include <sys/sysctl.h>
++#include <sys/types.h>
++#include <sys/un.h>
++
++#include <ctype.h>
++#include <dirent.h>
++#include <errno.h>
++#include <err.h>
++#include <fcntl.h>
++#include <libutil.h>
++#include <regex.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <algorithm>
++#include <map>
++#include <string>
++#include <list>
++#include <vector>
++
++#include "devd.h" /* C compatible definitions */
++#include "devd.hh" /* C++ class definitions */
++
++#define PIPE "/var/run/devd.pipe"
++#define CF "/etc/devd.conf"
++#define SYSCTL "hw.bus.devctl_disable"
++
++using namespace std;
++
++extern FILE *yyin;
++extern int lineno;
++
++static const char notify = '!';
++static const char nomatch = '?';
++static const char attach = '+';
++static const char detach = '-';
++
++static struct pidfh *pfh;
++
++int Dflag;
++int dflag;
++int nflag;
++int romeo_must_die = 0;
++
++static const char *configfile = CF;
++
++static void event_loop(void);
++static void usage(void);
++
++template <class T> void
++delete_and_clear(vector<T *> &v)
++{
++ typename vector<T *>::const_iterator i;
++
++ for (i = v.begin(); i != v.end(); i++)
++ delete *i;
++ v.clear();
++}
++
++config cfg;
++
++event_proc::event_proc() : _prio(-1)
++{
++ // nothing
++}
++
++event_proc::~event_proc()
++{
++ delete_and_clear(_epsvec);
++}
++
++void
++event_proc::add(eps *eps)
++{
++ _epsvec.push_back(eps);
++}
++
++bool
++event_proc::matches(config &c)
++{
++ vector<eps *>::const_iterator i;
++
++ for (i = _epsvec.begin(); i != _epsvec.end(); i++)
++ if (!(*i)->do_match(c))
++ return (false);
++ return (true);
++}
++
++bool
++event_proc::run(config &c)
++{
++ vector<eps *>::const_iterator i;
++
++ for (i = _epsvec.begin(); i != _epsvec.end(); i++)
++ if (!(*i)->do_action(c))
++ return (false);
++ return (true);
++}
++
++action::action(const char *cmd)
++ : _cmd(cmd)
++{
++ // nothing
++}
++
++action::~action()
++{
++ // nothing
++}
++
++bool
++action::do_action(config &c)
++{
++ string s = c.expand_string(_cmd);
++ if (Dflag)
++ fprintf(stderr, "Executing '%s'\n", s.c_str());
++ ::system(s.c_str());
++ return (true);
++}
++
++match::match(config &c, const char *var, const char *re)
++ : _var(var)
++{
++ string pattern = re;
++ _re = "^";
++ _re.append(c.expand_string(string(re)));
++ _re.append("$");
++ regcomp(&_regex, _re.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE);
++}
++
++match::~match()
++{
++ regfree(&_regex);
++}
++
++bool
++match::do_match(config &c)
++{
++ string value = c.get_variable(_var);
++ bool retval;
++
++ if (Dflag)
++ fprintf(stderr, "Testing %s=%s against %s\n", _var.c_str(),
++ value.c_str(), _re.c_str());
++
++ retval = (regexec(&_regex, value.c_str(), 0, NULL, 0) == 0);
++ return retval;
++}
++
++#include <sys/sockio.h>
++#include <net/if.h>
++#include <net/if_media.h>
++
++media::media(config &, const char *var, const char *type)
++ : _var(var), _type(-1)
++{
++ static struct ifmedia_description media_types[] = {
++ { IFM_ETHER, "Ethernet" },
++ { IFM_TOKEN, "Tokenring" },
++ { IFM_FDDI, "FDDI" },
++ { IFM_IEEE80211, "802.11" },
++ { IFM_ATM, "ATM" },
++ { IFM_CARP, "CARP" },
++ { -1, "unknown" },
++ { 0, NULL },
++ };
++ for (int i = 0; media_types[i].ifmt_string != NULL; i++)
++ if (strcasecmp(type, media_types[i].ifmt_string) == 0) {
++ _type = media_types[i].ifmt_word;
++ break;
++ }
++}
++
++media::~media()
++{
++}
++
++bool
++media::do_match(config &c)
++{
++ string value;
++ struct ifmediareq ifmr;
++ bool retval;
++ int s;
++
++ // Since we can be called from both a device attach/detach
++ // context where device-name is defined and what we want,
++ // as well as from a link status context, where subsystem is
++ // the name of interest, first try device-name and fall back
++ // to subsystem if none exists.
++ value = c.get_variable("device-name");
++ if (value.length() == 0)
++ value = c.get_variable("subsystem");
++ if (Dflag)
++ fprintf(stderr, "Testing media type of %s against 0x%x\n",
++ value.c_str(), _type);
++
++ retval = false;
++
++ s = socket(PF_INET, SOCK_DGRAM, 0);
++ if (s >= 0) {
++ memset(&ifmr, 0, sizeof(ifmr));
++ strncpy(ifmr.ifm_name, value.c_str(), sizeof(ifmr.ifm_name));
++
++ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0 &&
++ ifmr.ifm_status & IFM_AVALID) {
++ if (Dflag)
++ fprintf(stderr, "%s has media type 0x%x\n",
++ value.c_str(), IFM_TYPE(ifmr.ifm_active));
++ retval = (IFM_TYPE(ifmr.ifm_active) == _type);
++ } else if (_type == -1) {
++ if (Dflag)
++ fprintf(stderr, "%s has unknown media type\n",
++ value.c_str());
++ retval = true;
++ }
++ close(s);
++ }
++
++ return retval;
++}
++
++const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_";
++const string var_list::nothing = "";
++
++const string &
++var_list::get_variable(const string &var) const
++{
++ map<string, string>::const_iterator i;
++
++ i = _vars.find(var);
++ if (i == _vars.end())
++ return (var_list::bogus);
++ return (i->second);
++}
++
++bool
++var_list::is_set(const string &var) const
++{
++ return (_vars.find(var) != _vars.end());
++}
++
++void
++var_list::set_variable(const string &var, const string &val)
++{
++ if (Dflag)
++ fprintf(stderr, "setting %s=%s\n", var.c_str(), val.c_str());
++ _vars[var] = val;
++}
++
++void
++config::reset(void)
++{
++ _dir_list.clear();
++ delete_and_clear(_var_list_table);
++ delete_and_clear(_attach_list);
++ delete_and_clear(_detach_list);
++ delete_and_clear(_nomatch_list);
++ delete_and_clear(_notify_list);
++}
++
++void
++config::parse_one_file(const char *fn)
++{
++ if (Dflag)
++ fprintf(stderr, "Parsing %s\n", fn);
++ yyin = fopen(fn, "r");
++ if (yyin == NULL)
++ err(1, "Cannot open config file %s", fn);
++ lineno = 1;
++ if (yyparse() != 0)
++ errx(1, "Cannot parse %s at line %d", fn, lineno);
++ fclose(yyin);
++}
++
++void
++config::parse_files_in_dir(const char *dirname)
++{
++ DIR *dirp;
++ struct dirent *dp;
++ char path[PATH_MAX];
++
++ if (Dflag)
++ fprintf(stderr, "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_one_file(path);
++ }
++ }
++}
++
++class epv_greater {
++public:
++ int operator()(event_proc *const&l1, event_proc *const&l2)
++ {
++ return (l1->get_priority() > l2->get_priority());
++ }
++};
++
++void
++config::sort_vector(vector<event_proc *> &v)
++{
++ sort(v.begin(), v.end(), epv_greater());
++}
++
++void
++config::parse(void)
++{
++ vector<string>::const_iterator i;
++
++ parse_one_file(configfile);
++ for (i = _dir_list.begin(); i != _dir_list.end(); i++)
++ parse_files_in_dir((*i).c_str());
++ sort_vector(_attach_list);
++ sort_vector(_detach_list);
++ sort_vector(_nomatch_list);
++ sort_vector(_notify_list);
++}
++
++void
++config::open_pidfile()
++{
++ pid_t otherpid;
++
++ if (_pidfile == "")
++ return;
++ pfh = pidfile_open(_pidfile.c_str(), 0600, &otherpid);
++ if (pfh == NULL) {
++ if (errno == EEXIST)
++ errx(1, "devd already running, pid: %d", (int)otherpid);
++ warn("cannot open pid file");
++ }
++}
++
++void
++config::write_pidfile()
++{
++
++ pidfile_write(pfh);
++}
++
++void
++config::remove_pidfile()
++{
++
++ pidfile_remove(pfh);
++}
++
++void
++config::add_attach(int prio, event_proc *p)
++{
++ p->set_priority(prio);
++ _attach_list.push_back(p);
++}
++
++void
++config::add_detach(int prio, event_proc *p)
++{
++ p->set_priority(prio);
++ _detach_list.push_back(p);
++}
++
++void
++config::add_directory(const char *dir)
++{
++ _dir_list.push_back(string(dir));
++}
++
++void
++config::add_nomatch(int prio, event_proc *p)
++{
++ p->set_priority(prio);
++ _nomatch_list.push_back(p);
++}
++
++void
++config::add_notify(int prio, event_proc *p)
++{
++ p->set_priority(prio);
++ _notify_list.push_back(p);
++}
++
++void
++config::set_pidfile(const char *fn)
++{
++ _pidfile = string(fn);
++}
++
++void
++config::push_var_table()
++{
++ var_list *vl;
++
++ vl = new var_list();
++ _var_list_table.push_back(vl);
++ if (Dflag)
++ fprintf(stderr, "Pushing table\n");
++}
++
++void
++config::pop_var_table()
++{
++ delete _var_list_table.back();
++ _var_list_table.pop_back();
++ if (Dflag)
++ fprintf(stderr, "Popping table\n");
++}
++
++void
++config::set_variable(const char *var, const char *val)
++{
++ _var_list_table.back()->set_variable(var, val);
++}
++
++const string &
++config::get_variable(const string &var)
++{
++ vector<var_list *>::reverse_iterator i;
++
++ for (i = _var_list_table.rbegin(); i != _var_list_table.rend(); i++) {
++ if ((*i)->is_set(var))
++ return ((*i)->get_variable(var));
++ }
++ return (var_list::nothing);
++}
++
++bool
++config::is_id_char(char ch)
++{
++ return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' ||
++ ch == '-'));
++}
++
++void
++config::expand_one(const char *&src, string &dst)
++{
++ int count;
++ string buffer, varstr;
++
++ src++;
++ // $$ -> $
++ if (*src == '$') {
++ dst.append(src++, 1);
++ return;
++ }
++
++ // $(foo) -> $(foo)
++ // Not sure if I want to support this or not, so for now we just pass
++ // it through.
++ if (*src == '(') {
++ dst.append("$");
++ count = 1;
++ /* If the string ends before ) is matched , return. */
++ while (count > 0 && *src) {
++ if (*src == ')')
++ count--;
++ else if (*src == '(')
++ count++;
++ dst.append(src++, 1);
++ }
++ return;
++ }
++
++ // ${^A-Za-z] -> $\1
++ if (!isalpha(*src)) {
++ dst.append("$");
++ dst.append(src++, 1);
++ return;
++ }
++
++ // $var -> replace with value
++ do {
++ buffer.append(src++, 1);
++ } while (is_id_char(*src));
++ buffer.append("", 1);
++ varstr = get_variable(buffer.c_str());
++ dst.append(varstr);
++}
++
++const string
++config::expand_string(const string &s)
++{
++ const char *src;
++ string dst;
++
++ src = s.c_str();
++ while (*src) {
++ if (*src == '$')
++ expand_one(src, dst);
++ else
++ dst.append(src++, 1);
++ }
++ dst.append("", 1);
++
++ return (dst);
++}
++
++bool
++config::chop_var(char *&buffer, char *&lhs, char *&rhs)
++{
++ char *walker;
++
++ if (*buffer == '\0')
++ return (false);
++ walker = lhs = buffer;
++ while (is_id_char(*walker))
++ walker++;
++ if (*walker != '=')
++ return (false);
++ walker++; // skip =
++ if (*walker == '"') {
++ walker++; // skip "
++ rhs = walker;
++ while (*walker && *walker != '"')
++ walker++;
++ if (*walker != '"')
++ return (false);
++ rhs[-2] = '\0';
++ *walker++ = '\0';
++ } else {
++ rhs = walker;
++ while (*walker && !isspace(*walker))
++ walker++;
++ if (*walker != '\0')
++ *walker++ = '\0';
++ rhs[-1] = '\0';
++ }
++ while (isspace(*walker))
++ walker++;
++ buffer = walker;
++ return (true);
++}
++
++
++char *
++config::set_vars(char *buffer)
++{
++ char *lhs;
++ char *rhs;
++
++ while (1) {
++ if (!chop_var(buffer, lhs, rhs))
++ break;
++ set_variable(lhs, rhs);
++ }
++ return (buffer);
++}
++
++void
++config::find_and_execute(char type)
++{
++ vector<event_proc *> *l;
++ vector<event_proc *>::const_iterator i;
++ const char *s;
++
++ switch (type) {
++ default:
++ return;
++ case notify:
++ l = &_notify_list;
++ s = "notify";
++ break;
++ case nomatch:
++ l = &_nomatch_list;
++ s = "nomatch";
++ break;
++ case attach:
++ l = &_attach_list;
++ s = "attach";
++ break;
++ case detach:
++ l = &_detach_list;
++ s = "detach";
++ break;
++ }
++ if (Dflag)
++ fprintf(stderr, "Processing %s event\n", s);
++ for (i = l->begin(); i != l->end(); i++) {
++ if ((*i)->matches(*this)) {
++ (*i)->run(*this);
++ break;
++ }
++ }
++
++}
++
++
++static void
++process_event(char *buffer)
++{
++ char type;
++ char *sp;
++
++ sp = buffer + 1;
++ if (Dflag)
++ fprintf(stderr, "Processing event '%s'\n", buffer);
++ type = *buffer++;
++ cfg.push_var_table();
++ // No match doesn't have a device, and the format is a little
++ // different, so handle it separately.
++ switch (type) {
++ case notify:
++ sp = cfg.set_vars(sp);
++ break;
++ case nomatch:
++ //? at location pnp-info on bus
++ sp = strchr(sp, ' ');
++ if (sp == NULL)
++ return; /* Can't happen? */
++ *sp++ = '\0';
++ if (strncmp(sp, "at ", 3) == 0)
++ sp += 3;
++ sp = cfg.set_vars(sp);
++ if (strncmp(sp, "on ", 3) == 0)
++ cfg.set_variable("bus", sp + 3);
++ break;
++ case attach: /*FALLTHROUGH*/
++ case detach:
++ sp = strchr(sp, ' ');
++ if (sp == NULL)
++ return; /* Can't happen? */
++ *sp++ = '\0';
++ cfg.set_variable("device-name", buffer);
++ if (strncmp(sp, "at ", 3) == 0)
++ sp += 3;
++ sp = cfg.set_vars(sp);
++ if (strncmp(sp, "on ", 3) == 0)
++ cfg.set_variable("bus", sp + 3);
++ break;
++ }
++
++ cfg.find_and_execute(type);
++ cfg.pop_var_table();
++}
++
++int
++create_socket(const char *name)
++{
++ int fd, slen;
++ struct sockaddr_un sun;
++
++ if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0)
++ err(1, "socket");
++ bzero(&sun, sizeof(sun));
++ sun.sun_family = AF_UNIX;
++ strlcpy(sun.sun_path, name, sizeof(sun.sun_path));
++ slen = SUN_LEN(&sun);
++ unlink(name);
++ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
++ err(1, "fcntl");
++ if (bind(fd, (struct sockaddr *) & sun, slen) < 0)
++ err(1, "bind");
++ listen(fd, 4);
++ chown(name, 0, 0); /* XXX - root.wheel */
++ chmod(name, 0666);
++ return (fd);
++}
++
++list<int> clients;
++
++void
++notify_clients(const char *data, int len)
++{
++ list<int> bad;
++ list<int>::const_iterator i;
++
++ for (i = clients.begin(); i != clients.end(); i++) {
++ if (write(*i, data, len) <= 0) {
++ bad.push_back(*i);
++ close(*i);
++ }
++ }
++
++ for (i = bad.begin(); i != bad.end(); i++)
++ clients.erase(find(clients.begin(), clients.end(), *i));
++}
++
++void
++new_client(int fd)
++{
++ int s;
++
++ s = accept(fd, NULL, NULL);
++ if (s != -1)
++ clients.push_back(s);
++}
++
++static void
++event_loop(void)
++{
++ int rv;
++ int fd;
++ char buffer[DEVCTL_MAXBUF];
++ int once = 0;
++ int server_fd, max_fd;
++ timeval tv;
++ fd_set fds;
++
++ fd = open(PATH_DEVCTL, O_RDONLY);
++ if (fd == -1)
++ err(1, "Can't open devctl device %s", PATH_DEVCTL);
++ if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0)
++ err(1, "Can't set close-on-exec flag on devctl");
++ server_fd = create_socket(PIPE);
++ max_fd = max(fd, server_fd) + 1;
++ while (1) {
++ if (romeo_must_die)
++ break;
++ if (!once && !dflag && !nflag) {
++ // Check to see if we have any events pending.
++ tv.tv_sec = 0;
++ tv.tv_usec = 0;
++ FD_ZERO(&fds);
++ FD_SET(fd, &fds);
++ rv = select(fd + 1, &fds, &fds, &fds, &tv);
++ // No events -> we've processed all pending events
++ if (rv == 0) {
++ if (Dflag)
++ fprintf(stderr, "Calling daemon\n");
++ cfg.remove_pidfile();
++ cfg.open_pidfile();
++ daemon(0, 0);
++ cfg.write_pidfile();
++ once++;
++ }
++ }
++ FD_ZERO(&fds);
++ FD_SET(fd, &fds);
++ FD_SET(server_fd, &fds);
++ rv = select(max_fd, &fds, NULL, NULL, NULL);
++ if (rv == -1) {
++ if (errno == EINTR)
++ continue;
++ err(1, "select");
++ }
++ if (FD_ISSET(fd, &fds)) {
++ rv = read(fd, buffer, sizeof(buffer) - 1);
++ if (rv > 0) {
++ notify_clients(buffer, rv);
++ buffer[rv] = '\0';
++ while (buffer[--rv] == '\n')
++ buffer[rv] = '\0';
++ process_event(buffer);
++ } else if (rv < 0) {
++ if (errno != EINTR)
++ break;
++ } else {
++ /* EOF */
++ break;
++ }
++ }
++ if (FD_ISSET(server_fd, &fds))
++ new_client(server_fd);
++ }
++ close(fd);
++}
++
++/*
++ * functions that the parser uses.
++ */
++void
++add_attach(int prio, event_proc *p)
++{
++ cfg.add_attach(prio, p);
++}
++
++void
++add_detach(int prio, event_proc *p)
++{
++ cfg.add_detach(prio, p);
++}
++
++void
++add_directory(const char *dir)
++{
++ cfg.add_directory(dir);
++ free(const_cast<char *>(dir));
++}
++
++void
++add_nomatch(int prio, event_proc *p)
++{
++ cfg.add_nomatch(prio, p);
++}
++
++void
++add_notify(int prio, event_proc *p)
++{
++ cfg.add_notify(prio, p);
++}
++
++event_proc *
++add_to_event_proc(event_proc *ep, eps *eps)
++{
++ if (ep == NULL)
++ ep = new event_proc();
++ ep->add(eps);
++ return (ep);
++}
++
++eps *
++new_action(const char *cmd)
++{
++ eps *e = new action(cmd);
++ free(const_cast<char *>(cmd));
++ return (e);
++}
++
++eps *
++new_match(const char *var, const char *re)
++{
++ eps *e = new match(cfg, var, re);
++ free(const_cast<char *>(var));
++ free(const_cast<char *>(re));
++ return (e);
++}
++
++eps *
++new_media(const char *var, const char *re)
++{
++ eps *e = new media(cfg, var, re);
++ free(const_cast<char *>(var));
++ free(const_cast<char *>(re));
++ return (e);
++}
++
++void
++set_pidfile(const char *name)
++{
++ cfg.set_pidfile(name);
++ free(const_cast<char *>(name));
++}
++
++void
++set_variable(const char *var, const char *val)
++{
++ cfg.set_variable(var, val);
++ free(const_cast<char *>(var));
++ free(const_cast<char *>(val));
++}
++
++
++
++static void
++gensighand(int)
++{
++ romeo_must_die++;
++ _exit(0);
++}
++
++static void
++usage()
++{
++ fprintf(stderr, "usage: %s [-Ddn] [-f file]\n", getprogname());
++ exit(1);
++}
++
++static void
++check_devd_enabled()
++{
++ int val = 0;
++ size_t len;
++
++ len = sizeof(val);
++ if (sysctlbyname(SYSCTL, &val, &len, NULL, 0) != 0)
++ errx(1, "devctl sysctl missing from kernel!");
++ if (val) {
++ warnx("Setting " SYSCTL " to 0");
++ val = 0;
++ sysctlbyname(SYSCTL, NULL, NULL, &val, sizeof(val));
++ }
++}
++
++/*
++ * main
++ */
++int
++main(int argc, char **argv)
++{
++ int ch;
++
++ check_devd_enabled();
++ while ((ch = getopt(argc, argv, "Ddf:n")) != -1) {
++ switch (ch) {
++ case 'D':
++ Dflag++;
++ break;
++ case 'd':
++ dflag++;
++ break;
++ case 'f':
++ configfile = optarg;
++ break;
++ case 'n':
++ nflag++;
++ break;
++ default:
++ usage();
++ }
++ }
++
++ cfg.parse();
++ if (!dflag && nflag) {
++ cfg.open_pidfile();
++ daemon(0, 0);
++ cfg.write_pidfile();
++ }
++ signal(SIGPIPE, SIG_IGN);
++ signal(SIGHUP, gensighand);
++ signal(SIGINT, gensighand);
++ signal(SIGTERM, gensighand);
++ event_loop();
++ return (0);
++}
+diff -Nurd a/sbin/devd/devd.conf.5 b/sbin/devd/devd.conf.5
+--- a/sbin/devd/devd.conf.5 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/devd.conf.5 2009-03-08 19:02:30.000000000 +0100
+@@ -0,0 +1,488 @@
++.\"
++.\" 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 March 8, 2009
++.Dt DEVD.CONF 5
++.Os
++.Sh NAME
++.Nm devd.conf
++.Nd configuration file for
++.Xr devd 8
++.Sh DESCRIPTION
++.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 also
++terminated with a semicolon.
++.Pp
++The following statements are supported:
++.Bl -tag -width ".Ic options"
++.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 detached 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.
++.It Ic notify
++Specifies various matching criteria and actions to perform when the kernel
++sends an event notification to userland.
++.It Ic options
++Specifies various options and parameters for the operation of
++.Xr devd 8 .
++.El
++.Pp
++Statements may occur in any order in the configuration file, and may be
++repeated as often as required.
++Further details on the syntax and meaning of each statement and their
++substatements are explained below.
++.Pp
++Each statement, except
++.Ic options
++has a priority (an arbitrary number) associated with it, where
++.Ql 0
++is defined as the lowest priority.
++If two statements match the same event, only the action of the statement with
++highest priority will be executed.
++In this way generic statements can be overridden for devices or
++notifications that require special attention.
++.Pp
++The general syntax of a statement is:
++.Pp
++.Bd -literal -offset indent
++statement priority {
++ substatement "value";
++ ...
++ substatement "value";
++};
++.Ed
++.Ss Sub-statements
++The following sub-statements are supported within the
++.Ic options
++statement.
++.Bl -tag -width ".Ic directory"
++.It Ic directory Qq Ar /some/path ;
++Adds the given directory to the list of directories from which
++.Xr devd 8
++will read all files named "*.conf" as further
++configuration files.
++Any number of
++.Ic directory
++statements can be used.
++.It Ic pid-file Qq Pa /var/run/devd.pid ;
++Specifies PID file.
++.It Ic set Ar regexp-name Qq Ar (some|regexp) ;
++Creates a regular expression and assigns it to the variable
++.Ar regexp-name .
++The variable is available throughout the rest of
++the configuration file.
++All regular expressions have an implicit
++.Ql ^$
++around them.
++.El
++.Pp
++The following sub-statements are supported within the
++.Ic attach
++and
++.Ic detach
++statements.
++.Bl -tag -width ".Ic directory"
++.It Ic action Qq Ar command ;
++Command to execute upon a successful match.
++Example
++.Dq Li "/etc/pccard_ether $device-name start" .
++.It Ic class Qq Ar string ;
++This is shorthand for
++.Dq Ic match Qo Li class Qc Qq Ar string .
++.It Ic device-name Qq string ;
++This is shorthand for
++.Dq Ic match Qo Li device-name Qc Qq Ar string .
++This matches a device named
++.Ar string ,
++which is allowed to be a regular expression or a variable previously created
++containing a regular expression.
++The
++.Dq Li device-name
++variable
++is available for later use with the
++.Ic action
++statement.
++.It Ic match Qo Ar variable Qc Qq Ar value ;
++Matches the content of
++.Ar value
++against
++.Ar variable ;
++the content of
++.Ar value
++may be a regular expression.
++Not required during
++.Ic attach
++nor
++.Ic detach
++events since the
++.Ic device-name
++statement takes care of all device matching.
++For a partial list of variables, see below.
++.It Ic media-type Qq Ar string ;
++For network devices,
++.Ic media-type
++will match devices that have the given media type.
++Valid media types are:
++.Dq Li Ethernet ,
++.Dq Li Tokenring ,
++.Dq Li FDDI ,
++.Dq Li 802.11 ,
++.Dq Li ATM ,
++and
++.Dq Li CARP .
++.It Ic subdevice Qq Ar string ;
++This is shorthand for
++.Dq Ic match Qo Li subdevice Qc Qq Ar string .
++.El
++.Pp
++The following sub-statements are supported within the
++.Ic nomatch
++statement.
++.Bl -tag -width ".Ic directory"
++.It Ic action Qq Ar command ;
++Same as above.
++.It Ic match Qo Ar variable Qc Qq Ar value ;
++Matches the content of
++.Ar value
++against
++.Ar variable ;
++the content of
++.Ar value
++may be a regular expression.
++For a partial list of variables, see below.
++.El
++.Pp
++The following sub-statements are supported within the
++.Ic notify
++statement.
++The
++.Dq Li notify
++variable is available inside this statement and contains, a value, depending
++on which system and subsystem that delivered the event.
++.Bl -tag -width ".Ic directory"
++.It Ic action Qq Ar command ;
++Command to execute upon a successful match.
++Example
++.Dq Li "/etc/rc.d/power_profile $notify" .
++.It Ic match Qo Ar system | subsystem | type | notify Qc Qq Ar value ;
++Any number of
++.Ic match
++statements can exist within a
++.Ic notify
++statement;
++.Ar value
++can be either a fixed string or a regular expression.
++Below is a list of available systems, subsystems, and types.
++.It Ic media-type Qq Ar string ;
++See above.
++.El
++.Ss Variables that can be used with the match statement
++A partial list of variables and their possible values that can be used together
++with the
++.Ic match
++statement.
++.Pp
++.Bl -tag -width ".Li manufacturer" -compact
++.It Ic Variable
++.Ic Description
++.It Li bus
++Device name of parent bus.
++.It Li cdev
++Device node path if one is created by the
++.Xr devfs 5
++filesystem.
++.It Li cisproduct
++CIS-product.
++.It Li cisvendor
++CIS-vendor.
++.It Li class
++Device class.
++.It Li device
++Device ID.
++.It Li device-name
++Name of attached/detached device.
++.It Li function
++Card functions.
++.It Li manufacturer
++Manufacturer ID (pccard).
++.It Li notify
++Match the value of the
++.Dq Li notify
++variable.
++.It Li product
++Product ID (pccard).
++.It Li serial
++Serial Number (USB).
++.It Li slot
++Card slot.
++.It Li subvendor
++Sub-vendor ID.
++.It Li subdevice
++Sub-device ID.
++.It Li subsystem
++Matches a subsystem of a system, see below.
++.It Li system
++Matches a system type, see below.
++.It Li type
++Type of notification, see below.
++.It Li vendor
++Vendor ID.
++.El
++.Ss Notify matching
++A partial list of systems, subsystems, and types used within the
++.Ic notify
++mechanism.
++.Pp
++.Bl -tag -width ".Li coretemp" -compact
++.It Sy System
++.It Li ACPI
++Events related to the ACPI subsystem.
++.Bl -tag -width ".Sy Subsystem" -compact
++.It Sy Subsystem
++.It Li ACAD
++AC line state ($notify=0x00 is offline, 0x01 is online).
++.It Li Button
++Button state ($notify=0x00 is power, 0x01 is sleep).
++.It Li CMBAT
++Battery events.
++.It Li Lid
++Lid state ($notify=0x00 is closed, 0x01 is open).
++.It Li Thermal
++Thermal zone events.
++.El
++.Pp
++.It Li IFNET
++Events related to the network subsystem.
++.Bl -tag -width ".Sy Subsystem" -compact
++.It Sy Subsystem
++.It Ar interface
++The
++.Dq subsystem
++is the actual name of the network interface on which the event
++took place.
++.Bl -tag -width ".Li LINK_DOWN" -compact
++.It Sy Type
++.It Li LINK_UP
++Carrier status changed to UP.
++.It Li LINK_DOWN
++Carrier status changed to DOWN.
++.It Li ATTACH
++The network interface is attached to the system.
++.It Li DETACH
++The network interface is detached from the system.
++.El
++.El
++.It Li DEVFS
++Events related to the
++.Xr devfs 5
++filesystem.
++.Bl -tag -width ".Sy Subsystem" -compact
++.It Sy Subsystem
++.It Li CDEV
++.Bl -tag -width ".Li DESTROY" -compact
++.It Sy Type
++.It Li CREATE
++The
++.Xr devfs 5
++node is created.
++.It Li DESTROY
++The
++.Xr devfs 5
++node is destroyed.
++.El
++.El
++.It Li coretemp
++Events related to the
++.Xr coretemp 4
++device.
++.Bl -tag -width ".Sy Subsystem" -compact
++.It Sy Subsystem
++.It Li Thermal
++Notification that the CPU core has reached critical temperature.
++.Bl -tag -width ".Ar temperature" -compact
++.It Sy Type
++.It Ar temperature
++String containing the temperature of the core that has become too hot.
++.El
++.El
++.It Li kern
++Events related to the kernel.
++.Bl -tag -width ".Sy Subsystem" -compact
++.It Sy Subsystem
++.It Li power
++Information about the state of the system.
++.Bl -tag -width ".li resume" -compact
++.It Sy Type
++.It Li resume
++Notification that the system has woken from the suspended state.
++.El
++.El
++.El
++.Pp
++A link state change to UP on the interface
++.Dq Li fxp0
++would result in the following notify event:
++.Bd -literal -offset indent
++system=IFNET, subsystem=fxp0, type=LINK_UP
++.Ed
++.Pp
++An AC line state change to
++.Dq offline
++would result in the following event:
++.Bd -literal -offset indent
++system=ACPI, subsystem=ACAD, notify=0x00
++.Ed
++.Ss Comments
++Comments may appear anywhere that whitespace may appear in a
++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
++.Ql /*
++(slash, star) and end with
++.Ql */
++(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
++.Ql */ :
++.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
++.Ql //
++(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
++.Ql //
++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
++.Sh FILES
++.Bl -tag -width ".Pa /etc/devd.conf" -compact
++.It Pa /etc/devd.conf
++The
++.Xr devd 8
++configuration file.
++.El
++.Sh EXAMPLES
++.Bd -literal
++#
++# This will catch link down events on the interfaces fxp0 and ath0
++#
++notify 0 {
++ match "system" "IFNET";
++ match "subsystem" "(fxp0|ath0)";
++ match "type" "LINK_DOWN";
++ action "logger $subsystem is DOWN";
++};
++
++#
++# Match lid open/close events
++# These can be combined to a single event, by passing the
++# value of $notify to the external script.
++#
++notify 0 {
++ match "system" "ACPI";
++ match "subsystem" "Lid";
++ match "notify" "0x00";
++ action "logger Lid closed, we can sleep now!";
++};
++
++notify 0 {
++ match "system" "ACPI";
++ match "subsystem" "Lid";
++ match "notify" "0x01";
++ action "logger Lid opened, the sleeper must awaken!";
++};
++
++#
++# Try to configure ath and wi devices with pccard_ether
++# as they are attached.
++#
++attach 0 {
++ device-name "(ath|wi)[0-9]+";
++ action "/etc/pccard_ether $device-name start";
++};
++
++#
++# Stop ath and wi devices as they are detached from
++# the system.
++#
++detach 0 {
++ device-name "(ath|wi)[0-9]+";
++ action "/etc/pccard_ether $device-name stop";
++};
++.Ed
++.Pp
++The installed
++.Pa /etc/devd.conf
++has many additional examples.
++.Sh SEE ALSO
++.Xr coretemp 4 ,
++.Xr devfs 5 ,
++.Xr devd 8
+diff -Nurd a/sbin/devd/devd.h b/sbin/devd/devd.h
+--- a/sbin/devd/devd.h 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/devd.h 2005-07-10 05:37:15.000000000 +0200
+@@ -0,0 +1,58 @@
++/*-
++ * DEVD (Device action daemon)
++ *
++ * Copyright (c) 2002 M. Warner Losh <imp at 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$
++ */
++
++#ifndef DEVD_H
++#define DEVD_H
++
++/** @warning This file needs to be purely 'C' compatible.
++ */
++struct event_proc;
++struct eps;
++__BEGIN_DECLS
++void add_attach(int, struct event_proc *);
++void add_detach(int, struct event_proc *);
++void add_directory(const char *);
++void add_nomatch(int, struct event_proc *);
++void add_notify(int, struct event_proc *);
++struct event_proc *add_to_event_proc(struct event_proc *, struct eps *);
++struct eps *new_match(const char *, const char *);
++struct eps *new_media(const char *, const char *);
++struct eps *new_action(const char *);
++void set_pidfile(const char *);
++void set_variable(const char *, const char *);
++void yyerror(const char *s);
++int yylex(void);
++int yyparse(void);
++__END_DECLS
++
++#define PATH_DEVCTL "/dev/devctl"
++#define DEVCTL_MAXBUF 1025
++
++#endif /* DEVD_H */
+diff -Nurd a/sbin/devd/devd.hh b/sbin/devd/devd.hh
+--- a/sbin/devd/devd.hh 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/devd.hh 2007-12-21 02:00:04.000000000 +0100
+@@ -0,0 +1,183 @@
++/*-
++ * Copyright (c) 2002-2003 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$
++ */
++
++#ifndef DEVD_HH
++#define DEVD_HH
++
++class config;
++
++/**
++ * var_list is a collection of variables. These collections of variables
++ * are stacked up and popped down for each event that we have to process.
++ * We have multiple levels so that we can push variables that are unique
++ * to the event in question, in addition to having global variables. This
++ * allows for future flexibility.
++ */
++class var_list
++{
++public:
++ var_list() {}
++ virtual ~var_list() {}
++ /** Set a variable in this var list.
++ */
++ void set_variable(const std::string &var, const std::string &val);
++ /** Get the variable out of this, and no other, var_list. If
++ * no variable of %var is set, then %bogus will be returned.
++ */
++ const std::string &get_variable(const std::string &var) const;
++ /** Is there a variable of %var set in thi stable?
++ */
++ bool is_set(const std::string &var) const;
++ /** A completely bogus string.
++ */
++ static const std::string bogus;
++ static const std::string nothing;
++private:
++ std::map<std::string, std::string> _vars;
++};
++
++/**
++ * eps is short for event_proc_single. It is a single entry in an
++ * event_proc. Each keyword needs its own subclass from eps.
++ */
++class eps
++{
++public:
++ eps() {}
++ virtual ~eps() {}
++ /** Does this eps match the current config?
++ */
++ virtual bool do_match(config &) = 0;
++ /** Perform some action for this eps.
++ */
++ virtual bool do_action(config &) = 0;
++};
++
++/**
++ * match is the subclass used to match an individual variable. Its
++ * actions are nops.
++ */
++class match : public eps
++{
++public:
++ match(config &, const char *var, const char *re);
++ virtual ~match();
++ virtual bool do_match(config &);
++ virtual bool do_action(config &) { return true; }
++private:
++ std::string _var;
++ std::string _re;
++ regex_t _regex;
++};
++
++/**
++ * media is the subclass used to match an individual variable. Its
++ * actions are nops.
++ */
++class media : public eps
++{
++public:
++ media(config &, const char *var, const char *type);
++ virtual ~media();
++ virtual bool do_match(config &);
++ virtual bool do_action(config &) { return true; }
++private:
++ std::string _var;
++ int _type;
++};
++
++/**
++ * action is used to fork a process. It matches everything.
++ */
++class action : public eps
++{
++public:
++ action(const char *cmd);
++ virtual ~action();
++ virtual bool do_match(config &) { return true; }
++ virtual bool do_action(config &);
++private:
++ std::string _cmd;
++};
++
++class event_proc
++{
++public:
++ event_proc();
++ virtual ~event_proc();
++ int get_priority() const { return (_prio); }
++ void set_priority(int prio) { _prio = prio; }
++ void add(eps *);
++ bool matches(config &);
++ bool run(config &);
++private:
++ int _prio;
++ std::vector<eps *> _epsvec;
++};
++
++class config
++{
++public:
++ config() { _pidfile = ""; push_var_table(); }
++ virtual ~config() { reset(); }
++ void add_attach(int, event_proc *);
++ void add_detach(int, event_proc *);
++ void add_directory(const char *);
++ void add_nomatch(int, event_proc *);
++ void add_notify(int, event_proc *);
++ void set_pidfile(const char *);
++ void reset();
++ void parse();
++ void open_pidfile();
++ void write_pidfile();
++ void remove_pidfile();
++ void push_var_table();
++ void pop_var_table();
++ void set_variable(const char *var, const char *val);
++ const std::string &get_variable(const std::string &var);
++ const std::string expand_string(const std::string &var);
++ char *set_vars(char *);
++ void find_and_execute(char);
++protected:
++ void sort_vector(std::vector<event_proc *> &);
++ void parse_one_file(const char *fn);
++ void parse_files_in_dir(const char *dirname);
++ void expand_one(const char *&src, std::string &dst);
++ bool is_id_char(char);
++ bool chop_var(char *&buffer, char *&lhs, char *&rhs);
++private:
++ std::vector<std::string> _dir_list;
++ std::string _pidfile;
++ std::vector<var_list *> _var_list_table;
++ std::vector<event_proc *> _attach_list;
++ std::vector<event_proc *> _detach_list;
++ std::vector<event_proc *> _nomatch_list;
++ std::vector<event_proc *> _notify_list;
++};
++
++#endif /* DEVD_HH */
+diff -Nurd a/sbin/devd/Makefile b/sbin/devd/Makefile
+--- a/sbin/devd/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/Makefile 2007-11-19 01:19:01.000000000 +0100
+@@ -0,0 +1,20 @@
++# $FreeBSD$
++
++PROG_CXX=devd
++SRCS= devd.cc token.l parse.y y.tab.h
++MAN= devd.8 devd.conf.5
++
++WARNS= 0
++#WARNS?= 4
++
++NO_SHARED?=YES
++
++DPADD= ${LIBL} ${LIBUTIL}
++LDADD= -ll -lutil
++
++YFLAGS+=-v
++CFLAGS+=-I. -I${.CURDIR}
++
++CLEANFILES= y.output
++
++.include <bsd.prog.mk>
+diff -Nurd a/sbin/devd/parse.y b/sbin/devd/parse.y
+--- a/sbin/devd/parse.y 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/parse.y 2005-07-10 05:37:15.000000000 +0200
+@@ -0,0 +1,152 @@
++%{
++/*-
++ * DEVD (Device action daemon)
++ *
++ * Copyright (c) 2002 M. Warner Losh <imp at 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>
++#include <string.h>
++
++%}
++
++%union {
++ char *str;
++ int i;
++ struct eps *eps; /* EventProcStatement */
++ struct event_proc *eventproc;
++}
++
++%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 NOTIFY MEDIA_TYPE CLASS SUBDEVICE
++
++%type <eventproc> match_or_action_list
++%type <eps> match_or_action match action
++
++%%
++
++config_file
++ : config_list
++ |
++ ;
++
++config_list
++ : config
++ | config_list config
++ ;
++
++config
++ : option_block
++ | attach_block
++ | detach_block
++ | nomatch_block
++ | notify_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_pidfile($2); }
++ ;
++
++set_option
++ : SET ID STRING SEMICOLON { set_variable($2, $3); }
++ ;
++
++attach_block
++ : ATTACH NUMBER BEGINBLOCK match_or_action_list ENDBLOCK SEMICOLON
++ { add_attach($2, $4); }
++ | ATTACH NUMBER BEGINBLOCK ENDBLOCK SEMICOLON
++ ;
++
++detach_block
++ : DETACH NUMBER BEGINBLOCK match_or_action_list ENDBLOCK SEMICOLON
++ { add_detach($2, $4); }
++ | DETACH NUMBER BEGINBLOCK ENDBLOCK SEMICOLON
++ ;
++
++nomatch_block
++ : NOMATCH NUMBER BEGINBLOCK match_or_action_list ENDBLOCK SEMICOLON
++ { add_nomatch($2, $4); }
++ | NOMATCH NUMBER BEGINBLOCK ENDBLOCK SEMICOLON
++ ;
++
++notify_block
++ : NOTIFY NUMBER BEGINBLOCK match_or_action_list ENDBLOCK SEMICOLON
++ { add_notify($2, $4); }
++ | NOTIFY NUMBER BEGINBLOCK ENDBLOCK SEMICOLON
++ ;
++
++match_or_action_list
++ : match_or_action { $$ = add_to_event_proc( NULL, $1); }
++ | match_or_action_list match_or_action
++ { $$ = add_to_event_proc($1, $2); }
++ ;
++
++match_or_action
++ : match
++ | action
++ ;
++
++match
++ : MATCH STRING STRING SEMICOLON { $$ = new_match($2, $3); }
++ | DEVICE_NAME STRING SEMICOLON
++ { $$ = new_match(strdup("device-name"), $2); }
++ | MEDIA_TYPE STRING SEMICOLON
++ { $$ = new_media(strdup("media-type"), $2); }
++ | CLASS STRING SEMICOLON
++ { $$ = new_match(strdup("class"), $2); }
++ | SUBDEVICE STRING SEMICOLON
++ { $$ = new_match(strdup("subdevice"), $2); }
++ ;
++
++action
++ : ACTION STRING SEMICOLON { $$ = new_action($2); }
++ ;
++
++%%
+diff -Nurd a/sbin/devd/token.l b/sbin/devd/token.l
+--- a/sbin/devd/token.l 1970-01-01 01:00:00.000000000 +0100
++++ b/sbin/devd/token.l 2008-03-21 21:38:28.000000000 +0100
+@@ -0,0 +1,110 @@
++%{
++/*-
++ * DEVD (Device action daemon)
++ *
++ * Copyright (c) 2002 M. Warner Losh <imp at 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 <ctype.h>
++#include <stdlib.h>
++#include <string.h>
++#include <syslog.h>
++#include "devd.h"
++#include "y.tab.h"
++
++int lineno = 1;
++#define YY_NO_UNPUT
++
++static void
++update_lineno(const char *cp)
++{
++ while (*cp)
++ if (*cp++ == '\n')
++ lineno++;
++}
++
++%}
++
++%%
++
++[ \t]+ ;
++\n lineno++;
++; { return SEMICOLON; }
++#.*$ ;
++\/\/.*$ ;
++\/\*([^*]|(\*+([^*\/])))*\*+\/ { update_lineno(yytext); }
++\{ { return BEGINBLOCK; }
++\} { return ENDBLOCK; }
++[0-9]+ { yylval.i = atoi(yytext); return NUMBER; }
++\"[^"]+\" {
++ int len = strlen(yytext) - 2;
++ char *walker;
++ int i;
++ update_lineno(yytext);
++ if ((yylval.str = (char *) malloc(len + 1)) == NULL)
++ goto out;
++ walker = yylval.str;
++ for (i = 1; i <= len; i++) {
++ if (yytext[i] == '\\' &&
++ yytext[i + 1] == '\n') {
++ i += 2;
++ while(isspace(yytext[i]))
++ i++;
++ }
++ *walker++ = yytext[i];
++ }
++ *walker++ = '\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; }
++media-type { return MEDIA_TYPE; }
++class { return CLASS; }
++subdevice { return SUBDEVICE; }
++action { return ACTION; }
++match { return MATCH; }
++nomatch { return NOMATCH; }
++notify { return NOTIFY; }
++[A-Za-z][A-Za-z0-9_-]* {
++ yylval.str = strdup(yytext);
++ return ID;
++ }
++%%
++
++void
++yyerror(const char *s)
++{
++ syslog(LOG_ERR, "line %d: %s%s %s.\n", lineno, yytext, yytext?":":"", s);
++}
Added: trunk/freebsd-utils/debian/patches/022_devd.diff
===================================================================
--- trunk/freebsd-utils/debian/patches/022_devd.diff (rev 0)
+++ trunk/freebsd-utils/debian/patches/022_devd.diff 2010-01-16 11:05:29 UTC (rev 2930)
@@ -0,0 +1,37 @@
+--- freebsd-utils-8.0.orig/sbin/devd/parse.y (revision 200600)
++++ freebsd-utils-8.0/sbin/devd/parse.y (working copy)
+@@ -29,9 +29,9 @@
+ * $FreeBSD$
+ */
+
+-#include "devd.h"
+ #include <stdio.h>
+ #include <string.h>
++#include "devd.h"
+
+ %}
+
+--- freebsd-utils-8.0.orig/sbin/devd/devd.cc (revision 200600)
++++ freebsd-utils-8.0/sbin/devd/devd.cc (working copy)
+@@ -55,6 +55,8 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <unistd.h>
++#include <bsd/stdlib.h>
++#include <bsd/string.h>
+
+ #include <algorithm>
+ #include <map>
+--- freebsd-utils-8.0.orig/sbin/devd/Makefile (revision 200600)
++++ freebsd-utils-8.0/sbin/devd/Makefile (working copy)
+@@ -10,7 +10,7 @@
+ NO_SHARED?=YES
+
+ DPADD= ${LIBL} ${LIBUTIL}
+-LDADD= -ll -lutil
++LDADD= -ll -lutil -lbsd
+
+ YFLAGS+=-v
+ CFLAGS+=-I. -I${.CURDIR}
+
+
Added: trunk/freebsd-utils/debian/patches/023_acpiconf.diff
===================================================================
--- trunk/freebsd-utils/debian/patches/023_acpiconf.diff (rev 0)
+++ trunk/freebsd-utils/debian/patches/023_acpiconf.diff 2010-01-16 11:05:29 UTC (rev 2930)
@@ -0,0 +1,17 @@
+--- freebsd-utils-8.0.orig/usr.sbin/acpi/acpiconf/acpiconf.c (revision 200600)
++++ freebsd-utils-8.0/usr.sbin/acpi/acpiconfacpiconf.c (working copy)
+@@ -35,10 +35,13 @@
+ #include <sys/ioctl.h>
+ #include <sysexits.h>
+ #include <unistd.h>
++#include <stdlib.h>
+
+ #include <dev/acpica/acpiio.h>
+
++#ifndef __GLIBC__
+ #include <contrib/dev/acpica/include/acpi.h>
++#endif
+
+ #define ACPIDEV "/dev/acpi"
+
+
Modified: trunk/freebsd-utils/debian/patches/series
===================================================================
--- trunk/freebsd-utils/debian/patches/series 2010-01-15 15:23:31 UTC (rev 2929)
+++ trunk/freebsd-utils/debian/patches/series 2010-01-16 11:05:29 UTC (rev 2930)
@@ -1,3 +1,5 @@
+000_acpiconf_sources.diff
+000_devd_sources.diff
001_dmesg.diff
002_ifconfig.diff
003_kbdcontrol.diff
@@ -18,3 +20,5 @@
018_umount.diff
020_lib.diff
021_netstat.diff
+022_devd.diff
+023_acpiconf.diff
Modified: trunk/freebsd-utils/debian/rules
===================================================================
--- trunk/freebsd-utils/debian/rules 2010-01-15 15:23:31 UTC (rev 2929)
+++ trunk/freebsd-utils/debian/rules 2010-01-16 11:05:29 UTC (rev 2930)
@@ -6,11 +6,14 @@
#export DH_VERBOSE=1
CFLAGS = -Wall -g -pipe -fPIC -I. -D_GNU_SOURCE -D'__FBSDID(string)='
+CXXFLAGS = -Wall -g -pipe -fPIC -I. -D_GNU_SOURCE -D'__FBSDID(string)='
ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
CFLAGS += -O0
+ CXXFLAGS += -O0
else
CFLAGS += -O2
+ CXXFLAGS += -O2
endif
VERSION=$(shell dpkg-parsechangelog | sed -e '/^Version:/!d' -e 's/^Version: //g' -e 's/-.*//g')
@@ -25,7 +28,7 @@
get-orig-source:
rm -rf $(ORIGDIR)
for i in sbin/dmesg sbin/sysctl usr.bin/kdump usr.bin/ktrace \
- usr.sbin/jail bin/chflags \
+ usr.sbin/jail bin/chflags sbin/devd usr.sbin/acpi/acpiconf \
sbin/kldconfig sbin/kldload sbin/kldstat sbin/kldunload \
sbin/ifconfig sbin/route usr.bin/netstat usr.sbin/rpc.umntall \
usr.sbin/ppp usr.sbin/pppctl usr.sbin/pppd \
@@ -59,6 +62,7 @@
# $(PMAKE) -C bin/chflags
$(PMAKE) -C bin/kenv
$(PMAKE) -C sbin/ccdconfig
+ $(PMAKE) -C sbin/devd
$(PMAKE) -C sbin/dmesg
$(PMAKE) -C sbin/mdconfig
$(PMAKE) -C sbin/mount
@@ -79,6 +83,7 @@
$(PMAKE) -C sbin/umount
# $(PMAKE) -C usr.bin/kdump
$(PMAKE) -C usr.bin/ktrace
+ $(PMAKE) -C usr.sbin/acpi/acpiconf
$(PMAKE) -C usr.sbin/rpc.umntall
touch $@
@@ -123,10 +128,13 @@
clean:
dh_testdir
dh_testroot
+
[ ! -f lib/Makefile ] || $(MAKE) -C lib clean
+
$(PMAKE) -C bin/chflags clean
- [ ! -f bin/kenv/Makefile ] || $(PMAKE) -C bin/kenv clean
+ $(PMAKE) -C bin/kenv clean
$(PMAKE) -C sbin/ccdconfig clean
+ ! [ -f sbin/devd/Makefile ] || $(PMAKE) -C sbin/devd clean
$(PMAKE) -C sbin/dmesg clean
$(PMAKE) -C sbin/mdconfig clean
$(PMAKE) -C sbin/mount clean
@@ -147,18 +155,24 @@
$(PMAKE) -C sbin/umount clean
$(PMAKE) -C usr.bin/kdump clean
$(PMAKE) -C usr.bin/ktrace clean
+ ! [ -d usr.sbin/acpi/acpiconf ] || $(PMAKE) -C usr.sbin/acpi/acpiconf clean
$(PMAKE) -C usr.sbin/rpc.umntall clean
+
$(PMAKE) -C sbin/gbde clean
+
$(PMAKE) -C usr.sbin/kbdcontrol clean
+
$(PMAKE) -C sbin/kldconfig clean
$(PMAKE) -C sbin/kldload clean
$(PMAKE) -C sbin/kldstat clean
$(PMAKE) -C sbin/kldunload clean
+
$(PMAKE) -C sbin/ifconfig clean
$(PMAKE) -C sbin/pfctl clean
$(PMAKE) -C sbin/route clean
$(PMAKE) -C usr.bin/netstat clean
$(PMAKE) -C usr.sbin/authpf clean
+
QUILT_PATCHES=debian/patches quilt pop -a -R || test $$? = 2
rm -rf .pc
rm -f *stamp
More information about the Glibc-bsd-commits
mailing list