experimental erlang driver

This commit is contained in:
Doug MacEachern 2009-06-14 21:29:08 -07:00
parent 0cecd10a4d
commit 22c0d9e356
17 changed files with 858 additions and 1 deletions

View File

@ -1625,6 +1625,13 @@ $comment
EOF
}
sub erl_warning_comment {
my $self = shift;
my $comment = $self->warning_comment;
$comment =~ s/^/% /mg;
"$comment\n";
}
sub generate {
my($lang, $dir) = @_ ? @_ : @ARGV;
@ -1689,7 +1696,9 @@ sub uptodate {
return 1;
}
my(%warning_comment) = map { $_ => \&c_warning_comment } qw(c h java);
my(%warning_comment) =
((map { $_ => \&c_warning_comment } qw(c h java)),
(map { $_ => \&erl_warning_comment } qw(erl hrl)));
sub create {
my($self, $file) = @_;
@ -2777,6 +2786,168 @@ sub finish {
$self->SUPER::finish;
}
package SigarWrapper::Erlang;
use vars qw(@ISA);
@ISA = qw(SigarWrapper);
my %field_types = (
Long => "esigar_encode_ulonglong",
Double => "esigar_encode_double",
Int => "esigar_encode_long",
Char => "esigar_encode_char",
String => "esigar_encode_string",
NetAddress => "esigar_encode_netaddr",
);
my $c_file = 'priv/gen/sigar_drv_gen.c';
my $h_file = 'priv/gen/sigar.hrl';
my $g_file = 'priv/gen/sigar_gen.hrl';
sub sources {
return $c_file;
}
sub start {
my $self = shift;
$self->SUPER::start;
$self->{cfh} = $self->create($c_file);
$self->{hfh} = $self->create($h_file);
$self->{gfh} = $self->create($g_file);
}
sub generate_class {
my($self, $func) = @_;
my $cfh = $self->{cfh};
my $cname = $func->{cname};
my $parse_args = "";
my $vars = "";
my $args = 'sigar';
if ($func->{num_args} == 1) {
if ($func->{is_proc}) {
$parse_args = 'pid = esigar_pid_get(sigar, bytes);';
$vars = "long $func->{arg};\n";
}
else {
$parse_args .= 'name = bytes;';
$vars = "char *$func->{arg};\n";
}
$args .= ", $func->{arg}";
}
my $encoder = "esigar_encode_$cname";
my $n = scalar @{ $func->{fields} };
print $cfh <<EOF;
static void $encoder(ei_x_buff *x,
$func->{sigar_type} *$cname)
{
ei_x_encode_list_header(x, $n);
EOF
for my $field (@{ $func->{fields} }) {
my $name = $field->{name};
my $type = $field_types{ $field->{type} };
print $cfh qq{ $type(x, "$name", $cname->$name);\n};
}
print $cfh " ei_x_encode_empty_list(x);\n}\n\n";
print $cfh <<EOF if $func->{has_get};
static int e$func->{sigar_function}(ErlDrvPort port, sigar_t *sigar, char *bytes)
{
int status;
ei_x_buff x;
$func->{sigar_type} $cname;
$vars
$parse_args
ESIGAR_NEW(&x);
if ((status = $func->{sigar_function}($args, &$cname)) == SIGAR_OK) {
ESIGAR_OK(&x);
$encoder(&x, &$cname);
ESIGAR_SEND(port, &x);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
return status;
}
EOF
}
my(@nongens) =
qw{net_interface_list net_route_list net_connection_list
file_system_list cpu_info_list who_list
loadavg};
sub finish {
my $self = shift;
my $mappings = $self->get_mappings;
my $cfh = $self->{cfh};
my $hfh = $self->{hfh};
my $gfh = $self->{gfh};
my $ncmd = 1;
for my $ngen (@nongens) {
my $cmd = uc $ngen;
print $cfh "#define ESIGAR_$cmd $ncmd\n";
print $hfh "-define($cmd, $ncmd).\n";
$ncmd++;
}
for my $func (@$mappings) {
next unless $func->{has_get};
my $name = $func->{cname};
my $cmd = uc $name;
my $nargs = 1 + $func->{num_args};
print $cfh "#define ESIGAR_$cmd $ncmd\n";
print $hfh "-define($cmd, $ncmd).\n";
print $hfh "-export([$name/$nargs]).\n";
$ncmd++;
}
print $cfh <<EOF;
static int esigar_dispatch(ErlDrvPort port, sigar_t *sigar, int cmd, char *bytes) {
switch (cmd) {
EOF
for my $func (@$mappings) {
next unless $func->{has_get};
my $name = $func->{cname};
my $cmd = uc $name;
my $arg = "";
if ($func->{num_args}) {
$arg = ", Arg";
}
print $gfh <<EOF;
$name({sigar, S}$arg) ->
do_command(S, ?$cmd$arg).
EOF
print $cfh <<EOF
case ESIGAR_$cmd:
return e$func->{sigar_function}(port, sigar, bytes);
EOF
}
print $cfh <<EOF;
default:
esigar_notimpl(port, sigar, cmd);
return SIGAR_ENOTIMPL;
}
}
EOF
$self->SUPER::finish;
}
#XXX not currently supporting netware
package SigarWrapper::Netware;

12
bindings/erl/Makefile Normal file
View File

@ -0,0 +1,12 @@
all:
perl -Mlib=.. -MSigarWrapper -e generate Erlang .
cd src && make
cd c_src && make
shell:
make all
erl -pa ebin
clean:
cd src && make clean
cd c_src && make clean

View File

@ -0,0 +1,40 @@
## SIGAR driver for Erlang
If you're not already familar with sigar, have a look at the [SIGAR Wiki](http://sigar.hyperic.com).
Also helpful: **../../include/sigar.h**, **../*/examples** and
**../java/src/org/hyperic/sigar/cmd/** to get an idea of what you can do.
### Building
The other bindings/* inline the libsigar sources by default, haven't done that yet for erl.
So, you'll need a libsigar to link against, one of:
Ant build:
cd ../java ; ant
ln -s sigar-bin/lib/libsigar-amd64-linux.so sigar-lib/lib/libsigar.so
Or, download release binary created by the ant build:
curl -o priv/libsigar.so http://svn.hyperic.org/projects/sigar_bin/dist/SIGAR_1_6_2/lib/libsigar-amd64-linux.so
Or, top-level autotools build (WIP):
cd ../.. ; ./autogen.sh && ./configure && make install
Once you have a libsigar in place, just run **make** and have a look at the **examples/**.
Note that the majority of the driver code is generated by **../SigarWrapper.pm** and output to **priv/gen**.
### ToDo/Help Wanted
* Fill out the **examples/** - currently weaksauce in part due to me having just a few hours w/ Erlang
* Build system - doubt the current will work anywhere cept Linux
* EUnit
* Other stuff Erlangers know that I don't

View File

@ -0,0 +1,16 @@
GCC = gcc
OTP_ROOT = $(shell ./check_otp -root)
EI_ROOT = $(shell ./check_otp -ei)
EI_LIB = $(EI_ROOT)/lib
EI_INC = $(EI_ROOT)/include
SIGAR_LIB = ../../java/sigar-bin/lib
LDFLAGS = -shared -L${EI_LIB} -lei -lpthread -L${SIGAR_LIB} -L../priv -lsigar
SRCS = sigar_drv.c
OUTPUT = ../priv/sigar_drv.so
CFLAGS = -Wall -fPIC -I../../../include -I${OTP_ROOT}/usr/include -I${EI_INC} -o ${OUTPUT}
all:
${GCC} ${SRCS} ${LDFLAGS} ${CFLAGS}
clean:
rm -rf ${OUTPUT} ../priv/gen/*.c ../priv/gen/*.hrl

17
bindings/erl/c_src/check_otp Executable file
View File

@ -0,0 +1,17 @@
#!/bin/bash
#copied from jungerl
if [ "$1" == "-root" -o "$1" == "" ]; then
erl -noinput -eval 'io:format("~s~n", [code:root_dir()]), halt(0).'
fi
if [ "$1" == "-ei" -o "$1" == "" ]; then
erl -noinput -eval \
'case code:lib_dir("erl_interface") of
{error, bad_name} ->
io:format("not found~n", []),
halt(1);
LibDir ->
io:format("~s~n", [LibDir]),
halt(0)
end.'
fi

View File

@ -0,0 +1,394 @@
#include <erl_driver.h>
#include <ei.h>
#include <ctype.h>
#include <string.h>
#include "sigar.h"
#include "sigar_fileinfo.h"
#include "sigar_format.h"
#include "sigar_ptql.h"
typedef struct {
ErlDrvPort port;
sigar_t *sigar;
} sigar_drv_t;
static ErlDrvData start(ErlDrvPort port, char *cmd) {
sigar_drv_t *sd = (sigar_drv_t *)driver_alloc(sizeof(*sd));
int status;
status = sigar_open(&sd->sigar);
if (status != SIGAR_OK) {
sd->sigar = NULL;
driver_failure_posix(port, status);
}
sd->port = port;
return (ErlDrvData)sd;
}
static void stop(ErlDrvData handle) {
sigar_drv_t *driver_data = (sigar_drv_t *)handle;
if (driver_data->sigar) {
sigar_close(driver_data->sigar);
}
}
#ifdef SIGAR_64BIT
#define str2pid(value) strtoull(value, NULL, 10)
#else
#define str2pid(value) strtoul(value, NULL, 10)
#endif
static sigar_pid_t esigar_pid_get(sigar_t *sigar, char *pid)
{
if (isdigit(*pid)) {
return str2pid(pid);
}
else if ((*pid == '$') && (*(pid + 1) == '$')) {
return sigar_pid_get(sigar);
}
else {
/* XXX cache queries */
sigar_ptql_query_t *query;
sigar_ptql_error_t error;
int status =
sigar_ptql_query_create(&query, (char *)pid, &error);
if (status == SIGAR_OK) {
sigar_pid_t qpid;
status = sigar_ptql_query_find_process(sigar, query, &qpid);
sigar_ptql_query_destroy(query);
if (status == SIGAR_OK) {
return qpid;
}
}
}
return 0;
}
static void esigar_to_strlist(ei_x_buff *x,
char **data, unsigned long number)
{
unsigned long i;
ei_x_encode_list_header(x, number);
for (i=0; i<number; i++) {
ei_x_encode_string(x, data[i]);
}
ei_x_encode_empty_list(x);
}
typedef void (*esigar_encoder_func_t)(ei_x_buff *x, void *data);
static void esigar_to_list(ei_x_buff *x,
char *data, unsigned long number, int size,
esigar_encoder_func_t encoder)
{
unsigned long i;
ei_x_encode_list_header(x, number);
for (i=0; i<number; i++, data += size) {
encoder(x, data);
}
ei_x_encode_empty_list(x);
}
#define ESIGAR_NEW(x) \
ei_x_new_with_version(x)
#define ESIGAR_OK(x) \
ei_x_encode_tuple_header(x, 2); \
ei_x_encode_atom(x, "ok")
#define ESIGAR_ERROR(x, sigar, status) \
ei_x_encode_tuple_header(x, 2); \
ei_x_encode_atom(x, "error"); \
ei_x_encode_string(x, sigar_strerror(sigar, status))
#define ESIGAR_SEND(p, x) \
driver_output(port, (x)->buff, (x)->index); \
ei_x_free(x)
#define esigar_encode_long(x, k, v) \
ei_x_encode_tuple_header(x, 2); \
ei_x_encode_atom(x, k); \
ei_x_encode_long(x, v)
#define esigar_encode_ulonglong(x, k, v) \
ei_x_encode_tuple_header(x, 2); \
ei_x_encode_atom(x, k); \
ei_x_encode_ulonglong(x, v)
#define esigar_encode_char(x, k, v) \
ei_x_encode_tuple_header(x, 2); \
ei_x_encode_atom(x, k); \
ei_x_encode_char(x, v)
#define esigar_encode_string(x, k, v) \
ei_x_encode_tuple_header(x, 2); \
ei_x_encode_atom(x, k); \
ei_x_encode_string(x, v)
#define esigar_encode_double(x, k, v) \
ei_x_encode_tuple_header(x, 2); \
ei_x_encode_atom(x, k); \
ei_x_encode_double(x, v)
static void esigar_encode_net_address(ei_x_buff *x, const char *key,
sigar_net_address_t *address)
{
char buf[SIGAR_INET6_ADDRSTRLEN];
sigar_net_address_to_string(NULL, address, buf);
esigar_encode_string(x, key, buf);
}
#define esigar_encode_netaddr(x, k, v) \
esigar_encode_net_address(x, k, &v)
static void esigar_notimpl(ErlDrvPort port, sigar_t *sigar, int cmd)
{
ei_x_buff x;
ESIGAR_NEW(&x);
ESIGAR_ERROR(&x, sigar, SIGAR_ENOTIMPL);
ESIGAR_SEND(port, &x);
}
#include "../priv/gen/sigar_drv_gen.c"
static void esigar_loadavg_get(ErlDrvPort port, sigar_t *sigar)
{
int status;
ei_x_buff x;
sigar_loadavg_t loadavg;
ESIGAR_NEW(&x);
if ((status = sigar_loadavg_get(sigar, &loadavg)) == SIGAR_OK) {
ESIGAR_OK(&x);
ei_x_encode_list_header(&x, 3);
ei_x_encode_double(&x, loadavg.loadavg[0]);
ei_x_encode_double(&x, loadavg.loadavg[1]);
ei_x_encode_double(&x, loadavg.loadavg[2]);
ei_x_encode_empty_list(&x);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
ESIGAR_SEND(port, &x);
}
static void esigar_net_connection_list_get(ErlDrvPort port, sigar_t *sigar,
unsigned int flags)
{
int status;
ei_x_buff x;
sigar_net_connection_list_t list;
ei_x_new_with_version(&x);
if ((status = sigar_net_connection_list_get(sigar, &list, flags) == SIGAR_OK)) {
ESIGAR_OK(&x);
esigar_to_list(&x,
(char *)&list.data[0], list.number,
sizeof(*list.data),
(esigar_encoder_func_t)esigar_encode_net_connection);
sigar_net_connection_list_destroy(sigar, &list);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
ESIGAR_SEND(port, &x);
}
static void esigar_net_interface_list_get(ErlDrvPort port, sigar_t *sigar)
{
int status;
ei_x_buff x;
sigar_net_interface_list_t list;
ei_x_new_with_version(&x);
if ((status = sigar_net_interface_list_get(sigar, &list) == SIGAR_OK)) {
ESIGAR_OK(&x);
esigar_to_strlist(&x, list.data, list.number);
sigar_net_interface_list_destroy(sigar, &list);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
ESIGAR_SEND(port, &x);
}
static void esigar_file_system_list_get(ErlDrvPort port, sigar_t *sigar)
{
int status;
ei_x_buff x;
sigar_file_system_list_t list;
ei_x_new_with_version(&x);
if ((status = sigar_file_system_list_get(sigar, &list) == SIGAR_OK)) {
ESIGAR_OK(&x);
esigar_to_list(&x,
(char *)&list.data[0], list.number,
sizeof(*list.data),
(esigar_encoder_func_t)esigar_encode_file_system);
sigar_file_system_list_destroy(sigar, &list);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
ESIGAR_SEND(port, &x);
}
static void esigar_net_route_list_get(ErlDrvPort port, sigar_t *sigar)
{
int status;
ei_x_buff x;
sigar_net_route_list_t list;
ei_x_new_with_version(&x);
if ((status = sigar_net_route_list_get(sigar, &list) == SIGAR_OK)) {
ESIGAR_OK(&x);
esigar_to_list(&x,
(char *)&list.data[0], list.number,
sizeof(*list.data),
(esigar_encoder_func_t)esigar_encode_net_route);
sigar_net_route_list_destroy(sigar, &list);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
ESIGAR_SEND(port, &x);
}
static void esigar_cpu_info_list_get(ErlDrvPort port, sigar_t *sigar)
{
int status;
ei_x_buff x;
sigar_cpu_info_list_t list;
ei_x_new_with_version(&x);
if ((status = sigar_cpu_info_list_get(sigar, &list) == SIGAR_OK)) {
ESIGAR_OK(&x);
esigar_to_list(&x,
(char *)&list.data[0], list.number,
sizeof(*list.data),
(esigar_encoder_func_t)esigar_encode_cpu_info);
sigar_cpu_info_list_destroy(sigar, &list);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
ESIGAR_SEND(port, &x);
}
static void esigar_who_list_get(ErlDrvPort port, sigar_t *sigar)
{
int status;
ei_x_buff x;
sigar_who_list_t list;
ei_x_new_with_version(&x);
if ((status = sigar_who_list_get(sigar, &list) == SIGAR_OK)) {
ESIGAR_OK(&x);
esigar_to_list(&x,
(char *)&list.data[0], list.number,
sizeof(*list.data),
(esigar_encoder_func_t)esigar_encode_who);
sigar_who_list_destroy(sigar, &list);
}
else {
ESIGAR_ERROR(&x, sigar, status);
}
ESIGAR_SEND(port, &x);
}
static void outputv(ErlDrvData handle, ErlIOVec *ev) {
sigar_drv_t *sd = (sigar_drv_t *)handle;
sigar_t *sigar = sd->sigar;
ErlDrvPort port = sd->port;
ErlDrvBinary *data = ev->binv[1];
int cmd = data->orig_bytes[0];
switch(cmd) {
case ESIGAR_NET_CONNECTION_LIST:
esigar_net_connection_list_get(port, sigar,
data->orig_bytes[1]);
break;
case ESIGAR_NET_INTERFACE_LIST:
esigar_net_interface_list_get(port, sigar);
break;
case ESIGAR_NET_ROUTE_LIST:
esigar_net_route_list_get(port, sigar);
break;
case ESIGAR_FILE_SYSTEM_LIST:
esigar_file_system_list_get(port, sigar);
break;
case ESIGAR_CPU_INFO_LIST:
esigar_cpu_info_list_get(port, sigar);
break;
case ESIGAR_WHO_LIST:
esigar_who_list_get(port, sigar);
break;
case ESIGAR_LOADAVG:
esigar_loadavg_get(port, sigar);
break;
default:
esigar_dispatch(port, sigar, cmd, &data->orig_bytes[1]);
break;
}
}
static ErlDrvEntry sigar_driver_entry = {
NULL, /* init */
start, /* startup */
stop, /* shutdown */
NULL, /* output */
NULL, /* ready_input */
NULL, /* ready_output */
"sigar_drv", /* name of the driver */
NULL, /* finish */
NULL, /* handle */
NULL, /* control */
NULL, /* timeout */
outputv, /* outputv */
NULL, /* ready_async */
NULL, /* flush */
NULL, /* call */
NULL, /* event */
ERL_DRV_EXTENDED_MARKER, /* ERL_DRV_EXTENDED_MARKER */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MAJOR_VERSION */
ERL_DRV_EXTENDED_MAJOR_VERSION, /* ERL_DRV_EXTENDED_MINOR_VERSION */
ERL_DRV_FLAG_USE_PORT_LOCKING /* ERL_DRV_FLAGs */
};
DRIVER_INIT(sigar_driver) {
return &sigar_driver_entry;
}

1
bindings/erl/ebin/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.beam

14
bindings/erl/examples/df.erl Executable file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env escript
-include(sigar).
main(_) ->
{ok, S} = sigar:start(),
{ok, FsList} = sigar:file_system_list(S),
lists:map(
fun(Fs) ->
io:format("~s ~n", [sigar:get_value(dir_name, Fs)]) end,
FsList),
sigar:stop(S).

25
bindings/erl/examples/free.erl Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env escript
-include(sigar).
main(_) ->
{ok, S} = sigar:start(),
{ok, Mem} = sigar:mem(S),
io:format("\tTotal\tUsed\tFree~n"),
io:format("Mem: "),
lists:map(
fun(K) ->
io:format("~w\t", [sigar:get_value(K, Mem)/1024]) end,
[total, used, free]),
io:format("~n"),
{ok, Swap} = sigar:swap(S),
io:format("Swap: "),
lists:map(
fun(K) ->
io:format("~w\t", [sigar:get_value(K, Swap)/1024]) end,
[total, used, free]),
io:format("~n"),
io:format("RAM: ~wMB~n", [sigar:get_value(ram, Mem)]),
sigar:stop(S).

View File

@ -0,0 +1,15 @@
#!/usr/bin/env escript
-include(sigar).
main(_) ->
{ok, S} = sigar:start(),
{ok, Names} = sigar:net_interface_list(S),
lists:map(
fun(K) ->
{ok, Ifconfig} = sigar:net_interface_config(S, K),
io:format("~s ~s~n", [K, sigar:get_value(address, Ifconfig)]) end,
Names),
sigar:stop(S).

16
bindings/erl/examples/ps.erl Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env escript
-include(sigar).
main(_) ->
{ok, S} = sigar:start(),
{ok, Mem} = sigar:proc_mem(S, "$$"),
io:format("Size\tResident~n"),
lists:map(
fun(K) ->
io:format("~w\t", [sigar:get_value(K, Mem)/1024]) end,
[size, resident]),
io:format("~n"),
sigar:stop(S).

View File

@ -0,0 +1,19 @@
#!/usr/bin/env escript
-include(sigar).
main(_) ->
{ok, S} = sigar:start(),
case sigar:loadavg(S) of
{ok, Avg} ->
lists:map(
fun(A) ->
io:format("~w% ", [A]) end,
Avg);
{error, Err} ->
Err
end,
io:format("~n"),
sigar:stop(S).

16
bindings/erl/examples/who.erl Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env escript
-include(sigar).
main(_) ->
{ok, S} = sigar:start(),
{ok, List} = sigar:who_list(S),
lists:map(
fun(Who) ->
lists:map(
fun(K) ->
io:format("~s\t", [sigar:get_value(K, Who)]) end,
[user, device, host]),
io:format("~n")
end, List),
sigar:stop(S).

1
bindings/erl/priv/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.so

2
bindings/erl/priv/gen/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.c
*.hrl

11
bindings/erl/src/Makefile Normal file
View File

@ -0,0 +1,11 @@
ERLC=erlc
EBIN=../ebin
INCLUDE=../include
EFLAGS=-I ${INCLUDE} -o ${EBIN}
SRCS=`ls *.erl`
all:
${ERLC} ${EFLAGS} ${SRCS}
clean:
rm -rf ${EBIN}/*.beam

View File

@ -0,0 +1,87 @@
-module(sigar).
% generated by SigarWrapper.pm
-include("../priv/gen/sigar.hrl").
-export([start/0, stop/1, get_value/2]).
% handrolled wrappers
-export([loadavg/1,
net_connection_list/2,
net_interface_list/1,
net_route_list/1,
file_system_list/1,
cpu_info_list/1,
who_list/1]).
-define(NETCONN_CLIENT, 0x01).
-define(NETCONN_SERVER, 0x02).
-define(SIGAR_NETCONN_TCP, 0x10).
-define(SIGAR_NETCONN_UDP, 0x20).
-define(SIGAR_NETCONN_RAW, 0x40).
-define(SIGAR_NETCONN_UNIX, 0x80).
start() ->
case load_driver() of
ok ->
S = open_port({spawn, 'sigar_drv'}, [binary]),
{ok, {sigar, S}};
{error, Err} ->
Msg = erl_ddll:format_error(Err),
{error, Msg}
end.
% handrolled wrappers
loadavg({sigar, S}) ->
do_command(S, ?LOADAVG).
net_connection_list({sigar, S}, F) ->
do_command(S, ?NET_CONNECTION_LIST, F).
net_interface_list({sigar, S}) ->
do_command(S, ?NET_INTERFACE_LIST).
net_route_list({sigar, S}) ->
do_command(S, ?NET_ROUTE_LIST).
file_system_list({sigar, S}) ->
do_command(S, ?FILE_SYSTEM_LIST).
cpu_info_list({sigar, S}) ->
do_command(S, ?CPU_INFO_LIST).
who_list({sigar, S}) ->
do_command(S, ?WHO_LIST).
% generated by SigarWrapper.pm
-include("../priv/gen/sigar_gen.hrl").
% XXX must be a better way
get_value(Key, List) ->
case lists:keysearch(Key,1,List) of
false ->
1;
{ value, {Key, N} } ->
N
end.
stop({sigar, S}) ->
unlink(S),
port_close(S).
load_driver() ->
Dir = filename:join([filename:dirname(code:which(sigar)), "..", "priv"]),
erl_ddll:load(Dir, "sigar_drv").
do_command(S, C) ->
port_command(S, [C]),
receive
{S, {data, Bin}} -> binary_to_term(Bin)
end.
do_command(S, C, A) ->
port_command(S, [C, A]),
receive
{S, {data, Bin}} -> binary_to_term(Bin)
end.