crond: reorder functions to follow usual order: "main last"
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		@@ -17,25 +17,25 @@
 | 
			
		||||
/* glibc frees previous setenv'ed value when we do next setenv()
 | 
			
		||||
 * of the same variable. uclibc does not do this! */
 | 
			
		||||
#if (defined(__GLIBC__) && !defined(__UCLIBC__)) /* || OTHER_SAFE_LIBC... */
 | 
			
		||||
#define SETENV_LEAKS 0
 | 
			
		||||
# define SETENV_LEAKS 0
 | 
			
		||||
#else
 | 
			
		||||
#define SETENV_LEAKS 1
 | 
			
		||||
# define SETENV_LEAKS 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define TMPDIR          CONFIG_FEATURE_CROND_DIR
 | 
			
		||||
#define CRONTABS        CONFIG_FEATURE_CROND_DIR "/crontabs"
 | 
			
		||||
#ifndef SENDMAIL
 | 
			
		||||
#define SENDMAIL        "sendmail"
 | 
			
		||||
# define SENDMAIL       "sendmail"
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef SENDMAIL_ARGS
 | 
			
		||||
#define SENDMAIL_ARGS   "-ti", NULL
 | 
			
		||||
# define SENDMAIL_ARGS  "-ti", NULL
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef CRONUPDATE
 | 
			
		||||
#define CRONUPDATE      "cron.update"
 | 
			
		||||
# define CRONUPDATE     "cron.update"
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef MAXLINES
 | 
			
		||||
#define MAXLINES        256	/* max lines in non-root crontabs */
 | 
			
		||||
# define MAXLINES       256	/* max lines in non-root crontabs */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -108,20 +108,6 @@ struct globals {
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void CheckUpdates(void);
 | 
			
		||||
static void SynchronizeDir(void);
 | 
			
		||||
static int TestJobs(time_t t1, time_t t2);
 | 
			
		||||
static void RunJobs(void);
 | 
			
		||||
static int CheckJobs(void);
 | 
			
		||||
static void RunJob(const char *user, CronLine *line);
 | 
			
		||||
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
 | 
			
		||||
static void EndJob(const char *user, CronLine *line);
 | 
			
		||||
#else
 | 
			
		||||
#define EndJob(user, line)  ((line)->cl_Pid = 0)
 | 
			
		||||
#endif
 | 
			
		||||
static void DeleteFile(const char *userName);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* 0 is the most verbose, default 8 */
 | 
			
		||||
#define LVL5  "\x05"
 | 
			
		||||
#define LVL7  "\x07"
 | 
			
		||||
@@ -163,101 +149,6 @@ static void crondlog(const char *ctl, ...)
 | 
			
		||||
		exit(20);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 | 
			
		||||
int crond_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	time_t t2;
 | 
			
		||||
	int rescan;
 | 
			
		||||
	int sleep_time;
 | 
			
		||||
	unsigned opts;
 | 
			
		||||
 | 
			
		||||
	INIT_G();
 | 
			
		||||
 | 
			
		||||
	/* "-b after -f is ignored", and so on for every pair a-b */
 | 
			
		||||
	opt_complementary = "f-b:b-f:S-L:L-S" IF_FEATURE_CROND_D(":d-l")
 | 
			
		||||
			":l+:d+"; /* -l and -d have numeric param */
 | 
			
		||||
	opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"),
 | 
			
		||||
			&LogLevel, &LogFile, &CDir
 | 
			
		||||
			IF_FEATURE_CROND_D(,&LogLevel));
 | 
			
		||||
	/* both -d N and -l N set the same variable: LogLevel */
 | 
			
		||||
 | 
			
		||||
	if (!(opts & OPT_f)) {
 | 
			
		||||
		/* close stdin, stdout, stderr.
 | 
			
		||||
		 * close unused descriptors - don't need them. */
 | 
			
		||||
		bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(opts & OPT_d) && LogFile == NULL) {
 | 
			
		||||
		/* logging to syslog */
 | 
			
		||||
		openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON);
 | 
			
		||||
		logmode = LOGMODE_SYSLOG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xchdir(CDir);
 | 
			
		||||
	//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
 | 
			
		||||
	xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
 | 
			
		||||
	crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", LogLevel);
 | 
			
		||||
	SynchronizeDir();
 | 
			
		||||
	write_pidfile("/var/run/crond.pid");
 | 
			
		||||
 | 
			
		||||
	/* main loop - synchronize to 1 second after the minute, minimum sleep
 | 
			
		||||
	 * of 1 second. */
 | 
			
		||||
	t2 = time(NULL);
 | 
			
		||||
	rescan = 60;
 | 
			
		||||
	sleep_time = 60;
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		time_t t1;
 | 
			
		||||
		long dt;
 | 
			
		||||
 | 
			
		||||
		t1 = t2;
 | 
			
		||||
		sleep((sleep_time + 1) - (time(NULL) % sleep_time));
 | 
			
		||||
 | 
			
		||||
		t2 = time(NULL);
 | 
			
		||||
		dt = (long)t2 - (long)t1;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * The file 'cron.update' is checked to determine new cron
 | 
			
		||||
		 * jobs.  The directory is rescanned once an hour to deal
 | 
			
		||||
		 * with any screwups.
 | 
			
		||||
		 *
 | 
			
		||||
		 * Check for time jump.  Disparities over an hour either way
 | 
			
		||||
		 * result in resynchronization.  A negative disparity
 | 
			
		||||
		 * less than an hour causes us to effectively sleep until we
 | 
			
		||||
		 * match the original time (i.e. no re-execution of jobs that
 | 
			
		||||
		 * have just been run).  A positive disparity less than
 | 
			
		||||
		 * an hour causes intermediate jobs to be run, but only once
 | 
			
		||||
		 * in the worst case.
 | 
			
		||||
		 *
 | 
			
		||||
		 * When running jobs, the inequality used is greater but not
 | 
			
		||||
		 * equal to t1, and less then or equal to t2.
 | 
			
		||||
		 */
 | 
			
		||||
		if (--rescan == 0) {
 | 
			
		||||
			rescan = 60;
 | 
			
		||||
			SynchronizeDir();
 | 
			
		||||
		}
 | 
			
		||||
		CheckUpdates();
 | 
			
		||||
		if (DebugOpt)
 | 
			
		||||
			crondlog(LVL5 "wakeup dt=%ld", dt);
 | 
			
		||||
		if (dt < -60 * 60 || dt > 60 * 60) {
 | 
			
		||||
			crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60);
 | 
			
		||||
			/* and we do not run any jobs in this case */
 | 
			
		||||
		} else if (dt > 0) {
 | 
			
		||||
			/* Usual case: time advances forwad, as expected */
 | 
			
		||||
			TestJobs(t1, t2);
 | 
			
		||||
			RunJobs();
 | 
			
		||||
			sleep(5);
 | 
			
		||||
			if (CheckJobs() > 0) {
 | 
			
		||||
				sleep_time = 10;
 | 
			
		||||
			} else {
 | 
			
		||||
				sleep_time = 60;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/* else: time jumped back, do not run any jobs */
 | 
			
		||||
	} /* for (;;) */
 | 
			
		||||
 | 
			
		||||
	return 0; /* not reached */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if SETENV_LEAKS
 | 
			
		||||
/* We set environment *before* vfork (because we want to use vfork),
 | 
			
		||||
 * so we cannot use setenv() - repeated calls to setenv() may leak memory!
 | 
			
		||||
@@ -452,6 +343,48 @@ static void FixDayDow(CronLine *line)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DeleteFile() - delete user database
 | 
			
		||||
 *
 | 
			
		||||
 * Note: multiple entries for same user may exist if we were unable to
 | 
			
		||||
 * completely delete a database due to running processes.
 | 
			
		||||
 */
 | 
			
		||||
static void DeleteFile(const char *userName)
 | 
			
		||||
{
 | 
			
		||||
	CronFile **pfile = &FileBase;
 | 
			
		||||
	CronFile *file;
 | 
			
		||||
 | 
			
		||||
	while ((file = *pfile) != NULL) {
 | 
			
		||||
		if (strcmp(userName, file->cf_User) == 0) {
 | 
			
		||||
			CronLine **pline = &file->cf_LineBase;
 | 
			
		||||
			CronLine *line;
 | 
			
		||||
 | 
			
		||||
			file->cf_Running = 0;
 | 
			
		||||
			file->cf_Deleted = 1;
 | 
			
		||||
 | 
			
		||||
			while ((line = *pline) != NULL) {
 | 
			
		||||
				if (line->cl_Pid > 0) {
 | 
			
		||||
					file->cf_Running = 1;
 | 
			
		||||
					pline = &line->cl_Next;
 | 
			
		||||
				} else {
 | 
			
		||||
					*pline = line->cl_Next;
 | 
			
		||||
					free(line->cl_Shell);
 | 
			
		||||
					free(line);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (file->cf_Running == 0) {
 | 
			
		||||
				*pfile = file->cf_Next;
 | 
			
		||||
				free(file->cf_User);
 | 
			
		||||
				free(file);
 | 
			
		||||
			} else {
 | 
			
		||||
				pfile = &file->cf_Next;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			pfile = &file->cf_Next;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void SynchronizeFile(const char *fileName)
 | 
			
		||||
{
 | 
			
		||||
	struct parser_t *parser;
 | 
			
		||||
@@ -600,51 +533,7 @@ static void SynchronizeDir(void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * DeleteFile() - delete user database
 | 
			
		||||
 *
 | 
			
		||||
 * Note: multiple entries for same user may exist if we were unable to
 | 
			
		||||
 * completely delete a database due to running processes.
 | 
			
		||||
 */
 | 
			
		||||
static void DeleteFile(const char *userName)
 | 
			
		||||
{
 | 
			
		||||
	CronFile **pfile = &FileBase;
 | 
			
		||||
	CronFile *file;
 | 
			
		||||
 | 
			
		||||
	while ((file = *pfile) != NULL) {
 | 
			
		||||
		if (strcmp(userName, file->cf_User) == 0) {
 | 
			
		||||
			CronLine **pline = &file->cf_LineBase;
 | 
			
		||||
			CronLine *line;
 | 
			
		||||
 | 
			
		||||
			file->cf_Running = 0;
 | 
			
		||||
			file->cf_Deleted = 1;
 | 
			
		||||
 | 
			
		||||
			while ((line = *pline) != NULL) {
 | 
			
		||||
				if (line->cl_Pid > 0) {
 | 
			
		||||
					file->cf_Running = 1;
 | 
			
		||||
					pline = &line->cl_Next;
 | 
			
		||||
				} else {
 | 
			
		||||
					*pline = line->cl_Next;
 | 
			
		||||
					free(line->cl_Shell);
 | 
			
		||||
					free(line);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (file->cf_Running == 0) {
 | 
			
		||||
				*pfile = file->cf_Next;
 | 
			
		||||
				free(file->cf_User);
 | 
			
		||||
				free(file);
 | 
			
		||||
			} else {
 | 
			
		||||
				pfile = &file->cf_Next;
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			pfile = &file->cf_Next;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * TestJobs()
 | 
			
		||||
 *
 | 
			
		||||
 * determine which jobs need to be run.  Under normal conditions, the
 | 
			
		||||
 * Determine which jobs need to be run.  Under normal conditions, the
 | 
			
		||||
 * period is about a minute (one scan).  Worst case it will be one
 | 
			
		||||
 * hour (60 scans).
 | 
			
		||||
 */
 | 
			
		||||
@@ -695,35 +584,63 @@ static int TestJobs(time_t t1, time_t t2)
 | 
			
		||||
	return nJobs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void RunJobs(void)
 | 
			
		||||
#if ENABLE_FEATURE_CROND_CALL_SENDMAIL
 | 
			
		||||
static void
 | 
			
		||||
ForkJob(const char *user, CronLine *line, int mailFd,
 | 
			
		||||
		const char *prog, const char *cmd, const char *arg,
 | 
			
		||||
		const char *mail_filename);
 | 
			
		||||
/*
 | 
			
		||||
 * EndJob - called when job terminates and when mail terminates
 | 
			
		||||
 */
 | 
			
		||||
static void EndJob(const char *user, CronLine *line)
 | 
			
		||||
{
 | 
			
		||||
	CronFile *file;
 | 
			
		||||
	CronLine *line;
 | 
			
		||||
	int mailFd;
 | 
			
		||||
	char mailFile[128];
 | 
			
		||||
	struct stat sbuf;
 | 
			
		||||
 | 
			
		||||
	for (file = FileBase; file; file = file->cf_Next) {
 | 
			
		||||
		if (!file->cf_Ready)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		file->cf_Ready = 0;
 | 
			
		||||
		for (line = file->cf_LineBase; line; line = line->cl_Next) {
 | 
			
		||||
			if (line->cl_Pid >= 0)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			RunJob(file->cf_User, line);
 | 
			
		||||
			crondlog(LVL8 "USER %s pid %3d cmd %s",
 | 
			
		||||
				file->cf_User, (int)line->cl_Pid, line->cl_Shell);
 | 
			
		||||
			if (line->cl_Pid < 0) {
 | 
			
		||||
				file->cf_Ready = 1;
 | 
			
		||||
			} else if (line->cl_Pid > 0) {
 | 
			
		||||
				file->cf_Running = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	/* No job */
 | 
			
		||||
	if (line->cl_Pid <= 0) {
 | 
			
		||||
		line->cl_Pid = 0;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * End of job and no mail file
 | 
			
		||||
	 * End of sendmail job
 | 
			
		||||
	 */
 | 
			
		||||
	snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, line->cl_Pid);
 | 
			
		||||
	line->cl_Pid = 0;
 | 
			
		||||
 | 
			
		||||
	if (line->cl_MailFlag == 0) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	line->cl_MailFlag = 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * End of primary job - check for mail file.  If size has increased and
 | 
			
		||||
	 * the file is still valid, we sendmail it.
 | 
			
		||||
	 */
 | 
			
		||||
	mailFd = open(mailFile, O_RDONLY);
 | 
			
		||||
	unlink(mailFile);
 | 
			
		||||
	if (mailFd < 0) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid
 | 
			
		||||
	 || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos
 | 
			
		||||
	 || !S_ISREG(sbuf.st_mode)
 | 
			
		||||
	) {
 | 
			
		||||
		close(mailFd);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (line->cl_MailTo)
 | 
			
		||||
		ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
# define EndJob(user, line)  ((line)->cl_Pid = 0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * CheckJobs() - check for job completion
 | 
			
		||||
 *
 | 
			
		||||
 * Check for job completion, return number of jobs still running after
 | 
			
		||||
 * all done.
 | 
			
		||||
 */
 | 
			
		||||
@@ -855,55 +772,7 @@ static void RunJob(const char *user, CronLine *line)
 | 
			
		||||
	ForkJob(user, line, mailFd, DEFAULT_SHELL, "-c", line->cl_Shell, mailFile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * EndJob - called when job terminates and when mail terminates
 | 
			
		||||
 */
 | 
			
		||||
static void EndJob(const char *user, CronLine *line)
 | 
			
		||||
{
 | 
			
		||||
	int mailFd;
 | 
			
		||||
	char mailFile[128];
 | 
			
		||||
	struct stat sbuf;
 | 
			
		||||
 | 
			
		||||
	/* No job */
 | 
			
		||||
	if (line->cl_Pid <= 0) {
 | 
			
		||||
		line->cl_Pid = 0;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * End of job and no mail file
 | 
			
		||||
	 * End of sendmail job
 | 
			
		||||
	 */
 | 
			
		||||
	snprintf(mailFile, sizeof(mailFile), "%s/cron.%s.%d", TMPDIR, user, line->cl_Pid);
 | 
			
		||||
	line->cl_Pid = 0;
 | 
			
		||||
 | 
			
		||||
	if (line->cl_MailFlag == 0) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	line->cl_MailFlag = 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * End of primary job - check for mail file.  If size has increased and
 | 
			
		||||
	 * the file is still valid, we sendmail it.
 | 
			
		||||
	 */
 | 
			
		||||
	mailFd = open(mailFile, O_RDONLY);
 | 
			
		||||
	unlink(mailFile);
 | 
			
		||||
	if (mailFd < 0) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fstat(mailFd, &sbuf) < 0 || sbuf.st_uid != DaemonUid
 | 
			
		||||
	 || sbuf.st_nlink != 0 || sbuf.st_size == line->cl_MailPos
 | 
			
		||||
	 || !S_ISREG(sbuf.st_mode)
 | 
			
		||||
	) {
 | 
			
		||||
		close(mailFd);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (line->cl_MailTo)
 | 
			
		||||
		ForkJob(user, line, mailFd, SENDMAIL, SENDMAIL_ARGS, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else /* crond without sendmail */
 | 
			
		||||
#else /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */
 | 
			
		||||
 | 
			
		||||
static void RunJob(const char *user, CronLine *line)
 | 
			
		||||
{
 | 
			
		||||
@@ -943,4 +812,125 @@ static void RunJob(const char *user, CronLine *line)
 | 
			
		||||
	line->cl_Pid = pid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* ENABLE_FEATURE_CROND_CALL_SENDMAIL */
 | 
			
		||||
#endif /* !ENABLE_FEATURE_CROND_CALL_SENDMAIL */
 | 
			
		||||
 | 
			
		||||
static void RunJobs(void)
 | 
			
		||||
{
 | 
			
		||||
	CronFile *file;
 | 
			
		||||
	CronLine *line;
 | 
			
		||||
 | 
			
		||||
	for (file = FileBase; file; file = file->cf_Next) {
 | 
			
		||||
		if (!file->cf_Ready)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		file->cf_Ready = 0;
 | 
			
		||||
		for (line = file->cf_LineBase; line; line = line->cl_Next) {
 | 
			
		||||
			if (line->cl_Pid >= 0)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			RunJob(file->cf_User, line);
 | 
			
		||||
			crondlog(LVL8 "USER %s pid %3d cmd %s",
 | 
			
		||||
				file->cf_User, (int)line->cl_Pid, line->cl_Shell);
 | 
			
		||||
			if (line->cl_Pid < 0) {
 | 
			
		||||
				file->cf_Ready = 1;
 | 
			
		||||
			} else if (line->cl_Pid > 0) {
 | 
			
		||||
				file->cf_Running = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int crond_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 | 
			
		||||
int crond_main(int argc UNUSED_PARAM, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	time_t t2;
 | 
			
		||||
	int rescan;
 | 
			
		||||
	int sleep_time;
 | 
			
		||||
	unsigned opts;
 | 
			
		||||
 | 
			
		||||
	INIT_G();
 | 
			
		||||
 | 
			
		||||
	/* "-b after -f is ignored", and so on for every pair a-b */
 | 
			
		||||
	opt_complementary = "f-b:b-f:S-L:L-S" IF_FEATURE_CROND_D(":d-l")
 | 
			
		||||
			":l+:d+"; /* -l and -d have numeric param */
 | 
			
		||||
	opts = getopt32(argv, "l:L:fbSc:" IF_FEATURE_CROND_D("d:"),
 | 
			
		||||
			&LogLevel, &LogFile, &CDir
 | 
			
		||||
			IF_FEATURE_CROND_D(,&LogLevel));
 | 
			
		||||
	/* both -d N and -l N set the same variable: LogLevel */
 | 
			
		||||
 | 
			
		||||
	if (!(opts & OPT_f)) {
 | 
			
		||||
		/* close stdin, stdout, stderr.
 | 
			
		||||
		 * close unused descriptors - don't need them. */
 | 
			
		||||
		bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(opts & OPT_d) && LogFile == NULL) {
 | 
			
		||||
		/* logging to syslog */
 | 
			
		||||
		openlog(applet_name, LOG_CONS | LOG_PID, LOG_CRON);
 | 
			
		||||
		logmode = LOGMODE_SYSLOG;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	xchdir(CDir);
 | 
			
		||||
	//signal(SIGHUP, SIG_IGN); /* ? original crond dies on HUP... */
 | 
			
		||||
	xsetenv("SHELL", DEFAULT_SHELL); /* once, for all future children */
 | 
			
		||||
	crondlog(LVL8 "crond (busybox "BB_VER") started, log level %d", LogLevel);
 | 
			
		||||
	SynchronizeDir();
 | 
			
		||||
	write_pidfile("/var/run/crond.pid");
 | 
			
		||||
 | 
			
		||||
	/* main loop - synchronize to 1 second after the minute, minimum sleep
 | 
			
		||||
	 * of 1 second. */
 | 
			
		||||
	t2 = time(NULL);
 | 
			
		||||
	rescan = 60;
 | 
			
		||||
	sleep_time = 60;
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		time_t t1;
 | 
			
		||||
		long dt;
 | 
			
		||||
 | 
			
		||||
		t1 = t2;
 | 
			
		||||
		sleep((sleep_time + 1) - (time(NULL) % sleep_time));
 | 
			
		||||
 | 
			
		||||
		t2 = time(NULL);
 | 
			
		||||
		dt = (long)t2 - (long)t1;
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * The file 'cron.update' is checked to determine new cron
 | 
			
		||||
		 * jobs.  The directory is rescanned once an hour to deal
 | 
			
		||||
		 * with any screwups.
 | 
			
		||||
		 *
 | 
			
		||||
		 * Check for time jump.  Disparities over an hour either way
 | 
			
		||||
		 * result in resynchronization.  A negative disparity
 | 
			
		||||
		 * less than an hour causes us to effectively sleep until we
 | 
			
		||||
		 * match the original time (i.e. no re-execution of jobs that
 | 
			
		||||
		 * have just been run).  A positive disparity less than
 | 
			
		||||
		 * an hour causes intermediate jobs to be run, but only once
 | 
			
		||||
		 * in the worst case.
 | 
			
		||||
		 *
 | 
			
		||||
		 * When running jobs, the inequality used is greater but not
 | 
			
		||||
		 * equal to t1, and less then or equal to t2.
 | 
			
		||||
		 */
 | 
			
		||||
		if (--rescan == 0) {
 | 
			
		||||
			rescan = 60;
 | 
			
		||||
			SynchronizeDir();
 | 
			
		||||
		}
 | 
			
		||||
		CheckUpdates();
 | 
			
		||||
		if (DebugOpt)
 | 
			
		||||
			crondlog(LVL5 "wakeup dt=%ld", dt);
 | 
			
		||||
		if (dt < -60 * 60 || dt > 60 * 60) {
 | 
			
		||||
			crondlog(WARN9 "time disparity of %ld minutes detected", dt / 60);
 | 
			
		||||
			/* and we do not run any jobs in this case */
 | 
			
		||||
		} else if (dt > 0) {
 | 
			
		||||
			/* Usual case: time advances forwad, as expected */
 | 
			
		||||
			TestJobs(t1, t2);
 | 
			
		||||
			RunJobs();
 | 
			
		||||
			sleep(5);
 | 
			
		||||
			if (CheckJobs() > 0) {
 | 
			
		||||
				sleep_time = 10;
 | 
			
		||||
			} else {
 | 
			
		||||
				sleep_time = 60;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/* else: time jumped back, do not run any jobs */
 | 
			
		||||
	} /* for (;;) */
 | 
			
		||||
 | 
			
		||||
	return 0; /* not reached */
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user