commit 4a9061583a62707b5b97738b51bd64910d98bcfe Author: John-Mark Gurney Date: Thu Dec 5 23:29:45 2019 -0800 module for bsnmp sysctl interface diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..da59bd8 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +MOD= sysctl + +XSYM= sysctl + +SRCS= bsnmp-sysctl.c sysctl_sup.c + +WARNS?= 6 + +SHLIB_MAJOR= 6 + +.include diff --git a/bsnmp-sysctl.c b/bsnmp-sysctl.c new file mode 100644 index 0000000..e0ad457 --- /dev/null +++ b/bsnmp-sysctl.c @@ -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 + */ + +#include "usuals.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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, +}; diff --git a/sysctl_sup.c b/sysctl_sup.c new file mode 100644 index 0000000..4e29f4f --- /dev/null +++ b/sysctl_sup.c @@ -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 +#include + +#include +#include +#include + +#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); +} diff --git a/sysctl_sup.h b/sysctl_sup.h new file mode 100644 index 0000000..dbe56d3 --- /dev/null +++ b/sysctl_sup.h @@ -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_ */ diff --git a/sysctl_tree.def b/sysctl_tree.def new file mode 100644 index 0000000..c593cfd --- /dev/null +++ b/sysctl_tree.def @@ -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 +# + +(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) + ) + ) + ) + ) + ) +) diff --git a/usuals.h b/usuals.h new file mode 100644 index 0000000..627f7ba --- /dev/null +++ b/usuals.h @@ -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 + */ + +#ifndef __USUALS_H__ +#define __USUALS_H__ + +#include + +#include +#include +#include +#include +#include + +#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__ */