]> granicus.if.org Git - fcron/commitdiff
Added exe_list and lavg_list based on the new u_list (unordered lists) as a way to...
authorThibault Godouet <thib@storm.(none)>
Fri, 17 Oct 2008 14:15:31 +0000 (15:15 +0100)
committerThibault Godouet <thib@storm.(none)>
Fri, 17 Oct 2008 14:15:31 +0000 (15:15 +0100)
20 files changed:
.gitignore
Makefile.in
conf.c
configure
configure.in
database.c
doc/Makefile.in
exe_list.c
exe_list.h
fcron.c
fcron.h
global.h
job.c
lavg_list.c
lavg_list.h
socket.c
subs.c
subs.h
u_list.c
u_list.h

index 926ecf992dc6a1b201e519097498d1478c27c88f..5db7943df943e43bf3ef759874d1c75c814ebf68 100644 (file)
@@ -13,3 +13,6 @@ fcronsighup
 files/fcron.conf
 convert-fcrontab
 doc/stylesheets/fcron-doc.dsl
+PREVIOUS_VERSION
+doc/fcron-doc.mod
+exe_list_test
index b9654b28ba44413d9a2a8d29d0fcfcbe17e6e13c..40997919219c43b0e4d69d509a22a82a295aaa51 100644 (file)
@@ -73,7 +73,7 @@ CFLAGS += $(OPTIM) $(OPTION) $(DEFS) $(CPPFLAGS)
 ifeq ($(FCRONDYN), 1)
 LIBOBJS := socket.o $(LIBOBJS)
 endif
-OBJSD := fcron.o subs.o save.o temp_file.o log.o database.o job.o conf.o $(LIBOBJS)
+OBJSD := fcron.o subs.o save.o temp_file.o log.o database.o job.o conf.o u_list.o exe_list.o lavg_list.o $(LIBOBJS)
 OBJSTAB := fcrontab.o subs.o save.o temp_file.o  log.o fileconf.o allow.o read_string.o
 OBJSDYN := fcrondyn.o subs.o log.o allow.o read_string.o
 OBJCONV := convert-fcrontab.o subs.o save.o log.o
@@ -114,6 +114,9 @@ fcronsighup: $(OBJSIG)
 convert-fcrontab: $(OBJCONV)
        $(CC) $(CFLAGS) -o $@ $(OBJCONV) $(LIBS)
 
+exe_list_test: exe_list.o u_list.o exe_list_test.o log.o subs.o
+       $(CC) $(CFLAGS) -o $@  exe_list.o u_list.o exe_list_test.o log.o subs.o $(LIBS)
+
 %.o: $(SRCDIR)/%.c $(HEADERSALL) $(SRCDIR)/%.h
        $(CC) $(CFLAGS) -DPIDFILE="\"${PIDFILE}\"" \
        -DFIFOFILE="\"${FIFOFILE}\"" -DETC="\"${ETC}\"" \
diff --git a/conf.c b/conf.c
index af05798deea30695d3b12c5a130f354cb9c60ec9..9e20d4b928fb4393dbedabfd516a477551301580 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -904,6 +904,8 @@ delete_file(const char *user_name)
     struct job_t *prev_j;
     int i, k;
     struct cl_t **s_a = NULL;
+    exe_t *e = NULL;
+    lavg_t *l = NULL;
 
     file = file_base;
     while ( file != NULL) {
@@ -913,39 +915,29 @@ delete_file(const char *user_name)
            continue;
        }
 
-       for ( i = 0; i < exe_num; i++)
-           if ( exe_array[i].e_line != NULL && 
-                exe_array[i].e_line->cl_file == file ) {
+       for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) )
+           if ( e->e_line != NULL && 
+                e->e_line->cl_file == file ) {
                /* we set the e_line to NULL, as so we know in wait_chld()
                 * and wait_all() the corresponding file has been removed.
                 * Plus, we decrement serial_running and lavg_serial_running
                 * as we won't be able to do it at the end of the job */
-               if ( ( is_serial(exe_array[i].e_line->cl_option) ||
-                      is_serial_once(exe_array[i].e_line->cl_option) ) &&
-                    ! is_lavg(exe_array[i].e_line->cl_option) )
+               if ( ( is_serial(e->e_line->cl_option) ||
+                      is_serial_once(e->e_line->cl_option) ) &&
+                    ! is_lavg(e->e_line->cl_option) )
                    serial_running--;
-               else if ( is_serial(exe_array[i].e_line->cl_option) &&
-                         is_lavg(exe_array[i].e_line->cl_option) )
+               else if ( is_serial(e->e_line->cl_option) &&
+                         is_lavg(e->e_line->cl_option) )
                    lavg_serial_running--;
-               exe_array[i].e_line = NULL;
+               e->e_line = NULL;
            }
 
        /* free lavg queue entries */
-       i = 0;
-       while (i < lavg_num)
-           if ( lavg_array[i].l_line->cl_file == file ) {
-               debug("removing %s from lavg queue",
-                     lavg_array[i].l_line->cl_shell);
-               lavg_array[i].l_line->cl_numexe--;
-               if (i < --lavg_num) {
-                   lavg_array[i] = lavg_array[lavg_num];
-                   lavg_array[lavg_num].l_line = NULL;
-               }
-               else
-                   lavg_array[i].l_line = NULL;
+       for (l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list))
+           if ( l->l_line->cl_file == file ) {
+               debug("removing %s from lavg queue", l->l_line->cl_shell);
+               lavg_list_remove_cur(lavg_list);
            } 
-           else
-               i++;
 
        /* free serial queue entries */
        for ( i = 0; i < serial_array_size; i++)
index dd0b4b82007317bfd9294426f6f98106a4c08320..e8747904229aa7be8d39db29e67b4fef9f0b29ab 100755 (executable)
--- a/configure
+++ b/configure
@@ -1748,7 +1748,7 @@ ac_config_headers="$ac_config_headers config.h"
 
 
 
-vers="3.0.5"
+vers="3.1.0"
 vers_quoted="\"$vers\""
 cat >>confdefs.h <<_ACEOF
 #define VERSION $vers
index 6e1e757efe45e978ae789d1571675b56ba7365f6..0a8b97328a6cdfeb4b85ba7245b65986f274b8ed 100644 (file)
@@ -9,7 +9,7 @@ AC_INIT(allow.c)
 AC_CONFIG_HEADER(config.h)
 AC_PREREQ(2.57)
 
-vers="3.0.5"
+vers="3.1.0"
 vers_quoted="\"$vers\""
 AC_DEFINE_UNQUOTED(VERSION, $vers)
 AC_DEFINE_UNQUOTED(VERSION_QUOTED, $vers_quoted)
index a2b71b5f6e7047427ec158b747cf4bbe935737c5..e869a2a0fe7688c5a0fa54b9323b6388fcedb302 100644 (file)
@@ -38,9 +38,8 @@ void move_time_to(int where, cl_t *line, struct tm *ftime);
 #define BEGIN_NEXT_PERIOD 11  /* move_time_to()'s where possible value */
 #define END_OF_INTERVAL 12    /* move_time_to()'s where possible value */
 void run_serial_job(void);
-void run_lavg_job(int i);
+void run_lavg_job(lavg_t *l);
 void run_queue_job(cl_t *line);
-void resize_exe_array(void);
 
 
 #if ! defined(HAVE_SETENV) || ! defined(HAVE_UNSETENV)
@@ -209,21 +208,14 @@ run_normal_job(cl_t *line, int info_fd)
 }
 
 void
-run_lavg_job(int i)
+run_lavg_job(lavg_t *l)
 {
 
-    run_queue_job(lavg_array[i].l_line);
+    run_queue_job(l->l_line);
 
-    if ( is_serial(lavg_array[i].l_line->cl_option) )
+    if ( is_serial(l->l_line->cl_option) )
        lavg_serial_running++;
 
-    if (i < --lavg_num) {
-       lavg_array[i] = lavg_array[lavg_num];
-       lavg_array[lavg_num].l_line = NULL;
-    }
-    else
-       lavg_array[i].l_line = NULL;    
-
 }
 
 
@@ -250,47 +242,24 @@ run_serial_job(void)
 }
                    
 
-void 
-resize_exe_array(void)
-    /* make exe_array bigger */
-{
-    struct exe_t *ptr = NULL;
-    short int old_size = exe_array_size;
-
-    debug("Resizing exe_array");
-    exe_array_size = (exe_array_size + EXE_GROW_SIZE);
-       
-    if ( (ptr = calloc(exe_array_size, sizeof(struct exe_t))) == NULL )
-       die_e("could not calloc exe_array");
-
-    memcpy(ptr, exe_array, (sizeof(struct exe_t) * old_size));
-    free(exe_array);
-    exe_array = ptr;
-}
-
-
 void
 run_queue_job(cl_t *line)
     /* run a job */
 {
 
+    exe_t e = { NULL, 0, 0 };
+
 /*      // */
 /*      debug("run_queue_job"); */
 /*      // */
 
-    /* append job to the list of executed job */
-    if ( exe_num >= exe_array_size )
-       resize_exe_array();
-
-    exe_array[exe_num].e_line = line;
-    exe_num++;
+    e.e_line = line;
 
     /* run the job */
-    if ( run_job(&exe_array[exe_num-1]) != OK ) {
-       /* The job could not be run: remove it from the exe_array */
-       exe_array[exe_num-1].e_line->cl_numexe--;
-       exe_array[exe_num-1].e_line = NULL;
-       exe_num--;
+    if ( run_job(&e) == OK ) {
+       /* append job to the list of executed job */
+       exe_list_add(exe_list, &e);
+       line->cl_file->cf_running += 1;
     }
 
 }
@@ -428,6 +397,7 @@ add_lavg_job(cl_t *line, int info_fd)
     /* WARNING : must be run before a set_next_exe() to get the strict option
      * working correctly */
 {
+    lavg_t *lavg_entry = NULL;
 
     /* check if the line is already in the lavg queue
      * (we consider serial jobs currently running as in the queue) */
@@ -441,32 +411,16 @@ add_lavg_job(cl_t *line, int info_fd)
 /*     // */
        
     /* append job to the list of lavg job */
-    if ( lavg_num >= lavg_array_size ) {
-       if ( lavg_num >= lavg_queue_max ) {
-           error_fd(info_fd, "Could not add job : lavg queue is full (%d jobs)."
-                    " Consider using options lavgonce, until, strict and/or "
-                    "fcron's option -q.", lavg_queue_max, line->cl_shell);
-           if ( is_notice_notrun(line->cl_option) )
-               mail_notrun(line, QUEUE_FULL, NULL);
-           return;
-       }
-       else {
-           struct lavg_t *ptr = NULL;
-           short int old_size = lavg_array_size;
-               
-           debug("Resizing lavg_array");
-           lavg_array_size = (lavg_array_size + LAVG_GROW_SIZE);
-               
-           if ( (ptr = calloc(lavg_array_size, sizeof(lavg_t))) == NULL )
-               die_e("could not calloc lavg_array");
-               
-           memcpy(ptr, lavg_array, (sizeof(lavg_t) * old_size));
-           free(lavg_array);
-           lavg_array = ptr;
-       }
+    lavg_entry = lavg_list_add_line(lavg_list, line);
+    if ( lavg_entry == NULL ) {
+       error_fd(info_fd, "Could not add job : lavg queue is full (%d jobs)."
+                " Consider using options lavgonce, until, strict and/or "
+                "fcron's option -q.", lavg_list->max_entries, line->cl_shell);
+       if ( is_notice_notrun(line->cl_option) )
+           mail_notrun(line, QUEUE_FULL, NULL);
+       return;
     }
 
-    lavg_array[lavg_num].l_line = line;
     line->cl_numexe += 1;
     set_run_if_late(line->cl_option);
     if ( is_strict(line->cl_option) && line->cl_runfreq == 1) {
@@ -498,9 +452,9 @@ add_lavg_job(cl_t *line, int info_fd)
        end_of_cur_int = mktime_no_dst(&ftime) + (line->cl_file->cf_tzdiff * 3600);
 
        if ((line->cl_until > 0) && (line->cl_until + now < end_of_cur_int))
-           lavg_array[lavg_num].l_until = line->cl_until + now;
+           lavg_entry->l_until = line->cl_until + now;
        else {
-           lavg_array[lavg_num].l_until = end_of_cur_int;
+           lavg_entry->l_until = end_of_cur_int;
            clear_run_if_late(line->cl_option);
        }
 
@@ -508,10 +462,9 @@ add_lavg_job(cl_t *line, int info_fd)
            switch_back_timezone(orig_tz_envvar);
     }
     else
-       lavg_array[lavg_num].l_until = 
+       lavg_entry->l_until = 
            (line->cl_until > 0) ? now + line->cl_until : 0;
 
-    lavg_num++;
 }
 
 
@@ -519,10 +472,9 @@ void
 wait_chld(void)
   /* wait_chld() - check for job completion */
 {
-    short int i = 0;
     int pid;
     cl_t *line = NULL;
-
+    exe_t *e = NULL;
 
 /*      // */
 /*      debug("wait_chld"); */
@@ -530,17 +482,16 @@ wait_chld(void)
 
     while ( (pid = wait3(NULL, WNOHANG, NULL)) > 0 ) {
 
-       i = 0;
-       while ( i < exe_num ) {
+       for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) {
 
-           if (pid == exe_array[i].e_ctrl_pid) {
-               if ( exe_array[i].e_line == NULL ) {
+           if (pid == e->e_ctrl_pid) {
+               if ( e->e_line == NULL ) {
                    /* the corresponding file has been removed from memory */
                    debug("job finished: pid %d", pid);
                }
                else {
                    
-                   line = exe_array[i].e_line;
+                   line = e->e_line;
 /*                 debug("job finished: %s", line->cl_shell); */
                    line->cl_numexe -= 1;
                    line->cl_file->cf_running -= 1;
@@ -559,17 +510,10 @@ wait_chld(void)
                              is_serial(line->cl_option) )
                        lavg_serial_running--;
                }
-               if (i < --exe_num) {
-                   exe_array[i] = exe_array[exe_num];
-                   exe_array[exe_num].e_line = NULL;
-               }
-               else
-                   exe_array[i].e_line = NULL;
                
+               exe_list_remove_cur(exe_list);
                break;
            }
-
-           i++;
        }
 
     }
@@ -581,39 +525,32 @@ void
 wait_all(int *counter)
    /* return after all jobs completion. */
 {
-    short int i = 0;
     int pid;
+    exe_t *e = NULL;
     
     debug("Waiting for all jobs");
     
     while ( (*counter > 0) && (pid = wait3(NULL, 0, NULL)) > 0 ) {
-       i = 0;
-       while ( i < exe_num ) {
-           if (pid == exe_array[i].e_ctrl_pid) {
-               if ( exe_array[i].e_line == NULL ) {
+       for ( e = exe_list_first(exe_list) ; e != NULL ; e = exe_list_next(exe_list) ) {
+           if (pid == e->e_ctrl_pid) {
+               if ( e->e_line == NULL ) {
                    /* the corresponding file has been removed from memory */
                    debug("job finished: pid %d", pid);
                }
                else {
                    
-                   debug("job finished: %s", exe_array[i].e_line->cl_shell);
-                   exe_array[i].e_line->cl_numexe -= 1;
-                   exe_array[i].e_line->cl_file->cf_running -= 1;
+                   debug("job finished: %s", e->e_line->cl_shell);
+                   e->e_line->cl_numexe -= 1;
+                   e->e_line->cl_file->cf_running -= 1;
                    
-                   if ( is_serial_once(exe_array[i].e_line->cl_option) )
-                       clear_serial_once(exe_array[i].e_line->cl_option);
+                   if ( is_serial_once(e->e_line->cl_option) )
+                       clear_serial_once(e->e_line->cl_option);
                    
                }
-               if (i < --exe_num) {
-                   exe_array[i] = exe_array[exe_num];
-                   exe_array[exe_num].e_line = NULL;
-               }
-               else
-                   exe_array[i].e_line = NULL;
                
+               exe_list_remove_cur(exe_list);
                break;
            }
-           i++;
        }
     }    
     
@@ -1355,13 +1292,9 @@ mail_notrun(cl_t *line, char context, struct tm *since)
              line->cl_shell, pid);
 /*  // */
 
-       /* create an entry in exe_array */
-       if ( exe_num >= exe_array_size )
-           resize_exe_array();
+       /* create an entry in exe_list */
        /* set line to NULL as this is not a line ... */
-       exe_array[exe_num].e_line = NULL;
-       exe_array[exe_num].e_ctrl_pid = pid;
-       exe_num++;
+       exe_list_add_line(exe_list, NULL);
        return;
     }
 
@@ -1437,10 +1370,14 @@ check_lavg(time_t lim)
      * and return the time to sleep */
 {
     time_t tts = 0;
+    lavg_t *l = NULL;
 
 #ifdef NOLOADAVG
-    while ( lavg_num > 0 )
-       run_lavg_job(0);
+    for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) {
+       run_lavg_job(l);
+       lavg_list_remove_cur(lavg_list);
+    }
+
 
     tts = time_to_sleep(lim);
     return tts;
@@ -1450,44 +1387,37 @@ check_lavg(time_t lim)
     double l_avg[3]= {0, 0, 0};
 
     /* first, check if some lines must be executed because of until */
-    while ( i < lavg_num )
-       if ( (lavg_array[i].l_line->cl_until > 0 
-             || lavg_array[i].l_line->cl_runfreq == 1)
-            && lavg_array[i].l_until < now){
-           if ( ! is_run_if_late(lavg_array[i].l_line->cl_option) ) {
-               if ( ! is_nolog(lavg_array[i].l_line->cl_option) )
+    for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) )
+       if ( (l->l_line->cl_until > 0 || l->l_line->cl_runfreq == 1)
+            && l->l_until < now) {
+           if ( ! is_run_if_late(l->l_line->cl_option) ) {
+               if ( ! is_nolog(l->l_line->cl_option) )
                    explain("Interval of execution exceeded : %s (not run)",
-                           lavg_array[i].l_line->cl_shell);
+                           l->l_line->cl_shell);
 
                /* set time of the next execution and send a mail if needed */
-               if ( is_td(lavg_array[i].l_line->cl_option) &&
-                    is_notice_notrun(lavg_array[i].l_line->cl_option) )
-                   set_next_exe_notrun(lavg_array[i].l_line, LAVG);
+               if ( is_td(l->l_line->cl_option) &&
+                    is_notice_notrun(l->l_line->cl_option) )
+                   set_next_exe_notrun(l->l_line, LAVG);
                else
-                   set_next_exe(lavg_array[i].l_line, NO_GOTO_LOG, -1);
+                   set_next_exe(l->l_line, NO_GOTO_LOG, -1);
 
                /* remove this job from the lavg queue */
-               lavg_array[i].l_line->cl_numexe -= 1;
-               if (i < --lavg_num) {
-                   lavg_array[i] = lavg_array[lavg_num];
-                   lavg_array[lavg_num].l_line = NULL;
-               }
-               else
-                   lavg_array[i].l_line = NULL;
-
+               l->l_line->cl_numexe -= 1;
+               lavg_list_remove_cur(lavg_list);
            }
            else {
-               debug("until %s %d", lavg_array[i].l_line->cl_shell,
-                     lavg_array[i].l_until);
-               run_lavg_job(i);
+               debug("until %s %d", l->l_line->cl_shell,
+                     l->l_until);
+               run_lavg_job(l);
+               lavg_list_remove_cur(lavg_list);
            }
-       } else
-           i++;
+       }
 
     /* we do this set here as the nextexe of lavg line may change before */
     tts = time_to_sleep(lim);
 
-    if ( lavg_num == 0 )
+    if ( lavg_list->num_entries == 0 )
        return tts;
        
     if ( (i = getloadavg(l_avg, 3)) != 3 )
@@ -1497,43 +1427,38 @@ check_lavg(time_t lim)
     l_avg[0] *= 10;
     l_avg[1] *= 10;
     l_avg[2] *= 10;
-    i = 0;
-    while ( i < lavg_num ) {
+    for ( l = lavg_list_first(lavg_list) ; l != NULL ; l = lavg_list_next(lavg_list) ) {
        /* check if the line should be executed */
        if ( lavg_serial_running >= serial_max_running && 
-            is_serial(lavg_array[i].l_line->cl_option) ) {
-           i++;
+            is_serial(l->l_line->cl_option) ) {
            continue;
        }
-       if ( ( is_land(lavg_array[i].l_line->cl_option)
-              && ( l_avg[0] < lavg_array[i].l_line->cl_lavg[0]
-                   || lavg_array[i].l_line->cl_lavg[0] == 0 )
-              && ( l_avg[1] < lavg_array[i].l_line->cl_lavg[1]
-                   || lavg_array[i].l_line->cl_lavg[1] == 0 )
-              && ( l_avg[2] < lavg_array[i].l_line->cl_lavg[2]
-                   || lavg_array[i].l_line->cl_lavg[2] == 0 ) 
+       if ( ( is_land(l->l_line->cl_option)
+              && ( l_avg[0] < l->l_line->cl_lavg[0] || l->l_line->cl_lavg[0] == 0 )
+              && ( l_avg[1] < l->l_line->cl_lavg[1] || l->l_line->cl_lavg[1] == 0 )
+              && ( l_avg[2] < l->l_line->cl_lavg[2] || l->l_line->cl_lavg[2] == 0 ) 
            )
             || 
-            ( is_lor(lavg_array[i].l_line->cl_option) 
-              &&  ( l_avg[0] < lavg_array[i].l_line->cl_lavg[0]
-                    || l_avg[1] < lavg_array[i].l_line->cl_lavg[1]
-                    || l_avg[2] < lavg_array[i].l_line->cl_lavg[2] )
+            ( is_lor(l->l_line->cl_option) 
+              &&  ( l_avg[0] < l->l_line->cl_lavg[0]
+                    || l_avg[1] < l->l_line->cl_lavg[1]
+                    || l_avg[2] < l->l_line->cl_lavg[2] )
                 )
            ) {
            debug("lavg %s %s %.0f:%d %.0f:%d %.0f:%d",
-                 lavg_array[i].l_line->cl_shell,
-                 (is_lor(lavg_array[i].l_line->cl_option)) ? "or" : "and",
-                 l_avg[0], lavg_array[i].l_line->cl_lavg[0],
-                 l_avg[1], lavg_array[i].l_line->cl_lavg[1],
-                 l_avg[2], lavg_array[i].l_line->cl_lavg[2]);
-           run_lavg_job(i);
-
-       } else
-           i++;
+                 l->l_line->cl_shell,
+                 (is_lor(l->l_line->cl_option)) ? "or" : "and",
+                 l_avg[0], l->l_line->cl_lavg[0],
+                 l_avg[1], l->l_line->cl_lavg[1],
+                 l_avg[2], l->l_line->cl_lavg[2]);
+           run_lavg_job(l);
+           lavg_list_remove_cur(lavg_list);
+
+       }
     }
 
     
-    if ( lavg_num == 0 )
+    if ( lavg_list->num_entries == 0 )
        return tts;
     else
        return (LAVG_SLEEP < tts) ? LAVG_SLEEP : tts;
index dc24d7cc9578c68d8cafe3c7602b94ea8bd00287..09aab90260138c865a935cf7131f4071875db5a7 100644 (file)
@@ -50,7 +50,27 @@ doc:
 # Build all the HTML, text and manual pages in all the languages
        @(for i in $(LANGUAGES); \
        do \
-               make $$i/HTML/index.html $$i/txt/readme.txt $$i/man/fcron.8 ; \
+               test -d $(SRCDIR)/$$i/HTML || mkdir $(SRCDIR)/$$i/HTML ; \
+               test -d $(SRCDIR)/$$i/txt || mkdir $(SRCDIR)/$$i/txt ; \
+               test -d $(SRCDIR)/$$i/man || mkdir $(SRCDIR)/$$i/man ; \
+               make $(SRCDIR)/$$i/HTML/index.html $(SRCDIR)/$$i/txt/readme.txt \
+                       $(SRCDIR)/$$i/man/fcron.8 ; \
+       done)
+
+doc-if-none:
+# Only generate the doc if there is none (e.g. if the sources came from git
+# and not a tarball)
+# The reason we don't try to generate the doc everytime is that we want the user
+# to be able to compile and install fcron without needing all the tools required
+# to generate the documentations.
+#
+# "make doc" will be called once at max, as all the tests will 
+# succeed after the first time "make doc" is called
+       @(for i in $(LANGUAGES); \
+       do \
+               test -f $(SRCDIR)/$$i/HTML/index.html || make doc ; \
+               test -f $(SRCDIR)/$$i/txt/readme.txt || make doc ; \
+               test -f $(SRCDIR)/$$i/man/fcron.8 || make doc ; \
        done)
 
 # man/fcron.8 means in fact "build *all* the man pages"
@@ -97,7 +117,7 @@ fcron-doc.mod: fcron-doc.mod.in ../configure.in
 
 install: install-staged perms
 
-install-staged: clean
+install-staged: doc-if-none clean
        @(echo "Installing man pages in $(DESTDIR)$(DESTMAN)...")
        @(for l in $(LANGUAGES); do \
                if test "x$$l" = "xen"; then \
index f1427c47f246e760e7e43d906bf3c584773eeb99..6040cd09fc12e16070adbdcfd5b8fe6095cdb589 100644 (file)
@@ -38,7 +38,7 @@ exe_list_t *exe_list_init(void)
 }
 
 exe_t *
-exe_list_add(exe_list_t *list, struct cl_t *line)
+exe_list_add_line(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*/
@@ -46,6 +46,12 @@ exe_list_add(exe_list_t *list, struct cl_t *line)
     return (exe_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e);
 }
 
+exe_t *
+exe_list_add(exe_list_t *list, exe_t *e)
+{
+    return (exe_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) e);
+}
+
 exe_t *
 exe_list_first(exe_list_t *list)
 {
@@ -53,15 +59,21 @@ exe_list_first(exe_list_t *list)
 }
 
 exe_t *
-exe_list_next(exe_list_t *list, exe_t *cur_entry)
+exe_list_next(exe_list_t *list)
+{
+    return (exe_t *) u_list_next((u_list_t *) list);
+}
+
+void
+exe_list_end_iteration(exe_list_t *list)
 {
-    return (exe_t *) u_list_next((u_list_t *) list, (u_list_entry_t *) cur_entry);
+    u_list_end_iteration((u_list_t *) list);
 }
 
 void
-exe_list_remove(exe_list_t *list, exe_t *entry)
+exe_list_remove_cur(exe_list_t *list)
 {
-    u_list_remove((u_list_t *) list, (u_list_entry_t *) entry);
+    u_list_remove_cur((u_list_t *) list);
 }
 
 exe_list_t *
index 50c0483a88273900e700c114432e31872037667d..d80857d4c4bf98762eed4cd253d78f705009140b 100644 (file)
@@ -44,12 +44,14 @@ 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_add_line(exe_list_t *list, struct cl_t *line);
+extern exe_t *exe_list_add(exe_list_t *list, exe_t *e);
+/* WARNING: there should always be a unique iteration loop based on
+ *          u_list_first()/u_list_next() running at any one time in the code */
 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_t *exe_list_next(exe_list_t *list);
+extern void exe_list_end_iteration(exe_list_t *list);
+extern void exe_list_remove_cur(exe_list_t *list);
 extern exe_list_t *exe_list_destroy(exe_list_t *list);
 
 
diff --git a/fcron.c b/fcron.c
index e77b56f5023a23af3eb7842359f6d3ed91222e7b..be63f5b29eec78880325a04775aa8760cf97a8f8 100644 (file)
--- a/fcron.c
+++ b/fcron.c
@@ -104,16 +104,12 @@ short int serial_running;     /* number of running serial jobs */
 /* do not run more than this number of serial job simultaneously */
 short int serial_max_running = SERIAL_MAX_RUNNING; 
 short int serial_queue_max   = SERIAL_QUEUE_MAX;
-short int lavg_queue_max     = LAVG_QUEUE_MAX;
 
-struct lavg_t *lavg_array;      /* jobs waiting for a given system load value */
-short int lavg_array_size;    /* size of lavg_array */
-short int lavg_num;           /* number of job being queued */
+lavg_list_t *lavg_list;      /* jobs waiting for a given system load value */
+short int lavg_queue_max = LAVG_QUEUE_MAX;
 short int lavg_serial_running;/* number of serialized lavg job being running */
 
-struct exe_t *exe_array;        /* jobs which are executed */
-short int exe_array_size;     /* size of exe_array */
-short int exe_num;            /* number of job being executed */
+exe_list_t *exe_list;        /* jobs which are executed */
 
 time_t begin_sleep;           /* the time at which sleep began */
 time_t now;                   /* the current time */
@@ -610,10 +606,7 @@ main(int argc, char **argv)
     next_id = 0;
 
     /* initialize exe_array */
-    exe_num = 0;
-    exe_array_size = EXE_INITIAL_SIZE;
-    if ( (exe_array = calloc(exe_array_size, sizeof(struct exe_t))) == NULL )
-       die_e("could not calloc exe_array");
+    exe_list = exe_list_init();
 
     /* initialize serial_array */
     serial_running = 0;
@@ -624,11 +617,9 @@ main(int argc, char **argv)
        die_e("could not calloc serial_array");
 
     /* initialize lavg_array */
-    lavg_num = 0;
+    lavg_list = lavg_list_init();
+    lavg_list->max_entries = lavg_queue_max;
     lavg_serial_running = 0;
-    lavg_array_size = LAVG_INITIAL_SIZE;
-    if ( (lavg_array = calloc(lavg_array_size, sizeof(lavg_t))) == NULL )
-       die_e("could not calloc lavg_array");
 
 #ifdef FCRONDYN
     /* initialize socket */
diff --git a/fcron.h b/fcron.h
index f21b0df0b388591469a6658dc226e5c330f059bf..e26d5a8218713e74d8309239555e25cc8a73cddf 100644 (file)
--- a/fcron.h
+++ b/fcron.h
@@ -27,6 +27,8 @@
 #define __FCRON_H__
 
 #include "global.h"
+#include "exe_list.h"
+#include "lavg_list.h"
 
 #ifdef HAVE_CRYPT_H
 #include <crypt.h>
@@ -83,12 +85,8 @@ extern short int serial_running;
 extern short int serial_max_running; 
 extern short int serial_queue_max;
 extern short int lavg_queue_max;
-extern struct exe_t *exe_array;
-extern short int exe_array_size;
-extern short int exe_num;
-extern struct lavg_t *lavg_array;
-extern short int lavg_array_size;
-extern short int lavg_num;
+extern exe_list_t *exe_list;
+extern lavg_list_t *lavg_list;
 extern short int lavg_serial_running;
 /* end of global variables */
 
index 6f746cec2978cee6e589b6556054217db1abccd7..14fcdfd4d6004b25e5e284fde2e344c88e5f75f1 100644 (file)
--- a/global.h
+++ b/global.h
@@ -221,17 +221,6 @@ typedef struct job_t {
     struct job_t   *j_next;
 } job_t;
 
-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 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;
-
 
 #if SIZEOF_TIME_T == SIZEOF_SHORT_INT
 #define ATTR_SIZE_TIMET "h"
diff --git a/job.c b/job.c
index 1610e5d9d3e3fef0a8f19c9f1127e3a949a6890d..f4c7b543de49fdd5908cc3f81fd5b886e9be48ce 100644 (file)
--- a/job.c
+++ b/job.c
@@ -661,7 +661,6 @@ run_job(struct exe_t *exeent)
            error_e("parent: could not close(pipe_pid_fd[1])");
 
        exeent->e_ctrl_pid = pid;
-       line->cl_file->cf_running += 1;
 
 #ifdef CHECKRUNJOB
        debug("run_job(): about to read grand-child pid...");
index 8392dd44880381f91434992a9391f8025ea0e4b1..416ebcae9609ed54532ca46deeb990a5d4e72b77 100644 (file)
@@ -40,7 +40,7 @@ lavg_list_t *lavg_list_init(void)
 }
 
 lavg_t *
-lavg_list_add(lavg_list_t *list, struct cl_t *line)
+lavg_list_add_line(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*/
@@ -48,6 +48,12 @@ lavg_list_add(lavg_list_t *list, struct cl_t *line)
     return (lavg_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) &e);
 }
 
+lavg_t *
+lavg_list_add(lavg_list_t *list, lavg_t *entry)
+{
+    return (lavg_t *) u_list_add( (u_list_t *) list, (u_list_entry_t *) entry);
+}
+
 lavg_t *
 lavg_list_first(lavg_list_t *list)
 {
@@ -55,15 +61,21 @@ lavg_list_first(lavg_list_t *list)
 }
 
 lavg_t *
-lavg_list_next(lavg_list_t *list, lavg_t *cur_entry)
+lavg_list_next(lavg_list_t *list)
+{
+    return (lavg_t *) u_list_next((u_list_t *) list);
+}
+
+void
+lavg_list_end_iteration(lavg_list_t *list)
 {
-    return (lavg_t *) u_list_next((u_list_t *) list, (u_list_entry_t *) cur_entry);
+    u_list_end_iteration((u_list_t *) list);
 }
 
 void
-lavg_list_remove(lavg_list_t *list, lavg_t *entry)
+lavg_list_remove_cur(lavg_list_t *list)
 {
-    u_list_remove((u_list_t *) list, (u_list_entry_t *) entry);
+    u_list_remove_cur((u_list_t *) list);
 }
 
 lavg_list_t *
index 3c2af2e476e3ac51ac4edf7ec3636bbde43a4063..0b7c0d74f83a45243cdcb494248445803e587f24 100644 (file)
@@ -43,12 +43,14 @@ 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_add_line(lavg_list_t *list, struct cl_t *line);
+extern lavg_t *lavg_list_add(lavg_list_t *list, lavg_t *entry);
+/* WARNING: there should always be a unique iteration loop based on
+ *          u_list_first()/u_list_next() running at any one time in the code */
 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_t *lavg_list_next(lavg_list_t *list);
+extern void lavg_list_end_iteration(lavg_list_t *list);
+extern void lavg_list_remove_cur(lavg_list_t *list);
 extern lavg_list_t *lavg_list_destroy(lavg_list_t *list);
 
 
index 65adeb5414b120a2d998493056b6724e98d73e2f..2248e7334f7e3bf513faa131bd23ec62f5c33512 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -40,9 +40,9 @@ void print_fields(int fd, unsigned char *details);
 void print_line(int fd, struct cl_t *line,  unsigned char *details, pid_t pid, int index,
                time_t until);
 void cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root);
-void cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index,
+void cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e,
                int is_root);
-void cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index);
+void cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e);
 void cmd_run(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root);
 void add_to_select_set(int fd, fd_set *set, int *max_fd);
 void remove_from_select_set(int fd, fd_set *set, int *max_fd);
@@ -393,6 +393,8 @@ cmd_ls(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root)
     struct job_t *j;
     int i;
     unsigned char fields[FIELD_NUM_SIZE];
+    exe_t *e = NULL;
+    lavg_t *l = NULL;
 
     for (i = 0; i < FIELD_NUM_SIZE; i++)
        fields[i] = 0;
@@ -482,23 +484,22 @@ cmd_ls(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root)
            break;
 
        case CMD_LIST_EXEQ:
-           for ( i = 0; i < exe_num; i++) {
-               if ( exe_array[i].e_line == NULL ) {
+           for (e = exe_list_first(exe_list); e != NULL; e = exe_list_next(exe_list)) {
+               if ( e->e_line == NULL ) {
                    if ( is_root ) {
                        send_msg_fd(fd, "job no more in an fcrontab: pid %d", 
-                                   exe_array[i].e_job_pid);
+                                   e->e_job_pid);
                        found = 1;
                    }
                }
                else
-                   Test_line(exe_array[i].e_line, exe_array[i].e_job_pid,
-                             0, 0)
+                   Test_line(e->e_line, e->e_job_pid, 0, 0)
            }
            break;
 
        case CMD_LIST_LAVGQ:
-           for ( i = 0; i < lavg_num; i++)
-               Test_line(lavg_array[i].l_line, 0, 0, lavg_array[i].l_until);
+           for (l=lavg_list_first(lavg_list); l!=NULL; l=lavg_list_next(lavg_list))
+               Test_line(l->l_line, 0, 0, l->l_until);
            break;
 
        case CMD_LIST_SERIALQ:
@@ -530,21 +531,20 @@ void
 cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root)
 /* common code to all cmds working on jobs in the exeq */
 {
-    int exe_index;
     int found = 0;
     char *err_str = NULL;
+    exe_t *e = NULL;
 
     /* find the corresponding job */
-    for ( exe_index = 0 ; exe_index < exe_num; exe_index++ ) {
-       if ( exe_array[exe_index].e_line != NULL 
-            && cmd[2] == exe_array[exe_index].e_line->cl_id ) {
+    for (e = exe_list_first(exe_list); e != NULL; e = exe_list_next(exe_list)) {
+       if ( e->e_line != NULL 
+            && cmd[2] == e->e_line->cl_id ) {
 
            found = 1;
 
            /* check if the request is valid */
            if ( ! is_root &&
-                strcmp(client->fcl_user,
-                       exe_array[exe_index].e_line->cl_file->cf_user) != 0 ) {
+                strcmp(client->fcl_user, e->e_line->cl_file->cf_user) != 0 ) {
 
                if ( cmd[0] == CMD_RENICE )
                    err_str = "%s tried to renice to %ld job id %ld for %s : "
@@ -564,9 +564,9 @@ cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root)
                /* request is valid : do it */
 
                if ( cmd[0] == CMD_SEND_SIGNAL )
-                   cmd_send_signal(client, cmd, fd, exe_index);
+                   cmd_send_signal(client, cmd, fd, e);
                else if ( cmd[0] == CMD_RENICE )
-                   cmd_renice(client, cmd, fd, exe_index, is_root);
+                   cmd_renice(client, cmd, fd, e, is_root);
                else {
                    Send_err_msg_end(fd, err_cmd_unknown_str);
                    return;
@@ -598,36 +598,36 @@ cmd_on_exeq(struct fcrondyn_cl *client, long int *cmd, int fd, int is_root)
 
 
 void 
-cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index, int is_root)
+cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e, int is_root)
 /* change nice value of a running job */
 {
 
 #ifdef HAVE_SETPRIORITY
     /* check if arguments are valid */
-    if ( exe_array[exe_index].e_job_pid <= 0 || ((int)cmd[1] < 0 && ! is_root)
+    if ( e->e_job_pid <= 0 || ((int)cmd[1] < 0 && ! is_root)
        || (int)cmd[1] > 20 || (int)cmd[1] < -20 ) {
        warn("renice: invalid args : pid: %d nice_value: %d user: %s.",
-            exe_array[exe_index].e_job_pid, (int)cmd[1], client->fcl_user);    
+            e->e_job_pid, (int)cmd[1], client->fcl_user);      
        Send_err_msg_end(fd, err_invalid_args_str);
        return;
     }
 
     /* ok, now setpriority() the job */
-    if ( setpriority(PRIO_PROCESS, exe_array[exe_index].e_job_pid, (int)cmd[1]) != 0) {
+    if ( setpriority(PRIO_PROCESS, e->e_job_pid, (int)cmd[1]) != 0) {
        error_e("could not setpriority(PRIO_PROCESS, %d, %d)",
-               exe_array[exe_index].e_job_pid, (int)cmd[1]);
+               e->e_job_pid, (int)cmd[1]);
        Send_err_msg_end(fd, err_unknown_str);
        return;
     }
     else {
        send_msg_fd(fd, "Command successfully completed on process %d.",
-                   exe_array[exe_index].e_job_pid);
+                   e->e_job_pid);
        return;
     }
 
 #else /* HAVE_SETPRIORITY */
     warn("System has no setpriority() : cannot renice. pid: %d nice_value: %d user: %s.",
-        exe_array[exe_index].e_job_pid, (int)cmd[1], client->fcl_user);        
+        e->e_job_pid, (int)cmd[1], client->fcl_user);  
     Send_err_msg_end(fd, err_cmd_unknown_str);    
 
 #endif /* HAVE_SETPRIORITY */
@@ -635,25 +635,25 @@ cmd_renice(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index, int
 
 
 void
-cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, int exe_index)
+cmd_send_signal(struct fcrondyn_cl *client, long int *cmd, int fd, exe_t *e)
 /* send a signal to a running job */
 {
-    if ( exe_array[exe_index].e_job_pid <= 0 || (int)cmd[1] <= 0 ) {
+    if ( e->e_job_pid <= 0 || (int)cmd[1] <= 0 ) {
        warn("send_signal: invalid args : pid: %d signal: %d user: %s",
-            exe_array[exe_index].e_job_pid, (int)cmd[1], client->fcl_user);    
+            e->e_job_pid, (int)cmd[1], client->fcl_user);      
        Send_err_msg_end(fd, err_invalid_args_str);
        return;
     }
 
     /* ok, now kill() the job */
-    if ( kill(exe_array[exe_index].e_job_pid, (int)cmd[1]) != 0) {
-       error_e("could not kill(%d, %d)", exe_array[exe_index].e_job_pid, (int)cmd[1]);
+    if ( kill(e->e_job_pid, (int)cmd[1]) != 0) {
+       error_e("could not kill(%d, %d)", e->e_job_pid, (int)cmd[1]);
        Send_err_msg_end(fd, err_unknown_str);
        return;
     }
     else {
        send_msg_fd(fd, "Command successfully completed on process %d.",
-                   exe_array[exe_index].e_job_pid);
+                   e->e_job_pid);
        return;
     }
 }
diff --git a/subs.c b/subs.c
index f49c1c5dbae3074eb04f6eb431a3ad245cff84f7..cef1116d212ccd367f73a138674fec886a302118 100644 (file)
--- a/subs.c
+++ b/subs.c
@@ -123,6 +123,13 @@ strdup2(const char *str)
     return(ptr);
 }
 
+void
+free_safe(void *ptr)
+    /* free() p and set it to NULL to prevent errors if it is free()ed again */
+{
+    free(ptr);
+    ptr = NULL;
+}
 
 int
 get_word(char **str)
@@ -166,15 +173,15 @@ void
 free_conf(void)
 /* free() the memory allocated in init_conf() */
 {
-    free(fcronconf);
-    free(fcrontabs);
-    free(pidfile);
-    free(fifofile);
-    free(fcronallow);
-    free(fcrondeny);
-    free(shell);
-    free(sendmail);
-    free(editor);
+    free_safe(fcronconf);
+    free_safe(fcrontabs);
+    free_safe(pidfile);
+    free_safe(fifofile);
+    free_safe(fcronallow);
+    free_safe(fcrondeny);
+    free_safe(shell);
+    free_safe(sendmail);
+    free_safe(editor);
 }
 
 
diff --git a/subs.h b/subs.h
index ab4a1096dfd5c1beda9648778655f552c148acce..c04d6225e98bddd150c2abb772090b9dcd6bdd06 100644 (file)
--- a/subs.h
+++ b/subs.h
@@ -46,6 +46,7 @@ extern uid_t get_user_uid_safe(char *username);
 extern gid_t get_group_gid_safe(char *groupname);
 extern int remove_blanks(char *str);
 extern char *strdup2(const char *);
+extern void free_safe(void *ptr);
 extern int get_word(char **str);
 extern int temp_file(char **name);
 extern void read_conf(void);
index 2d3f40a0fbb3faeba648053b2010b5af120b9b7e..25e6ed27431eb810a864399241592c7e0938962a 100644 (file)
--- a/u_list.c
+++ b/u_list.c
@@ -60,6 +60,8 @@ u_list_init(size_t entry_size, int init_size, int grow_size)
     l->array_size = init_size;
     l->entry_size = entry_size;
     l->grow_size = grow_size;
+    l->cur_entry = NULL;
+    l->cur_removed = 0;
     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"
@@ -74,6 +76,7 @@ u_list_resize_array(u_list_t *l)
  * Returns OK on success, ERR if the array is already at maximum size */
 {
     u_list_entry_t *e = NULL;
+    int offset = 0;
     int old_size = l->array_size;
 
     /* sanity check */
@@ -85,6 +88,11 @@ u_list_resize_array(u_list_t *l)
        return ERR;
     }
 
+    if ( l->cur_entry != NULL )
+       /* Compute cur_entry's offset so as we can set cur_entry to the right place
+        * after we have allocated a new chunk of memory for the entries_array */
+       offset = (char *) l->cur_entry - (char *) l->entries_array;
+
     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;
@@ -99,6 +107,9 @@ u_list_resize_array(u_list_t *l)
     free_safe(l->entries_array);
     l->entries_array = e;    
 
+    if ( l->cur_entry != NULL )
+       l->cur_entry = (u_list_entry_t *) ( (char *) l->entries_array + offset );
+
     return OK;
 }
 
@@ -145,54 +156,80 @@ u_list_first(u_list_t *l)
     /* sanity check */
     if ( l == NULL )
        die("Invalid argument for u_list_first(): list=%d", l);
+    if ( l->cur_entry != NULL )
+       die("u_list_first() called but there is already an iteration");
 
-    return (l->num_entries > 0) ? l->entries_array : NULL;
+    if (l->num_entries > 0) {
+       l->cur_entry = l->entries_array;
+    }
+    
+    return l->cur_entry;
 }
 
 u_list_entry_t * 
-u_list_next(u_list_t *l, u_list_entry_t *e)
+u_list_next(u_list_t *l)
 /* Return the entry after e */
 {
+    /* // WHAT IF I CALL _ADD() (+RESIZE?) OR _REMOVE() BETWEEN TWO _NEXT CALLS? */
+
     /* 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;
+    if ( l == NULL )
+       die("Invalid arguments for u_list_next(): list=%d", l);
+    if ( l->cur_entry == NULL )
+       die("u_list_next() called outside an iteration: l->cur_entry=%d", l->cur_entry);
+
+    if ( l->cur_removed > 0 ) {
+       l->cur_removed = 0;
+       /* the current entry has just been removed and replaced by another one:
+        * we can return the same pointer again. 
+        * However if the removed entry was the last one then we reached the end
+        * of the list */
+        if ( l->cur_entry > u_list_last(l) )
+            l->cur_entry = NULL;
+    }
+    else {
+       /* cur_entry *not* removed (standard behavior) */
+
+       if ( l->cur_entry < u_list_last(l) )
+           l->cur_entry = (u_list_entry_t *) ( (char *) l->cur_entry + l->entry_size);
+       else
+           /* reached the end of the list */
+           l->cur_entry = NULL;
+    }
+
+    return l->cur_entry;
 }
 
 void
-u_list_remove(u_list_t *l, u_list_entry_t *e)
+u_list_end_iteration(u_list_t *list)
+    /* Stop an iteration before _next() reached the end of the list by itself */
 {
+    list->cur_entry = NULL;
+    list->cur_removed = 0;
+}
+
+
+void
+u_list_remove_cur(u_list_t *l)
+{
+    /* // MANAGE L->NEXT_ENTRY (+ SPECIAL CASE FIRST/LAST ENTRY) */
     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);
+    if ( l == NULL )
+       die("Invalid arguments for u_list_remove(): list=%d", l);
+    if ( l->cur_entry == NULL )
+       die("u_list_remove_cur() called outside of an iteration");
 
     last = u_list_last(l);
-    if ( e < last ) {
+    if ( l->cur_entry < last ) {
        /* Override e with the last entry */
-       memcpy(e, last, l->entry_size);
+       memcpy(l->cur_entry, last, l->entry_size);
     }
     /* erase the last entry and update the number of entries */
     memset(last, 0, l->entry_size);
     l->num_entries--;
-    
+    l->cur_removed = 1;
 
 }
 
index 2152a3db6ef6c3dfd453a1d7e9da5a6678ebcc35..c6a2038a0f99bfeb2c2a8fde14bd9bbd03c5447d 100644 (file)
--- a/u_list.h
+++ b/u_list.h
@@ -45,17 +45,24 @@ typedef struct u_list_t {
     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 *cur_entry;     /* Current entry in iteration
+                                   * (null if not in iteration, i.e. X_first() has
+                                   * not been called or we reached the list end */
+    char           cur_removed;    /* >0 if cur_entry has just been removed */
     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);
+/* WARNING: - there should always be a unique iteration loop based on
+ *            u_list_first()/u_list_next() running at any one time in the code
+ *          - the u_list_entry_t* returned by _first() and _next() should not 
+ *            be used anymore after a _add() or a _remove_cur() */
 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_entry_t *u_list_next(u_list_t *list);
+extern void u_list_end_iteration(u_list_t *list);
+extern void u_list_remove_cur(u_list_t *list);
 extern u_list_t *u_list_destroy(u_list_t *list);