]> git.ipfire.org Git - thirdparty/fcron.git/commitdiff
Added exe_list and lavg_list based on u_list (unordered list)
authorThibault Godouet <yo8192@users.noreply.github.com>
Fri, 17 Oct 2008 14:14:20 +0000 (15:14 +0100)
committerThibault Godouet <yo8192@users.noreply.github.com>
Fri, 17 Oct 2008 14:14:20 +0000 (15:14 +0100)
doc/bitstring.3 [new file with mode: 0644]
exe_list.c [new file with mode: 0644]
exe_list.h [new file with mode: 0644]
exe_list_test.c [new file with mode: 0644]
lavg_list.c [new file with mode: 0644]
lavg_list.h [new file with mode: 0644]
u_list.c [new file with mode: 0644]
u_list.h [new file with mode: 0644]

diff --git a/doc/bitstring.3 b/doc/bitstring.3
new file mode 100644 (file)
index 0000000..efe9ae3
--- /dev/null
@@ -0,0 +1,168 @@
+.\" Copyright (c) 1989 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Paul Vixie.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that the above copyright notice and this paragraph are
+.\" duplicated in all such forms and that any documentation,
+.\" advertising materials, and other materials related to such
+.\" distribution and use acknowledge that the software was developed
+.\" by the University of California, Berkeley.  The name of the
+.\" University may not be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.\"    @(#)bitstring.3 5.1 (Berkeley) 12/13/89
+.\"
+.TH BITSTRING 3  "December 13, 1989"
+.UC 4
+.SH NAME
+bit_alloc, bit_clear, bit_decl, bit_ffs, bit_nclear, bit_nset,
+bit_set, bitstr_size, bit_test \- bit-string manipulation macros
+.SH SYNOPSIS
+.ft B
+.nf
+#include <bitstring.h>
+
+name = bit_alloc(nbits)
+bitstr_t *name;
+int nbits;
+
+bit_decl(name, nbits)
+bitstr_t name;
+int nbits;
+
+bit_clear(name, bit)
+bitstr_t name;
+int bit;
+
+bit_ffc(name, nbits, value)
+bitstr_t name;
+int nbits, *value;
+
+bit_ffs(name, nbits, value)
+bitstr_t name;
+int nbits, *value;
+
+bit_nclear(name, start, stop)
+bitstr_t name;
+int start, stop;
+
+bit_nset(name, start, stop)
+bitstr_t name;
+int start, stop;
+
+bit_set(name, bit)
+bitstr_t name;
+int bit;
+
+bitstr_size(nbits)
+int nbits;
+
+bit_test(name, bit)
+bitstr_t name;
+int bit;
+.fi
+.ft R
+.SH DESCRIPTION
+These macros operate on strings of bits.
+.PP
+.I Bit_alloc
+returns a pointer of type
+.I bitstr_t\ *
+to sufficient space to store
+.I nbits
+bits, or NULL if no space is available.
+.PP
+.I Bit_decl
+is a macro for allocating sufficient space to store
+.I nbits
+bits on the stack.
+.PP
+.I Bitstr_size
+returns the number of elements of type
+.I bitstr_t
+necessary to store
+.I nbits
+bits.
+This is useful for copying bit strings.
+.PP
+.I Bit_clear
+and
+.I bit_set
+clear or set the zero-based numbered bit
+.IR bit ,
+in the bit string
+.IR name .
+.PP
+.I Bit_nset
+and
+.I bit_nclear
+set or clear the zero-based numbered bits from
+.I start
+to
+.I stop
+in the bit string
+.IR name .
+.PP
+.I Bit_test
+evaluates to zero if the zero-based numbered bit
+.I bit
+of bit string
+.I name
+is set, and non-zero otherwise.
+.PP
+.I Bit_ffs
+sets
+.I *value
+to the zero-based number of the first bit set in the array of
+.I nbits
+bits referenced by
+.IR name .
+If no bits are set,
+.I *value
+is set to -1.
+.PP
+.I Bit_ffc
+sets
+.I *value
+to the zero-based number of the first bit not set in the array of
+.I nbits
+bits referenced by
+.IR name .
+If all bits are set,
+.I value
+is set to -1.
+.SH EXAMPLE
+.nf
+.in +5
+#include <limits.h>
+#include <bitstring.h>
+
+...
+#define        LPR_BUSY_BIT            0
+#define        LPR_FORMAT_BIT          1
+#define        LPR_DOWNLOAD_BIT        2
+...
+#define        LPR_AVAILABLE_BIT       9
+#define        LPR_MAX_BITS            10
+
+make_lpr_available()
+{
+       bitstr_t bit_decl(bitlist, LPR_MAX_BITS);
+       ...
+       bit_nclear(bitlist, 0, LPR_MAX_BITS - 1);
+       ...
+       if (!bit_test(bitlist, LPR_BUSY_BIT)) {
+               bit_clear(bitlist, LPR_FORMAT_BIT);
+               bit_clear(bitlist, LPR_DOWNLOAD_BIT);
+               bit_set(bitlist, LPR_AVAILABLE_BIT);
+       }
+}
+.fi
+.SH "SEE ALSO"
+malloc(3)
diff --git a/exe_list.c b/exe_list.c
new file mode 100644 (file)
index 0000000..f1427c4
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * FCRON - periodic command scheduler 
+ *
+ *  Copyright 2000-2008 Thibault Godouet <fcron@free.fr>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ *  The GNU General Public License can also be found in the file
+ *  `LICENSE' that comes with the fcron source distribution.
+ */
+
+ /* $Id: temp_file.c,v 1.6 2007/04/14 18:04:19 thib Exp thib $ */
+
+/* List of jobs currently being executed.
+ * This is a wrapper for an u_list (unordered list) (see u_list.h and u_list.c),
+ * to make the rest of the code clearer and as a way to ensure the compiler can checks
+ * the type in the rest of the code (u_list extensively uses the void type) */
+
+#include "global.h"
+#include "fcron.h"
+#include "exe_list.h"
+
+exe_list_t *exe_list_init(void)
+{
+    return (exe_list_t *) u_list_init(sizeof(exe_t), EXE_INITIAL_SIZE, EXE_GROW_SIZE);
+}
+
+exe_t *
+exe_list_add(exe_list_t *list, struct cl_t *line)
+{
+    exe_t e = { NULL, 0, 0};
+    e.e_line = line; /* ANSI C does not allow us to directly replace NULL by line above*/
+
+    return (exe_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e);
+}
+
+exe_t *
+exe_list_first(exe_list_t *list)
+{
+    return (exe_t *) u_list_first((u_list_t *) list);
+}
+
+exe_t *
+exe_list_next(exe_list_t *list, exe_t *cur_entry)
+{
+    return (exe_t *) u_list_next((u_list_t *) list, (u_list_entry_t *) cur_entry);
+}
+
+void
+exe_list_remove(exe_list_t *list, exe_t *entry)
+{
+    u_list_remove((u_list_t *) list, (u_list_entry_t *) entry);
+}
+
+exe_list_t *
+exe_list_destroy(exe_list_t *list)
+    /* free() the memory allocated for list and returns NULL */
+{
+    return (exe_list_t *) u_list_destroy((u_list_t *) list);
+}
+
diff --git a/exe_list.h b/exe_list.h
new file mode 100644 (file)
index 0000000..50c0483
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * FCRON - periodic command scheduler 
+ *
+ *  Copyright 2000-2008 Thibault Godouet <fcron@free.fr>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ *  The GNU General Public License can also be found in the file
+ *  `LICENSE' that comes with the fcron source distribution.
+ */
+
+ /* $Id: temp_file.h,v 1.4 2007/04/14 18:04:20 thib Exp thib $ */
+
+/* List of jobs currently being executed.
+ * This is a wrapper for an u_list (unordered list) (see u_list.h and u_list.c),
+ * to make the rest of the code clearer and as a way to ensure the compiler can checks
+ * the type in the rest of the code (u_list extensively uses the void type) */
+
+#ifndef __EXE_LIST_H__
+#define __EXE_LIST_H__
+
+#include "u_list.h"
+
+/* Entry to describe one job being executed */
+typedef struct exe_t {
+    struct cl_t *e_line;
+    pid_t        e_ctrl_pid; /* pid of the fcron process controling the job */
+    pid_t        e_job_pid;  /* pid of the job itself */
+} exe_t;
+
+typedef struct u_list_t exe_list_t;
+
+/* functions prototypes */
+extern exe_list_t *exe_list_init(void);
+/* WARNING: exe_t pointers returned by those functions are only 
+ *          valid for as long as the list is not modified (add/remove) */
+extern exe_t *exe_list_add(exe_list_t *list, struct cl_t *line);
+extern exe_t *exe_list_first(exe_list_t *list);
+extern exe_t *exe_list_next(exe_list_t *list, exe_t *cur_entry);
+extern void exe_list_remove(exe_list_t *list, exe_t *entry);
+extern exe_list_t *exe_list_destroy(exe_list_t *list);
+
+
+#endif /* __EXE_LIST_H__ */
diff --git a/exe_list_test.c b/exe_list_test.c
new file mode 100644 (file)
index 0000000..a1210f0
--- /dev/null
@@ -0,0 +1,112 @@
+#include "exe_list.h"
+#include "global.h"
+#include "fcron.h"
+
+/* required by log.c */
+char debug_opt = 1;
+char *prog_name = NULL;
+char dosyslog = 1;
+char foreground = 1;
+pid_t daemon_pid = 0;
+uid_t rootuid = 0;
+
+void print_cur(exe_t *e) {
+    printf("Current entry's shell command: %s\n", e?e->e_line->cl_shell:"NULL");
+}
+
+void print_list(exe_list_t *list) {
+    exe_t *e = NULL;
+    printf("Current list:\n");
+    for ( e = exe_list_first(list) ; e != NULL ; e = exe_list_next(list) )
+       printf("  Shell command: %s\n", e?e->e_line->cl_shell:"NULL");
+}
+
+int main(int argc, char *argv[]) {
+    exe_list_t *list = NULL;
+    exe_t *e = NULL;
+    cl_t l1, l2, l3, l4, l5, l6, l7;
+
+    l1.cl_shell = "line 1";
+    l2.cl_shell = "line 2";
+    l3.cl_shell = "line 3";
+    l4.cl_shell = "line 4";
+    l5.cl_shell = "line 5";
+    l6.cl_shell = "line 6";
+    l7.cl_shell = "line 7";
+
+    list = exe_list_init();
+
+    /* trigger a resize of the list during an iteration */
+    printf("Adding l1...\n"); exe_list_add_line(list, &l1);
+    printf("Adding l2...\n"); exe_list_add_line(list, &l2);
+    printf("Adding l3...\n"); exe_list_add_line(list, &l3);
+    e = exe_list_first(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    printf("Adding l4...\n"); exe_list_add_line(list, &l4);
+    printf("Adding l5...\n"); exe_list_add_line(list, &l5);
+    printf("Adding l6...\n"); exe_list_add_line(list, &l6);
+    printf("Adding l7...\n"); exe_list_add_line(list, &l7);
+
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+
+    /* "standard" iteration: */
+    print_list(list);
+
+    /* remove item at the beginning and middle of the list + add an item which is already in there */
+    printf("removing l1, l3, adding l2\n");
+    e = exe_list_first(list); print_cur(e);
+    printf("Removing l1...\n"); exe_list_remove_cur(list);
+    e = exe_list_next(list); print_cur(e); /* this one will be the item replacing l1 */
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    printf("Removing l3...\n"); exe_list_remove_cur(list);
+    exe_list_end_iteration(list);
+    printf("Adding l2...\n"); exe_list_add_line(list, &l2); /* we suppose the list array won't be reallocated() */
+
+    print_list(list);
+
+    /* remove an item at the end of the list: */
+    printf("removing l5, l2\n");
+    e = exe_list_first(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    printf("Removing l5...\n"); exe_list_remove_cur(list);
+    exe_list_end_iteration(list);
+    e = exe_list_first(list); print_cur(e);
+    e = exe_list_next(list); print_cur(e);
+    printf("Removing l2...\n");exe_list_remove_cur(list);
+    exe_list_end_iteration(list);
+
+    print_list(list);
+
+    printf("Adding l1...\n"); exe_list_add_line(list, &l1);
+
+    print_list(list);
+
+    printf("empty the list\n");
+    e = exe_list_first(list); print_cur(e);
+    exe_list_remove_cur(list);
+    e = exe_list_next(list); print_cur(e);
+    exe_list_remove_cur(list);
+    e = exe_list_next(list); print_cur(e);
+    exe_list_remove_cur(list);
+    e = exe_list_next(list); print_cur(e);
+    exe_list_remove_cur(list);
+    e = exe_list_next(list); print_cur(e);
+    exe_list_remove_cur(list);
+    e = exe_list_next(list); print_cur(e);
+
+    print_list(list);
+
+    printf("Destroying the list...\n"); list = exe_list_destroy(list);
+
+    return 0;
+
+}
diff --git a/lavg_list.c b/lavg_list.c
new file mode 100644 (file)
index 0000000..8392dd4
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * FCRON - periodic command scheduler 
+ *
+ *  Copyright 2000-2008 Thibault Godouet <fcron@free.fr>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ *  The GNU General Public License can also be found in the file
+ *  `LICENSE' that comes with the fcron source distribution.
+ */
+
+ /* $Id: temp_file.c,v 1.6 2007/04/14 18:04:19 thib Exp thib $ */
+
+/* List of jobs waiting for an appropriate system load average to be executed.
+ * This is a wrapper for an u_list (unordered list) (see u_list.h and u_list.c),
+ * to make the rest of the code clearer and as a way to ensure the compiler can checks
+ * the type in the rest of the code (u_list extensively uses the void type) */
+
+#include "global.h"
+#include "fcron.h"
+#include "lavg_list.h"
+
+lavg_list_t *lavg_list_init(void)
+{
+    lavg_list_t *l = (lavg_list_t *)u_list_init(sizeof(lavg_t), LAVG_INITIAL_SIZE, LAVG_GROW_SIZE);
+    l->max_entries = LAVG_QUEUE_MAX;
+    return l;
+}
+
+lavg_t *
+lavg_list_add(lavg_list_t *list, struct cl_t *line)
+{
+    lavg_t e = { NULL, 0};
+    e.l_line = line; /* ANSI C does not allow us to directly replace NULL by line above*/
+
+    return (lavg_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e);
+}
+
+lavg_t *
+lavg_list_first(lavg_list_t *list)
+{
+    return (lavg_t *) u_list_first((u_list_t *) list);
+}
+
+lavg_t *
+lavg_list_next(lavg_list_t *list, lavg_t *cur_entry)
+{
+    return (lavg_t *) u_list_next((u_list_t *) list, (u_list_entry_t *) cur_entry);
+}
+
+void
+lavg_list_remove(lavg_list_t *list, lavg_t *entry)
+{
+    u_list_remove((u_list_t *) list, (u_list_entry_t *) entry);
+}
+
+lavg_list_t *
+lavg_list_destroy(lavg_list_t *list)
+{
+    return (lavg_list_t *) u_list_destroy((u_list_t *) list);
+}
+
diff --git a/lavg_list.h b/lavg_list.h
new file mode 100644 (file)
index 0000000..3c2af2e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * FCRON - periodic command scheduler 
+ *
+ *  Copyright 2000-2008 Thibault Godouet <fcron@free.fr>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ *  The GNU General Public License can also be found in the file
+ *  `LICENSE' that comes with the fcron source distribution.
+ */
+
+ /* $Id: temp_file.h,v 1.4 2007/04/14 18:04:20 thib Exp thib $ */
+
+/* List of jobs waiting for an appropriate system load average to be executed.
+ * This is a wrapper for an u_list (unordered list) (see u_list.h and u_list.c),
+ * to make the rest of the code clearer and as a way to ensure the compiler can checks
+ * the type in the rest of the code (u_list extensively uses the void type) */
+
+#ifndef __LAVG_LIST_H__
+#define __LAVG_LIST_H__
+
+#include "u_list.h"
+
+/* Entry to describe one job waiting for an appropriate load average to be executed */
+typedef struct lavg_t {
+    struct cl_t *l_line;  
+    time_t       l_until;   /* the timeout of the wait for load averages */
+} lavg_t;
+
+typedef struct u_list_t lavg_list_t;
+
+/* functions prototypes */
+extern lavg_list_t *lavg_list_init(void);
+/* WARNING: lavg_t pointers returned by those functions are only 
+ *          valid for as long as the list is not modified (add/remove) */
+extern lavg_t *lavg_list_add(lavg_list_t *list, struct cl_t *line);
+extern lavg_t *lavg_list_first(lavg_list_t *list);
+extern lavg_t *lavg_list_next(lavg_list_t *list, lavg_t *cur_entry);
+extern void lavg_list_remove(lavg_list_t *list, lavg_t *entry);
+extern lavg_list_t *lavg_list_destroy(lavg_list_t *list);
+
+
+#endif /* __LAVG_LIST_H__ */
diff --git a/u_list.c b/u_list.c
new file mode 100644 (file)
index 0000000..2d3f40a
--- /dev/null
+++ b/u_list.c
@@ -0,0 +1,209 @@
+/*
+ * FCRON - periodic command scheduler 
+ *
+ *  Copyright 2000-2008 Thibault Godouet <fcron@free.fr>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ *  The GNU General Public License can also be found in the file
+ *  `LICENSE' that comes with the fcron source distribution.
+ */
+
+ /* $Id: temp_file.c,v 1.6 2007/04/14 18:04:19 thib Exp thib $ */
+
+/*
+ * Unordered list of generic items
+ */
+
+#include "global.h"
+#include "fcron.h"
+#include "u_list.h"
+
+/* private functions: */
+int u_list_resize_array(u_list_t *l);
+u_list_entry_t *u_list_last(u_list_t *l);
+
+u_list_t *
+u_list_init(size_t entry_size, int init_size, int grow_size) 
+/* Create a new unordered list
+ * Returns the newly created unorderd list
+ * Enough memory to hold init_size entries will initially be allocated,
+ * and it will grow by grow_size entries when more space is needed.
+ * Dies on error. */
+{
+    u_list_t *l = NULL;
+
+    /* sanity check */
+    if ( entry_size < 1 || init_size < 1 || grow_size < 1 )
+       die("Invalid arguments for u_list_init(): entry_size=%d, init_size=%d, "
+           "grow_size=%d", entry_size, init_size, grow_size);
+
+    /* Allocate the list structure: */
+    l = calloc(1, sizeof(struct u_list_t));
+    if ( l == NULL )
+       die_e("Failed creating a new unordered list: could not calloc() u_list_t "
+             "(entry_size: %d)", entry_size);
+
+    /* Initialize the structure and allocate the array: */
+    l->array_size = init_size;
+    l->entry_size = entry_size;
+    l->grow_size = grow_size;
+    l->entries_array = calloc(init_size, entry_size);
+    if ( l->entries_array == NULL )
+       die_e("Failed creating a new unordered list: could not calloc array"
+             "(entry_size: %d, init_size: %d)", entry_size, init_size);
+
+    return l;
+}
+
+int
+u_list_resize_array(u_list_t *l)
+/* Resize l's entries_array up to l->max_entries
+ * Returns OK on success, ERR if the array is already at maximum size */
+{
+    u_list_entry_t *e = NULL;
+    int old_size = l->array_size;
+
+    /* sanity check */
+    if ( l == NULL )
+       die("Invalid argument for u_list_resize_array(): list=%d", l);
+    if ( l->max_entries > 0 && l->array_size >= l->max_entries ) {
+       debug("Resizing u_list_t failed because it is already at max size (size: %d)",
+             l->array_size);
+       return ERR;
+    }
+
+    l->array_size = (l->array_size + l->grow_size);
+    if ( l->max_entries > 0 && l->array_size > l->max_entries )
+       l->array_size = l->max_entries;
+
+    debug("Resizing u_list_t (old size: %d, new size: %d)...", old_size, l->array_size);
+       
+    if ( (e = calloc(l->array_size, l->entry_size)) == NULL )
+       die_e("Could not calloc u_list_t to grow entries_array "
+             "(old size: %d, new size: %d)...", old_size, l->array_size);
+
+    memcpy(e, l->entries_array, (l->entry_size * old_size));
+    free_safe(l->entries_array);
+    l->entries_array = e;    
+
+    return OK;
+}
+
+u_list_entry_t *
+u_list_last(u_list_t *l)
+/* Returns the pointer of the last entry in the list, or NULL if l is empty */
+{
+    if ( l->num_entries <= 0 )
+       return NULL;
+    else
+       return (u_list_entry_t *) 
+       ( (char *)l->entries_array + l->entry_size * ( l->num_entries - 1 ) );
+}
+
+u_list_entry_t * 
+u_list_add(u_list_t *l, u_list_entry_t *e)
+/* Add one entry to the list
+ * Returns a pointer to the added element, or NULL if list is already at max size */
+{
+    u_list_entry_t *new = NULL;
+
+    /* sanity check */
+    if ( l == NULL || e == NULL )
+       die("Invalid arguments for u_list_add(): list=%d, entry=%d", l, e);
+
+    /* Check there is some space left, or resize the array */
+    if ( l->num_entries >= l->array_size ) {
+       /* no more space: attempt to grow (the following function dies on error: */
+       if ( u_list_resize_array(l) != OK )
+           return NULL;
+    }
+
+    l->num_entries++;
+    new = u_list_last(l);
+    memcpy(new, e, l->entry_size);
+
+    return new;
+}
+
+u_list_entry_t * 
+u_list_first(u_list_t *l)
+/* Return the first entry of the list (then u_list_next() can be used) */
+{
+    /* sanity check */
+    if ( l == NULL )
+       die("Invalid argument for u_list_first(): list=%d", l);
+
+    return (l->num_entries > 0) ? l->entries_array : NULL;
+}
+
+u_list_entry_t * 
+u_list_next(u_list_t *l, u_list_entry_t *e)
+/* Return the entry after e */
+{
+    /* sanity checks */
+    if (l==NULL||e==NULL)
+       die("Invalid arguments for u_list_next(): list=%d, entry=%d", l, e);
+    if (e < l->entries_array || e > u_list_last(l) )
+       die("u_list_next(): entry out of list! (entries_array: %d, entry: %d,"
+           "num_entries: %d)", l->entries_array, e, l->num_entries);
+
+    /* // */
+    /* Undefined? -- convert soustraction to float and check if result is an int ? */
+/*    if ( ( (char *) e - (char *) l->entries_array ) % l->entry_size != 0 )
+       die("u_list_next(): entry shifted! (entries_array: %d, entry_size: %d, "
+           "entry: %d", l->entries_array, l->entry_size, e);
+*/
+    if ( e < u_list_last(l) )
+       return (u_list_entry_t *) ( (char *) e + l->entry_size);
+    else 
+       return NULL;
+}
+
+void
+u_list_remove(u_list_t *l, u_list_entry_t *e)
+{
+    u_list_entry_t *last = NULL;
+
+    /* sanity checks */
+    if ( l == NULL || e == NULL )
+       die("Invalid arguments for u_list_remove(): list=%d, entry=%d", l, e);
+    if (e < l->entries_array || e > u_list_last(l) )
+       die("u_list_next(): entry out of list! (entries_array: %d, entry: %d,"
+           "num_entries: %d)", l->entries_array, e, l->num_entries);
+
+    last = u_list_last(l);
+    if ( e < last ) {
+       /* Override e with the last entry */
+       memcpy(e, last, l->entry_size);
+    }
+    /* erase the last entry and update the number of entries */
+    memset(last, 0, l->entry_size);
+    l->num_entries--;
+    
+
+}
+
+u_list_t *
+u_list_destroy(u_list_t *list)
+    /* free() the memory allocated for list and returns NULL */
+{
+    if ( list == NULL )
+       die("Invalid argument for u_list_destroy(): list=%d", list);
+
+    free_safe(list->entries_array);
+    free_safe(list);
+    return NULL;
+}
diff --git a/u_list.h b/u_list.h
new file mode 100644 (file)
index 0000000..2152a3d
--- /dev/null
+++ b/u_list.h
@@ -0,0 +1,62 @@
+/*
+ * FCRON - periodic command scheduler 
+ *
+ *  Copyright 2000-2008 Thibault Godouet <fcron@free.fr>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ *  The GNU General Public License can also be found in the file
+ *  `LICENSE' that comes with the fcron source distribution.
+ */
+
+ /* $Id: temp_file.h,v 1.4 2007/04/14 18:04:20 thib Exp thib $ */
+
+/*
+ * Unordered list of generic items
+ */
+
+#ifndef __U_LIST_H__
+#define __U_LIST_H__
+
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "subs.h"
+
+typedef void u_list_entry_t;
+
+typedef struct u_list_t {
+    /* PUBLIC: */
+    int             max_entries;   /* max allowed element number (0: no limit) */
+    int             num_entries;   /* READ ONLY: num of entries in the list now */
+    /* PRIVATE: DO NOT ACCESS DIRECTLY */
+    int             array_size;    /* size of the array (in number of entries) */
+    size_t          entry_size;    /* number of element currently in the array */
+    int             grow_size;     /* grow array by grow_size entries at a time */
+    u_list_entry_t *entries_array; /* pointer to the actual array */
+} u_list_t;
+
+/* functions prototypes */
+extern u_list_t *u_list_init(size_t entry_size, int init_size, int grow_size);
+/* WARNING: u_list_entry_t pointers returned by those functions are only 
+ *          valid for as long as the list is not modified (add/remove) */
+extern u_list_entry_t *u_list_add(u_list_t *list, u_list_entry_t *entry);
+extern u_list_entry_t *u_list_first(u_list_t *list);
+extern u_list_entry_t *u_list_next(u_list_t *list, u_list_entry_t *cur_entry);
+extern void u_list_remove(u_list_t *list, u_list_entry_t *entry);
+extern u_list_t *u_list_destroy(u_list_t *list);
+
+
+#endif /* __U_LIST_H__ */