"Fossies" - the Fresh Open Source Software Archive

Member "anacron-2.5.3/readtab.c" (9 Dec 2007, 7467 Bytes) of package /linux/misc/old/anacron.2.5.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "readtab.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2     Anacron - run commands periodically
    3     Copyright (C) 1998  Itai Tzur <itzur@actcom.co.il>
    4     Copyright (C) 1999  Sean 'Shaleh' Perry <shaleh@debian.org>
    5  
    6     This program is free software; you can redistribute it and/or modify
    7     it under the terms of the GNU General Public License as published by
    8     the Free Software Foundation; either version 2 of the License, or
    9     (at your option) any later version.
   10  
   11     This program is distributed in the hope that it will be useful,
   12     but WITHOUT ANY WARRANTY; without even the implied warranty of
   13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14     GNU General Public License for more details.
   15  
   16     You should have received a copy of the GNU General Public License
   17     along with this program; if not, write to the Free Software
   18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   19  
   20     The GNU General Public License can also be found in the file
   21     `COPYING' that comes with the Anacron source distribution.
   22 */
   23 
   24 
   25 /*  /etc/anacrontab parsing, and job sorting
   26  */
   27 
   28 #include <string.h>
   29 #include <errno.h>
   30 #include <stdio.h>
   31 #include <stdlib.h>
   32 #include <obstack.h>
   33 #include <limits.h>
   34 #include <fnmatch.h>
   35 #include <unistd.h>
   36 #include <signal.h>
   37 #include "global.h"
   38 #include "matchrx.h"
   39 
   40 static struct obstack input_o;   /* holds input line */
   41 static struct obstack tab_o;    /* holds processed data read from anacrontab */
   42 static FILE *tab;
   43 job_rec **job_array;
   44 int njobs;                       /* number of jobs to run */
   45 static int jobs_read;            /* number of jobs read */
   46 static int line_num;             /* current line in anacrontab */
   47 static job_rec *last_job_rec;    /* last job stored in memory, at the moment */
   48 static env_rec *last_env_rec;    /* last environment assignment stored */
   49 
   50 /* some definitions for the obstack macros */
   51 #define obstack_chunk_alloc xmalloc
   52 #define obstack_chunk_free free
   53 
   54 static void *
   55 xmalloc (size_t size)
   56 /* Just like standard malloc(), only never returns NULL. */
   57 {
   58     void * ptr;
   59 
   60     ptr = malloc(size);
   61     if (ptr == NULL)
   62     die("Memory exhausted");
   63     return ptr;
   64 }
   65 
   66 static int
   67 conv2int(const char *s)
   68 /* Return the int or -1 on over/under-flow
   69  */
   70 {
   71     long l;
   72 
   73     errno = 0;
   74     l = strtol(s, NULL, 10);
   75     /* we use negative as error, so I am really returning unsigned int */
   76     if (errno == ERANGE || l < 0 || l > INT_MAX) return - 1;
   77     return l;
   78 }
   79 
   80 static char *
   81 read_tab_line ()
   82 /* Read one line and return a pointer to it.
   83 Return NULL if no more lines.
   84  */
   85 {
   86     int c;
   87 
   88     if (feof(tab)) return NULL;
   89     while ((c = getc(tab)) != EOF && c != '\n')
   90     obstack_1grow(&input_o, c);
   91     if (ferror(tab)) die_e("Error reading %s", anacrontab);
   92     obstack_1grow(&input_o, '\0');
   93     return obstack_finish(&input_o);
   94 }
   95 
   96 static int
   97 job_arg_num(const char *ident)
   98 /* Return the command-line-argument number refering to this job-identifier.
   99  * If it isn't specified, return -1.
  100  */
  101 {
  102     int i, r;
  103 
  104     for (i = 0; i < nargs; i++)
  105     {
  106     r = fnmatch(args[i], ident, 0);
  107     if (r == 0) return i;
  108     if (r != FNM_NOMATCH) die("fnmatch() error");
  109     }
  110     return - 1;
  111 }
  112 
  113 static void
  114 register_env(const char *env_var, const char *value)
  115 /* Store the environment assignment "env_var"="value" */
  116 {
  117     env_rec *er;
  118     int var_len, val_len;
  119 
  120     var_len = strlen(env_var);
  121     val_len = strlen(value);
  122     er = obstack_alloc(&tab_o, sizeof(env_rec));
  123     er->assign = obstack_alloc(&tab_o, var_len + 1 + val_len + 1);
  124     strcpy(er->assign, env_var);
  125     er->assign[var_len] = '=';
  126     strcpy(er->assign + var_len + 1, value);
  127     er->assign[var_len + 1 + val_len] = 0;
  128     if (last_env_rec != NULL) last_env_rec->next = er;
  129     else first_env_rec = er;
  130     last_env_rec = er;
  131     Debug(("on line %d: %s", line_num, er->assign));
  132 }
  133 
  134 static void
  135 register_job(const char *periods, const char *delays,
  136          const char *ident, char *command)
  137 /* Store a job definition */
  138 {
  139     int period, delay;
  140     job_rec *jr;
  141     int ident_len, command_len;
  142 
  143     ident_len = strlen(ident);
  144     command_len = strlen(command);
  145     jobs_read++;
  146     period = conv2int(periods);
  147     delay = conv2int(delays);
  148     if (period < 0 || delay < 0)
  149     {
  150     complain("%s: number out of range on line %d, skipping",
  151          anacrontab, line_num);
  152     return;
  153     }
  154     jr = obstack_alloc(&tab_o, sizeof(job_rec));
  155     jr->period = period;
  156     jr->delay = delay;
  157     jr->tab_line = line_num;
  158     jr->ident = obstack_alloc(&tab_o, ident_len + 1);
  159     strcpy(jr->ident, ident);
  160     jr->arg_num = job_arg_num(ident);
  161     jr->command = obstack_alloc(&tab_o, command_len + 1);
  162     strcpy(jr->command, command);
  163     jr->job_pid = jr->mailer_pid = 0;
  164     if (last_job_rec != NULL) last_job_rec->next = jr;
  165     else first_job_rec = jr;
  166     last_job_rec = jr;
  167     jr->prev_env_rec = last_env_rec;
  168     jr->next = NULL;
  169     Debug(("Read job - period=%d, delay=%d, ident=%s, command=%s",
  170        jr->period, jr->delay, jr->ident, jr->command));
  171 }
  172 
  173 static void
  174 parse_tab_line(char *line)
  175 {
  176     int r;
  177     char *env_var;
  178     char *value;
  179     char *periods;
  180     char *delays;
  181     char *ident;
  182     char *command;
  183 
  184     /* an empty line? */
  185     r = match_rx("^[ \t]*($|#)", line, 0);
  186     if (r == -1) goto reg_err;
  187     if (r)
  188     {
  189     Debug(("line %d empty", line_num));
  190     return;
  191     }
  192 
  193     /* an environment assignment? */
  194     r = match_rx("^[ \t]*([^ \t=]+)[ \t]*=(.*)$", line, 2,
  195          &env_var, &value);
  196     if (r == -1) goto reg_err;
  197     if (r)
  198     {
  199     register_env(env_var, value);
  200     return;
  201     }
  202 
  203     /* a job? */
  204     r = match_rx("^[ \t]*([[:digit:]]+)[ \t]+([[:digit:]]+)[ \t]+"
  205          "([^ \t/]+)[ \t]+([^ \t].*)$",
  206          line, 4, &periods, &delays, &ident, &command);
  207     if (r == -1) goto reg_err;
  208     if (r)
  209     {
  210     register_job(periods, delays, ident, command);
  211     return;
  212     }
  213     complain("Invalid syntax in %s on line %d - skipping this line",
  214          anacrontab, line_num);
  215     return;
  216 
  217  reg_err:
  218     die("Regex error reading %s", anacrontab);
  219 }
  220 
  221 void
  222 read_tab()
  223 /* Read the anacrontab file into memory */
  224 {
  225     char *tab_line;
  226 
  227     first_job_rec = last_job_rec = NULL;
  228     first_env_rec = last_env_rec = NULL;
  229     jobs_read = 0;
  230     line_num = 0;
  231     /* Open the anacrontab file */
  232     tab = fopen(anacrontab, "r");
  233     if (tab == NULL) die_e("Error opening %s", anacrontab);
  234     /* Initialize the obstacks */
  235     obstack_init(&input_o);
  236     obstack_init(&tab_o);
  237     while ((tab_line = read_tab_line()) != NULL)
  238     {
  239     line_num++;
  240     parse_tab_line(tab_line);
  241     obstack_free(&input_o, tab_line);
  242     }
  243     if (fclose(tab)) die_e("Error closing %s", anacrontab);
  244 }
  245 
  246 static int
  247 execution_order(const job_rec **job1, const job_rec **job2)
  248 /* Comparison function for sorting the jobs.
  249  */
  250 {
  251     int d;
  252 
  253     d = (*job1)->arg_num - (*job2)->arg_num;
  254     if (d != 0 && now) return d;
  255     d = (*job1)->delay - (*job2)->delay;
  256     if (d != 0) return d;
  257     d = (*job1)->tab_line - (*job2)->tab_line;
  258     return d;
  259 }
  260 
  261 void
  262 arrange_jobs()
  263 /* Make an array of pointers to jobs that are going to be executed,
  264  * and arrange them in the order of execution.
  265  * Also lock these jobs.
  266  */
  267 {
  268     job_rec *j;
  269 
  270     j = first_job_rec;
  271     njobs = 0;
  272     while (j != NULL)
  273     {
  274     if (j->arg_num != -1 && (update_only || consider_job(j)))
  275     {
  276         njobs++;
  277         obstack_grow(&tab_o, &j, sizeof(j));
  278     }
  279     j = j->next;
  280     }
  281     job_array = obstack_finish(&tab_o);
  282 
  283     /* sort the jobs */
  284     qsort(job_array, njobs, sizeof(*job_array),
  285       (int (*)(const void *, const void *))execution_order);
  286 }