entry.c (e93f27e3aeb7c0778012b7732bc6376e20f80427) entry.c (fe590ffe40f49fe09d8275fbf29f0d46c5b99dc7)
1/* Copyright 1988,1990,1993,1994 by Paul Vixie
1/*
2 * Copyright 1988,1990,1993,1994 by Paul Vixie
2 * All rights reserved
3 * All rights reserved
4 */
5
6/*
7 * Copyright (c) 1997 by Internet Software Consortium
3 *
8 *
4 * Distribute freely, except: don't remove my name from the source or
5 * documentation (don't take credit for my work), mark your changes (don't
6 * get me blamed for your possible bugs), don't alter or remove this
7 * notice. May be sold if buildable source is provided to buyer. No
8 * warrantee of any kind, express or implied, is included with this
9 * software; use at your own risk, responsibility for damages (if any) to
10 * anyone resulting from the use of this software rests entirely with the
11 * user.
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
12 *
13 * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
14 * I'll try to keep a version up to date. I can be reached as follows:
15 * Paul Vixie <paul@vix.com> uunet!decwrl!vixie!paul
13 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
14 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
16 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
17 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 * SOFTWARE.
16 */
17
18#if !defined(lint) && !defined(LINT)
19static const char rcsid[] =
21 */
22
23#if !defined(lint) && !defined(LINT)
24static const char rcsid[] =
20 "$FreeBSD$";
25 "$Id: entry.c,v 1.3 1998/08/14 00:32:39 vixie Exp $";
21#endif
22
23/* vix 26jan87 [RCS'd; rest of log is in RCS file]
24 * vix 01jan87 [added line-level error recovery]
25 * vix 31dec86 [added /step to the from-to range, per bob@acornrc]
26 * vix 30dec86 [written]
27 */
28

--- 8 unchanged lines hidden (view full) ---

37 e_none, e_minute, e_hour, e_dom, e_month, e_dow,
38 e_cmd, e_timespec, e_username, e_group, e_option,
39 e_mem
40#ifdef LOGIN_CAP
41 , e_class
42#endif
43} ecode_e;
44
26#endif
27
28/* vix 26jan87 [RCS'd; rest of log is in RCS file]
29 * vix 01jan87 [added line-level error recovery]
30 * vix 31dec86 [added /step to the from-to range, per bob@acornrc]
31 * vix 30dec86 [written]
32 */
33

--- 8 unchanged lines hidden (view full) ---

42 e_none, e_minute, e_hour, e_dom, e_month, e_dow,
43 e_cmd, e_timespec, e_username, e_group, e_option,
44 e_mem
45#ifdef LOGIN_CAP
46 , e_class
47#endif
48} ecode_e;
49
45static char get_list(bitstr_t *, int, int, char *[], int, FILE *),
46 get_range(bitstr_t *, int, int, char *[], int, FILE *),
47 get_number(int *, int, char *[], int, FILE *);
48static int set_element(bitstr_t *, int, int, int);
49
50static char *ecodes[] =
50static const char *ecodes[] =
51 {
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 group name",
62 "bad option",
63 "out of memory",
64#ifdef LOGIN_CAP
65 "bad class name",
66#endif
67 };
68
51 {
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 group name",
62 "bad option",
63 "out of memory",
64#ifdef LOGIN_CAP
65 "bad class name",
66#endif
67 };
68
69static char get_list(bitstr_t *, int, int, const char *[], int, FILE *),
70 get_range(bitstr_t *, int, int, const char *[], int, FILE *),
71 get_number(int *, int, const char *[], int, FILE *);
72static int set_element(bitstr_t *, int, int, int);
69
70void
71free_entry(entry *e)
72{
73#ifdef LOGIN_CAP
74 if (e->class != NULL)
75 free(e->class);
76#endif

--- 4 unchanged lines hidden (view full) ---

81 free(e);
82}
83
84
85/* return NULL if eof or syntax error occurs;
86 * otherwise return a pointer to a new entry.
87 */
88entry *
73
74void
75free_entry(entry *e)
76{
77#ifdef LOGIN_CAP
78 if (e->class != NULL)
79 free(e->class);
80#endif

--- 4 unchanged lines hidden (view full) ---

85 free(e);
86}
87
88
89/* return NULL if eof or syntax error occurs;
90 * otherwise return a pointer to a new entry.
91 */
92entry *
89load_entry(FILE *file, void (*error_func)(char *), struct passwd *pw,
93load_entry(FILE *file, void (*error_func)(const char *), struct passwd *pw,
90 char **envp)
91{
92 /* this function reads one crontab entry -- the next -- from a file.
93 * it skips any leading blank lines, ignores comments, and returns
94 * EOF if for any reason the entry can't be read and parsed.
95 *
96 * the entry is also parsed here.
97 *
98 * syntax:
99 * user crontab:
100 * minutes hours doms months dows cmd\n
101 * system crontab (/etc/crontab):
102 * minutes hours doms months dows USERNAME cmd\n
103 */
104
105 ecode_e ecode = e_none;
106 entry *e;
107 int ch;
94 char **envp)
95{
96 /* this function reads one crontab entry -- the next -- from a file.
97 * it skips any leading blank lines, ignores comments, and returns
98 * EOF if for any reason the entry can't be read and parsed.
99 *
100 * the entry is also parsed here.
101 *
102 * syntax:
103 * user crontab:
104 * minutes hours doms months dows cmd\n
105 * system crontab (/etc/crontab):
106 * minutes hours doms months dows USERNAME cmd\n
107 */
108
109 ecode_e ecode = e_none;
110 entry *e;
111 int ch;
112 int len;
108 char cmd[MAX_COMMAND];
109 char envstr[MAX_ENVSTR];
110 char **prev_env;
111
112 Debug(DPARS, ("load_entry()...about to eat comments\n"))
113
114 skip_comments(file);
115

--- 258 unchanged lines hidden (view full) ---

374 e->envp = env_copy(envp);
375 if (e->envp == NULL) {
376 warn("env_copy");
377 ecode = e_mem;
378 goto eof;
379 }
380 if (!env_get("SHELL", e->envp)) {
381 prev_env = e->envp;
113 char cmd[MAX_COMMAND];
114 char envstr[MAX_ENVSTR];
115 char **prev_env;
116
117 Debug(DPARS, ("load_entry()...about to eat comments\n"))
118
119 skip_comments(file);
120

--- 258 unchanged lines hidden (view full) ---

379 e->envp = env_copy(envp);
380 if (e->envp == NULL) {
381 warn("env_copy");
382 ecode = e_mem;
383 goto eof;
384 }
385 if (!env_get("SHELL", e->envp)) {
386 prev_env = e->envp;
382 sprintf(envstr, "SHELL=%s", _PATH_BSHELL);
383 e->envp = env_set(e->envp, envstr);
387 e->envp = env_set(e->envp, "SHELL=" _PATH_BSHELL);
384 if (e->envp == NULL) {
388 if (e->envp == NULL) {
385 warn("env_set(%s)", envstr);
389 warn("env_set(%s)", "SHELL=" _PATH_BSHELL);
386 env_free(prev_env);
387 ecode = e_mem;
388 goto eof;
389 }
390 }
391 /* If LOGIN_CAP, this is deferred to do_command where the login class
392 * is processed. If !LOGIN_CAP, do it here.
393 */
394#ifndef LOGIN_CAP
395 if (!env_get("HOME", e->envp)) {
396 prev_env = e->envp;
390 env_free(prev_env);
391 ecode = e_mem;
392 goto eof;
393 }
394 }
395 /* If LOGIN_CAP, this is deferred to do_command where the login class
396 * is processed. If !LOGIN_CAP, do it here.
397 */
398#ifndef LOGIN_CAP
399 if (!env_get("HOME", e->envp)) {
400 prev_env = e->envp;
397 sprintf(envstr, "HOME=%s", pw->pw_dir);
398 e->envp = env_set(e->envp, envstr);
399 if (e->envp == NULL) {
401 len = snprintf(envstr, sizeof(envstr), "HOME=%s", pw->pw_dir);
402 if (len < sizeof(envstr))
403 e->envp = env_set(e->envp, envstr);
404 if (len >= sizeof(envstr) || e->envp == NULL) {
400 warn("env_set(%s)", envstr);
401 env_free(prev_env);
402 ecode = e_mem;
403 goto eof;
404 }
405 }
406#endif
407 prev_env = e->envp;
405 warn("env_set(%s)", envstr);
406 env_free(prev_env);
407 ecode = e_mem;
408 goto eof;
409 }
410 }
411#endif
412 prev_env = e->envp;
408 sprintf(envstr, "%s=%s", "LOGNAME", pw->pw_name);
409 e->envp = env_set(e->envp, envstr);
410 if (e->envp == NULL) {
413 len = snprintf(envstr, sizeof(envstr), "LOGNAME=%s", pw->pw_name);
414 if (len < (int)sizeof(envstr))
415 e->envp = env_set(e->envp, envstr);
416 if (len >= (int)sizeof(envstr) || e->envp == NULL) {
411 warn("env_set(%s)", envstr);
412 env_free(prev_env);
413 ecode = e_mem;
414 goto eof;
415 }
416#if defined(BSD)
417 prev_env = e->envp;
417 warn("env_set(%s)", envstr);
418 env_free(prev_env);
419 ecode = e_mem;
420 goto eof;
421 }
422#if defined(BSD)
423 prev_env = e->envp;
418 sprintf(envstr, "%s=%s", "USER", pw->pw_name);
419 e->envp = env_set(e->envp, envstr);
420 if (e->envp == NULL) {
424 len = snprintf(envstr, sizeof(envstr), "USER=%s", pw->pw_name);
425 if (len < (int)sizeof(envstr))
426 e->envp = env_set(e->envp, envstr);
427 if (len >= (int)sizeof(envstr) || e->envp == NULL) {
421 warn("env_set(%s)", envstr);
422 env_free(prev_env);
423 ecode = e_mem;
424 goto eof;
425 }
426#endif
427
428 Debug(DPARS, ("load_entry()...checking for command options\n"))

--- 43 unchanged lines hidden (view full) ---

472
473 unget_char(ch, file);
474
475 Debug(DPARS, ("load_entry()...about to parse command\n"))
476
477 /* Everything up to the next \n or EOF is part of the command...
478 * too bad we don't know in advance how long it will be, since we
479 * need to malloc a string for it... so, we limit it to MAX_COMMAND.
428 warn("env_set(%s)", envstr);
429 env_free(prev_env);
430 ecode = e_mem;
431 goto eof;
432 }
433#endif
434
435 Debug(DPARS, ("load_entry()...checking for command options\n"))

--- 43 unchanged lines hidden (view full) ---

479
480 unget_char(ch, file);
481
482 Debug(DPARS, ("load_entry()...about to parse command\n"))
483
484 /* Everything up to the next \n or EOF is part of the command...
485 * too bad we don't know in advance how long it will be, since we
486 * need to malloc a string for it... so, we limit it to MAX_COMMAND.
480 * XXX - should use realloc().
481 */
482 ch = get_string(cmd, MAX_COMMAND, file, "\n");
483
484 /* a file without a \n before the EOF is rude, so we'll complain...
485 */
486 if (ch == EOF) {
487 ecode = e_cmd;
488 goto eof;

--- 18 unchanged lines hidden (view full) ---

507 if (ecode != e_none && error_func)
508 (*error_func)(ecodes[(int)ecode]);
509 while (ch != EOF && ch != '\n')
510 ch = get_char(file);
511 return NULL;
512}
513
514
487 */
488 ch = get_string(cmd, MAX_COMMAND, file, "\n");
489
490 /* a file without a \n before the EOF is rude, so we'll complain...
491 */
492 if (ch == EOF) {
493 ecode = e_cmd;
494 goto eof;

--- 18 unchanged lines hidden (view full) ---

513 if (ecode != e_none && error_func)
514 (*error_func)(ecodes[(int)ecode]);
515 while (ch != EOF && ch != '\n')
516 ch = get_char(file);
517 return NULL;
518}
519
520
521/*
522 * bits one bit per flag, default=FALSE
523 * low, high bounds, impl. offset for bitstr
524 * names NULL or names for these elements
525 * ch current character being processed
526 * file file being read
527 */
515static char
528static char
516get_list(bitstr_t *bits, int low, int high, char *names[], int ch, FILE *file)
529get_list(bitstr_t *bits, int low, int high, const char *names[], int ch,
530 FILE *file)
517{
531{
518 register int done;
532 int done;
519
520 /* we know that we point to a non-blank character here;
521 * must do a Skip_Blanks before we exit, so that the
522 * next call (or the code that picks up the cmd) can
523 * assume the same thing.
524 */
525
526 Debug(DPARS|DEXT, ("get_list()...entered\n"))

--- 22 unchanged lines hidden (view full) ---

549 Skip_Blanks(ch, file)
550
551 Debug(DPARS|DEXT, ("get_list()...exiting w/ %02x\n", ch))
552
553 return ch;
554}
555
556
533
534 /* we know that we point to a non-blank character here;
535 * must do a Skip_Blanks before we exit, so that the
536 * next call (or the code that picks up the cmd) can
537 * assume the same thing.
538 */
539
540 Debug(DPARS|DEXT, ("get_list()...entered\n"))

--- 22 unchanged lines hidden (view full) ---

563 Skip_Blanks(ch, file)
564
565 Debug(DPARS|DEXT, ("get_list()...exiting w/ %02x\n", ch))
566
567 return ch;
568}
569
570
571/*
572 * bits one bit per flag, default=FALSE
573 * low, high bounds, impl. offset for bitstr
574 * names NULL or names for these elements
575 * ch current character being processed
576 * file file being read
577 */
557static char
578static char
558get_range(bitstr_t *bits, int low, int high, char *names[], int ch, FILE *file)
579get_range(bitstr_t *bits, int low, int high, const char *names[], int ch,
580 FILE *file)
559{
560 /* range = number | number "-" number [ "/" number ]
561 */
562
581{
582 /* range = number | number "-" number [ "/" number ]
583 */
584
563 register int i;
564 auto int num1, num2, num3;
585 int i, num1, num2, num3;
565
566 Debug(DPARS|DEXT, ("get_range()...entering, exit won't show\n"))
567
568 if (ch == '*') {
569 /* '*' means "first-last" but can still be modified by /step
570 */
571 num1 = low;
572 num2 = high;

--- 58 unchanged lines hidden (view full) ---

631 for (i = num1; i <= num2; i += num3)
632 if (EOF == set_element(bits, low, high, i))
633 return EOF;
634
635 return ch;
636}
637
638
586
587 Debug(DPARS|DEXT, ("get_range()...entering, exit won't show\n"))
588
589 if (ch == '*') {
590 /* '*' means "first-last" but can still be modified by /step
591 */
592 num1 = low;
593 num2 = high;

--- 58 unchanged lines hidden (view full) ---

652 for (i = num1; i <= num2; i += num3)
653 if (EOF == set_element(bits, low, high, i))
654 return EOF;
655
656 return ch;
657}
658
659
660/*
661 * numptr where does the result go?
662 * low offset applied to enum result
663 * names symbolic names, if any, for enums
664 * ch current character
665 * file source
666 */
639static char
667static char
640get_number(int *numptr, int low, char *names[], int ch, FILE *file)
668get_number(int *numptr, int low, const char *names[], int ch, FILE *file)
641{
642 char temp[MAX_TEMPSTR], *pc;
643 int len, i, all_digits;
644
645 /* collect alphanumerics into our fixed-size temp array
646 */
647 pc = temp;
648 len = 0;

--- 53 unchanged lines hidden ---
669{
670 char temp[MAX_TEMPSTR], *pc;
671 int len, i, all_digits;
672
673 /* collect alphanumerics into our fixed-size temp array
674 */
675 pc = temp;
676 len = 0;

--- 53 unchanged lines hidden ---