This source file includes following definitions.
- free_entry
- load_entry
- get_list
- get_range
- get_number
- set_element
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "config.h"
30
31 #include <ctype.h>
32 #include <pwd.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <errno.h>
39
40 #include "bitstring.h"
41 #include "funcs.h"
42 #include "globals.h"
43 #include "macros.h"
44 #include "pathnames.h"
45
46 typedef enum ecode {
47 e_none, e_minute, e_hour, e_dom, e_month, e_dow,
48 e_cmd, e_timespec, e_username, e_option, e_memory
49 } ecode_e;
50
51 static const char *ecodes[] = {
52 "no error",
53 "bad minute",
54 "bad hour",
55 "bad day-of-month",
56 "bad month",
57 "bad day-of-week",
58 "bad command",
59 "bad time specifier",
60 "bad username",
61 "bad option",
62 "out of memory"
63 };
64
65 static int get_list(bitstr_t *, int, int, const char *[], int, FILE *),
66 get_range(bitstr_t *, int, int, const char *[], int, FILE *),
67 get_number(int *, int, const char *[], int, FILE *, const char *),
68 set_element(bitstr_t *, int, int, int);
69
70 void free_entry(entry * e) {
71 free(e->cmd);
72 free(e->pwd);
73 env_free(e->envp);
74 free(e);
75 }
76
77
78
79
80 entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
81 char **envp) {
82
83
84
85
86
87
88
89
90
91
92
93
94
95 ecode_e ecode = e_none;
96 entry *e;
97 int ch;
98 char cmd[MAX_COMMAND];
99 char envstr[MAX_ENVSTR];
100 char **tenvp;
101 char *p;
102 struct passwd temppw;
103
104 Debug(DPARS, ("load_entry()...about to eat comments\n"));
105
106 skip_comments(file);
107
108 ch = get_char(file);
109 if (ch == EOF)
110 return (NULL);
111
112
113
114
115
116
117 e = (entry *) calloc(sizeof (entry), sizeof (char));
118
119
120
121
122 if (ch == '-') {
123
124
125
126 if (pw == NULL || pw->pw_uid == 0)
127 e->flags |= DONT_LOG;
128 else {
129 log_it("CRON", getpid(), "ERROR", "Only privileged user can disable logging", 0);
130 ecode = e_option;
131 goto eof;
132 }
133 ch = get_char(file);
134 if (ch == EOF) {
135 free(e);
136 return NULL;
137 }
138 }
139
140 if (ch == '@') {
141
142
143
144
145
146
147
148
149
150
151
152
153 ch = get_string(cmd, MAX_COMMAND, file, " \t\n");
154 if (!strcmp("reboot", cmd)) {
155 e->flags |= WHEN_REBOOT;
156 }
157 else if (!strcmp("yearly", cmd) || !strcmp("annually", cmd)) {
158 bit_set(e->minute, 0);
159 bit_set(e->hour, 0);
160 bit_set(e->dom, 0);
161 bit_set(e->month, 0);
162 bit_nset(e->dow, 0, LAST_DOW - FIRST_DOW);
163 e->flags |= DOW_STAR;
164 }
165 else if (!strcmp("monthly", cmd)) {
166 bit_set(e->minute, 0);
167 bit_set(e->hour, 0);
168 bit_set(e->dom, 0);
169 bit_nset(e->month, 0, LAST_MONTH - FIRST_MONTH);
170 bit_nset(e->dow, 0, LAST_DOW - FIRST_DOW);
171 e->flags |= DOW_STAR;
172 }
173 else if (!strcmp("weekly", cmd)) {
174 bit_set(e->minute, 0);
175 bit_set(e->hour, 0);
176 bit_nset(e->dom, 0, LAST_DOM - FIRST_DOM);
177 bit_nset(e->month, 0, LAST_MONTH - FIRST_MONTH);
178 bit_set(e->dow, 0);
179 e->flags |= DOW_STAR;
180 }
181 else if (!strcmp("daily", cmd) || !strcmp("midnight", cmd)) {
182 bit_set(e->minute, 0);
183 bit_set(e->hour, 0);
184 bit_nset(e->dom, 0, LAST_DOM - FIRST_DOM);
185 bit_nset(e->month, 0, LAST_MONTH - FIRST_MONTH);
186 bit_nset(e->dow, 0, LAST_DOW - FIRST_DOW);
187 }
188 else if (!strcmp("hourly", cmd)) {
189 bit_set(e->minute, 0);
190 bit_nset(e->hour, 0, LAST_HOUR - FIRST_HOUR);
191 bit_nset(e->dom, 0, LAST_DOM - FIRST_DOM);
192 bit_nset(e->month, 0, LAST_MONTH - FIRST_MONTH);
193 bit_nset(e->dow, 0, LAST_DOW - FIRST_DOW);
194 e->flags |= HR_STAR;
195 }
196 else {
197 ecode = e_timespec;
198 goto eof;
199 }
200
201
202
203 Skip_Blanks(ch, file);
204 if (ch == EOF || ch == '\n') {
205 ecode = e_cmd;
206 goto eof;
207 }
208 }
209 else {
210 Debug(DPARS, ("load_entry()...about to parse numerics\n"));
211
212 if (ch == '*')
213 e->flags |= MIN_STAR;
214 ch = get_list(e->minute, FIRST_MINUTE, LAST_MINUTE, PPC_NULL, ch, file);
215 if (ch == EOF) {
216 ecode = e_minute;
217 goto eof;
218 }
219
220
221
222
223 if (ch == '*')
224 e->flags |= HR_STAR;
225 ch = get_list(e->hour, FIRST_HOUR, LAST_HOUR, PPC_NULL, ch, file);
226 if (ch == EOF) {
227 ecode = e_hour;
228 goto eof;
229 }
230
231
232
233
234 if (ch == '*')
235 e->flags |= DOM_STAR;
236 ch = get_list(e->dom, FIRST_DOM, LAST_DOM, PPC_NULL, ch, file);
237 if (ch == EOF) {
238 ecode = e_dom;
239 goto eof;
240 }
241
242
243
244
245 ch = get_list(e->month, FIRST_MONTH, LAST_MONTH, MonthNames, ch, file);
246 if (ch == EOF) {
247 ecode = e_month;
248 goto eof;
249 }
250
251
252
253
254 if (ch == '*')
255 e->flags |= DOW_STAR;
256 ch = get_list(e->dow, FIRST_DOW, LAST_DOW, DowNames, ch, file);
257 if (ch == EOF) {
258 ecode = e_dow;
259 goto eof;
260 }
261 }
262
263
264 if (bit_test(e->dow, 0) || bit_test(e->dow, 7)) {
265 bit_set(e->dow, 0);
266 bit_set(e->dow, 7);
267 }
268
269
270 if (ch == '\n' || ch == '*') {
271 ecode = e_cmd;
272 goto eof;
273 }
274
275
276 unget_char(ch, file);
277
278 if (!pw) {
279 char *username = cmd;
280
281 Debug(DPARS, ("load_entry()...about to parse username\n"));
282 ch = get_string(username, MAX_COMMAND, file, " \t\n");
283
284 Debug(DPARS, ("load_entry()...got %s\n", username));
285 if (ch == EOF || ch == '\n' || ch == '*') {
286 ecode = e_cmd;
287 goto eof;
288 }
289
290 pw = getpwnam(username);
291 if (pw == NULL) {
292 Debug(DPARS, ("load_entry()...unknown user entry\n"));
293 memset(&temppw, 0, sizeof (temppw));
294 temppw.pw_name = username;
295 temppw.pw_passwd = "";
296 pw = &temppw;
297 } else {
298 Debug(DPARS, ("load_entry()...uid %ld, gid %ld\n",
299 (long) pw->pw_uid, (long) pw->pw_gid));
300 }
301 }
302
303 if ((e->pwd = pw_dup(pw)) == NULL) {
304 ecode = e_memory;
305 goto eof;
306 }
307 memset(e->pwd->pw_passwd, 0, strlen(e->pwd->pw_passwd));
308
309 p = env_get("RANDOM_DELAY", envp);
310 if (p) {
311 char *endptr;
312 long val;
313
314 errno = 0;
315 val = strtol(p, &endptr, 10);
316 if (errno != 0 || val < 0 || val > 24*60) {
317 log_it("CRON", getpid(), "ERROR", "bad value of RANDOM_DELAY", 0);
318 } else {
319 e->delay = (int)((double)val * RandomScale);
320 }
321 }
322
323
324
325
326 if ((e->envp = env_copy(envp)) == NULL) {
327 ecode = e_memory;
328 goto eof;
329 }
330 if (!env_get("SHELL", e->envp)) {
331 if (glue_strings(envstr, sizeof envstr, "SHELL", _PATH_BSHELL, '=')) {
332 if ((tenvp = env_set(e->envp, envstr)) == NULL) {
333 ecode = e_memory;
334 goto eof;
335 }
336 e->envp = tenvp;
337 }
338 else
339 log_it("CRON", getpid(), "ERROR", "can't set SHELL", 0);
340 }
341 if ((tenvp = env_update_home(e->envp, pw->pw_dir)) == NULL) {
342 ecode = e_memory;
343 goto eof;
344 }
345 e->envp = tenvp;
346 #ifndef LOGIN_CAP
347
348 if (!env_get("PATH", e->envp)) {
349 char *defpath;
350
351 if (ChangePath)
352 defpath = _PATH_DEFPATH;
353 else {
354 defpath = getenv("PATH");
355 if (defpath == NULL)
356 defpath = _PATH_DEFPATH;
357 }
358
359 if (glue_strings(envstr, sizeof envstr, "PATH", defpath, '=')) {
360 if ((tenvp = env_set(e->envp, envstr)) == NULL) {
361 ecode = e_memory;
362 goto eof;
363 }
364 e->envp = tenvp;
365 }
366 else
367 log_it("CRON", getpid(), "ERROR", "can't set PATH", 0);
368 }
369 #endif
370 if (glue_strings(envstr, sizeof envstr, "LOGNAME", pw->pw_name, '=')) {
371 if ((tenvp = env_set(e->envp, envstr)) == NULL) {
372 ecode = e_memory;
373 goto eof;
374 }
375 e->envp = tenvp;
376 }
377 else
378 log_it("CRON", getpid(), "ERROR", "can't set LOGNAME", 0);
379 #if defined(BSD) || defined(__linux)
380 if (glue_strings(envstr, sizeof envstr, "USER", pw->pw_name, '=')) {
381 if ((tenvp = env_set(e->envp, envstr)) == NULL) {
382 ecode = e_memory;
383 goto eof;
384 }
385 e->envp = tenvp;
386 }
387 else
388 log_it("CRON", getpid(), "ERROR", "can't set USER", 0);
389 #endif
390
391 Debug(DPARS, ("load_entry()...about to parse command\n"));
392
393
394
395
396
397 ch = get_string(cmd, MAX_COMMAND, file, "\n");
398
399
400
401 if (ch == EOF) {
402 ecode = e_cmd;
403 goto eof;
404 }
405
406
407
408 if ((e->cmd = strdup(cmd)) == NULL) {
409 ecode = e_memory;
410 goto eof;
411 }
412
413 Debug(DPARS, ("load_entry()...returning successfully\n"));
414
415
416
417 return (e);
418
419 eof:
420 if (e->envp)
421 env_free(e->envp);
422 free(e->pwd);
423 free(e->cmd);
424 free(e);
425 while (ch != '\n' && !feof(file))
426 ch = get_char(file);
427 if (ecode != e_none && error_func)
428 (*error_func) (ecodes[(int) ecode]);
429 return (NULL);
430 }
431
432 static int
433 get_list(bitstr_t * bits, int low, int high, const char *names[],
434 int ch, FILE * file) {
435 int done;
436
437
438
439
440
441
442
443 Debug(DPARS | DEXT, ("get_list()...entered\n"));
444
445
446
447
448
449 bit_nclear(bits, 0, (high - low));
450
451
452
453 done = FALSE;
454 while (!done) {
455 if (EOF == (ch = get_range(bits, low, high, names, ch, file)))
456 return (EOF);
457 if (ch == ',')
458 ch = get_char(file);
459 else
460 done = TRUE;
461 }
462
463
464
465 Skip_Nonblanks(ch, file)
466 Skip_Blanks(ch, file)
467
468 Debug(DPARS | DEXT, ("get_list()...exiting w/ %02x\n", ch));
469
470 return (ch);
471 }
472
473
474 static int
475 get_range(bitstr_t * bits, int low, int high, const char *names[],
476 int ch, FILE * file) {
477
478
479
480 int i, num1, num2, num3;
481
482 Debug(DPARS | DEXT, ("get_range()...entering, exit won't show\n"));
483
484 if (ch == '*') {
485
486
487 num1 = low;
488 num2 = high;
489 ch = get_char(file);
490 if (ch == EOF)
491 return (EOF);
492 }
493 else {
494 ch = get_number(&num1, low, names, ch, file, ",- \t\n");
495 if (ch == EOF)
496 return (EOF);
497
498 if (ch != '-') {
499
500
501 if (EOF == set_element(bits, low, high, num1)) {
502 unget_char(ch, file);
503 return (EOF);
504 }
505 return (ch);
506 }
507 else {
508
509
510 ch = get_char(file);
511 if (ch == EOF)
512 return (EOF);
513
514
515
516 ch = get_number(&num2, low, names, ch, file, "/, \t\n");
517 if (ch == EOF || num1 > num2)
518 return (EOF);
519 }
520 }
521
522
523
524 if (ch == '/') {
525
526
527 ch = get_char(file);
528 if (ch == EOF)
529 return (EOF);
530
531
532
533
534
535
536 ch = get_number(&num3, 0, PPC_NULL, ch, file, ", \t\n");
537 if (ch == EOF || num3 == 0)
538 return (EOF);
539 }
540 else {
541
542
543 num3 = 1;
544 }
545
546
547
548
549
550
551 for (i = num1; i <= num2; i += num3)
552 if (EOF == set_element(bits, low, high, i)) {
553 unget_char(ch, file);
554 return (EOF);
555 }
556
557 return (ch);
558 }
559
560 static int
561 get_number(int *numptr, int low, const char *names[], int ch, FILE * file,
562 const char *terms) {
563 char temp[MAX_TEMPSTR], *pc;
564 int len, i;
565
566 pc = temp;
567 len = 0;
568
569
570 while (isdigit((unsigned char) ch)) {
571 if (++len >= MAX_TEMPSTR)
572 goto bad;
573 *pc++ = (char)ch;
574 ch = get_char(file);
575 }
576 *pc = '\0';
577 if (len != 0) {
578
579 if (!strchr(terms, ch))
580 goto bad;
581 *numptr = atoi(temp);
582 return (ch);
583 }
584
585
586 if (names) {
587 while (isalpha((unsigned char) ch)) {
588 if (++len >= MAX_TEMPSTR)
589 goto bad;
590 *pc++ = (char)ch;
591 ch = get_char(file);
592 }
593 *pc = '\0';
594 if (len != 0 && strchr(terms, ch)) {
595 for (i = 0; names[i] != NULL; i++) {
596 Debug(DPARS | DEXT,
597 ("get_num, compare(%s,%s)\n", names[i], temp));
598 if (!strcasecmp(names[i], temp)) {
599 *numptr = i + low;
600 return (ch);
601 }
602 }
603 }
604 }
605
606 bad:
607 unget_char(ch, file);
608 return (EOF);
609 }
610
611 static int set_element(bitstr_t * bits, int low, int high, int number) {
612 Debug(DPARS | DEXT, ("set_element(?,%d,%d,%d)\n", low, high, number));
613
614 if (number < low || number > high)
615 return (EOF);
616
617 bit_set(bits, (number - low));
618 return (OK);
619 }