This source file includes following definitions.
- set_cron_watched
- do_command
- get_security_context
- free_security_context
- printflags
- printentry
- printcrontab
- matchday
- nextmatch
- matchuser
- cronnext
- database
- usage
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include "config.h"
24
25 #define MAIN_PROGRAM
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <pwd.h>
30
31 #include "globals.h"
32 #include "funcs.h"
33 #include "cron-paths.h"
34
35
36 #define ENTRIES 0x01
37 #define CRONTABS 0x02
38 #define SYSTEM 0x04
39 #define ALLJOBS 0x08
40
41 #ifdef WITH_INOTIFY
42 void set_cron_watched(int fd) {
43
44 (void)fd;
45 }
46 #endif
47
48 void do_command(entry *e, user *u) {
49
50 (void)e;
51 (void)u;
52 }
53
54 #ifdef WITH_SELINUX
55 int get_security_context(const char *name, int crontab_fd,
56 security_context_t *rcontext, const char *tabname) {
57
58 (void)name;
59 (void)crontab_fd;
60 (void)tabname;
61 *rcontext = NULL;
62 return 0;
63 }
64
65 void free_security_context(security_context_t *scontext) {
66
67 (void)scontext;
68 }
69 #endif
70
71
72
73
74 const char *flagname[]= {
75 "MIN_STAR",
76 "HR_STAR",
77 "DOM_STAR",
78 "DOW_STAR",
79 "WHEN_REBOOT",
80 "DONT_LOG"
81 };
82
83 void printflags(char *indent, int flags) {
84 int f;
85 int first = 1;
86
87 printf("%s flagnames:", indent);
88 for (f = 0; f < sizeof(flagname)/sizeof(char *); f++)
89 if (flags & (int)1 << f) {
90 printf("%s%s", first ? " " : "|", flagname[f]);
91 first = 0;
92 }
93 printf("\n");
94 }
95
96
97
98
99 void printentry(char *indent, entry *e, time_t next) {
100 printf("%s - user: %s\n", indent, e->pwd->pw_name);
101 printf("%s cmd: \"%s\"\n", indent, e->cmd);
102 printf("%s flags: 0x%02X\n", indent, e->flags);
103 printflags(indent, e->flags);
104 printf("%s delay: %d\n", indent, e->delay);
105 printf("%s next: %ld\n", indent, (long)next);
106 printf("%s nextstring: ", indent);
107 printf("%s", asctime(localtime(&next)));
108 }
109
110
111
112
113 void printcrontab(user *u) {
114 printf(" - user: \"%s\"\n", u->name);
115 printf(" crontab: %s\n", u->tabname);
116 printf(" system: %d\n", u->system);
117 printf(" entries:\n");
118 }
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 int matchday(entry *e, time_t time) {
137 struct tm current;
138
139 localtime_r(&time, ¤t);
140
141 if (e->flags & DOW_STAR)
142 return bit_test(e->dom, current.tm_mday - 1);
143 if (e->flags & DOM_STAR)
144 return bit_test(e->dow, current.tm_wday);
145 return bit_test(e->dom, current.tm_mday - 1) ||
146 bit_test(e->dow, current.tm_wday);
147 }
148
149
150
151
152 time_t nextmatch(entry *e, time_t start, time_t end) {
153 time_t time;
154 struct tm current;
155
156 for (time = start; time <= end; ) {
157 localtime_r(&time, ¤t);
158
159
160 if (!bit_test(e->month, current.tm_mon)) {
161 current.tm_mon++;
162 if (current.tm_mon >= 12) {
163 current.tm_year++;
164 current.tm_mon = 0;
165 }
166 current.tm_mday = 1;
167 current.tm_hour = 0;
168 current.tm_min = 0;
169 time = mktime(¤t);
170 continue;
171 }
172
173
174 if (!matchday(e, time) && !matchday(e, time + 24 * 60 * 60)) {
175 time += 24 * 60 * 60;
176 continue;
177 }
178
179
180
181
182
183 if (bit_test(e->month, current.tm_mon) &&
184 matchday(e, time) &&
185 bit_test(e->hour, current.tm_hour) &&
186 bit_test(e->minute, current.tm_min)
187 )
188 return time;
189
190
191 time += 60;
192 }
193
194 return -1;
195 }
196
197
198
199
200 int matchuser(char *user, char *list) {
201 char *pos;
202 size_t l = strlen(user);
203
204 for (pos = list; (pos = strstr(pos, user)) != NULL; pos += l) {
205 if ((pos != list) && (*(pos - 1) != ','))
206 continue;
207 if ((pos[l] != '\0') && (pos[l] != ','))
208 continue;
209 return 1;
210 }
211 return 0;
212 }
213
214
215
216
217 time_t cronnext(cron_db database,
218 time_t start, time_t end,
219 char *include, char *exclude, int flags) {
220 time_t closest, next;
221 user *u;
222 entry *e;
223 char *indent = "";
224
225 if (flags & CRONTABS) {
226 printf("crontabs:\n");
227 indent = " ";
228 }
229 else if (flags & ALLJOBS)
230 printf("jobs:\n");
231
232
233 closest = -1;
234 for (u = database.head; u; u = u->next) {
235 if (include && !matchuser(u->name, include))
236 continue;
237 if (exclude && matchuser(u->name, exclude))
238 continue;
239 if (!(flags & SYSTEM) && u->system)
240 continue;
241
242 if (flags & CRONTABS)
243 printcrontab(u);
244
245 for (e = u->crontab; e; e = e->next)
246 for (next = nextmatch(e, start, end);
247 next <= end;
248 next = nextmatch(e, next + 60, end)) {
249 if (next < 0)
250 break;
251 if (closest < 0 || next < closest)
252 closest = next;
253 if (flags & ENTRIES)
254 printentry(indent, e, next);
255 if (! (flags & ALLJOBS))
256 break;
257 }
258 }
259
260 return closest;
261 }
262
263
264
265
266 cron_db database(int installed, char **additional) {
267 cron_db db = {NULL, NULL, (time_t) 0};
268 struct passwd pw;
269 int fd;
270 user *u;
271
272 if (installed)
273 load_database(&db);
274
275 for ( ; *additional != NULL; additional++) {
276 fd = open(*additional, O_RDONLY);
277 if (fd == -1) {
278 perror(*additional);
279 continue;
280 }
281 memset(&pw, 0, sizeof(pw));
282 pw.pw_name = *additional;
283 pw.pw_passwd = "";
284 pw.pw_dir = ".";
285 u = load_user(fd, &pw, *additional, *additional, *additional);
286 if (u == NULL) {
287 printf("cannot load crontab %s\n", *additional);
288 continue;
289 }
290 link_user(&db, u);
291 }
292
293 return db;
294 }
295
296 void usage() {
297 fprintf(stderr, "Find the time of the next scheduled cron job.\n");
298 fprintf(stderr, "Usage:\n");
299 fprintf(stderr, " cronnext [options] [file ...]\n");
300 fprintf(stderr, "\n");
301 fprintf(stderr, "Options:\n");
302 fprintf(stderr, " -i users include only the crontab of these users\n");
303 fprintf(stderr, " -e users exclude the crontab of these users\n");
304 fprintf(stderr, " -s do not include the system crontab\n");
305 fprintf(stderr, " -a examine installed crontabs even if files are given\n");
306 fprintf(stderr, " -t time start from this time (seconds since epoch)\n");
307 fprintf(stderr, " -q time end check at this time (seconds since epoch)\n");
308 fprintf(stderr, " -l print next jobs to be executed\n");
309 fprintf(stderr, " -c print next execution of each job\n");
310 fprintf(stderr, " -f print all jobs executed in the given interval\n");
311 fprintf(stderr, " -h this help\n");
312 fprintf(stderr, " -V print version and exit\n");
313 }
314
315
316
317
318 int main(int argn, char *argv[]) {
319 int opt;
320 char *include, *exclude;
321 int flags;
322 time_t start, next, end = 0;
323 int endtime, printjobs;
324 cron_db db;
325 int installed = 0;
326
327 include = NULL;
328 exclude = NULL;
329 flags = SYSTEM;
330 endtime = 0;
331 printjobs = 0;
332 start = time(NULL) / 60 * 60;
333
334 while (-1 != (opt = getopt(argn, argv, "i:e:ast:q:lcfhV"))) {
335 switch (opt) {
336 case 'i':
337 include = optarg;
338 break;
339 case 'e':
340 exclude = optarg;
341 break;
342 case 'a':
343 installed = 1;
344 break;
345 case 's':
346 flags &= ~SYSTEM;
347 break;
348 case 't':
349 start = atoi(optarg) / 60 * 60;
350 break;
351 case 'q':
352 end = atoi(optarg) / 60 * 60;
353 endtime = 1;
354 break;
355 case 'l':
356 printjobs = 1;
357 break;
358 case 'c':
359 flags |= ENTRIES | CRONTABS;
360 break;
361 case 'f':
362 flags |= ALLJOBS | ENTRIES;
363 break;
364 case 'h':
365 usage();
366 return EXIT_SUCCESS;
367 case 'V':
368 puts(PACKAGE_STRING);
369 return EXIT_SUCCESS;
370 default:
371 fprintf(stderr, "unrecognized option: %s\n",
372 argv[optind - 1]);
373 usage();
374 exit(EXIT_FAILURE);
375 }
376 }
377
378 if (flags & ALLJOBS && !endtime) {
379 fprintf(stderr, "no ending time specified: -f requires -q\n");
380 usage();
381 exit(EXIT_FAILURE);
382 }
383
384
385
386
387 if (!endtime)
388 end = start + 8 * 12 * 31 * 24 * 60 * 60;
389
390
391 if (flags & CRONTABS) {
392 printf("spool: %s\n", SPOOL_DIR);
393 set_debug_flags("");
394 }
395
396
397
398
399 db = database(installed || argv[optind] == NULL, argv + optind);
400
401
402 next = cronnext(db, start, end, include, exclude, flags);
403
404
405 if (next == -1)
406 return EXIT_FAILURE;
407 else
408 printf("next: %ld\n", (long) next);
409
410
411 if (printjobs) {
412 printf("nextjobs:\n");
413 cronnext(db, next, next, include, exclude, (flags & SYSTEM) | ENTRIES);
414 }
415
416 return EXIT_SUCCESS;
417 }
418