"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 }