Updating HEAD branch #4; Merging CABAL -> HEAD.

This commit is contained in:
Ivo Timmermans 2002-04-09 15:26:01 +00:00
parent e64ef59df4
commit 462ab530e5
58 changed files with 9898 additions and 2867 deletions

723
lib/avl_tree.c Normal file
View file

@ -0,0 +1,723 @@
/*
avl_tree.c -- avl_ tree and linked list convenience
Copyright (C) 1998 Michael H. Buselli
2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
2000,2001 Wessel Dankers <wsl@nl.linux.org>
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 Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
Modified 2000-11-28 by Wessel Dankers <wsl@nl.linux.org> to use counts
instead of depths, to add the ->next and ->prev and to generally obfuscate
the code. Mail me if you found a bug.
Cleaned up and incorporated some of the ideas from the red-black tree
library for inclusion into tinc (http://tinc.nl.linux.org/) by
Guus Sliepen <guus@sliepen.warande.net>.
$Id: avl_tree.c,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#include <stdio.h>
#include <stdlib.h>
#include <xalloc.h>
#include "avl_tree.h"
#ifdef AVL_COUNT
#define AVL_NODE_COUNT(n) ((n) ? (n)->count : 0)
#define AVL_L_COUNT(n) (AVL_NODE_COUNT((n)->left))
#define AVL_R_COUNT(n) (AVL_NODE_COUNT((n)->right))
#define AVL_CALC_COUNT(n) (AVL_L_COUNT(n) + AVL_R_COUNT(n) + 1)
#endif
#ifdef AVL_DEPTH
#define AVL_NODE_DEPTH(n) ((n) ? (n)->depth : 0)
#define L_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->left))
#define R_AVL_DEPTH(n) (AVL_NODE_DEPTH((n)->right))
#define AVL_CALC_DEPTH(n) ((L_AVL_DEPTH(n)>R_AVL_DEPTH(n)?L_AVL_DEPTH(n):R_AVL_DEPTH(n)) + 1)
#endif
#ifndef AVL_DEPTH
int lg(unsigned int u)
{
int r = 1;
if (!u)
return 0;
if (u & 0xffff0000)
{
u >>= 16;
r += 16;
}
if (u & 0x0000ff00)
{
u >>= 8;
r += 8;
}
if (u & 0x000000f0)
{
u >>= 4;
r += 4;
}
if (u & 0x0000000c)
{
u >>= 2;
r += 2;
}
if (u & 0x00000002)
r++;
return r;
}
#endif
/* Internal helper functions */
int avl_check_balance(avl_node_t *node)
{
#ifdef AVL_DEPTH
int d;
d = R_AVL_DEPTH(node) - L_AVL_DEPTH(node);
return d < -1 ? -1 : d > 1 ? 1 : 0;
#else
/* int d;
* d = lg(AVL_R_COUNT(node)) - lg(AVL_L_COUNT(node));
* d = d<-1?-1:d>1?1:0;
*/
int pl, r;
pl = lg(AVL_L_COUNT(node));
r = AVL_R_COUNT(node);
if (r >> pl + 1)
return 1;
if (pl < 2 || r >> pl - 2)
return 0;
return -1;
#endif
}
void avl_rebalance(avl_tree_t *tree, avl_node_t *node)
{
avl_node_t *child;
avl_node_t *gchild;
avl_node_t *parent;
avl_node_t **superparent;
parent = node;
while (node)
{
parent = node->parent;
superparent = parent ? node == parent->left ? &parent->left : &parent->right : &tree->root;
switch (avl_check_balance(node))
{
case -1:
child = node->left;
#ifdef AVL_DEPTH
if(L_AVL_DEPTH(child) >= R_AVL_DEPTH(child)) {
#else
if (AVL_L_COUNT(child) >= AVL_R_COUNT(child))
{
#endif
node->left = child->right;
if (node->left)
node->left->parent = node;
child->right = node;
node->parent = child;
*superparent = child;
child->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
#endif
} else
{
gchild = child->right;
node->left = gchild->right;
if (node->left)
node->left->parent = node;
child->right = gchild->left;
if (child->right)
child->right->parent = child;
gchild->right = node;
if (gchild->right)
gchild->right->parent = gchild;
gchild->left = child;
if (gchild->left)
gchild->left->parent = gchild;
*superparent = gchild;
gchild->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
gchild->count = AVL_CALC_COUNT(gchild);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
gchild->depth = AVL_CALC_DEPTH(gchild);
#endif
}
break;
case 1:
child = node->right;
#ifdef AVL_DEPTH
if(R_AVL_DEPTH(child) >= L_AVL_DEPTH(child)) {
#else
if (AVL_R_COUNT(child) >= AVL_L_COUNT(child))
{
#endif
node->right = child->left;
if (node->right)
node->right->parent = node;
child->left = node;
node->parent = child;
*superparent = child;
child->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
#endif
} else
{
gchild = child->left;
node->right = gchild->left;
if (node->right)
node->right->parent = node;
child->left = gchild->right;
if (child->left)
child->left->parent = child;
gchild->left = node;
if (gchild->left)
gchild->left->parent = gchild;
gchild->right = child;
if (gchild->right)
gchild->right->parent = gchild;
*superparent = gchild;
gchild->parent = parent;
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
child->count = AVL_CALC_COUNT(child);
gchild->count = AVL_CALC_COUNT(gchild);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
child->depth = AVL_CALC_DEPTH(child);
gchild->depth = AVL_CALC_DEPTH(gchild);
#endif
}
break;
default:
#ifdef AVL_COUNT
node->count = AVL_CALC_COUNT(node);
#endif
#ifdef AVL_DEPTH
node->depth = AVL_CALC_DEPTH(node);
#endif
}
node = parent;
}
}
/* (De)constructors */
avl_tree_t *avl_alloc_tree(avl_compare_t compare, avl_action_t delete)
{
avl_tree_t *tree;
tree = xmalloc_and_zero(sizeof(avl_tree_t));
tree->compare = compare;
tree->delete = delete;
return tree;
}
void avl_free_tree(avl_tree_t *tree)
{
free(tree);
}
avl_node_t *avl_alloc_node(void)
{
avl_node_t *node;
node = xmalloc_and_zero(sizeof(avl_node_t));
return node;
}
void avl_free_node(avl_tree_t *tree, avl_node_t *node)
{
if(node->data && tree->delete)
tree->delete(node->data);
free(node);
}
/* Searching */
void *avl_search(const avl_tree_t *tree, const void *data)
{
avl_node_t *node;
node = avl_search_node(tree, data);
return node?node->data:NULL;
}
void *avl_search_closest(const avl_tree_t *tree, const void *data, int *result)
{
avl_node_t *node;
node = avl_search_closest_node(tree, data, result);
return node?node->data:NULL;
}
void *avl_search_closest_smaller(const avl_tree_t *tree, const void *data)
{
avl_node_t *node;
node = avl_search_closest_smaller_node(tree, data);
return node?node->data:NULL;
}
void *avl_search_closest_greater(const avl_tree_t *tree, const void *data)
{
avl_node_t *node;
node = avl_search_closest_greater_node(tree, data);
return node?node->data:NULL;
}
avl_node_t *avl_search_node(const avl_tree_t *tree, const void *data)
{
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
return result?NULL:node;
}
avl_node_t *avl_search_closest_node(const avl_tree_t *tree, const void *data, int *result)
{
avl_node_t *node;
int c;
node = tree->root;
if (!node)
{
if(result)
*result = 0;
return NULL;
}
for (;;)
{
c = tree->compare(data, node->data);
if (c < 0)
{
if (node->left)
node = node->left;
else
{
if(result)
*result = -1;
break;
}
}
else if (c > 0)
{
if (node->right)
node = node->right;
else
{
if(result)
*result = 1;
break;
}
}
else
{
if(result)
*result = 0;
break;
}
}
return node;
}
avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *tree, const void *data)
{
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
if(result < 0)
node = node->prev;
return node;
}
avl_node_t *avl_search_closest_greater_node(const avl_tree_t *tree, const void *data)
{
avl_node_t *node;
int result;
node = avl_search_closest_node(tree, data, &result);
if(result > 0)
node = node->next;
return node;
}
/* Insertion and deletion */
avl_node_t *avl_insert(avl_tree_t *tree, void *data)
{
avl_node_t *closest, *new;
int result;
if (!tree->root)
{
new = avl_alloc_node();
new->data = data;
avl_insert_top(tree, new);
}
else
{
closest = avl_search_closest_node(tree, data, &result);
switch(result)
{
case -1:
new = avl_alloc_node();
new->data = data;
avl_insert_before(tree, closest, new);
break;
case 1:
new = avl_alloc_node();
new->data = data;
avl_insert_after(tree, closest, new);
break;
default:
return NULL;
}
}
#ifdef AVL_COUNT
new->count = 1;
#endif
#ifdef AVL_DEPTH
new->depth = 1;
#endif
return new;
}
avl_node_t *avl_insert_node(avl_tree_t *tree, avl_node_t *node)
{
avl_node_t *closest;
int result;
if (!tree->root)
avl_insert_top(tree, node);
else
{
closest = avl_search_closest_node(tree, node->data, &result);
switch(result)
{
case -1:
avl_insert_before(tree, closest, node);
break;
case 1:
avl_insert_after(tree, closest, node);
break;
case 0:
return NULL;
}
}
#ifdef AVL_COUNT
node->count = 1;
#endif
#ifdef AVL_DEPTH
node->depth = 1;
#endif
return node;
}
void avl_insert_top(avl_tree_t *tree, avl_node_t *node)
{
node->prev = node->next = node->parent = NULL;
tree->head = tree->tail = tree->root = node;
}
void avl_insert_before(avl_tree_t *tree, avl_node_t *before, avl_node_t *node)
{
if (!before)
return tree->tail ? avl_insert_after(tree, tree->tail, node) : avl_insert_top(tree, node);
node->next = before;
node->parent = before;
node->prev = before->prev;
if(before->left)
return avl_insert_after(tree, before->prev, node);
if (before->prev)
before->prev->next = node;
else
tree->head = node;
before->prev = node;
before->left = node;
avl_rebalance(tree, before->parent);
}
void avl_insert_after(avl_tree_t *tree, avl_node_t *after, avl_node_t *node)
{
if (!after)
return tree->head ? avl_insert_before(tree, tree->head, node) : avl_insert_top(tree, node);
if(after->right)
return avl_insert_before(tree, after->next, node);
node->prev = after;
node->parent = after;
node->next = after->next;
if (after->next)
after->next->prev = node;
else
tree->tail = node;
after->next = node;
after->right = node;
avl_rebalance(tree, after->parent);
}
avl_node_t *avl_unlink(avl_tree_t *tree, void *data)
{
avl_node_t *node;
node = avl_search_node(tree, data);
if(node)
avl_unlink_node(tree, node);
return node;
}
void avl_unlink_node(avl_tree_t *tree, avl_node_t *node)
{
avl_node_t *parent;
avl_node_t **superparent;
avl_node_t *subst, *left, *right;
avl_node_t *balnode;
if (node->prev)
node->prev->next = node->next;
else
tree->head = node->next;
if (node->next)
node->next->prev = node->prev;
else
tree->tail = node->prev;
parent = node->parent;
superparent = parent ? node == parent->left ? &parent->left : &parent->right : &tree->root;
left = node->left;
right = node->right;
if (!left)
{
*superparent = right;
if (right)
right->parent = parent;
balnode = parent;
} else if (!right)
{
*superparent = left;
left->parent = parent;
balnode = parent;
} else
{
subst = node->prev;
if (subst == left)
{
balnode = subst;
} else
{
balnode = subst->parent;
balnode->right = subst->left;
if (balnode->right)
balnode->right->parent = balnode;
subst->left = left;
left->parent = subst;
}
subst->right = right;
subst->parent = parent;
right->parent = subst;
*superparent = subst;
}
avl_rebalance(tree, balnode);
node->next = node->prev = node->parent = node->left = node->right = NULL;
#ifdef AVL_COUNT
node->count = 0;
#endif
#ifdef AVL_DEPTH
node->depth = 0;
#endif
}
void avl_delete_node(avl_tree_t *tree, avl_node_t *node)
{
avl_unlink_node(tree, node);
avl_free_node(tree, node);
}
void avl_delete(avl_tree_t *tree, void *data)
{
avl_node_t *node;
node = avl_search_node(tree, data);
if (node)
avl_delete_node(tree, node);
}
/* Fast tree cleanup */
void avl_delete_tree(avl_tree_t *tree)
{
avl_node_t *node, *next;
for(node = tree->root; node; node = next)
{
next = node->next;
avl_free_node(tree, node);
}
avl_free_tree(tree);
}
/* Tree walking */
void avl_foreach(avl_tree_t *tree, avl_action_t action)
{
avl_node_t *node, *next;
for(node = tree->head; node; node = next)
{
next = node->next;
action(node->data);
}
}
void avl_foreach_node(avl_tree_t *tree, avl_action_t action)
{
avl_node_t *node, *next;
for(node = tree->head; node; node = next)
{
next = node->next;
action(node);
}
}
/* Indexing */
#ifdef AVL_COUNT
unsigned int avl_count(avl_tree_t *tree)
{
return AVL_NODE_COUNT(tree->root);
}
avl_node_t *avl_get_node(const avl_tree_t *tree, unsigned int index)
{
avl_node_t *node;
unsigned int c;
node = tree->root;
while (node)
{
c = AVL_L_COUNT(node);
if (index < c)
{
node = node->left;
} else if (index > c)
{
node = node->right;
index -= c + 1;
} else
{
return node;
}
}
return NULL;
}
unsigned int avl_index(const avl_node_t *node)
{
avl_node_t *next;
unsigned int index;
index = AVL_L_COUNT(node);
while ((next = node->parent))
{
if (node == next->right)
index += AVL_L_COUNT(next) + 1;
node = next;
}
return index;
}
#endif
#ifdef AVL_DEPTH
unsigned int avl_depth(avl_tree_t *tree)
{
return AVL_NODE_DEPTH(tree->root);
}
#endif

145
lib/avl_tree.h Normal file
View file

@ -0,0 +1,145 @@
/*
avl_tree.h -- header file for avl_tree.c
Copyright (C) 1998 Michael H. Buselli
2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
2000,2001 Wessel Dankers <wsl@nl.linux.org>
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 Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Original AVL tree library by Michael H. Buselli <cosine@cosine.org>.
Modified 2000-11-28 by Wessel Dankers <wsl@nl.linux.org> to use counts
instead of depths, to add the ->next and ->prev and to generally obfuscate
the code. Mail me if you found a bug.
Cleaned up and incorporated some of the ideas from the red-black tree
library for inclusion into tinc (http://tinc.nl.linux.org/) by
Guus Sliepen <guus@sliepen.warande.net>.
$Id: avl_tree.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#ifndef __AVL_TREE_H__
#define __AVL_TREE_H__
#ifndef AVL_DEPTH
#ifndef AVL_COUNT
#define AVL_DEPTH
#endif
#endif
typedef struct avl_node_t {
/* Linked list part */
struct avl_node_t *next;
struct avl_node_t *prev;
/* Tree part */
struct avl_node_t *parent;
struct avl_node_t *left;
struct avl_node_t *right;
#ifdef AVL_COUNT
unsigned int count;
#endif
#ifdef AVL_DEPTH
unsigned char depth;
#endif
/* Payload */
void *data;
} avl_node_t;
typedef int (*avl_compare_t) (const void *, const void *);
typedef void (*avl_action_t) (const void *);
typedef void (*avl_action_node_t) (const avl_node_t *);
typedef struct avl_tree_t {
/* Linked list part */
avl_node_t *head;
avl_node_t *tail;
/* Tree part */
avl_node_t *root;
avl_compare_t compare;
avl_action_t delete;
} avl_tree_t;
/* (De)constructors */
extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_action_t);
extern void avl_free_tree(avl_tree_t *);
extern avl_node_t *avl_alloc_node(void);
extern void avl_free_node(avl_tree_t *tree, avl_node_t *);
/* Insertion and deletion */
extern avl_node_t *avl_insert(avl_tree_t *, void *);
extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *);
extern void avl_insert_top(avl_tree_t *, avl_node_t *);
extern void avl_insert_before(avl_tree_t *, avl_node_t *, avl_node_t *);
extern void avl_insert_after(avl_tree_t *, avl_node_t *, avl_node_t *);
extern avl_node_t *avl_unlink(avl_tree_t *, void *);
extern void avl_unlink_node(avl_tree_t *tree, avl_node_t *);
extern void avl_delete(avl_tree_t *, void *);
extern void avl_delete_node(avl_tree_t *, avl_node_t *);
/* Fast tree cleanup */
extern void avl_delete_tree(avl_tree_t *);
/* Searching */
extern void *avl_search(const avl_tree_t *, const void *);
extern void *avl_search_closest(const avl_tree_t *, const void *, int *);
extern void *avl_search_closest_smaller(const avl_tree_t *, const void *);
extern void *avl_search_closest_greater(const avl_tree_t *, const void *);
extern avl_node_t *avl_search_node(const avl_tree_t *, const void *);
extern avl_node_t *avl_search_closest_node(const avl_tree_t *, const void *, int *);
extern avl_node_t *avl_search_closest_smaller_node(const avl_tree_t *, const void *);
extern avl_node_t *avl_search_closest_greater_node(const avl_tree_t *, const void *);
/* Tree walking */
extern void avl_foreach(avl_tree_t *, avl_action_t);
extern void avl_foreach_node(avl_tree_t *, avl_action_t);
/* Indexing */
#ifdef AVL_COUNT
extern unsigned int avl_count(avl_tree_t *);
extern avl_node_t *avl_get_node(const avl_tree_t *, unsigned int);
extern unsigned int avl_index(const avl_node_t *);
#endif
#ifdef AVL_DEPTH
extern unsigned int avl_depth(avl_tree_t *);
#endif
#endif /* __AVL_TREE_H__ */

171
lib/dropin.c Normal file
View file

@ -0,0 +1,171 @@
/*
dropin.c -- a set of drop-in replacements for libc functions
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
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 Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: dropin.c,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <xalloc.h>
#include <system.h>
#include <errno.h>
#ifndef HAVE_DAEMON
/*
Replacement for the daemon() function.
The daemon() function is for programs wishing to detach themselves
from the controlling terminal and run in the background as system
daemons.
Unless the argument nochdir is non-zero, daemon() changes the
current working directory to the root (``/'').
Unless the argument noclose is non-zero, daemon() will redirect
standard input, standard output and standard error to /dev/null.
*/
int daemon(int nochdir, int noclose)
{
pid_t pid;
int fd;
pid = fork();
/* Check if forking failed */
if(pid < 0)
{
perror("fork");
exit(-1);
}
/* If we are the parent, terminate */
if(pid)
exit(0);
/* Detach by becoming the new process group leader */
if(setsid() < 0)
{
perror("setsid");
return -1;
}
/* Change working directory to the root (to avoid keeping mount
points busy) */
if(!nochdir)
{
chdir("/");
}
/* Redirect stdin/out/err to /dev/null */
if(!noclose)
{
fd = open("/dev/null", O_RDWR);
if(fd < 0)
{
perror("opening /dev/null");
return -1;
}
else
{
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
}
return 0;
}
#endif
#ifndef HAVE_GET_CURRENT_DIR_NAME
/*
Replacement for the GNU get_current_dir_name function:
get_current_dir_name will malloc(3) an array big enough to hold the
current directory name. If the environment variable PWD is set, and
its value is correct, then that value will be returned.
*/
char *get_current_dir_name(void)
{
size_t size;
char *buf;
char *r;
/* Start with 100 bytes. If this turns out to be insufficient to
contain the working directory, double the size. */
size = 100;
buf = xmalloc(size);
errno = 0; /* Success */
r = getcwd(buf, size);
/* getcwd returns NULL and sets errno to ERANGE if the bufferspace
is insufficient to contain the entire working directory. */
while(r == NULL && errno == ERANGE)
{
free(buf);
size <<= 1; /* double the size */
buf = xmalloc(size);
r = getcwd(buf, size);
}
return buf;
}
#endif
#ifndef HAVE_ASPRINTF
int asprintf(char **buf, const char *fmt, ...)
{
int status;
va_list ap;
int len;
len = 4096;
*buf = xmalloc(len);
va_start(ap, fmt);
status = vsnprintf (*buf, len, fmt, ap);
va_end (ap);
if(status >= 0)
*buf = xrealloc(*buf, status);
if(status > len-1)
{
len = status;
va_start(ap, fmt);
status = vsnprintf (*buf, len, fmt, ap);
va_end (ap);
}
return status;
}
#endif

38
lib/dropin.h Normal file
View file

@ -0,0 +1,38 @@
/*
dropin.h -- header file for dropin.c
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>,
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
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 Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: dropin.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#ifndef __DROPIN_H__
#define __DROPIN_H__
#ifndef HAVE_DAEMON
extern int daemon(int, int);
#endif
#ifndef HAVE_GET_CURRENT_DIR_NAME
extern char* get_current_dir_name(void);
#endif
#ifndef HAVE_ASPRINTF
extern int asprintf(char **, const char *, ...);
#endif
#endif /* __DROPIN_H__ */

View file

@ -1,7 +1,7 @@
/*
list.c -- functions to deal with double linked lists
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
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
@ -17,130 +17,181 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: list.c,v 1.1 2000/10/20 16:44:32 zarq Exp $
$Id: list.c,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <error.h>
#include <list.h>
#include <xalloc.h>
#include <system.h>
/*
list_new
#include "list.h"
Initialize a new list.
*/
list_t *list_new(void)
/* (De)constructors */
list_t *list_alloc(list_action_t delete)
{
list_t *list;
list = xmalloc_and_zero(sizeof(list_t));
list->delete = delete;
return list;
}
/*
list_delete
Delete the element pointed to by idx from the list.
*/
list_node_t *list_delete(list_t *list, list_node_t *idx)
void list_free(list_t *list)
{
list_node_t *res;
if(!list)
return NULL;
if(!idx)
return NULL;
if(list->callbacks->delete != NULL)
if(list->callbacks->delete(idx->data))
error(ERR_WARNING, N_("List callback[delete] failed for %08lx - freeing anyway"), idx->data);
free(idx->data);
if(idx->prev == NULL)
/* First element in list */
{
res = idx->next;
list->head = idx->next;
}
if(idx->next == NULL)
/* Last element in list */
{
res = NULL;
list->tail = idx->prev;
}
if(idx->prev != NULL && idx->next != NULL)
/* Neither first nor last element */
{
idx->prev->next = idx->next;
idx->next->prev = idx->prev;
}
if(list->head == NULL)
list->tail = NULL;
else
if(list->tail == NULL)
list->head = NULL;
free(idx);
return res;
}
/*
list_forall_nodes
Call function() on each element in the list. If this function
returns non-zero, the element will be removed from the list.
*/
void list_forall_nodes(list_t *list, int (*function)(void *data))
{
list_node_t *p;
int res;
if(!list) /* no list given */
return;
if(!function) /* no function given */
return;
if(!list->head) /* list is empty */
return;
for(p = list->head; p != NULL; p = p->next)
{
res = function(p->data);
if(res != 0)
p = list_delete(list, p);
}
}
/*
list_destroy
Free all datastructures contained in this list. It uses the delete
callback for this list to free each element.
*/
void list_destroy(list_t *list)
{
if(!list)
return;
list_destroy_nodes(list);
free(list);
}
/*
list_append
Append a new node to the list that points to data.
*/
list_append(list_t *list, void *data)
list_node_t *list_alloc_node(void)
{
list_node_t *n;
n = xmalloc_and_zero(sizeof(list_node_t));
n->data = data;
n->prev = list->tail;
list->tail->next = n;
list->tail = n;
list_node_t *node;
node = xmalloc_and_zero(sizeof(list_node_t));
return node;
}
void list_free_node(list_t *list, list_node_t *node)
{
if(node->data && list->delete)
list->delete(node->data);
free(node);
}
/* Insertion and deletion */
list_node_t *list_insert_head(list_t *list, void *data)
{
list_node_t *node;
node = list_alloc_node();
node->data = data;
node->prev = NULL;
node->next = list->head;
list->head = node;
if(node->next)
node->next->prev = node;
else
list->tail = node;
list->count++;
return node;
}
list_node_t *list_insert_tail(list_t *list, void *data)
{
list_node_t *node;
node = list_alloc_node();
node->data = data;
node->next = NULL;
node->prev = list->tail;
list->tail = node;
if(node->prev)
node->prev->next = node;
else
list->head = node;
list->count++;
return node;
}
void list_unlink_node(list_t *list, list_node_t *node)
{
if(node->prev)
node->prev->next = node->next;
else
list->head = node->next;
if(node->next)
node->next->prev = node->prev;
else
list->tail = node->prev;
list->count--;
}
void list_delete_node(list_t *list, list_node_t *node)
{
list_unlink_node(list, node);
list_free_node(list, node);
}
void list_delete_head(list_t *list)
{
list_delete_node(list, list->head);
}
void list_delete_tail(list_t *list)
{
list_delete_node(list, list->tail);
}
/* Head/tail lookup */
void *list_get_head(list_t *list)
{
if(list->head)
return list->head->data;
else
return NULL;
}
void *list_get_tail(list_t *list)
{
if(list->tail)
return list->tail->data;
else
return NULL;
}
/* Fast list deletion */
void list_delete_list(list_t *list)
{
list_node_t *node, *next;
for(node = list->head; node; node = next)
{
next = node->next;
list_free_node(list, node);
}
list_free(list);
}
/* Traversing */
void list_foreach_node(list_t *list, list_action_node_t action)
{
list_node_t *node, *next;
for(node = list->head; node; node = next)
{
next = node->next;
action(node);
}
}
void list_foreach(list_t *list, list_action_t action)
{
list_node_t *node, *next;
for(node = list->head; node; node = next)
{
next = node->next;
if(node->data)
action(node->data);
}
}

View file

@ -1,7 +1,7 @@
/*
list.h -- header file for list.c
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 2000,2001 Ivo Timmermans <itimmermans@bigfoot.com>
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
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
@ -17,28 +17,66 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: list.h,v 1.1 2000/10/20 16:44:32 zarq Exp $
$Id: list.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#ifndef __TINC_LIST_H__
#define __TINC_LIST_H__
typedef struct list_callbacks_t {
int (*delete) (void *);
} list_callbacks_t;
typedef struct list_node_t {
void *data;
typedef struct list_node_t
{
struct list_node_t *prev;
struct list_node_t *next;
/* Payload */
void *data;
} list_node_t;
typedef struct list_t {
typedef void (*list_action_t) (const void *);
typedef void (*list_action_node_t) (const list_node_t *);
typedef struct list_t
{
list_node_t *head;
list_node_t *tail;
list_callbacks_t *callbacks;
int count;
/* Callbacks */
list_action_t delete;
} list_t;
/* (De)constructors */
extern list_t *list_alloc(list_action_t);
extern void list_free(list_t *);
extern list_node_t *list_alloc_node(void);
extern void list_free_node(list_t *, list_node_t *);
/* Insertion and deletion */
extern list_node_t *list_insert_head(list_t *, void *);
extern list_node_t *list_insert_tail(list_t *, void *);
extern void list_unlink_node(list_t *, list_node_t *);
extern void list_delete_node(list_t *, list_node_t *);
extern void list_delete_head(list_t *);
extern void list_delete_tail(list_t *);
/* Head/tail lookup */
extern void *list_get_head(list_t *);
extern void *list_get_tail(list_t *);
/* Fast list deletion */
extern void list_delete_list(list_t *);
/* Traversing */
extern void list_foreach(list_t *, list_action_t);
extern void list_foreach_node(list_t *, list_action_node_t);
#endif /* __TINC_LIST_H__ */

View file

@ -32,6 +32,8 @@
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
/* read_pid
*
@ -71,6 +73,7 @@ int check_pid (char *pidfile)
* be found -- GW
*/
/* But... errno is usually changed only on error.. */
errno = 0;
if (kill(pid, 0) && errno == ESRCH)
return(0);
@ -93,13 +96,15 @@ int write_pid (char *pidfile)
fprintf(stderr, "Can't open or create %s.\n", pidfile);
return 0;
}
#ifdef HAVE_FLOCK
if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
fscanf(f, "%d", &pid);
fclose(f);
printf("Can't lock, lock is held by pid %d.\n", pid);
return 0;
}
#endif
pid = getpid();
if (!fprintf(f,"%d\n", pid)) {
@ -109,11 +114,13 @@ int write_pid (char *pidfile)
}
fflush(f);
#ifdef HAVE_FLOCK
if (flock(fd, LOCK_UN) == -1) {
printf("Can't unlock pidfile %s, %s.\n", pidfile, strerror(errno));
close(fd);
return 0;
}
#endif
close(fd);
return pid;

596
lib/rbl.c Normal file
View file

@ -0,0 +1,596 @@
/*
rbl.c -- red-black tree + linked list convenience
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>,
2000 Guus Sliepen <guus@sliepen.warande.net>
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 Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: rbl.c,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#include "config.h"
#include <stdlib.h>
#include <xalloc.h>
#include "rbl.h"
#include <system.h>
/* Allocate a new rbl node */
rbl_t *new_rbl()
{
return (rbl_t *)xmalloc_and_zero(sizeof(rbl_t));
}
/* Free a rbl node */
void free_rbl(rbl_t *rbl)
{
if(rbl->data && rbl->tree->delete)
rbl->tree->delete(rbl->data);
free(rbl);
}
/* Allocate a new rbltree header */
rbltree_t *new_rbltree(rbl_compare_t compare, rbl_action_t delete)
{
rbltree_t *tree;
tree = (rbltree_t *)xmalloc_and_zero(sizeof(rbltree_t));
if(tree)
{
tree->compare = compare;
tree->delete = delete;
}
return tree;
}
/* Free a rbltree header */
void free_rbltree(rbltree_t *tree)
{
free(tree);
}
/* Search closest match in the tree */
rbl_t *rbl_search_closest_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl, *next;
int result;
next = rbl = tree->top;
while(next)
{
rbl = next;
result = tree->compare(data, rbl->data);
if(result < 0)
next = rbl->left;
else if(result > 0)
next = rbl->right;
else
break;
}
return rbl;
}
/* Search closest match in the tree */
rbl_t *rbl_search_closest_greater_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_rbl(tree, data);
if(rbl)
{
if(tree->compare(data, rbl->data) > 0)
rbl = rbl->next;
}
return rbl;
}
/* Search closest match in the tree */
rbl_t *rbl_search_closest_smaller_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_rbl(tree, data);
if(rbl)
{
if(tree->compare(data, rbl->data) < 0)
rbl = rbl->next;
}
return rbl;
}
void *rbl_search_closest(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
void *rbl_search_closest_greater(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_greater_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
void *rbl_search_closest_smaller(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_closest_smaller_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
/* Search exact match or return NULL pointer */
rbl_t *rbl_search_rbl(rbltree_t *tree, void *data)
{
rbl_t *rbl;
int result;
rbl = tree->top;
while(rbl)
{
result = tree->compare(data, rbl->data);
if(result < 0)
rbl = rbl->left;
else if(result > 0)
rbl = rbl->right;
else
return rbl;
}
return NULL;
}
void *rbl_search(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_rbl(tree, data);
if(rbl)
return rbl->data;
else
return NULL;
}
/* Red-black tree operations taken from Introduction to Algorithms,
Cormen, Leiserson & Rivest, chapter 14.
*/
void rbl_left_rotate(rbl_t *x)
{
rbl_t *y;
y = x->right;
x->right = y->left;
if(y->left)
y->left->parent = x;
y->parent = x->parent;
if(!x->parent)
x->tree->top = y;
else
if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
void rbl_right_rotate(rbl_t *y)
{
rbl_t *x;
x = y->left;
y->left = x->right;
if(x->right)
x->right->parent = y;
x->parent = y->parent;
if(!y->parent)
y->tree->top = x;
else
if(y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y;
y->parent = x;
}
/* Insert a node into the rbl tree */
rbl_t *rbl_insert_rbl(rbltree_t *tree, rbl_t *rbl)
{
rbl_t *closest, *x, *y;
int result;
rbl->tree = tree;
/* Binary tree and linked list insert */
if(tree->top)
{
closest = rbl_search_closest_rbl(tree, rbl->data);
result = tree->compare(rbl->data, closest->data);
if(result < 0)
{
closest->left = rbl;
rbl->prev = closest->prev;
rbl->next = closest;
closest->prev = rbl;
if(rbl->prev)
rbl->prev->next = rbl;
else
tree->head = rbl;
}
else if(result > 0)
{
closest->right = rbl;
rbl->next = closest->next;
rbl->prev = closest;
closest->next = rbl;
if(rbl->next)
rbl->next->prev = rbl;
else
tree->tail = rbl;
}
else
return closest; /* Ofcourse, we cannot add two identical things */
rbl->parent = closest;
}
else
{
tree->top = rbl;
tree->head = rbl;
tree->tail = rbl;
}
/* Red-black part of insert */
x = rbl;
x->color = RBL_RED;
while(x != tree->top && x->parent->color == RBL_RED)
{
if(x->parent == x->parent->parent->left)
{
y = x->parent->parent->right;
if(y && y->color == RBL_RED)
{
x->parent->color = RBL_BLACK;
y->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->right)
{
x = x->parent;
rbl_left_rotate(x);
}
x->parent->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
rbl_right_rotate(x->parent->parent);
}
}
else
{
y = x->parent->parent->left;
if(y && y->color == RBL_RED)
{
x->parent->color = RBL_BLACK;
y->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->left)
{
x = x->parent;
rbl_right_rotate(x);
}
x->parent->color = RBL_BLACK;
x->parent->parent->color = RBL_RED;
rbl_left_rotate(x->parent->parent);
}
}
}
tree->top->color = RBL_BLACK;
return rbl;
}
/* Create a new node and insert it into the tree */
rbl_t *rbl_insert(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = new_rbl();
rbl->data = data;
if(rbl_insert_rbl(tree, rbl) == rbl)
return rbl;
else
{
free_rbl(rbl);
return NULL;
}
}
/* Restore red-black property after violation due to a deletion */
void rbl_delete_fixup(rbl_t *x)
{
rbl_t *w;
while(x != x->tree->top && x->color == RBL_BLACK)
{
if(x == x->parent->left)
{
w = x->parent->right;
if(w->color == RBL_RED)
{
w->color = RBL_BLACK;
x->parent->color = RBL_RED;
rbl_left_rotate(x->parent);
w = x->parent->right;
}
if(w->left->color == RBL_BLACK && w->right->color == RBL_BLACK)
{
w->color = RBL_RED;
x = x->parent;
}
else
{
if(w->right->color == RBL_BLACK)
{
w->left->color = RBL_BLACK;
w->color = RBL_RED;
rbl_right_rotate(w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = RBL_BLACK;
w->right->color = RBL_BLACK;
rbl_left_rotate(x->parent);
x = x->tree->top;
}
}
else
{
w = x->parent->left;
if(w->color == RBL_RED)
{
w->color = RBL_BLACK;
x->parent->color = RBL_RED;
rbl_right_rotate(x->parent);
w = x->parent->left;
}
if(w->right->color == RBL_BLACK && w->left->color == RBL_BLACK)
{
w->color = RBL_RED;
x = x->parent;
}
else
{
if(w->left->color == RBL_BLACK)
{
w->right->color = RBL_BLACK;
w->color = RBL_RED;
rbl_left_rotate(w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = RBL_BLACK;
w->left->color = RBL_BLACK;
rbl_right_rotate(x->parent);
x = x->tree->top;
}
}
}
x->color = RBL_BLACK;
}
/* Unlink node from the tree, but keep the node intact. */
rbl_t *rbl_unlink_rbl(rbl_t *rbl)
{
rbl_t *x, *y;
/* Binary tree delete */
if(rbl->left && rbl->right)
y = rbl->next;
else
y = rbl;
if(y->left)
x = y->left;
else
x = y->right;
if(x)
x->parent = y->parent;
if(!y->parent)
rbl->tree->top = x;
else
if(y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
if(y != rbl)
{
y->left = rbl->left;
y->right = rbl->right;
y->parent = rbl->parent;
if(rbl == rbl->parent->left)
rbl->parent->left = y;
else
rbl->parent->right = y;
}
/* Linked list delete */
if(rbl->prev)
rbl->prev->next = rbl->next;
else
rbl->tree->head = rbl->next;
if(rbl->next)
rbl->next->prev = rbl->prev;
else
rbl->tree->tail = rbl->prev;
/* Red-black part of delete */
if(y->color == RBL_BLACK && x)
rbl_delete_fixup(x);
return rbl;
}
/* Search node in tree and unlink it */
rbl_t *rbl_unlink(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_search_rbl(tree, data);
if(rbl)
rbl_unlink_rbl(rbl);
return rbl;
}
/* Unlink node and free it */
void rbl_delete_rbl(rbl_t *rbl)
{
rbl_unlink_rbl(rbl);
free_rbl(rbl);
}
/* Search node in tree, unlink and free it */
void rbl_delete(rbltree_t *tree, void *data)
{
rbl_t *rbl;
rbl = rbl_unlink(tree, data);
if(rbl)
free_rbl(rbl);
}
/* Optimized unlinking for a complete tree */
void rbl_unlink_rbltree(rbltree_t *tree)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
rbl->tree = NULL;
rbl->parent = NULL;
rbl->left = NULL;
rbl->right = NULL;
rbl->prev = NULL;
rbl->next = NULL;
}
tree->top = NULL;
tree->head = NULL;
tree->tail = NULL;
}
/* Optimized deletion for a complete tree */
void rbl_delete_rbltree(rbltree_t *tree)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
free_rbl(rbl);
}
tree->top = NULL;
tree->head = NULL;
tree->tail = NULL;
}
/* Do action for each list entry (in order)
Deletion of entry for which action is called is allowed.
*/
void rbl_foreach(rbltree_t *tree, rbl_action_t action)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
action(rbl->data);
}
}
void rbl_foreach_rbl(rbltree_t *tree, rbl_action_rbl_t action)
{
rbl_t *rbl, *next;
for(rbl = tree->head; rbl; rbl = next)
{
next = rbl->next;
action(rbl);
}
}

104
lib/rbl.h Normal file
View file

@ -0,0 +1,104 @@
/*
rbl.h -- header file for rbl.c
Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>,
2000 Guus Sliepen <guus@sliepen.warande.net>
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 Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id: rbl.h,v 1.2 2002/04/09 15:26:00 zarq Exp $
*/
#ifndef __RBL_H__
#define __RBL_H__
#define RBL_FOREACH(tree,rbl) for(rbl = tree->head; rbl; rbl = rbl->next)
typedef struct rbl_t
{
/* 'red-black tree' part */
struct rbltree_t *tree;
int color;
struct rbl_t *parent;
struct rbl_t *left;
struct rbl_t *right;
/* 'linked list' part */
struct rbl_t *prev;
struct rbl_t *next;
/* payload */
void *data;
} rbl_t;
typedef int (*rbl_compare_t) (const void *, const void *);
typedef void (*rbl_action_t) (const void *);
typedef void (*rbl_action_rbl_t) (const struct rbl_t *);
typedef struct rbltree_t
{
/* callback functions */
rbl_compare_t compare;
rbl_action_t delete;
/* tree part */
struct rbl_t *top;
/* linked list */
struct rbl_t *head;
struct rbl_t *tail;
} rbltree_t;
enum color
{
RBL_RED,
RBL_BLACK
} color;
extern rbltree_t *new_rbltree(rbl_compare_t, rbl_action_t);
extern void free_rbltree(rbltree_t *);
extern rbl_t *new_rbl(void);
extern void free_rbl(rbl_t *);
extern void *rbl_search(rbltree_t *, void *);
extern void *rbl_search_closest(rbltree_t *, void *);
extern void *rbl_search_closest_greater(rbltree_t *, void *);
extern void *rbl_search_closest_smaller(rbltree_t *, void *);
extern rbl_t *rbl_search_rbl(rbltree_t *, void *);
extern rbl_t *rbl_search_closest_rbl(rbltree_t *, void *);
extern rbl_t *rbl_search_closest_greater_rbl(rbltree_t *, void *);
extern rbl_t *rbl_search_closest_smaller_rbl(rbltree_t *, void *);
extern rbl_t *rbl_insert(rbltree_t *, void *);
extern rbl_t *rbl_unlink(rbltree_t *, void *);
extern void rbl_delete(rbltree_t *, void *);
extern rbl_t *rbl_insert_rbl(rbltree_t *, rbl_t *);
extern rbl_t *rbl_unlink_rbl(rbl_t *);
extern void rbl_delete_rbl(rbl_t *);
extern void rbl_unlink_rbltree(rbltree_t *);
extern void rbl_delete_rbltree(rbltree_t *);
extern void rbl_foreach(rbltree_t *, rbl_action_t);
extern void rbl_foreach_rbl(rbltree_t *, rbl_action_rbl_t);
#endif /* __RBL_H__ */

View file

@ -1,7 +1,7 @@
/*
utils.c -- gathering of some stupid small functions
Copyright (C) 1999,2000 Ivo Timmermans <zarq@iname.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 1999-2001 Ivo Timmermans <zarq@iname.com>
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
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
@ -26,10 +26,13 @@
#include <utils.h>
#include <syslog.h>
#include <xalloc.h>
volatile int (cp_line[]) = {0, 0, 0, 0, 0, 0, 0, 0};
volatile char (*cp_file[]) = {"?", "?", "?", "?", "?", "?", "?", "?"};
#ifdef ENABLE_TRACING
volatile int (cp_line[]) = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
volatile char (*cp_file[]) = {"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?"};
volatile int cp_index = 0;
#endif
char *hexadecimals = "0123456789ABCDEF";
@ -59,16 +62,26 @@ void bin2hex(char *src, char *dst, int length)
}
}
char *cp_trace()
#ifdef ENABLE_TRACING
void cp_trace()
{
syslog(LOG_DEBUG, "Checkpoint trace: %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d ...",
cp_file[(cp_index+7)%8], cp_line[(cp_index+7)%8],
cp_file[(cp_index+6)%8], cp_line[(cp_index+6)%8],
cp_file[(cp_index+5)%8], cp_line[(cp_index+5)%8],
cp_file[(cp_index+4)%8], cp_line[(cp_index+4)%8],
cp_file[(cp_index+3)%8], cp_line[(cp_index+3)%8],
cp_file[(cp_index+2)%8], cp_line[(cp_index+2)%8],
cp_file[(cp_index+1)%8], cp_line[(cp_index+1)%8],
syslog(LOG_DEBUG, "Checkpoint trace: %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d...",
cp_file[(cp_index+15)%16], cp_line[(cp_index+15)%16],
cp_file[(cp_index+14)%16], cp_line[(cp_index+14)%16],
cp_file[(cp_index+13)%16], cp_line[(cp_index+13)%16],
cp_file[(cp_index+12)%16], cp_line[(cp_index+12)%16],
cp_file[(cp_index+11)%16], cp_line[(cp_index+11)%16],
cp_file[(cp_index+10)%16], cp_line[(cp_index+10)%16],
cp_file[(cp_index+9)%16], cp_line[(cp_index+9)%16],
cp_file[(cp_index+8)%16], cp_line[(cp_index+8)%16],
cp_file[(cp_index+7)%16], cp_line[(cp_index+7)%16],
cp_file[(cp_index+6)%16], cp_line[(cp_index+6)%16],
cp_file[(cp_index+5)%16], cp_line[(cp_index+5)%16],
cp_file[(cp_index+4)%16], cp_line[(cp_index+4)%16],
cp_file[(cp_index+3)%16], cp_line[(cp_index+3)%16],
cp_file[(cp_index+2)%16], cp_line[(cp_index+2)%16],
cp_file[(cp_index+1)%16], cp_line[(cp_index+1)%16],
cp_file[cp_index], cp_line[cp_index]
);
}
#endif

View file

@ -1,7 +1,7 @@
/*
utils.h -- header file for utils.c
Copyright (C) 1999,2000 Ivo Timmermans <zarq@iname.com>
2000 Guus Sliepen <guus@sliepen.warande.net>
Copyright (C) 1999-2001 Ivo Timmermans <zarq@iname.com>
2000,2001 Guus Sliepen <guus@sliepen.warande.net>
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
@ -24,24 +24,34 @@
#include <ctype.h>
enum {
DEBUG_CONNECTIONS = 0,
DEBUG_PROTOCOL,
DEBUG_STATUS,
DEBUG_ERROR,
DEBUG_META
DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */
DEBUG_CONNECTIONS = 1, /* Show (dis)connects of other tinc daemons via TCP */
DEBUG_ERROR = 2, /* Show error messages received from other hosts */
DEBUG_STATUS = 2, /* Show status messages received from other hosts */
DEBUG_PROTOCOL = 3, /* Show the requests that are sent/received */
DEBUG_META = 4, /* Show contents of every request that is sent/received */
DEBUG_TRAFFIC = 5, /* Show network traffic information */
DEBUG_PACKET = 6, /* Show contents of each packet that is being sent/received */
DEBUG_SCARY_THINGS = 10 /* You have been warned */
};
#define min(a,b) (((a)<(b))?(a):(b))
#ifdef ENABLE_TRACING
extern volatile int cp_line[];
extern volatile char *cp_file[];
extern volatile int cp_index;
extern void cp_trace(void);
#define cp { cp_line[cp_index] = __LINE__; cp_file[cp_index] = __FILE__; cp_index++; cp_index %= 8; }
#define ecp { fprintf(stderr, "Explicit checkpoint in %s line %d\n", __FILE__, __LINE__); }
#define cp { cp_line[cp_index] = __LINE__; cp_file[cp_index] = __FILE__; cp_index++; cp_index %= 16; }
#define ecp { fprintf(stderr, "Explicit checkpoint in %s line %d\n", __FILE__, __LINE__); }
#else
#define cp
#define ecp
#define cp_trace()
#endif
extern void hex2bin(char *src, char *dst, int length);
extern void bin2hex(char *src, char *dst, int length);
extern char *cp_trace(void);
#endif /* __TINC_UTILS_H__ */

View file

@ -22,3 +22,5 @@ void *xmalloc PARAMS ((size_t n));
void *xmalloc_and_zero PARAMS ((size_t n));
void *xcalloc PARAMS ((size_t n, size_t s));
void *xrealloc PARAMS ((void *p, size_t n));
char *xstrdup PARAMS ((const char *s));

View file

@ -21,6 +21,7 @@
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#if STDC_HEADERS
# include <stdlib.h>
@ -124,6 +125,18 @@ xrealloc (p, n)
return p;
}
/* Duplicate a string */
char *xstrdup(const char *s)
{
char *p;
p = strdup(s);
if(!p)
xalloc_fail ((int)strlen(s));
return p;
}
#ifdef NOT_USED
/* Allocate memory for N elements of S bytes, with error checking. */