114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma/* crond.c - daemon to execute scheduled commands.
214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma *
314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * Copyright 2014 Ranjan Kumar <ranjankumar.bth@gmail.com>
414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma *
514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * No Standard
614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
714c8ef42870ca9623b44e369c0231766e8371bfdAshwini SharmaUSE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmaconfig CROND
1014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  bool "crond"
1114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  default n
1214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  help
1314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    usage: crond [-fbS] [-l N] [-d N] [-L LOGFILE] [-c DIR]
1414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
1514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    A daemon to execute scheduled commands.
1614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
1714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    -b Background (default)
1814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    -c crontab dir
1914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    -d Set log level, log to stderr
2014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    -f Foreground
2114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    -l Set log level. 0 is the most verbose, default 8
2214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    -S Log to syslog (default)
2314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    -L Log to file
2414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma*/
2514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
2614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#define FOR_crond
2714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#include "toys.h"
2814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
2914c8ef42870ca9623b44e369c0231766e8371bfdAshwini SharmaGLOBALS(
3014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char *crontabs_dir;
3114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char *logfile;
3214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int loglevel_d;
3314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int loglevel;
3414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
3514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  time_t crontabs_dir_mtime;
3614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  uint8_t flagd;
3714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma)
3814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
3914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmatypedef struct _var {
4014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  struct _var *next, *prev;
4114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char *name, *val;
4214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma} VAR;
4314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
4414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmatypedef struct _job {
4514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  struct _job *next, *prev;
4614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char min[60], hour[24], dom[31], mon[12], dow[7], *cmd;
4714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int isrunning, needstart, mailsize;
4814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  pid_t pid;
4914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma} JOB;
5014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
5114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmatypedef struct _cronfile {
5214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  struct _cronfile *next, *prev;
5314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  struct double_list *job, *var;
5414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char *username, *mailto;
5514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int invalid;
5614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma} CRONFILE;
5714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
5814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic char days[]={"sun""mon""tue""wed""thu""fri""sat"};
5914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic char months[]={"jan""feb""mar""apr""may""jun""jul"
6014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  "aug""sep""oct""nov""dec"};
6114c8ef42870ca9623b44e369c0231766e8371bfdAshwini SharmaCRONFILE *gclist;
6214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
6314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#define LOG_EXIT 0
6414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#define LOG_LEVEL5 5
6514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#define LOG_LEVEL7 7
6614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#define LOG_LEVEL8 8
6714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#define LOG_LEVEL9 9 // warning
6814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma#define LOG_ERROR 20
6914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
7014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void loginfo(uint8_t loglevel, char *msg, ...)
7114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
7214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  va_list s, d;
7314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
7414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  va_start(s, msg);
7514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  va_copy(d, s);
7614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (loglevel >= TT.loglevel) {
7714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    int used;
7814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    char *smsg;
7914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
8014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (!TT.flagd && TT.logfile) {
8114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      int fd = open(TT.logfile, O_WRONLY | O_CREAT | O_APPEND, 0666);
8214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (fd >=0 && fd != 2) {
8314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        dup2(fd, 2);
8414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        close(fd);
8514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      } else if (fd < 0) perror_msg("'%s", TT.logfile);
8614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
8714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    used = vsnprintf(NULL, 0, msg, d);
8814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    smsg = xzalloc(++used);
8914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    vsnprintf(smsg, used, msg, s);
9014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (TT.flagd || TT.logfile) {
9114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      fflush(NULL);
9214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      smsg[used-1] = '\n';
9314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      writeall((loglevel > 8) ? 2 : 1, smsg, used);
9414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    } else syslog((loglevel > 8) ? LOG_ERR : LOG_INFO, "%s", smsg);
9514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    free(smsg);
9614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
9714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  va_end(d);
9814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  va_end(s);
9914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!loglevel) exit(20);
10014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
10114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
10214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma/*
10314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * Names can also be used for the 'month' and 'day of week' fields
10414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * (First three letters of the particular day or month).
10514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma */
10614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic int getindex(char *src, int size)
10714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
10814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int i;
10914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char *field = (size == 12) ? months : days;
11014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
11114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  // strings are not allowed for min, hour and dom fields.
11214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!(size == 7 || size == 12)) return -1;
11314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
11414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  for (i = 0; field[i]; i += 3) {
11514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (!strncasecmp(src, &field[i], 3))
11614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      return (i/3);
11714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
11814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  return -1;
11914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
12014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
12114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma// set elements of minute, hour, day of month, month and day of week arrays.
12214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void fillarray(char *dst, int start, int end, int skip)
12314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
12414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int sk = 1;
12514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
12614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (end < 0) {
12714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    dst[start] = 1;
12814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    return;
12914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
13014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!skip) skip = 1;
13114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  do {
13214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (!--sk) {
13314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      dst[start] = 1;
13414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      sk = skip;
13514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
13614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  } while (start++ != end);
13714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
13814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
13914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic long getval(char *num, long low, long high)
14014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
14114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  long val = strtol(num, &num, 10);
14214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
14314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (*num || (val < low) || (val > high)) return -1;
14414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  return val;
14514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
14614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
14714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma//static int parse_and_fillarray(char *dst, int size, char *src)
14814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic int parse_and_fillarray(char *dst, int min, int max, char *src)
14914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
15014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int start, end, skip = 0;
15114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char *ptr = strchr(src, '/');
15214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
15314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (ptr) {
15414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    *ptr++ = 0;
15514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if ((skip = getval(ptr, min, (min ? max: max-1))) < 0) goto ERROR;
15614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
15714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
15814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (*src == '-' || *src == ',') goto ERROR;
15914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (*src == '*') {
16014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (*(src+1)) goto ERROR;
16114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    fillarray(dst, 0, max-1, skip);
16214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  } else {
16314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    for (;;) {
16414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      char *ctoken = strsep(&src, ","), *dtoken;
16514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
16614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!ctoken) break;
16714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!*ctoken) goto ERROR;
16814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
16914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      // Get start position.
17014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      dtoken = strsep(&ctoken, "-");
17114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (isdigit(*dtoken)) {
17214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if ((start = getval(dtoken, min, (min ? max : max-1))) < 0) goto ERROR;
17314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        start = min ? (start-1) : start;
17414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      } else if ((start = getindex(dtoken, max)) < 0) goto ERROR;
17514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
17614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      // Get end position.
17714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!ctoken) end = -1; // e.g. N1,N2,N3
17814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      else if (*ctoken) {// e.g. N-M
17914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (isdigit(*ctoken)) {
18014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          if ((end = getval(ctoken, min, (min ? max : max-1))) < 0) goto ERROR;
18114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          end = min ? (end-1) : end;
18214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        } else if ((end = getindex(ctoken, max)) < 0) goto ERROR;
18314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (end == start) end = -1;
18414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      } else goto ERROR; // error condition 'N-'
18514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      fillarray(dst, start, end, skip);
18614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
18714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
18814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
18914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (TT.flagd && (TT.loglevel <= 5)) {
19014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    for (start = 0; start < max; start++)
19114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      fprintf(stderr, "%d", (unsigned char)dst[start]);
19214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    fputc('\n', stderr);
19314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
19414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  return 0;
19514c8ef42870ca9623b44e369c0231766e8371bfdAshwini SharmaERROR:
19614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  loginfo(LOG_LEVEL9, "parse error at %s", src);
19714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  return -1;
19814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
19914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
20014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic char *omitspace(char *line)
20114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
20214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while (*line == ' ' || *line == '\t') line++;
20314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  return line;
20414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
20514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
20614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void parse_line(char *line, CRONFILE *cfile)
20714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
20814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int count = 0;
20914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  char *name, *val, *tokens[5] = {0,};
21014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  VAR *v;
21114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  JOB *j;
21214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
21314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  line = omitspace(line);
21414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!*line || *line == '#') return;
21514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
21614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  /*
21714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * TODO: Enhancement to support 8 special strings
21814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @reboot -> Run once at startup.
21914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @yearly -> Run once a year (0 0 1 1 *).
22014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @annually -> Same as above.
22114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @monthly -> Run once a month (0 0 1 * *).
22214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @weekly -> Run once a week (0 0 * * 0).
22314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @daily -> Run once a day (0 0 * * *).
22414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @midnight -> same as above.
22514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   * @hourly -> Run once an hour (0 * * * *).
22614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma   */
22714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (*line == '@') return;
22814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (TT.flagd) loginfo(LOG_LEVEL5, "user:%s entry:%s", cfile->username, line);
22914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while (count<5) {
23014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    int len = strcspn(line, " \t");
23114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
23214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (line[len]) line[len++] = '\0';
23314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    tokens[count++] = line;
23414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    line += len;
23514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    line = omitspace(line);
23614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (!*line) break;
23714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
23814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
23914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  switch (count) {
24014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    case 1: // form SHELL=/bin/sh
24114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      name = tokens[0];
24214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if ((val = strchr(name, '='))) *val++ = 0;
24314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!val || !*val) return;
24414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      break;
24514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    case 2: // form SHELL =/bin/sh or SHELL= /bin/sh
24614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      name = tokens[0];
24714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if ((val = strchr(name, '='))) {
24814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        *val = 0;
24914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        val = tokens[1];
25014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      } else {
25114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (*(tokens[1]) != '=') return;
25214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        val = tokens[1] + 1;
25314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
25414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!*val) return;
25514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      break;
25614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    case 3: // NAME = VAL
25714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      name = tokens[0];
25814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      val = tokens[2];
25914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (*(tokens[1]) != '=') return;
26014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      break;
26114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    case 5:
26214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      // don't have any cmd to execute.
26314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!*line) return;
26414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      j = xzalloc(sizeof(JOB));
26514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
26614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (parse_and_fillarray(j->min, 0, sizeof(j->min), tokens[0]))
26714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        goto STOP_PARSING;
26814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (parse_and_fillarray(j->hour, 0, sizeof(j->hour), tokens[1]))
26914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        goto STOP_PARSING;
27014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (parse_and_fillarray(j->dom, 1, sizeof(j->dom), tokens[2]))
27114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        goto STOP_PARSING;
27214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (parse_and_fillarray(j->mon, 1, sizeof(j->mon), tokens[3]))
27314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        goto STOP_PARSING;
27414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (parse_and_fillarray(j->dow, 0, sizeof(j->dow), tokens[4]))
27514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        goto STOP_PARSING;
27614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      j->cmd = xstrdup(line);
27714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
27814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (TT.flagd) loginfo(LOG_LEVEL5, " command:%s", j->cmd);
27914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      dlist_add_nomalloc((struct double_list **)&cfile->job, (struct double_list *)j);
28014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      return;
28114c8ef42870ca9623b44e369c0231766e8371bfdAshwini SharmaSTOP_PARSING:
28214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      free(j);
28314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      return;
28414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    default: return;
28514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
28614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!strcmp(name, "MAILTO")) cfile->mailto = xstrdup(val);
28714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  else {
28814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    v = xzalloc(sizeof(VAR));
28914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    v->name = xstrdup(name);
29014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    v->val = xstrdup(val);
29114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    dlist_add_nomalloc((struct double_list **)&cfile->var, (struct double_list *)v);
29214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
29314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
29414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
29514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void free_jobs(JOB **jlist)
29614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
29714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  JOB *j = dlist_pop(jlist);
29814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  free(j->cmd);
29914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  free(j);
30014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
30114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
30214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void free_cronfile(CRONFILE **list)
30314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
30414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  CRONFILE *l = dlist_pop(list);
30514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  VAR *v, *vnode = (VAR *)l->var;
30614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
30714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (l->username != l->mailto) free(l->mailto);
30814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  free(l->username);
30914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while (vnode && (v = dlist_pop(&vnode))) {
31014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    free(v->name);
31114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    free(v->val);
31214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    free(v);
31314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
31414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  free(l);
31514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
31614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
31714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma/*
31814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * Iterate all cronfiles to identify the completed jobs and freed them.
31914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * If all jobs got completed for a cronfile, freed cronfile too.
32014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma */
32114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void remove_completed_jobs()
32214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
32314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  CRONFILE *lstart, *list = gclist;
32414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
32514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  lstart = list;
32614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while (list) {
32714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    int delete = 1;
32814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    JOB *jstart, *jlist = (JOB *)list->job;
32914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
33014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    list->invalid = 1;
33114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    jstart = jlist;
33214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    while (jlist) {
33314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      jlist->isrunning = 0;
33414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (jlist->pid > 0) {
33514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        jlist->isrunning = 1;
33614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        delete = 0;
33714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        jlist = jlist->next;
33814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      } else {
33914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (jlist == jstart) { // if 1st node has to delete.
34014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          jstart = jstart->next;
34114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          free_jobs(&jlist);
34214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          continue;
34314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        } else free_jobs(&jlist);
34414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
34514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (jlist == jstart) break;
34614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
34714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    list->job = (struct double_list *)jlist;
34814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
34914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (delete) {
35014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (lstart == list) {
35114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        lstart = lstart->next;
35214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        free_cronfile(&list);
35314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        continue;
35414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      } else free_cronfile(&list);
35514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
35614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    list = list->next;
35714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (lstart == list) break;
35814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
35914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  gclist = list;
36014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
36114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
36214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma// Scan cronfiles and prepare the list of cronfiles with their jobs.
36314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void scan_cronfiles()
36414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
36514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  DIR *dp;
36614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  struct dirent *entry;
36714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
36814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  remove_completed_jobs();
36914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (chdir(TT.crontabs_dir)) loginfo(LOG_EXIT, "chdir(%s)", TT.crontabs_dir);
37014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!(dp = opendir("."))) loginfo(LOG_EXIT, "chdir(%s)", ".");
37114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
37214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while ((entry = readdir(dp))) {
37314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    int fd;
37414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    char *line;
37514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    CRONFILE *cfile;
37614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
37714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (entry->d_name[0] == '.' && (!entry->d_name[1] ||
37814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          (entry->d_name[1] == '.' && !entry->d_name[2])))
37914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      continue;
38014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
38114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (!getpwnam(entry->d_name)) {
38214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      loginfo(LOG_LEVEL7, "ignoring file '%s' (no such user)", entry->d_name);
38314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      continue;
38414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
38514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if ((fd = open(entry->d_name, O_RDONLY)) < 0) continue;
38614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
38714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    // one node for each user
38814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    cfile = xzalloc(sizeof(CRONFILE));
38914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    cfile->username = xstrdup(entry->d_name);
39014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
39114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    for (; (line = get_line(fd)); free(line))
39214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      parse_line(line, cfile);
39314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
39414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    // If there is no job for a cron, remove the VAR list.
39514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (!cfile->job) {
39614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      VAR *v, *vnode = (VAR *)cfile->var;
39714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
39814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      free(cfile->username);
39914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (cfile->mailto) free(cfile->mailto);
40014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
40114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      while (vnode && (v = dlist_pop(&vnode))) {
40214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        free(v->name);
40314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        free(v->val);
40414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        free(v);
40514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
40614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      free(cfile);
40714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    } else {
40814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!cfile->mailto) cfile->mailto = cfile->username;
40914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      dlist_add_nomalloc((struct double_list **)&gclist,
41014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          (struct double_list *)cfile);
41114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
41214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    close(fd);
41314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
41414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  closedir(dp);
41514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
41614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
41714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma/*
41814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * Set env variables, if any in the cronfile. Execute given job with the given
41914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * SHELL or Default SHELL and send an e-mail with respect to every successfully
42014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma * completed job (as per the given param 'prog').
42114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma */
42214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void do_fork(CRONFILE *cfile, JOB *job, int fd, char *prog)
42314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
42414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  pid_t pid = vfork();
42514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
42614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (pid == 0) {
42714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    VAR *v, *vstart = (VAR *)cfile->var;
42814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    struct passwd *pwd = getpwnam(cfile->username);
42914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
43014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (!pwd) loginfo(LOG_LEVEL9, "can't get uid for %s", cfile->username);
43114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    else {
43214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      char *file = "/bin/sh";
43314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
43414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (setenv("USER", pwd->pw_name, 1)) _exit(1);
43514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      for (v = vstart; v;) {
43614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (!strcmp("SHELL", v->name)) file = v->val;
43714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (setenv(v->name, v->val, 1)) _exit(1);
43814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if ((v=v->next) == vstart) break;
43914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
44014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!getenv("HOME")) {
44114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (setenv("HOME", pwd->pw_dir, 1))
44214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          _exit(1);
44314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
44414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      xsetuser(pwd);
44514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (chdir(pwd->pw_dir)) loginfo(LOG_LEVEL9, "chdir(%s)", pwd->pw_dir);
44614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (prog) file = prog;
44714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (TT.flagd) loginfo(LOG_LEVEL5, "child running %s", file);
44814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
44914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (fd >= 0) {
45014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        int newfd = prog ? 0 : 1;
45114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (fd != newfd) {
45214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          dup2(fd, newfd);
45314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          close(fd);
45414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        }
45514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        dup2(1, 2);
45614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
45714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      setpgrp();
45814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      execlp(file, file, (prog ? "-ti" : "-c"), (prog ? NULL : job->cmd), (char *) NULL);
45914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      loginfo(LOG_ERROR, "can't execute '%s' for user %s", file, cfile->username);
46014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
46114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!prog) dprintf(1, "Exec failed: %s -c %s\n", file, job->cmd);
46214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      _exit(EXIT_SUCCESS);
46314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
46414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
46514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (pid < 0) {
46614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    loginfo(LOG_ERROR, "can't vfork");
46714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    pid = 0;
46814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
46914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (fd >=0) close(fd);
47014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  job->pid = pid;
47114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
47214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
47314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma// Send an e-mail for each successfully completed jobs.
47414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void sendmail(CRONFILE *cfile, JOB *job)
47514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
47614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  pid_t pid = job->pid;
47714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int mailfd;
47814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  struct stat sb;
47914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
48014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  job->pid = 0;
48114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (pid <=0 || job->mailsize <=0) {
48214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    job->isrunning = 0;
48314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    job->needstart = 1;
48414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    return;
48514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
48614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  snprintf(toybuf, sizeof(toybuf), "/var/spool/cron/cron.%s.%d",
48714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      cfile->username, (int)pid);
48814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
48914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  mailfd = open(toybuf, O_RDONLY);
49014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  unlink(toybuf);
49114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (mailfd < 0) return;
49214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
49314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (fstat(mailfd, &sb) == -1 || sb.st_uid != 0 || sb.st_nlink != 0
49414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      || sb.st_size == job->mailsize || !S_ISREG(sb.st_mode)) {
49514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    xclose(mailfd);
49614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    return;
49714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
49814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  job->mailsize = 0;
49914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  do_fork(cfile, job, mailfd, "sendmail");
50014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
50114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
50214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma// Count the number of jobs, which are not completed.
50314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic int count_running_jobs()
50414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
50514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  CRONFILE *cfile = gclist;
50614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  JOB *job, *jstart;
50714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int count = 0;
50814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
50914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while (cfile) {
51014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    job = jstart = (JOB *)cfile->job;
51114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    while (job) {
51214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      int ret;
51314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
51414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (!job->isrunning || job->pid<=0) goto NEXT_JOB;
51514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      job->isrunning = 0;
51614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      ret = waitpid(job->pid, NULL, WNOHANG);
51714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (ret < 0 || ret == job->pid) {
51814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        sendmail(cfile, job);
51914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (job->pid) count += (job->isrunning=1);
52014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        else {
52114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          job->isrunning = 0;
52214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          job->needstart = 1;
52314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        }
52414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
52514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      else count += (job->isrunning=1);
52614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
52714c8ef42870ca9623b44e369c0231766e8371bfdAshwini SharmaNEXT_JOB:
52814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if ((job = job->next) == jstart) break;
52914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
53014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if ((cfile = cfile->next) == gclist) break;
53114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
53214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  return count;
53314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
53414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
53514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma// Execute jobs one by one and prepare for the e-mail sending.
53614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void execute_jobs(void)
53714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
53814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  CRONFILE *cfile = gclist;
53914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  JOB *job, *jstart;
54014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
54114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while (cfile) {
54214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    job = jstart = (JOB *)cfile->job;
54314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    while (job) {
54414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (job->needstart) {
54514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        job->needstart = 0;
54614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (job->pid < 0) {
54714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          int mailfd = -1;
54814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
54914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          job->mailsize = job->pid = 0;
55014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          snprintf(toybuf, sizeof(toybuf), "/var/spool/cron/cron.%s.%d",
55114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma              cfile->username, getpid());
55214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          if ((mailfd = open(toybuf, O_CREAT|O_TRUNC|O_WRONLY|O_EXCL|O_APPEND,
55314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma                  0600)) < 0) {
55414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            loginfo(LOG_ERROR, "can't create mail file %s for user %s, "
55514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma                "discarding output", toybuf, cfile->username);
55614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          } else {
55714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            dprintf(mailfd, "To: %s\nSubject: cron: %s\n\n", cfile->mailto, job->cmd);
55814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            job->mailsize = lseek(mailfd, 0, SEEK_CUR);
55914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          }
56014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          do_fork(cfile, job, mailfd, NULL);
56114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          if (mailfd >= 0) {
56214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            if (job->pid <= 0) unlink(toybuf);
56314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            else {
56414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma              char *mailfile = xmprintf("/var/spool/cron/cron.%s.%d",
56514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma                  cfile->username, (int)job->pid);
56614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma              rename(toybuf, mailfile);
56714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma              free(mailfile);
56814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            }
56914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          }
57014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          loginfo(LOG_LEVEL8, "USER %s pid %3d cmd %s",
57114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma              cfile->username, job->pid, job->cmd);
57214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          if (job->pid < 0) job->needstart = 1;
57314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          else job->isrunning = 1;
57414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        }
57514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
57614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if ((job = job->next) == jstart) break;
57714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
57814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if ((cfile = cfile->next) == gclist) break;
57914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
58014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
58114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
58214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma// Identify jobs, which needs to be started at the given time interval.
58314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmastatic void schedule_jobs(time_t ctime, time_t ptime)
58414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
58514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  time_t tm = ptime-ptime%60;
58614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
58714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  for (; tm <= ctime; tm += 60) {
58814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    struct tm *lt;
58914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    CRONFILE *cfile = gclist;
59014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    JOB *job, *jstart;
59114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
59214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (tm <= ptime) continue;
59314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    lt = localtime(&tm);
59414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
59514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    while (cfile) {
59614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (TT.flagd) loginfo(LOG_LEVEL5, "file %s:", cfile->username);
59714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (cfile->invalid) goto NEXT_CRONFILE;
59814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      job = jstart = (JOB *)cfile->job;
59914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
60014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      while (job) {
60114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (TT.flagd) loginfo(LOG_LEVEL5, " line %s", job->cmd);
60214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
60314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if (job->min[lt->tm_min] && job->hour[lt->tm_hour]
60414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            && (job->dom[lt->tm_mday] || job->dow[lt->tm_wday])
60514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            && job->mon[lt->tm_mon-1]) {
60614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          if (TT.flagd)
60714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            loginfo(LOG_LEVEL5, " job: %d %s\n", (int)job->pid, job->cmd);
60814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          if (job->pid > 0) {
60914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            loginfo(LOG_LEVEL8, "user %s: process already running: %s",
61014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma                cfile->username, job->cmd);
61114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          } else if (!job->pid) {
61214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            job->pid = -1;
61314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            job->needstart = 1;
61414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma            job->isrunning = 0;
61514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma          }
61614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        }
61714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma        if ((job = job->next) == jstart) break;
61814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      }
61914c8ef42870ca9623b44e369c0231766e8371bfdAshwini SharmaNEXT_CRONFILE:
62014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if ((cfile = cfile->next) == gclist) break;
62114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
62214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
62314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
62414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
62514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharmavoid crond_main(void)
62614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma{
62714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  time_t ctime, ptime;
62814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  int sleepfor = 60;
62914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  struct stat sb;
63014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
63114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  TT.flagd = (toys.optflags & FLAG_d);
63214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
63314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  // Setting default params.
63414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (TT.flagd) TT.loglevel = TT.loglevel_d;
63514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!(toys.optflags & (FLAG_f | FLAG_b))) toys.optflags |= FLAG_b;
63614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!(toys.optflags & (FLAG_S | FLAG_L))) toys.optflags |= FLAG_S;
63714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
63814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if ((toys.optflags & FLAG_c)
63914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      && (TT.crontabs_dir[strlen(TT.crontabs_dir)-1] != '/'))
64014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    TT.crontabs_dir = xmprintf("%s/", TT.crontabs_dir);
64114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
64214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!TT.crontabs_dir) TT.crontabs_dir = xstrdup("/var/spool/cron/crontabs/");
64314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (toys.optflags & FLAG_b) daemon(0,0);
64414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
64514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (!TT.flagd && !TT.logfile)
64614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    openlog(toys.which->name, LOG_CONS | LOG_PID, LOG_CRON);
64714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
64814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  // Set default shell once.
64914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (setenv("SHELL", "/bin/sh", 1)) error_exit("Can't set default shell");
65014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  xchdir(TT.crontabs_dir);
65114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  loginfo(LOG_LEVEL8, "crond started, log level %d", TT.loglevel);
65214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
65314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  if (stat(TT.crontabs_dir, &sb)) sb.st_mtime = 0;
65414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  TT.crontabs_dir_mtime = sb.st_mtime;
65514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  scan_cronfiles();
65614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  ctime = time(NULL);
65714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
65814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  while (1) {
65914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    long tdiff;
66014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
66114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    ptime = ctime;
66214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    sleep(sleepfor - (ptime%sleepfor) +1);
66314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    tdiff =(long) ((ctime = time(NULL)) - ptime);
66414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
66514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (stat(TT.crontabs_dir, &sb)) sb.st_mtime = 0;
66614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (TT.crontabs_dir_mtime != sb.st_mtime) {
66714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      TT.crontabs_dir_mtime = sb.st_mtime;
66814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      scan_cronfiles();
66914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
67014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma
67114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (TT.flagd) loginfo(LOG_LEVEL5, "wakeup diff=%ld\n", tdiff);
67214c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    if (tdiff < -60 * 60 || tdiff > 60 * 60)
67314c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      loginfo(LOG_LEVEL9, "time disparity of %ld minutes detected", tdiff / 60);
67414c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    else if (tdiff > 0) {
67514c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      schedule_jobs(ctime, ptime);
67614c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      execute_jobs();
67714c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      if (count_running_jobs()) sleepfor = 10;
67814c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma      else sleepfor = 60;
67914c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma    }
68014c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma  }
68114c8ef42870ca9623b44e369c0231766e8371bfdAshwini Sharma}
682