From: Thibault Godouet Date: Fri, 17 Oct 2008 14:14:20 +0000 (+0100) Subject: Added exe_list and lavg_list based on u_list (unordered list) X-Git-Tag: ver3_1_0~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a1fe53d9c905ddac3b1ba7545f074b43e6342983;p=thirdparty%2Ffcron.git Added exe_list and lavg_list based on u_list (unordered list) --- diff --git a/doc/bitstring.3 b/doc/bitstring.3 new file mode 100644 index 0000000..efe9ae3 --- /dev/null +++ b/doc/bitstring.3 @@ -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 + +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 +#include + +... +#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 index 0000000..f1427c4 --- /dev/null +++ b/exe_list.c @@ -0,0 +1,73 @@ +/* + * FCRON - periodic command scheduler + * + * Copyright 2000-2008 Thibault Godouet + * + * 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 index 0000000..50c0483 --- /dev/null +++ b/exe_list.h @@ -0,0 +1,56 @@ +/* + * FCRON - periodic command scheduler + * + * Copyright 2000-2008 Thibault Godouet + * + * 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 index 0000000..a1210f0 --- /dev/null +++ b/exe_list_test.c @@ -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 index 0000000..8392dd4 --- /dev/null +++ b/lavg_list.c @@ -0,0 +1,74 @@ +/* + * FCRON - periodic command scheduler + * + * Copyright 2000-2008 Thibault Godouet + * + * 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 index 0000000..3c2af2e --- /dev/null +++ b/lavg_list.h @@ -0,0 +1,55 @@ +/* + * FCRON - periodic command scheduler + * + * Copyright 2000-2008 Thibault Godouet + * + * 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 index 0000000..2d3f40a --- /dev/null +++ b/u_list.c @@ -0,0 +1,209 @@ +/* + * FCRON - periodic command scheduler + * + * Copyright 2000-2008 Thibault Godouet + * + * 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 index 0000000..2152a3d --- /dev/null +++ b/u_list.h @@ -0,0 +1,62 @@ +/* + * FCRON - periodic command scheduler + * + * Copyright 2000-2008 Thibault Godouet + * + * 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 +#include +#include +#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__ */