AC_HEADER_SYS_WAIT
AC_HEADER_DIRENT
- AC_CHECK_HEADERS(stdint.h stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h)
+ AC_CHECK_HEADERS(stdint.h stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h)
# For ping library
AC_CHECK_HEADERS(netinet/in_systm.h, [], [],
then
with_libcurl="no ($with_curl_config failed)"
else
- SAVE_CFLAGS=$CFLAGS
- CFLAGS="$CFLAGS $with_curl_cflags"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_curl_cflags"
AC_CHECK_HEADERS(curl/curl.h, [], [with_libcurl="no (curl/curl.h not found)"], [])
- CFLAGS="$SAVE_CFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
fi
if test "x$with_libcurl" = "xyes"
then
with_libmysql="no"
else
- SAVE_CFLAGS=$CFLAGS
- CFLAGS="$CFLAGS $with_mysql_cflags"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_mysql_cflags"
AC_CHECK_HEADERS(mysql/mysql.h, [], [with_libmysql="no (mysql/mysql.h not found)"], [])
- CFLAGS="$SAVE_CFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
fi
if test "x$with_libmysql" = "xyes"
then
with_libnetsnmp="no ($with_snmp_config failed)"
else
- SAVE_CFLAGS=$CFLAGS
- CFLAGS="$CFLAGS $with_snmp_cflags"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_snmp_cflags"
AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"])
- CFLAGS="$SAVE_CFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
fi
if test "x$with_libnetsnmp" = "xyes"
fi
if test "x$with_libupsclient" = "xyes"
then
- SAVE_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $with_upsclient_cflags"
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_upsclient_cflags"
AC_CHECK_HEADERS(upsclient.h, [], [with_libupsclient="no (upsclient.h not found)"])
- CFLAGS="$SAVE_CFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
if test "x$with_libupsclient" = "xyes"
then
fi
if test "x$with_libupsclient" = "xyes"
then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_upsclient_cflags"
+
AC_CHECK_TYPES([UPSCONN_t, UPSCONN], [], [],
[#include <stdlib.h>
#include <stdio.h>
#include <upsclient.h>])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
AM_CONDITIONAL(BUILD_WITH_LIBUPSCLIENT, test "x$with_libupsclient" = "xyes")
plugin_tape="no"
plugin_tcpconns="no"
plugin_users="no"
+plugin_vmem="no"
plugin_vserver="no"
plugin_wireless="no"
plugin_serial="yes"
plugin_swap="yes"
plugin_tcpconns="yes"
+ plugin_vmem="yes"
plugin_vserver="yes"
plugin_wireless="yes"
AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter])
AC_PLUGIN([ping], [$with_liboping], [Network latency statistics])
+AC_PLUGIN([powerdns], [yes], [PowerDNS statistics])
AC_PLUGIN([processes], [$plugin_processes], [Process statistics])
AC_PLUGIN([rrdtool], [$with_rrdtool], [RRDTool output plugin])
AC_PLUGIN([sensors], [$with_lm_sensors], [lm_sensors statistics])
AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin])
AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin])
+AC_PLUGIN([tail], [yes], [Parsing of logfiles])
AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics])
AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics])
AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin])
AC_PLUGIN([users], [$plugin_users], [User statistics])
AC_PLUGIN([uuid], [yes], [UUID as hostname plugin])
+AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics])
AC_PLUGIN([vserver], [$plugin_vserver], [Linux VServer statistics])
AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics])
AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics])
nut . . . . . . . . $enable_nut
perl . . . . . . . $enable_perl
ping . . . . . . . $enable_ping
+ powerdns . . . . . $enable_powerdns
processes . . . . . $enable_processes
rrdtool . . . . . . $enable_rrdtool
sensors . . . . . . $enable_sensors
snmp . . . . . . . $enable_snmp
swap . . . . . . . $enable_swap
syslog . . . . . . $enable_syslog
+ tail . . . . . . . $enable_tail
tape . . . . . . . $enable_tape
tcpconns . . . . . $enable_tcpconns
unixsock . . . . . $enable_unixsock
users . . . . . . . $enable_users
uuid . . . . . . . $enable_uuid
+ vmem . . . . . . . $enable_vmem
vserver . . . . . . $enable_vserver
wireless . . . . . $enable_wireless
xmms . . . . . . . $enable_xmms
/**
* collectd - src/plugin.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2008 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
*
* Authors:
* Florian octo Forster <octo at verplant.org>
+ * Sebastian Harl <sh at tokkee.org>
**/
#include "collectd.h"
static llist_t *list_init;
static llist_t *list_read;
static llist_t *list_write;
+static llist_t *list_flush;
static llist_t *list_shutdown;
static llist_t *list_log;
static llist_t *list_notification;
{
DIR *dh;
const char *dir;
- char filename[BUFSIZE];
+ char filename[BUFSIZE] = "";
char typename[BUFSIZE];
int typename_len;
int ret;
closedir (dh);
+ if (filename[0] == '\0')
+ fprintf (stderr, "Could not find plugin %s.\n", type);
+
return (ret);
}
return (register_callback (&list_write, name, (void *) callback));
} /* int plugin_register_write */
+int plugin_register_flush (const char *name, int (*callback) (const int))
+{
+ return (register_callback (&list_flush, name, (void *) callback));
+} /* int plugin_register_flush */
+
int plugin_register_shutdown (char *name,
int (*callback) (void))
{
return (plugin_unregister (list_write, name));
}
+int plugin_unregister_flush (const char *name)
+{
+ return (plugin_unregister (list_flush, name));
+}
+
int plugin_unregister_shutdown (const char *name)
{
return (plugin_unregister (list_shutdown, name));
pthread_mutex_unlock (&read_lock);
} /* void plugin_read_all */
+int plugin_flush_one (int timeout, const char *name)
+{
+ int (*callback) (int);
+ llentry_t *le;
+ int status;
+
+ if (list_flush == NULL)
+ return (-1);
+
+ le = llist_search (list_flush, name);
+ if (le == NULL)
+ return (-1);
+ callback = (int (*) (int)) le->value;
+
+ status = (*callback) (timeout);
+
+ return (status);
+} /* int plugin_flush_ont */
+
+void plugin_flush_all (int timeout)
+{
+ int (*callback) (int);
+ llentry_t *le;
+
+ if (list_flush == NULL)
+ return;
+
+ le = llist_head (list_flush);
+ while (le != NULL)
+ {
+ callback = (int (*) (int)) le->value;
+ le = le->next;
+
+ (*callback) (timeout);
+ }
+} /* void plugin_flush_all */
+
void plugin_shutdown_all (void)
{
int (*callback) (void);
data_set_t *ds;
llentry_t *le;
- if ((list_write == NULL) || (data_sets == NULL))
+ if (list_write == NULL)
+ {
+ ERROR ("plugin_dispatch_values: No write callback has been "
+ "registered. Please load at least one plugin "
+ "that provides a write function.");
+ return (-1);
+ }
+
+ if (data_sets == NULL)
+ {
+ ERROR ("plugin_dispatch_values: No data sets registered. "
+ "Could the types database be read? Check "
+ "your `TypesDB' setting!");
return (-1);
+ }
if (c_avl_get (data_sets, name, (void *) &ds) != 0)
{
- DEBUG ("No such dataset registered: %s", name);
+ INFO ("plugin_dispatch_values: Dataset not found: %s", name);
return (-1);
}
- DEBUG ("plugin: plugin_dispatch_values: time = %u; interval = %i; "
+ DEBUG ("plugin_dispatch_values: time = %u; interval = %i; "
"host = %s; "
"plugin = %s; plugin_instance = %s; "
"type = %s; type_instance = %s;",
#else
if (ds->ds_num != vl->values_len)
{
- ERROR ("plugin: ds->type = %s: (ds->ds_num = %i) != "
+ ERROR ("plugin_dispatch_values: ds->type = %s: "
+ "(ds->ds_num = %i) != "
"(vl->values_len = %i)",
ds->type, ds->ds_num, vl->values_len);
return (-1);
#include "plugin.h"
#include "configfile.h"
+#include "utils_cmd_flush.h"
+#include "utils_cmd_getval.h"
+#include "utils_cmd_listval.h"
#include "utils_cmd_putval.h"
#include "utils_cmd_putnotif.h"
#define US_DEFAULT_PATH LOCALSTATEDIR"/run/"PACKAGE_NAME"-unixsock"
/*
- * Private data structures
- */
-/* linked list of cached values */
-typedef struct value_cache_s
-{
- char name[4*DATA_MAX_NAME_LEN];
- int values_num;
- gauge_t *gauge;
- counter_t *counter;
- const data_set_t *ds;
- time_t time;
- struct value_cache_s *next;
-} value_cache_t;
-
-/*
* Private variables
*/
/* valid configuration file keys */
{
"SocketFile",
"SocketGroup",
- "SocketPerms",
- NULL
+ "SocketPerms"
};
-static int config_keys_num = 3;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static int loop = 0;
static pthread_t listen_thread = (pthread_t) 0;
-/* Linked list and auxilliary variables for saving values */
-static value_cache_t *cache_head = NULL;
-static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
-static time_t cache_oldest = -1;
-
/*
* Functions
*/
-static value_cache_t *cache_search (const char *name)
-{
- value_cache_t *vc;
-
- for (vc = cache_head; vc != NULL; vc = vc->next)
- {
- if (strcmp (vc->name, name) == 0)
- break;
- } /* for vc = cache_head .. NULL */
-
- return (vc);
-} /* value_cache_t *cache_search */
-
-static int cache_insert (const data_set_t *ds, const value_list_t *vl)
-{
- /* We're called from `cache_update' so we don't need to lock the mutex */
- value_cache_t *vc;
- int i;
-
- DEBUG ("unixsock plugin: cache_insert: ds->type = %s; ds->ds_num = %i;"
- " vl->values_len = %i;",
- ds->type, ds->ds_num, vl->values_len);
-#if COLLECT_DEBUG
- assert (ds->ds_num == vl->values_len);
-#else
- if (ds->ds_num != vl->values_len)
- {
- ERROR ("unixsock plugin: ds->type = %s: (ds->ds_num = %i) != "
- "(vl->values_len = %i)",
- ds->type, ds->ds_num, vl->values_len);
- return (-1);
- }
-#endif
-
- vc = (value_cache_t *) malloc (sizeof (value_cache_t));
- if (vc == NULL)
- {
- char errbuf[1024];
- pthread_mutex_unlock (&cache_lock);
- ERROR ("unixsock plugin: malloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- vc->gauge = (gauge_t *) malloc (sizeof (gauge_t) * vl->values_len);
- if (vc->gauge == NULL)
- {
- char errbuf[1024];
- pthread_mutex_unlock (&cache_lock);
- ERROR ("unixsock plugin: malloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- free (vc);
- return (-1);
- }
-
- vc->counter = (counter_t *) malloc (sizeof (counter_t) * vl->values_len);
- if (vc->counter == NULL)
- {
- char errbuf[1024];
- pthread_mutex_unlock (&cache_lock);
- ERROR ("unixsock plugin: malloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- free (vc->gauge);
- free (vc);
- return (-1);
- }
-
- if (FORMAT_VL (vc->name, sizeof (vc->name), vl, ds))
- {
- pthread_mutex_unlock (&cache_lock);
- ERROR ("unixsock plugin: FORMAT_VL failed.");
- free (vc->counter);
- free (vc->gauge);
- free (vc);
- return (-1);
- }
-
- for (i = 0; i < ds->ds_num; i++)
- {
- if (ds->ds[i].type == DS_TYPE_COUNTER)
- {
- vc->gauge[i] = 0.0;
- vc->counter[i] = vl->values[i].counter;
- }
- else if (ds->ds[i].type == DS_TYPE_GAUGE)
- {
- vc->gauge[i] = vl->values[i].gauge;
- vc->counter[i] = 0;
- }
- else
- {
- vc->gauge[i] = 0.0;
- vc->counter[i] = 0;
- }
- }
- vc->values_num = ds->ds_num;
- vc->ds = ds;
-
- vc->next = cache_head;
- cache_head = vc;
-
- vc->time = vl->time;
- if ((vc->time < cache_oldest) || (-1 == cache_oldest))
- cache_oldest = vc->time;
-
- pthread_mutex_unlock (&cache_lock);
- return (0);
-} /* int cache_insert */
-
-static int cache_update (const data_set_t *ds, const value_list_t *vl)
-{
- char name[4*DATA_MAX_NAME_LEN];;
- value_cache_t *vc;
- int i;
-
- if (FORMAT_VL (name, sizeof (name), vl, ds) != 0)
- return (-1);
-
- pthread_mutex_lock (&cache_lock);
-
- vc = cache_search (name);
-
- /* pthread_mutex_lock is called by cache_insert. */
- if (vc == NULL)
- return (cache_insert (ds, vl));
-
- assert (vc->values_num == ds->ds_num);
- assert (vc->values_num == vl->values_len);
-
- /* Avoid floating-point exceptions due to division by zero. */
- if (vc->time >= vl->time)
- {
- pthread_mutex_unlock (&cache_lock);
- ERROR ("unixsock plugin: vc->time >= vl->time. vc->time = %u; "
- "vl->time = %u; vl = %s;",
- (unsigned int) vc->time, (unsigned int) vl->time,
- name);
- return (-1);
- } /* if (vc->time >= vl->time) */
-
- /*
- * Update the values. This is possibly a lot more that you'd expect
- * because we honor min and max values and handle counter overflows here.
- */
- for (i = 0; i < ds->ds_num; i++)
- {
- if (ds->ds[i].type == DS_TYPE_COUNTER)
- {
- if (vl->values[i].counter < vc->counter[i])
- {
- if (vl->values[i].counter <= 4294967295U)
- {
- vc->gauge[i] = ((4294967295U - vl->values[i].counter)
- + vc->counter[i]) / (vl->time - vc->time);
- }
- else
- {
- vc->gauge[i] = ((18446744073709551615ULL - vl->values[i].counter)
- + vc->counter[i]) / (vl->time - vc->time);
- }
- }
- else
- {
- vc->gauge[i] = (vl->values[i].counter - vc->counter[i])
- / (vl->time - vc->time);
- }
-
- vc->counter[i] = vl->values[i].counter;
- }
- else if (ds->ds[i].type == DS_TYPE_GAUGE)
- {
- vc->gauge[i] = vl->values[i].gauge;
- vc->counter[i] = 0;
- }
- else
- {
- vc->gauge[i] = NAN;
- vc->counter[i] = 0;
- }
-
- if (isnan (vc->gauge[i])
- || (!isnan (ds->ds[i].min) && (vc->gauge[i] < ds->ds[i].min))
- || (!isnan (ds->ds[i].max) && (vc->gauge[i] > ds->ds[i].max)))
- vc->gauge[i] = NAN;
- } /* for i = 0 .. ds->ds_num */
-
- vc->ds = ds;
- vc->time = vl->time;
-
- if ((vc->time < cache_oldest) || (-1 == cache_oldest))
- cache_oldest = vc->time;
-
- pthread_mutex_unlock (&cache_lock);
- return (0);
-} /* int cache_update */
-
-static void cache_flush (int max_age)
-{
- value_cache_t *this;
- value_cache_t *prev;
- time_t now;
-
- pthread_mutex_lock (&cache_lock);
-
- now = time (NULL);
-
- if ((now - cache_oldest) <= max_age)
- {
- pthread_mutex_unlock (&cache_lock);
- return;
- }
-
- cache_oldest = now;
-
- prev = NULL;
- this = cache_head;
-
- while (this != NULL)
- {
- if ((now - this->time) <= max_age)
- {
- if (this->time < cache_oldest)
- cache_oldest = this->time;
-
- prev = this;
- this = this->next;
- continue;
- }
-
- if (prev == NULL)
- cache_head = this->next;
- else
- prev->next = this->next;
-
- free (this->gauge);
- free (this->counter);
- free (this);
-
- if (prev == NULL)
- this = cache_head;
- else
- this = prev->next;
- } /* while (this != NULL) */
-
- pthread_mutex_unlock (&cache_lock);
-} /* void cache_flush */
-
static int us_open_socket (void)
{
struct sockaddr_un sa;
return (0);
} /* int us_open_socket */
-static int us_handle_getval (FILE *fh, char **fields, int fields_num)
-{
- char *hostname;
- char *plugin;
- char *plugin_instance;
- char *type;
- char *type_instance;
- char name[4*DATA_MAX_NAME_LEN];
- value_cache_t *vc;
- int status;
- int i;
-
- if (fields_num != 2)
- {
- DEBUG ("unixsock plugin: Wrong number of fields: %i", fields_num);
- fprintf (fh, "-1 Wrong number of fields: Got %i, expected 2.\n",
- fields_num);
- fflush (fh);
- return (-1);
- }
- DEBUG ("unixsock plugin: Got query for `%s'", fields[1]);
-
- status = parse_identifier (fields[1], &hostname,
- &plugin, &plugin_instance,
- &type, &type_instance);
- if (status != 0)
- {
- DEBUG ("unixsock plugin: Cannot parse `%s'", fields[1]);
- fprintf (fh, "-1 Cannot parse identifier.\n");
- fflush (fh);
- return (-1);
- }
-
- status = format_name (name, sizeof (name),
- hostname, plugin, plugin_instance, type, type_instance);
- if (status != 0)
- {
- fprintf (fh, "-1 format_name failed.\n");
- return (-1);
- }
-
- pthread_mutex_lock (&cache_lock);
-
- DEBUG ("vc = cache_search (%s)", name);
- vc = cache_search (name);
-
- if (vc == NULL)
- {
- DEBUG ("Did not find cache entry.");
- fprintf (fh, "-1 No such value");
- }
- else
- {
- DEBUG ("Found cache entry.");
- fprintf (fh, "%i", vc->values_num);
- for (i = 0; i < vc->values_num; i++)
- {
- fprintf (fh, " %s=", vc->ds->ds[i].name);
- if (isnan (vc->gauge[i]))
- fprintf (fh, "NaN");
- else
- fprintf (fh, "%12e", vc->gauge[i]);
- }
- }
-
- /* Free the mutex as soon as possible and definitely before flushing */
- pthread_mutex_unlock (&cache_lock);
-
- fprintf (fh, "\n");
- fflush (fh);
-
- return (0);
-} /* int us_handle_getval */
-
-static int us_handle_listval (FILE *fh, char **fields, int fields_num)
-{
- char buffer[1024];
- char **value_list = NULL;
- int value_list_len = 0;
- value_cache_t *entry;
- int i;
-
- if (fields_num != 1)
- {
- DEBUG ("unixsock plugin: us_handle_listval: "
- "Wrong number of fields: %i", fields_num);
- fprintf (fh, "-1 Wrong number of fields: Got %i, expected 1.\n",
- fields_num);
- fflush (fh);
- return (-1);
- }
-
- pthread_mutex_lock (&cache_lock);
-
- for (entry = cache_head; entry != NULL; entry = entry->next)
- {
- char **tmp;
-
- snprintf (buffer, sizeof (buffer), "%u %s\n",
- (unsigned int) entry->time, entry->name);
- buffer[sizeof (buffer) - 1] = '\0';
-
- tmp = realloc (value_list, sizeof (char *) * (value_list_len + 1));
- if (tmp == NULL)
- continue;
- value_list = tmp;
-
- value_list[value_list_len] = strdup (buffer);
-
- if (value_list[value_list_len] != NULL)
- value_list_len++;
- } /* for (entry) */
-
- pthread_mutex_unlock (&cache_lock);
-
- DEBUG ("unixsock plugin: us_handle_listval: value_list_len = %i", value_list_len);
- fprintf (fh, "%i Values found\n", value_list_len);
- for (i = 0; i < value_list_len; i++)
- fputs (value_list[i], fh);
- fflush (fh);
-
- return (0);
-} /* int us_handle_listval */
-
static void *us_handle_client (void *arg)
{
int fd;
if (strcasecmp (fields[0], "getval") == 0)
{
- us_handle_getval (fhout, fields, fields_num);
+ handle_getval (fhout, fields, fields_num);
}
else if (strcasecmp (fields[0], "putval") == 0)
{
}
else if (strcasecmp (fields[0], "listval") == 0)
{
- us_handle_listval (fhout, fields, fields_num);
+ handle_listval (fhout, fields, fields_num);
}
else if (strcasecmp (fields[0], "putnotif") == 0)
{
handle_putnotif (fhout, fields, fields_num);
}
+ else if (strcasecmp (fields[0], "flush") == 0)
+ {
+ handle_flush (fhout, fields, fields_num);
+ }
else
{
fprintf (fhout, "-1 Unknown command: %s\n", fields[0]);
{
if (strcasecmp (key, "SocketFile") == 0)
{
+ char *new_sock_file = strdup (val);
+ if (new_sock_file == NULL)
+ return (1);
+
sfree (sock_file);
- sock_file = strdup (val);
+ sock_file = new_sock_file;
}
else if (strcasecmp (key, "SocketGroup") == 0)
{
+ char *new_sock_group = strdup (val);
+ if (new_sock_group == NULL)
+ return (1);
+
sfree (sock_group);
- sock_group = strdup (val);
+ sock_group = new_sock_group;
}
else if (strcasecmp (key, "SocketPerms") == 0)
{
}
plugin_unregister_init ("unixsock");
- plugin_unregister_write ("unixsock");
plugin_unregister_shutdown ("unixsock");
return (0);
} /* int us_shutdown */
-static int us_write (const data_set_t *ds, const value_list_t *vl)
-{
- cache_update (ds, vl);
- cache_flush (2 * interval_g);
-
- return (0);
-}
-
void module_register (void)
{
plugin_register_config ("unixsock", us_config,
config_keys, config_keys_num);
plugin_register_init ("unixsock", us_init);
- plugin_register_write ("unixsock", us_write);
plugin_register_shutdown ("unixsock", us_shutdown);
} /* void module_register (void) */