示例#1
0
文件: yash.c 项目: amlweems/EE379L
/*
 * helper function to wait on process exit or background the job
 */
void queue_job(job_t *job) {
	siginfo_t si;
	if (job->bg) {
		job->state = RUNNING;
		job_add(&root, job);
	} else {
		fg = job;
		si.si_pid = 0;
		waitid(P_PID, job->pid, &si, WEXITED|WSTOPPED);
		tcsetpgrp(0, s_pgid);
		if (si.si_pid != 0) {
			switch (si.si_code) {
				case CLD_EXITED:
					job_rm(&root, fg);
					job_free(&fg);
					break;
				case CLD_STOPPED:
					job->state = STOPPED;
					job_add(&root, fg);
					fg = NULL;
					break;
			}
		}
	}
}
示例#2
0
文件: cron.c 项目: enukane/netbsd-src
static void
run_reboot_jobs(cron_db *db) {
	user *u;
	entry *e;

	for (u = db->head; u != NULL; u = u->next) {
		for (e = u->crontab; e != NULL; e = e->next) {
			if (e->flags & WHEN_REBOOT)
				job_add(e, u, StartTime);
		}
	}
	(void) job_runqueue();
}
示例#3
0
文件: main.c 项目: hsjhsj110cs/hehe
void*
master_thread_routine(int *accept_fd)
{
    int fd;

    while(1)
    {
        fd = server_accept(*accept_fd);
        if(fd != -1)
        {
            pthread_mutex_lock(&mutex);
            job_add(fd);
            pthread_mutex_unlock(&mutex);
            printf("master: added a job\n");
            pthread_cond_signal(&cond);
            printf("master: signaled others\n");
        }
    }
    return NULL;
}
示例#4
0
int
cmd_if_shell_exec(struct cmd *self, struct cmd_ctx *ctx)
{
	struct cmd_target_data		*data = self->data;
	struct cmd_if_shell_data	*cdata;
	struct job			*job;

	cdata = xmalloc(sizeof *cdata);
	cdata->cmd = xstrdup(data->arg2);
	memcpy(&cdata->ctx, ctx, sizeof cdata->ctx);

	if (ctx->cmdclient != NULL)
		ctx->cmdclient->references++;
	if (ctx->curclient != NULL)
		ctx->curclient->references++;

	job = job_add(NULL, 0, NULL,
	    data->arg, cmd_if_shell_callback, cmd_if_shell_free, cdata);
	job_run(job);

	return (1);	/* don't let client exit */
}
示例#5
0
int
main (int argc, char *argv[])
{
  cron_db database;
  char *config_file;		/*Name of our configuration file; NULL if none */
  struct sigaction my_sigaction;

  /* We need to put Program_Name in its own storage because later we will
   * modify argv[0] in an attempt to change the process name.
   */
  ProcessName = argv[0];
  ProgramName = strdup (argv[0]);

#if HAVE_SETLINEBUF
  setlinebuf (stdout);
  setlinebuf (stderr);
#endif /*HAVE_SETLINEBUF */

  parse_args (argc, argv, &pass_environment, &config_file);

  read_config (config_file, &allow_only_root, &log_syslog, &allow_file,
	       &deny_file, &crondir, &spool_dir, &log_file, &syscrontab,
	       &lastrun_file, &pidfile, &mailprog, &mailargs);

#ifdef USE_SIGCHLD
  memset (&my_sigaction, 0, sizeof (my_sigaction));
  my_sigaction.sa_handler = sigchld_handler;
  my_sigaction.sa_flags |= SA_NOCLDSTOP | SA_NODEFER;
  if (sigaction (SIGCHLD, &my_sigaction, NULL))
    perror ("sigaction");
#else
  (void) signal (SIGCHLD, SIG_IGN);
#endif

  memset (&my_sigaction, 0, sizeof (my_sigaction));
  my_sigaction.sa_handler = sigterm_handler;
  if (sigaction (SIGTERM, &my_sigaction, NULL))
    perror ("sigaction");

  memset (&my_sigaction, 0, sizeof (my_sigaction));
  my_sigaction.sa_handler = sighup_handler;
  if (sigaction (SIGHUP, &my_sigaction, NULL))
    perror ("sigaction");

  acquire_daemonlock (0);
  set_cron_uid ();
  set_cron_cwd ();

#if HAVE_SETENV
  if (!pass_environment)
    setenv ("PATH", _PATH_DEFPATH, 1);
#endif

  /* if there are no debug flags turned on, fork as a daemon should. */

#if DEBUGGING
  if (DebugFlags)
    {
#else
  if (0)
    {
#endif
      (void) fprintf (stderr, "[%d] cron started\n", getpid ());
    }
  else
    {
      switch (fork ())
	{
	case -1:
	  log_it ("CRON", getpid (), "DEATH", "can't fork");
	  exit (0);
	  break;
	case 0:
	  /* child process */
	  log_it ("CRON", getpid (), "STARTUP", "fork ok");
	  (void) setsid ();
	  break;
	default:
	  /* parent process should just die */
	  _exit (0);
	}
    }

  acquire_daemonlock (0);

  /* initialize waiting for busy disk */
  init_diskload ();

  database.head = NULL;
  database.tail = NULL;
  database.mtime = (time_t) 0;

  Debug (DMISC, ("about to load database"));
  load_database (&database);
  Debug (DMISC, ("about to build catch up list"));
  build_cu_list (&database, &CatchUpList);
  Debug (DMISC, ("about to run reboot jobs"));
  run_reboot_jobs (&database);

  while (TRUE)
    {
      cron_sync (); 
# if DEBUGGING
      if (!(DebugFlags & DTEST))
# endif	 /*DEBUGGING*/
	  cron_sleep ();

      load_database (&database);

      /* first catch up any jobs that are on the CatchUpList */
      if (CatchUpList && (!jhead))
	CatchUpList = run_cu_list (CatchUpList);
      /* then run the regular jobs for this minute */
      cron_tick (&database);
    }
}


static void
run_reboot_jobs (cron_db * db)
{
  register user *u;
  register entry *e;

  for (u = db->head; u != NULL; u = u->next)
    {
      for (e = u->crontab; e != NULL; e = e->next)
	{
	  if (e->flags & WHEN_REBOOT)
	    {
	      job_add (e, u);
	    }
	}
    }
  (void) job_runqueue ();
}


static void
cron_tick (cron_db * db)
{
  register struct tm *tm = localtime (&TargetTime);
  register int minute, hour, dom, month, dow;
  register user *u;
  register entry *e;

  /* make 0-based values out of these so we can use them as indicies
   */
  minute = tm->tm_min - FIRST_MINUTE;
  hour = tm->tm_hour - FIRST_HOUR;
  dom = tm->tm_mday - FIRST_DOM;
  month = tm->tm_mon + 1 /* 0..11 -> 1..12 */  - FIRST_MONTH;
  dow = tm->tm_wday - FIRST_DOW;

  Debug (DSCH, ("[%d] tick(%d,%d,%d,%d,%d)\n",
		getpid (), minute, hour, dom, month, dow));
  /* the dom/dow situation is odd.  '* * 1,15 * Sun' will run on the
   * first and fifteenth AND every Sunday;  '* * * * Sun' will run *only*
   * on Sundays;  '* * 1,15 * *' will run *only* the 1st and 15th.  this
   * is why we keep 'e->dow_star' and 'e->dom_star'.  yes, it's bizarre.
   * like many bizarre things, it's the standard.
   */
  for (u = db->head; u != NULL; u = u->next)
    {
      for (e = u->crontab; e != NULL; e = e->next)
	{
	  Debug (DSCH | DEXT, ("user [%s:%d:%d:...] cmd=\"%s\"\n",
			       env_get ("LOGNAME", e->envp),
			       e->uid, e->gid, e->cmd));
	  if (bit_test (e->minute, minute)
	      && bit_test (e->hour, hour)
	      && bit_test (e->month, month)
	      && (((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
		  ? (bit_test (e->dow, dow) && bit_test (e->dom, dom))
		  : (bit_test (e->dow, dow) || bit_test (e->dom, dom))))
	    {
	      job_add (e, u);
	    }
	}
    }
}


/* the task here is to figure out how long it's going to be until :00 of the
 * following minute and initialize TargetTime to this value.  TargetTime
 * will subsequently slide 60 seconds at a time, with correction applied
 * implicitly in cron_sleep().  it would be nice to let cron execute in
 * the "current minute" before going to sleep, but by restarting cron you
 * could then get it to execute a given minute's jobs more than once.
 * instead we have the chance of missing a minute's jobs completely, but
 * that's something sysadmin's know to expect what with crashing computers..
 * 
 * Patch from <*****@*****.**>:
 *   Do cron_sync() before each cron_sleep(), to handle changes to the system
 *   time.
 */
static void
cron_sync (void)
{
  register struct tm *tm;

  TargetTime = time ((time_t *) 0);
  tm = localtime (&TargetTime);
  TargetTime += (60 - tm->tm_sec);
}


static void
cron_sleep (void)
{
  register int seconds_to_wait;

  do
    {
      seconds_to_wait = (int) (TargetTime - time ((time_t *) 0));
      Debug (DSCH, ("[%d] TargetTime=%ld, sec-to-wait=%d\n",
		    getpid (), TargetTime, seconds_to_wait));
      /* if we intend to sleep, this means that it's finally
       * time to empty the job queue (execute it).
       *
       * if we run any jobs, we'll probably screw up our timing,
       * so go recompute.
       *
       * note that we depend here on the left-to-right nature
       * of &&, and the short-circuiting.
       */
    }
  while (seconds_to_wait > 0 && job_runqueue ());

  while (seconds_to_wait > 0)
    {
      Debug (DSCH, ("[%d] sleeping for %d seconds\n",
		    getpid (), seconds_to_wait));
      seconds_to_wait = (int) sleep ((unsigned int) seconds_to_wait);
    }
}


#ifdef USE_SIGCHLD
static RETSIGTYPE
sigchld_handler (int x)
{
  WAIT_T waiter;
  pid_t pid;

  for (;;)
    {
#if 1
      pid = waitpid (-1, &waiter, WNOHANG);
#else
      pid = wait3 (&waiter, WNOHANG, (struct rusage *) 0);
#endif
      switch (pid)
	{
	case -1:
	  Debug (DPROC, ("[%d] sigchld...no children\n", getpid ()));
	  return;
	case 0:
	  Debug (DPROC, ("[%d] sigchld...no dead kids\n", getpid ()));
	  return;
	default:
	  Debug (DPROC,
		 ("[%d] sigchld...pid #%d died, stat=%d\n",
		  getpid (), pid, WEXITSTATUS (waiter)));
	  save_lastrun (CatchUpList);
	}
    }
}
示例#6
0
int main(int argc, char **argv) {
     time_t now;

     /* Initialise route, runq and job classes */
     now = time(NULL);
     route_init(NULL, 0);
     route_register(&rt_filea_method);
     route_register(&rt_fileov_method);
     route_register(&rt_stdin_method);
     route_register(&rt_stdout_method);
     route_register(&rt_stderr_method);
     if ( ! elog_init(1, "job test", NULL))
	  elog_die(FATAL, "didn't initialise elog\n");
     sig_init();
     callback_init();
     runq_init(now);
     meth_init();
     job_init();

     /* Test should fail due to incorrect method */
     elog_printf(DEBUG, "Expect a complaint! -> ");
     if (job_add(5, 5, 0, 1, "test1a1", "internal_test", "stdout", 
		  "stderr", 100, NULL, "echo \"Hello, world\"") != -1)
     {
	  elog_die(FATAL, "[1a] Shouldn't be able to add\n");
     }

     /* Single test in five seconds, never to run */
     if (job_add(5, 5, 0, 1, "test1a2", "internal_test", "stdout", 
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1a] Can't add\n");
     }
				/* Attention: some white box testing */
     itree_first(runq_event);
     if (itree_getkey(runq_event) != now+5) {
	  elog_die(FATAL, "[1a] Queued at an incorrect time\n");
     }
     job_clear();
     if (!itree_empty(runq_event) || !itree_empty(runq_tab)) {
	  elog_die(FATAL, 
		  "[1a] Trees not emptied. runq_events=%d, runq_tab=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab));
     }
     now = time(NULL);
     
     /* Two tests both in five seconds, never to run */
     if (job_add(5, 5, 0, 1, "test1b1", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1b] Can't add first\n");
     }
     if (job_add(5, 5, 0, 1, "test1b2", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1b] Can't add second\n");
     }
     itree_first(runq_event);
     if (itree_getkey(runq_event) != now+5) {
	  elog_die(FATAL, "[1b] First queued at an incorrect time\n");
     }
     itree_next(runq_event);
     if (itree_getkey(runq_event) != now+5) {
	  elog_die(FATAL, "[1b] Second queued at an incorrect time\n");
     }
     job_clear();
     if (!itree_empty(runq_event) || !itree_empty(runq_tab)) {
	  elog_die(FATAL, 
		  "[1b] Trees not emptied. runq_events=%d, runq_tab=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab));
     }
     now = time(NULL);

     /* Two tests one in five seconds, the other in six, never to run */
     if (job_add(6, 6, 0, 1, "test1c1", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1c] Can't add first\n");
     }
     if (job_add(now+5, 5, 0, 1, "test1c2", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1c] Can't add second\n");
     }
     itree_first(runq_event);
     if (itree_getkey(runq_event) != now+5) {
	  elog_die(FATAL, "[1c] First queued at an incorrect time\n");
     }
     itree_next(runq_event);
     if (itree_getkey(runq_event) != now+6) {
	  elog_die(FATAL, "[1c] Second queued at an incorrect time\n");
     }
     job_clear();
     if (!itree_empty(runq_event) || !itree_empty(runq_tab)) {
	  elog_die(FATAL, 
		  "[1c] Trees not emptied. runq_events=%d, runq_tab=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab));
     }
     now = time(NULL);
     
     /* Continuous single test supposed to start two seconds ago, 
      * next run in three; never to run */
     if (job_add(-2, 5, 0, 0, "test1d1", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1d] Can't add\n");
     }
     itree_first(runq_event);
     if (itree_getkey(runq_event) != now+3) {
	  elog_die(FATAL, 
		  "[1d] Event queued at an incorrect time: bad=%d good=%ld\n", 
		  itree_getkey(runq_event), now+3);
     }
     job_clear();
     if (runq_nsched() > 0) {
	  elog_die(FATAL, "[1d] Still active work scheduled. runq_events=%d, "
		  "runq_tab=%d runq_nsched()=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab), runq_nsched());
	  runq_dump();
     }
     now = time(NULL);
     
     /* Two continous tests, starting two seconds ago, next next run in four;
      * never to run */
     if (job_add(-2, 6, 0, 0, "test1e1", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1e] Can't add first\n");
     }
     if (job_add(-3, 5, 0, 0, "test1e2", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1e] Can't add second\n");
     }
     itree_first(runq_event);
     while (((struct runq_work*) itree_get(runq_event))->expired)
	  itree_next(runq_event);
     if (itree_getkey(runq_event) != now+2) {
	  elog_die(FATAL, "[1e] First queued at an incorrect time\n");
     }
     itree_next(runq_event);
     while (((struct runq_work*) itree_get(runq_event))->expired)
	  itree_next(runq_event);
     if (itree_getkey(runq_event) != now+4) {
	  elog_die(FATAL, "[1e] Second queued at an incorrect time\n");
     }
     job_clear();
     if (runq_nsched() > 0) {
	  elog_die(FATAL, "[1e] Still active work scheduled. runq_events=%d, "
		  "runq_tab=%d runq_nsched()=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab), runq_nsched());
	  runq_dump();
     }
     now = time(NULL);
     
     /* Two 5 run jobs, scheduled to start 10 seconds ago, with periods
      * of 5 and 6 seconds; never to run */
     if (job_add(-10, 6, 0, 5, "test1f1", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1f] Can't add first\n");
     }
     if (job_add(-10, 5, 0, 5, "test1f2", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1f] Can't add second\n");
     }

     itree_first(runq_event);
     while (((struct runq_work*) itree_get(runq_event))->expired)
	  itree_next(runq_event);
     if (itree_getkey(runq_event) != now+2) {
	  elog_die(FATAL, "[1f] First queued at an incorrect time\n");
     }
     itree_next(runq_event);
     while (((struct runq_work*) itree_get(runq_event))->expired)
	  itree_next(runq_event);
     if (itree_getkey(runq_event) != now+5) {
	  elog_die(FATAL, "[1f] Second queued at an incorrect time\n");
     }
     job_clear();
     if (runq_nsched() > 0) {
	  elog_die(FATAL, "[1f] Still active work scheduled. runq_events=%d, "
		  "runq_tab=%d runq_nsched()=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab), runq_nsched());
	  runq_dump();
     }
     now = time(NULL);
     
     /* Two 5 run jobs, scheduled to start 100 seconds ago, with periods
      * of 5 and 6 seconds; they should never be scheduled */
     if (job_add(-100, 6, 0, 5, "test1g1", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1g] Can't add first\n");
     }
     if (job_add(-100, 5, 0, 5, "test1g2", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1g] Can't add second\n");
     }
     if (runq_nsched() > 0) {
	  elog_die(FATAL, "[1g] Still active work scheduled. runq_events=%d, "
		  "runq_tab=%d runq_nsched()=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab), runq_nsched());
	  runq_dump();
     }
     job_clear();
     now = time(NULL);

     /* Two five run tests, starting at different times in the past,
      * five runs each wittth different periods; they should both
      * run now */
     if (job_add(-24, 6, 0, 5, "test1h1", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1h] Can't add first\n");
     }
     if (job_add(-20, 5, 0, 5, "test1h2", "internal_test", "stdout",
		  "stderr", 100, "exec", "echo \"Hello, world\"") == -1)
     {
	  elog_die(FATAL, "[1h] Can't add second\n");
     }
     if (runq_nsched() != 2) {
	  elog_die(FATAL, "[1h] Two jobs should be scheduled not %d\n",
		  runq_nsched());
	  runq_dump();
     }
     sig_on();
     sleep(6);		/* let it run */
     sleep(1);		/* let it run */
     sleep(1);		/* let it run */
     sleep(1);		/* let it run */
     sig_off();
     if (runq_nsched() > 0) {
	  elog_die(FATAL, "[1h] Still active work scheduled. runq_events=%d, "
		  "runq_tab=%d runq_nsched()=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab), runq_nsched());
	  runq_dump();
     }

     job_clear();

#if 0
     /* check all tables/lists are empty */
     if (!itree_empty(runq_event) || !itree_empty(runq_tab)) {
	  elog_die(FATAL, "[1i] Still entries in tables. runq_events=%d, "
		  "runq_tab=%d runq_nsched()=%d\n", 
		  itree_n(runq_event), itree_n(runq_tab), runq_nsched());
	  runq_dump();
     }
#endif

     job_fini();
     meth_fini();
     runq_fini();
     elog_fini();
     route_fini();
     callback_fini();

     printf("%s: tests finished\n", argv[0]);
     exit(0);
}
示例#7
0
/*
 * Read in job definitions from the pseudo-url and add them to the
 * job class. If there is a problem with a job definition, it will not
 * be added to the job class, but other jobs will continue to be processed.
 *
 * File format: one line per job. magic string of 'job 1' at top
 * Fields/columns match the job_add() spec and are:
 * 1. start time (seconds)
 * 2. interval (currently seconds, but ought to have weekly or monthly based
 *    intervals as well)
 * 3. phase (int; job order at each scheduled point)
 * 4. count (int; how many times to run; 0=indefinately)
 * 5. key (unique job id)
 * 6. origin (char *; no spaces)
 * 7. result (pseudo-url; where to send results)
 * 8. errors (pseudo-url; where to send errors)
 * 9. keep (number of results to keep in timestore or tablestore)
 * 10.method (char *; string representation of method)
 * 11.command (char *; command for method to run)
 *
 * The result url, error url and command are parsed for tokens of the
 * form %x, where x is a single letter. These are expanded into context
 * specific strings. Currently, %h is hostname and %j is jobname. See
 * route_expand() for more details.
 *
 * Returns the number of jobs added, or -1 for a major problem
 */
int job_loadroute(char *purl 	/* p-url location of file */ )
{
     long start, interval, phase, count, keep;
     char *key, *origin, *result, *error, *method, *command;
     char *endint;
     ITREE *jobdefs, *job;
     int r, njobdefs, jobsadded = 0;
     char key_t[60], result_t[256], error_t[256], command_t[1024];

     /* read jobs into parse structure */
     njobdefs = util_parseroute(purl, " \t", "job 1", &jobdefs);
     if (njobdefs < 1)
	  return -1;

     util_parsedump(jobdefs);
     itree_traverse(jobdefs) {
          job = itree_get(jobdefs);

	  /* check the size of each row */
	  if (itree_n(job) != 11) {
	       elog_startprintf(ERROR, "%s row %d has %d fields, want 11 (",
				purl, itree_getkey(jobdefs)+1, itree_n(job) );
	       itree_traverse(job)
		    elog_contprintf(ERROR, "%s ", (char *) itree_get(job));
	       elog_endprintf(ERROR, ")");
	       continue;
	  }

	  /* 
	   * validate each column 
	   * we dont need to strdup() any space because job_add() will
	   * do that for itself
	   */
	  /* column 1: start time */
	  itree_find(job, 0);
	  start = strtol( itree_get(job), &endint, 10 );
	  if (start == LONG_MIN || start == LONG_MAX || 
	      itree_get(job) == endint) {
	       elog_printf(ERROR, "%s row %d start time (column 1) is "
			   "incorrect: '%s'; skipping", 
			   purl, itree_getkey(jobdefs), itree_get(job));
	       continue;
	  }

	  /* column 2: interval */
	  itree_find(job, 1);
	  interval = strtol( itree_get(job), &endint, 10 );
	  if (interval == LONG_MIN || interval == LONG_MAX ||
	      itree_get(job) == endint) {
	       elog_printf(ERROR, "%s row %d interval (column 2) is "
			   "incorrect: '%s'; skipping", 
			   purl, itree_getkey(jobdefs), itree_get(job));
	       continue;
	  }

	  /* column 3: phase */
	  itree_find(job, 2);
	  phase = strtol( itree_get(job), &endint, 10 );
	  if (phase == LONG_MIN || phase == LONG_MAX ||
	      itree_get(job) == endint) {
	       elog_printf(ERROR, "%s row %d phase (column 3) is incorrect: "
			   "'%s'; skipping",
			   purl, itree_getkey(jobdefs), itree_get(job));
	       continue;
	  }

	  /* column 4: count */
	  itree_find(job, 3);
	  count = strtol( itree_get(job), &endint, 10 );
	  if (count == LONG_MIN || count == LONG_MAX ||
	      itree_get(job) == endint) {
	       elog_printf(ERROR, "%s row %d count (column 4) is incorrect: "
			   "'%s'; skipping",  purl, itree_getkey(jobdefs), 
			   itree_get(job));
	       continue;
	  }

	  /* column 5: key */
	  itree_find(job, 4);
	  key = itree_get(job);
	  if (route_expand(key_t, key, key, interval) != -1)
	       key = key_t;

	  /* column 6: origin  */
	  itree_find(job, 5);
	  origin = itree_get(job);

	  /* column 7: result  */
	  itree_find(job, 6);
	  result = itree_get(job);
	  if (route_expand(result_t, result, key, interval) != -1)
	       result = result_t;

	  /* column 8: error  */
	  itree_find(job, 7);
	  error = itree_get(job);
	  if (route_expand(error_t, error, key, interval) != -1)
	       error = error_t;

	  /* column 9: keep */
	  itree_find(job, 8);
	  keep = strtol( itree_get(job), &endint, 10 );
	  if (keep == LONG_MIN || keep == LONG_MAX ||
	      itree_get(job) == endint) {
	       elog_printf(ERROR, "%s row %d keep (column 9) is incorrect: "
			   "'%s'; skipping", purl, itree_getkey(jobdefs), 
			   itree_get(job));
	       continue;
	  }

	  /* column 10: method  */
	  itree_find(job, 9);
	  method = itree_get(job);

	  /* column 11: command  */
	  itree_find(job, 10);
	  command = itree_get(job);
	  if (route_expand(command_t, command, key, interval) != -1)
	       command = command_t;

	  elog_printf(DEBUG, "%s row %d read: start=%ld interval=%ld phase=%ld "
		      "count=%ld key=%s origin=%s result=%s error=%s keep=%ld "
		      "method=%s command=%s", purl, itree_getkey(jobdefs), 
		      start, interval, phase, count, key, origin, result, 
		      error, keep, method, command);

	  if (meth_check(method)) {
	       elog_printf(ERROR, "%s row %d method %s not loaded; skipping",
			    purl, itree_getkey(jobdefs), method);
	       continue;
	  }

	  /* insert into job class */
	  r = job_add(start, interval, phase, count, key, origin, result, 
		      error, keep, method, command);
	  if (r == -1)
	       elog_printf(ERROR, "%s row %d unable to add job; skipping",
			   purl, itree_getkey(jobdefs));
	  else
	       jobsadded++;
     }

     util_freeparse(jobdefs);

     return jobsadded;
}
示例#8
0
文件: cron.c 项目: enukane/netbsd-src
static void
find_jobs(time_t vtime, cron_db *db, int doWild, int doNonWild) {
	time_t virtualSecond = vtime * SECONDS_PER_MINUTE;
	struct tm *tm;
	int minute, hour, dom, month, dow;
	user *u;
	entry *e;
#ifndef CRON_LOCALTIME
	char *orig_tz, *job_tz;

#define maketime(tz1, tz2) do { \
	char *t = tz1; \
	if (t != NULL && *t != '\0') \
		setenv("TZ", t, 1); \
	else if ((tz2) != NULL) \
		setenv("TZ", (tz2), 1); \
	else \
		unsetenv("TZ"); \
	tzset(); \
	tm = localtime(&virtualSecond); \
	minute = tm->tm_min -FIRST_MINUTE; \
	hour = tm->tm_hour -FIRST_HOUR; \
	dom = tm->tm_mday -FIRST_DOM; \
	month = tm->tm_mon + 1 /* 0..11 -> 1..12 */ -FIRST_MONTH; \
	dow = tm->tm_wday -FIRST_DOW; \
	} while (/*CONSTCOND*/0)

	orig_tz = getenv("TZ");
	maketime(NULL, orig_tz);
#else
	tm = gmtime(&virtualSecond);
#endif

	Debug(DSCH, ("[%ld] tick(%d,%d,%d,%d,%d) %s %s\n",
		     (long)getpid(), minute, hour, dom, month, dow,
		     doWild?" ":"No wildcard",doNonWild?" ":"Wildcard only"));

	/* the dom/dow situation is odd.  '* * 1,15 * Sun' will run on the
	 * first and fifteenth AND every Sunday;  '* * * * Sun' will run *only*
	 * on Sundays;  '* * 1,15 * *' will run *only* the 1st and 15th.  this
	 * is why we keep 'e->dow_star' and 'e->dom_star'.  yes, it's bizarre.
	 * like many bizarre things, it's the standard.
	 */
	for (u = db->head; u != NULL; u = u->next) {
		for (e = u->crontab; e != NULL; e = e->next) {
#ifndef CRON_LOCALTIME
			job_tz = env_get("CRON_TZ", e->envp);
			maketime(job_tz, orig_tz);
#else
#define job_tz "N/A"
#define orig_tz "N/A"
#endif
			Debug(DSCH|DEXT, ("user [%s:%ld:%ld:...] "
			    "[jobtz=%s, origtz=%s] "
			    "tick(%s), cmd=\"%s\"\n",
			    e->pwd->pw_name, (long)e->pwd->pw_uid,
			    (long)e->pwd->pw_gid, job_tz, orig_tz,
			    tick(e), e->cmd));
			if (bit_test(e->minute, minute) &&
			    bit_test(e->hour, hour) &&
			    bit_test(e->month, month) &&
			    ( ((e->flags & DOM_STAR) || (e->flags & DOW_STAR))
			      ? (bit_test(e->dow,dow) && bit_test(e->dom,dom))
			      : (bit_test(e->dow,dow) || bit_test(e->dom,dom))
			    )
			   ) {
				if ((doNonWild &&
				    !(e->flags & (MIN_STAR|HR_STAR))) || 
				    (doWild && (e->flags & (MIN_STAR|HR_STAR))))
					job_add(e, u, StartTime);
			}
		}
	}
#ifndef CRON_LOCALTIME
	if (orig_tz != NULL)
		setenv("TZ", orig_tz, 1);
	else
		unsetenv("TZ");
#endif
}