Browse Source

module for bsnmp sysctl interface

main
John-Mark Gurney 4 years ago
commit
4a9061583a
6 changed files with 993 additions and 0 deletions
  1. +11
    -0
      Makefile
  2. +731
    -0
      bsnmp-sysctl.c
  3. +108
    -0
      sysctl_sup.c
  4. +9
    -0
      sysctl_sup.h
  5. +68
    -0
      sysctl_tree.def
  6. +66
    -0
      usuals.h

+ 11
- 0
Makefile View File

@@ -0,0 +1,11 @@
MOD= sysctl

XSYM= sysctl

SRCS= bsnmp-sysctl.c sysctl_sup.c

WARNS?= 6

SHLIB_MAJOR= 6

.include <bsd.snmpmod.mk>

+ 731
- 0
bsnmp-sysctl.c View File

@@ -0,0 +1,731 @@
/*
* Copyright (c) 2006, Stefan Walter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * 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.
* * The names of contributors to this software may not be
* used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
* COPYRIGHT OWNER 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.
*
*
* CONTRIBUTORS
* Stef Walter <stef@memberwebs.com>
*/

#include "usuals.h"

#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/un.h>
#include <syslog.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include <fcntl.h>

#include <bsnmp/snmpmod.h>

#include "sysctl_sup.h"

#include "sysctl_tree.h"
#include "sysctl_oid.h"

#define DEFAULT_CONFIG "/usr/local/etc" "/bsnmp-sysctl.conf"
#define DEFAULT_CACHE 10

/* our module handle */
static struct lmodule *module;

/* OIDs */
static const struct asn_oid oid_sysctl = OIDX_sysctl;

/* the Object Resource registration index */
static u_int reg_index = 0;

struct data_entry {
uint32_t index;
TAILQ_ENTRY(data_entry) link;

char *descr;
char *fmt;
u_int type;

uint64_t cache;
int error;

char *sysctl;
int *name;
u_int namelen;

uint64_t last_update;
int64_t value_int;
char *value_raw;
size_t value_rawlen;
char *value_str;
size_t value_strlen;
};

TAILQ_HEAD(data_entry_list, data_entry);

/* list of sysctls */
static struct data_entry_list entries = TAILQ_HEAD_INITIALIZER(entries);
static uint32_t entry_count = 0;

/* configuration */
static u_char *sysctl_config = NULL;
static char *config_memory = NULL;
static uint64_t option_cache = DEFAULT_CACHE;

/* -----------------------------------------------------------------------------
* HELPERS
*/

static void
emsg(const char *format, ...)
{
va_list va;
va_start(va, format);
vsyslog(LOG_ERR, format, va);
va_end(va);
}

static void
strcln (char* data, char ch)
{
char* p;
for (p = data; *data; data++, p++) {
while (*data == ch)
data++;
*p = *data;
}
/* null terminate */
*p = 0;
}

static void
stretrim (char* data)
{
char* t = data + strlen (data);
while (t > data && isspace (*(t - 1))) {
t--;
*t = 0;
}
}

static char*
strbtrim (char* data)
{
while (*data && isspace (*data))
++data;
return (char*)data;
}

static char*
strtrim (char* data)
{
data = (char*)strbtrim (data);
stretrim (data);
return data;
}

static uint64_t
getcurrticks (void)
{
return get_ticks ();
}

/* -----------------------------------------------------------------------------
* CONFIG PARSING
*/

static void
config_free (struct data_entry *data)
{

free(data->name);
free(data->fmt);
free (data->value_str);
free (data->value_raw);

free (data);
}

static void
config_free_all (void)
{
struct data_entry *data;
while ((data = TAILQ_FIRST(&entries)) != NULL) {
TAILQ_REMOVE (&entries, data, link);
config_free (data);
}
}

static int
config_entry (struct data_entry *data, char *name, char *value,
int line)
{

ASSERT (data);
ASSERT (name);
ASSERT (value);

(void)value;

/* The name */
data->descr = name; /* XXX - from sysctl desc */
data->sysctl = name;
data->error = 0;

/* Parse the sysctl */
data->namelen = CTL_MAXNAME;
data->name = malloc(sizeof *data->name * data->namelen);
data->fmt = NULL;
data->value_str = NULL;
data->value_raw = NULL;

if (data->name == NULL) {
emsg ("out of memory parsing config file");
return -1;
}
do {
if (sysctlnametomib(name, data->name, &data->namelen) == -1) {
emsg ("[line %d] sysctlnametomib: %s", line, strerror(errno));
break;
}

data->name = realloc(data->name, sizeof *data->name * data->namelen);

if (sysctl_oidfmt(data->name, data->namelen, &data->fmt, &data->type)) {
emsg ("[line %d] sysctl_oidfmt: %s", line, strerror(errno));
break;
}

/* Options */
data->cache = option_cache;

return 0;
} while (0);

free(data->name);
free(data->fmt);
return -1;
}

static int
config_line (char *name, char *value, int line)
{
struct data_entry *data;
int r;

/* config_parse trims this for us */
ASSERT (!isspace(value[0]));

/* Now populate an entry */
data = (struct data_entry*)calloc(1, sizeof *data);
if (!data) {
emsg ("out of memory");
return -1;
}

/* Now make an entry out of it all */
r = config_entry (data, name, value, line);

if (r < 0) {
free (data);
return r;
}

/* Put it in our table */
data->index = entry_count++;
INSERT_OBJECT_INT (data, &entries);

return 0;
}

static void
config_var (char *name, char *value, int line)
{
char *t2;
int i;

/* The cache variable */
if (strcmp (name, "cache") == 0) {

i = strtol (value, &t2, 10);
if (i <= 0 || *t2)
emsg("[line %d] invalid value for '%s' variable. ignoring: %s",
line, name, value);
else
option_cache = i * 100;
return;
}

emsg ("unknown or invalid variable. ignoring: %s", name);
}

static int
config_read (void)
{
FILE *f = NULL;
long len;

ASSERT (sysctl_config && sysctl_config[0]);

f = fopen (sysctl_config, "r");
if (f == NULL) {
emsg ("couldn't open config file: %s", sysctl_config);
return -1;
}

/* Figure out size */
if (fseek (f, 0, SEEK_END) == -1 || (len = ftell (f)) == -1 || fseek (f, 0, SEEK_SET) == -1) {
emsg ("couldn't seek config file: %s", sysctl_config);
return -1;
}

ASSERT (!config_memory);

if ((config_memory = (char*)malloc (len + 2)) == NULL) {
emsg ("out of memory");
return -1;
}

/* And read in one block */
if(fread(config_memory, 1, len, f) != (size_t)len) {
emsg ("couldn't read config file: %s", sysctl_config);
free (config_memory);
config_memory = NULL;
return -1;
}

fclose (f);

/* Null terminate the data */
config_memory[len] = '\n';
config_memory[len + 1] = 0;

return 0;
}

static int
config_parse (void)
{
char* next;
char* p;
char* t;
int line = 0;
int var = 0;
int r;

config_free_all ();

/* Reads raw config file into config_memory */
if (config_read () < 0)
return -1;

ASSERT (config_memory);

/* Remove nasty dos line endings */
strcln(config_memory, '\r');

next = config_memory;
while ((t = strchr (next, '\n')) != NULL) {

*t = 0;
p = next;
next = t + 1;
t = strbtrim (p);
line++;

/* blank lines, comments */
if (!*t || *t == '#')
continue;

t = t + strcspn (t, ":=");
if (!*t) {
emsg ("invalid config line: %s", p);
return -1;
}

/* Equal sign denotes a variable */
var = (*t == '=');
*t = 0;
t++;

/* Pass variables to the appropriate place */
if (var) {
config_var (strtrim (p), strtrim (t), line);

/* And config lines to the appropriate place */
} else {

r = config_line (strtrim (p), strtrim (t), line);
if (r < 0) {

/* If -2 was returned, no error message was printed */
if (r == -2)
emsg ("[line %d] invalid configuration file", line);

return -1;
}
}
}

return 0;
}


/* -----------------------------------------------------------------------------
* CALLBACKS
*/

int
op_sysctlconfig (struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx, enum snmp_op op)
{
asn_subid_t which = value->var.subs[sub - 1];
int r = SNMP_ERR_NOERROR;

(void)iidx;

switch (which) {
case LEAF_sysctlConfig:

if (op == SNMP_OP_GET)
return string_get (value, sysctl_config, -1);

/* Remainder only at initialization */
if (community != COMM_INITIALIZE)
return SNMP_ERR_NOT_WRITEABLE;

switch (op) {
case SNMP_OP_SET:
if ((r = string_save (value, ctx, -1, &sysctl_config)) == SNMP_ERR_NOERROR) {
if (!sysctl_config[0])
r = SNMP_ERR_WRONG_VALUE;
else if (config_parse () < 0)
r = SNMP_ERR_GENERR;
}
if (r != SNMP_ERR_NOERROR)
string_rollback (ctx, &sysctl_config);
break;
case SNMP_OP_COMMIT:
string_commit (ctx);
break;
case SNMP_OP_ROLLBACK:
string_rollback (ctx, &sysctl_config);
break;
default:
ASSERT(0);
break;
}

return r;

}

ASSERT(0);
return -1;
}

int
op_sysctl (struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx, enum snmp_op op)
{
asn_subid_t which = value->var.subs[sub - 1];
int stdval = 0x01234567;

(void)ctx;
(void)iidx;

switch (op) {
case SNMP_OP_GET:
break;

case SNMP_OP_SET:
/* XXX - maybe in the future */
return SNMP_ERR_NOT_WRITEABLE;

case SNMP_OP_ROLLBACK:
case SNMP_OP_COMMIT:
return SNMP_ERR_NOERROR;

default:
ASSERT(0);
break;
}

switch (which) {
case LEAF_sysctlCount:
value->v.integer = entry_count;
break;

case LEAF_sysctlEndian:
return string_get(value, (char *)&stdval, sizeof stdval);
break;

default:
ASSERT(0);
break;
}

return SNMP_ERR_NOERROR;
}

#if 0
static int
strisprint(char *str, size_t buflen)
{

while (buflen--) {
if (!isprint(*str) && !isspace(*str))
return 0;
str++;
}

return 1;
}
#endif

static char *
makehexstr(unsigned char *buf, size_t buflen)
{
char *ostr, *str;

ostr = str = malloc(buflen * 2 + 1);

while (buflen--) {
sprintf(str, "%02x", (unsigned)*buf++);
str += 2;
}

str[0] = '\x00';

return ostr;
}

int
op_sysctlentry (struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int iidx, enum snmp_op op)
{
char buffer[512];
asn_subid_t which = value->var.subs[sub - 1];
struct data_entry *data;
uint64_t ticks;
size_t buflen;
int fetch = 1;

(void)ctx;

switch (op) {
case SNMP_OP_GETNEXT:
data = NEXT_OBJECT_INT (&entries, &value->var, sub);
if (data == NULL)
return SNMP_ERR_NOSUCHNAME;
value->var.len = sub + 1;
value->var.subs[sub] = data->index;
break;

case SNMP_OP_GET:
data = FIND_OBJECT_INT (&entries, &value->var, sub);
if (data == NULL)
return SNMP_ERR_NOSUCHNAME;
break;

case SNMP_OP_SET:
if (index_decode (&value->var, sub, iidx, &data))
return SNMP_ERR_NO_CREATION;
data = FIND_OBJECT_INT (&entries, &value->var, sub);
if (data != NULL)
return SNMP_ERR_NOT_WRITEABLE;
return SNMP_ERR_NO_CREATION;

default:
ASSERT(0);
break;
}

/* Figure out if we should fetch or not */
/* XXX - only fetch on value fetches? */
ticks = getcurrticks ();
if (ticks == 0)
return SNMP_ERR_GENERR;
if (data->cache && data->last_update) {
if (ticks < (data->last_update + data->cache))
fetch = 0;
}

if (fetch) {
free(data->value_raw);
data->value_raw = NULL;
data->value_rawlen = 0;

free(data->value_str);
data->value_str = NULL;
data->value_strlen = 0;

/* XXX - oidfmt and friends from sysctl */
/* XXX - length */
buflen = sizeof buffer;
if (sysctl(data->name, data->namelen, buffer, &buflen, NULL, 0) == -1) {
data->error = errno;
data->value_int = 0;
} else {
data->last_update = getcurrticks();
data->error = 0;

data->value_raw = malloc(buflen);
data->value_rawlen = buflen;
memcpy(data->value_raw, buffer, buflen);

data->value_int = 0;

emsg("test: buflen %d, sysctl: %s, ticks: %llu, lu: %llu", buflen, data->descr, ticks, data->last_update);

if (strcmp("A", data->fmt) == 0) {
data->value_str = malloc(buflen);
strlcpy(data->value_str, buffer, buflen);
} else if (strcmp("I", data->fmt) == 0) {
data->value_int = *(int32_t *)buffer;
} else {
data->value_str = makehexstr(buffer, buflen);
}
}
}

if (data->value_str == NULL)
asprintf(&data->value_str, "%jd", (intmax_t)data->value_int);

data->value_strlen = strlen(data->value_str);

switch (which) {
case LEAF_sysctlIndex:
value->v.integer = data->index;
break;

case LEAF_sysctlDescr:
return (string_get (value, data->descr, -1));

case LEAF_sysctlType:
value->v.uint32 = data->type;
break;

case LEAF_sysctlFmt:
return (string_get (value, data->fmt, -1));

case LEAF_sysctlErrno:
value->v.uint32 = data->error;
break;

case LEAF_sysctlLast:
if (data->last_update)
value->v.uint32 = (ticks - data->last_update);
else
value->v.uint32 = 0;
break;

case LEAF_sysctlInteger:
value->v.uint32 = data->value_int;
break;

case LEAF_sysctlValue:
return string_get(value, data->value_str, data->value_strlen);

case LEAF_sysctlRaw:
return string_get(value, data->value_raw, data->value_rawlen);

case LEAF_sysctlCounter:
value->v.counter64 = data->value_int;
break;

default:
ASSERT(0);
break;
};

return SNMP_ERR_NOERROR;
}

/* -----------------------------------------------------------------------------
* MODULE
*/

/* the initialisation function */
static int
module_init(struct lmodule *mod, int argc, char *argv[])
{

(void)argv;

module = mod;

if (argc != 0) {
syslog(LOG_ERR, "bad number of arguments for %s", __func__);
return EINVAL;
}

sysctl_config = strdup(DEFAULT_CONFIG);
if (!sysctl_config)
return ENOMEM;

return 0;
}

/* Module is started */
static void
module_start (void)
{
reg_index = or_register (&oid_sysctl, "The MIB for sysctl data.", module);
}

/* Called, when the module is to be unloaded after it was successfully loaded */
static int
module_fini (void)
{
if (reg_index)
or_unregister (reg_index);

ASSERT (sysctl_config);
free (sysctl_config);

config_free_all ();

return 0;
}

const struct snmp_module config = {
.comment = "This module implements SNMP listing of data from sysctl.",
.init = module_init,
.start = module_start,
.fini = module_fini,
.tree = sysctl_ctree,
.tree_size = sysctl_CTREE_SIZE,
};

+ 108
- 0
sysctl_sup.c View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
* Copyright 2011 John-Mark Gurney
*
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/

#include <sys/types.h>
#include <sys/sysctl.h>

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "sysctl_sup.h"

int
sysctl_alloc(int *name, u_int namelen, void **oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
void *buf;
size_t curr, prev;
int r;

buf = NULL;

if (sysctl(name, namelen, NULL, &curr, NULL, 0) == -1 &&
errno != ENOMEM)
return -1;

for (;;) {
buf = realloc(buf, curr);
prev = curr;

if (((r = sysctl(name, namelen, buf, &curr, newp, newlen)) ==
-1 && errno != ENOMEM) || r == 0) {
if (r == 0) {
*oldlenp = curr;
*oldp = realloc(buf, *oldlenp);
}

return r;
}

/* previous estimate was short, try again. */
if (curr <= prev)
curr = prev + 16;
}
}

int
sysctl_oidfmt(int *oid, int len, char **fmt, u_int *kind)
{
int qoid[CTL_MAXNAME+2];
void *buf;
u_char *fmtstart;
int i;
size_t j;

qoid[0] = 0;
qoid[1] = 4;
memcpy(qoid + 2, oid, len * sizeof(int));

i = sysctl_alloc(qoid, len + 2, &buf, &j, NULL, 0);
if (i)
return i;

if (kind)
*kind = *(u_int *)buf;

if (fmt) {
fmtstart = (char *)buf + sizeof(u_int);
*fmt = malloc(strlen(fmtstart) + 1);
if (*fmt == NULL) {
free(buf);
errno = ENOMEM;
return -1;
}
strcpy(*fmt, fmtstart);
}

free(buf);

return (0);
}

+ 9
- 0
sysctl_sup.h View File

@@ -0,0 +1,9 @@
#ifndef _SYSCTL_SUP_H_

#define _SYSCTL_SUP_H_

int sysctl_oidfmt(int *, int, char **, u_int *);
int sysctl_alloc(int *name, u_int namelen, void **oldp, size_t *oldlenp,
void *newp, size_t newlen);

#endif /* _SYSCTL_SUP_H_ */

+ 68
- 0
sysctl_tree.def View File

@@ -0,0 +1,68 @@
#
# Copyright (c) 2006, Stefan Walter
# Copyright 2011 John-Mark Gurney
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above
# copyright notice, this list of conditions and the
# following disclaimer.
# * 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.
# * The names of contributors to this software may not be
# used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
# COPYRIGHT OWNER 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.
#
#
# CONTRIBUTORS
# Stef Walter <stef@memberwebs.com>
#

(1 internet
(4 private
(1 enterprises
(12325 fokus
(1 begemot
(204 sysctl
(0 sysctlCount INTEGER op_sysctl GET)
(1 sysctlEndian OCTETSTRING op_sysctl GET)
(2 sysctlEntry : INTEGER op_sysctlentry
(1 sysctlIndex INTEGER GET)
(2 sysctlDescr OCTETSTRING GET)
(3 sysctlType UNSIGNED32 GET)
(4 sysctlFmt OCTETSTRING GET)
(5 sysctlErrno INTEGER GET)
(6 sysctlLast TIMETICKS GET)
(7 sysctlInteger INTEGER GET)
(8 sysctlValue OCTETSTRING GET)
(9 sysctlRaw OCTETSTRING GET)
(10 sysctlCounter COUNTER64 GET)
)
# Valid only during configuration
(100 sysctlConfig OCTETSTRING op_sysctlconfig GET SET)
)
)
)
)
)
)

+ 66
- 0
usuals.h View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 2006, Stefan Walter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * 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.
* * The names of contributors to this software may not be
* used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
* COPYRIGHT OWNER 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.
*
*
* CONTRIBUTORS
* Stef Walter <stef@memberwebs.com>
*/

#ifndef __USUALS_H__
#define __USUALS_H__

#include <sys/types.h>

#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif

#define countof(x) (sizeof(x) / sizeof(x[0]))

#ifdef _DEBUG
#include "assert.h"
#define ASSERT(x) assert(x)
#else
#define ASSERT(x)
#endif

#endif /* __USUALS_H__ */

Loading…
Cancel
Save