457 lines
14 KiB
Groff
457 lines
14 KiB
Groff
.\" $NetBSD: envsys.4,v 1.50 2013/01/12 03:16:43 pgoyette Exp $
|
|
.\"
|
|
.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Juan Romero Pardines.
|
|
.\"
|
|
.\" 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
|
.\"
|
|
.Dd January 10, 2013
|
|
.Dt ENVSYS 4
|
|
.Os
|
|
.Sh NAME
|
|
.Nm envsys
|
|
.Nd Environmental Systems framework (version 2)
|
|
.Sh SYNOPSIS
|
|
.In sys/envsys.h
|
|
.Sh DESCRIPTION
|
|
The
|
|
.Nm
|
|
framework provides support to handle hardware monitor devices.
|
|
Hardware monitoring chips are able to report values from different types of
|
|
sensors.
|
|
.Pp
|
|
The
|
|
.Nm
|
|
framework consists of two parts:
|
|
.Pp
|
|
.Bl -enum -offset indent -compact
|
|
.It
|
|
the userland part, to receive the current sensor data and
|
|
to set some properties on sensors:
|
|
.Xr envstat 8 .
|
|
.It
|
|
The kernel part that is able to talk to the devices providing sensor
|
|
data:
|
|
.Xr sysmon_envsys 9 .
|
|
.El
|
|
.Pp
|
|
The
|
|
.Nm
|
|
framework uses
|
|
.Xr proplib 3
|
|
for communication between kernel and user space.
|
|
The following
|
|
.Xr ioctl 2
|
|
types are available:
|
|
.Pp
|
|
.Bl -tag -width XX
|
|
.It Dv ENVSYS_GETDICTIONARY Pq prop_dictionary_t
|
|
.Pp
|
|
This
|
|
.Xr ioctl 2
|
|
is used to receive the global dictionary that is being used in
|
|
the kernel by the
|
|
.Xr sysmon_envsys 9
|
|
framework.
|
|
It will contain an array of dictionaries per device
|
|
and one dictionary per sensor plus another special dictionary that
|
|
contains the properties for a device.
|
|
Each sensor dictionary will have its own characteristics and values.
|
|
.Pp
|
|
The following XML property list represents a virtual device
|
|
.Dq device0
|
|
with one entry for sensor
|
|
.Dq sensor0
|
|
and all available properties set on it, plus another entry for the
|
|
.Dq device-properties
|
|
dictionary (which contains specific properties for a device):
|
|
.Pp
|
|
.Bd -literal
|
|
\&\*[Lt]key\&\*[Gt]device0\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]array\&\*[Gt]
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]allow-rfact\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]avg-value\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]36400\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]battery-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]NORMAL\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]critical-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]21417\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]critical-max\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]343150000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]critical-min\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]288150000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]cur-value\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]406000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]description\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]CPU Temp\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]high-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]21417\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]index\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]sensor0\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]max-value\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]3894000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]maximum-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]21417\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]min-value\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]2894000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]monitoring-state-critical\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]monitoring-state-critover\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]monitoring-state-critunder\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]monitoring-state-state-changed\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]monitoring-state-warnover\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]monitoring-state-warnunder\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]monitoring-supported\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]state\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]valid\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]type\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]Ampere hour\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]want-percentage\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]true\&/\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]warning-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]19234\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]warning-max\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]323150000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]warning-min\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]298150000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]device-properties\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]refresh-timeout\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]0xa\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
\&\*[Lt]\&/array\&\*[Gt]
|
|
.Ed
|
|
.Pp
|
|
Let's explain some more about those objects:
|
|
.Bl -tag -width "monitoring-state-critical-overxx"
|
|
.It Fa allow-rfact
|
|
Set to
|
|
.Em true
|
|
means that the sensor is able to change the resistor factor,
|
|
only used in Voltage sensors.
|
|
.It Fa avg-value
|
|
Current average value in the sensor.
|
|
.It Fa battery-capacity
|
|
Current capacity state for a battery capacity sensor.
|
|
.It Fa critical-capacity
|
|
Critical capacity set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
Only available on sensors with the
|
|
.Em want-percentage
|
|
object enabled.
|
|
.It Fa critical-max
|
|
Critical max limit set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
.It Fa critical-min
|
|
Critical min limit set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
.It Fa cur-value
|
|
Current value in the sensor.
|
|
.It Fa description
|
|
Description of the sensor.
|
|
.It Fa high-capacity
|
|
High capacity set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
Only available on sensors with the
|
|
.Em want-percentage
|
|
object enabled.
|
|
Used to monitor possible over-charging of batteries.
|
|
.It Fa index
|
|
Index position of the sensor.
|
|
.It Fa max-value
|
|
Current max value in the sensor.
|
|
.It Fa maximum-capacity
|
|
Maximum capacity set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
Only available on sensors with the
|
|
.Em want-percentage
|
|
object enabled.
|
|
Used to monitor possible over-charging of batteries.
|
|
.It Fa min-value
|
|
Current min value in the sensor.
|
|
.It Fa monitoring-state-critical
|
|
If true, the device has enabled the flag to monitor a critical state.
|
|
.It Fa monitoring-state-hw-range-limits
|
|
If true, the device has enabled the flag to monitor warning or critical
|
|
limits.
|
|
.It Fa monitoring-state-state-changed
|
|
If true, the device has enabled the flag to monitor for state changes in
|
|
a drive or Battery state sensor.
|
|
.It Fa monitoring-supported
|
|
If true, critical/warning capacity/max/min limits may be set by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
.It Fa state
|
|
Current state in the sensor.
|
|
.It Fa type
|
|
Type of unit in the sensor.
|
|
.It Fa want-percentage
|
|
If true,
|
|
.Em max-value
|
|
and
|
|
.Em cur-value
|
|
are valid and a percentage may be computed from them.
|
|
.It Fa warning-capacity
|
|
Warning capacity set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
Only available on sensors with the
|
|
.Em want-percentage
|
|
object enabled.
|
|
.It Fa warning-max
|
|
Warning max limit set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
.It Fa warning-min
|
|
Warning min limit set previously by the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 .
|
|
.El
|
|
.It Dv ENVSYS_REMOVEPROPS Pq prop_dictionary_t
|
|
.Pp
|
|
This
|
|
.Xr ioctl 2
|
|
is used to remove all properties that are currently set via the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
ioctl.
|
|
The values will be set to defaults, the ones that the device uses.
|
|
.Pp
|
|
Only one object is allowed on this dictionary:
|
|
.Bd -literal -offset ident
|
|
\*[Lt]key\*[Gt]envsys-remove-props\*[Lt]/key\*[Gt]
|
|
\*[Lt]true/\*[Gt]
|
|
.Ed
|
|
.Pp
|
|
It is a boolean object and must be set to
|
|
.Em true
|
|
to be effective.
|
|
.It Dv ENVSYS_SETDICTIONARY Pq prop_dictionary_t
|
|
This
|
|
.Xr ioctl 2
|
|
is used to send a dictionary with new properties that should be
|
|
processed by the
|
|
.Nm
|
|
framework.
|
|
Only a set of predefined keywords are recognized by the kernel part.
|
|
The following is the property list representation
|
|
of a dictionary with all recognized and required keywords that
|
|
a sensor understands:
|
|
.Bd -literal
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]description\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]cpu temp\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]rfact\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]56000\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]critical-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]10\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]critical-max\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]3400\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]critical-min\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]2800\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]high-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]95\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]maximum-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]100\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]warning-capacity\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]15\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]warning-max\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]3200\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]warning-min\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]2900\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
.Ed
|
|
.Pp
|
|
Also if some properties in a device need to be changed, the
|
|
.Dq device-properties
|
|
dictionary must be used.
|
|
At this moment only the
|
|
.Dq refresh-timeout
|
|
property is understood.
|
|
This has the following structure:
|
|
.Bd -literal
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]device-properties\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]refresh-timeout\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]integer\&\*[Gt]0xa\&\*[Lt]\&/integer\&\*[Gt]
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
.Ed
|
|
.Pp
|
|
A dictionary sent to the kernel with this
|
|
.Xr ioctl 2
|
|
should have the following structure:
|
|
.Bd -literal
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]device_name\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]array\&\*[Gt]
|
|
\&\*[Lt]dict\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]index\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]sensor0\&\*[Lt]\&/string\&\*[Gt]
|
|
\&\*[Lt]key\&\*[Gt]description\&\*[Lt]\&/key\&\*[Gt]
|
|
\&\*[Lt]string\&\*[Gt]cpu temp\&\*[Lt]\&/string\&\*[Gt]
|
|
...
|
|
Another property for this sensor
|
|
...
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
...
|
|
Another dictionary for device-properties or sensor
|
|
...
|
|
\&\*[Lt]\&/array\&\*[Gt]
|
|
...
|
|
Another device as above
|
|
...
|
|
\&\*[Lt]\&/dict\&\*[Gt]
|
|
.Ed
|
|
.Pp
|
|
The named device will be an array and will contain dictionaries,
|
|
any dictionary needs to have the
|
|
.Em index
|
|
object specifying the sensor that is required for the new properties.
|
|
.Pp
|
|
If an unknown object was sent with the dictionary,
|
|
.Er EINVAL
|
|
will be returned, or if the sensor does not support changing
|
|
rfact (voltage sensors) or critical/warning/capacity limits,
|
|
.Er ENOTSUP
|
|
will be returned.
|
|
.El
|
|
.Sh NOTES
|
|
When setting a critical/warning max or min limit with the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 ,
|
|
the user must be aware that
|
|
.Xr sysmon_envsys 9
|
|
expects to have a proper unit, so the value must be converted.
|
|
Please see
|
|
.Xr sysmon_envsys 9
|
|
for more information.
|
|
.Pp
|
|
Also when setting a critical or warning capacity limit, the formula to send a
|
|
proper value to
|
|
.Xr sysmon_envsys 9
|
|
is the following:
|
|
.Em value = (value / 100) * max value .
|
|
The max value is available in the sensor's dictionary.
|
|
.Sh EXAMPLES
|
|
The following example shows how to change the description
|
|
of
|
|
.Ql sensor0
|
|
in the
|
|
.Ql aibs0
|
|
device with the
|
|
.Dv ENVSYS_SETDICTIONARY
|
|
.Xr ioctl 2 :
|
|
.Bd -literal
|
|
int
|
|
main(void)
|
|
{
|
|
prop_dictionary_t global_dict, sensor_dict;
|
|
prop_array_t array;
|
|
prop_object_t obj;
|
|
int fd, error;
|
|
|
|
global_dict = prop_dictionary_create();
|
|
sensor_dict = prop_dictionary_create();
|
|
array = prop_array_create();
|
|
|
|
if (!prop_dictionary_set(global_dict, "aibs0", array))
|
|
err(EINVAL, "prop_dictionary_set global");
|
|
|
|
obj = prop_string_create_cstring_nocopy("sensor0");
|
|
if (obj == NULL ||
|
|
!prop_dictionary_set(sensor_dict, "index", obj))
|
|
err(EINVAL, "sensor index");
|
|
|
|
prop_object_release(obj);
|
|
|
|
/* new description */
|
|
obj = prop_string_create_cstring_nocopy("CPU core voltage");
|
|
if (obj == NULL ||
|
|
!prop_dictionary_set(sensor_dict, "description", obj))
|
|
err(EINVAL, "new description");
|
|
|
|
prop_object_release(obj);
|
|
|
|
if (!prop_array_add(array, sensor_dict))
|
|
err(EINVAL, "prop_array_add");
|
|
|
|
if ((fd = open(_DEV_SYSMON, O_RDWR)) == \-1)
|
|
err(EXIT_FAILURE, "open");
|
|
|
|
/* we are done, send the dictionary */
|
|
error = prop_dictionary_send_ioctl(global_dict,
|
|
fd,
|
|
ENVSYS_SETDICTIONARY);
|
|
prop_object_release(array);
|
|
prop_object_release(global_dict);
|
|
(void)close(fd);
|
|
return error;
|
|
}
|
|
.Ed
|
|
.Sh SEE ALSO
|
|
.Xr envsys.conf 5 ,
|
|
.Xr envstat 8 ,
|
|
.Xr powerd 8 ,
|
|
.Xr sysmon_envsys 9
|
|
.Sh HISTORY
|
|
The first
|
|
.Em envsys
|
|
framework first appeared in
|
|
.Nx 1.5 .
|
|
The
|
|
.Em envsys 2
|
|
framework first appeared in
|
|
.Nx 5.0 .
|
|
.Sh AUTHORS
|
|
The (current)
|
|
.Em envsys 2
|
|
framework was implemented by
|
|
.An Juan Romero Pardines .
|
|
Additional input on the design was provided by many
|
|
.Nx
|
|
developers around the world.
|
|
.Pp
|
|
The first
|
|
.Em envsys
|
|
framework was implemented by Jason R. Thorpe, Tim Rightnour,
|
|
and Bill Squier.
|