Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: main.c
===================================================================
--- main.c	(nonexistent)
+++ main.c	(revision 5)
@@ -0,0 +1,365 @@
+
+/*
+ * MAIN.C
+ *
+ * crond [-s dir] [-c dir] [-t dir] [-m user@host] [-M mailer] [-S|-L [file]] [-l level] [-b|-f|-d]
+ * run as root, but NOT setuid root
+ *
+ * Copyright 1994 Matthew Dillon (dillon@apollo.backplane.com)
+ * Copyright 2009-2011 James Pryor <profjim@jimpryor.net>
+ * May be distributed under the GNU General Public License
+ */
+
+#include "defs.h"
+
+Prototype short DebugOpt;
+Prototype short LogLevel;
+Prototype short ForegroundOpt;
+Prototype short SyslogOpt;
+Prototype const char *CDir;
+Prototype const char *SCDir;
+Prototype const char *TSDir;
+Prototype const char *LogFile;
+Prototype const char *LogHeader;
+Prototype uid_t DaemonUid;
+Prototype pid_t DaemonPid;
+Prototype const char *SendMail;
+Prototype const char *Mailto;
+Prototype char *TempDir;
+Prototype char *TempFileFmt;
+
+short DebugOpt = 0;
+short LogLevel = LOG_LEVEL;
+short ForegroundOpt = 0;
+short SyslogOpt = 1;
+const char  *CDir = CRONTABS;
+const char  *SCDir = SCRONTABS;
+const char *TSDir = CRONSTAMPS;
+const char *LogFile = NULL; 	/* opened with mode 0600 */
+const char *LogHeader = LOGHEADER;
+const char *SendMail = NULL;
+const char *Mailto = NULL;
+char *TempDir;
+char *TempFileFmt;
+
+uid_t DaemonUid;
+pid_t DaemonPid;
+
+int
+main(int ac, char **av)
+{
+	const char *LevelAry[] = {
+		"emerg",
+		"alert",
+		"crit",
+		"err",
+		"warning",
+		"notice",
+		"info",
+		"debug",
+		"panic",
+		"error",
+		"warn",
+		NULL
+	};
+	int i;
+
+	/*
+	 * parse options
+	 */
+
+	DaemonUid = getuid();
+
+	opterr = 0;
+
+	while ((i = getopt(ac,av,"dl:L:fbSc:s:m:M:t:")) != -1) {
+		switch (i) {
+			case 'l':
+				{
+					char *ptr;
+					int j;
+					ptr = optarg;
+					for (j = 0; LevelAry[j]; ++j) {
+						if (strncmp(ptr, LevelAry[j], strlen(LevelAry[j])) == 0) {
+							break;
+						}
+					}
+					switch(j) {
+						case 0:
+						case 8:
+							/* #define	LOG_EMERG	0	[* system is unusable *] */
+							LogLevel = LOG_EMERG;
+							break;
+						case 1:
+							/* #define	LOG_ALERT	1	[* action must be taken immediately *] */
+							LogLevel = LOG_ALERT;
+							break;
+						case 2:
+							/* #define	LOG_CRIT	2	[* critical conditions *] */
+							LogLevel = LOG_CRIT;
+							break;
+						case 3:
+						case 9:
+							/* #define	LOG_ERR		3	[* error conditions *] */
+							LogLevel = LOG_ERR;
+							break;
+						case 4:
+						case 10:
+							/* #define	LOG_WARNING	4	[* warning conditions *] */
+							LogLevel = LOG_WARNING;
+							break;
+						case 5:
+							/* #define	LOG_NOTICE	5	[* normal but significant condition *] */
+							LogLevel = LOG_NOTICE;
+							break;
+						case 6:
+							/* #define	LOG_INFO	6	[* informational *] */
+							LogLevel = LOG_INFO;
+							break;
+						case 7:
+							/* #define	LOG_DEBUG	7	[* debug-level messages *] */
+							LogLevel = LOG_DEBUG;
+							break;
+						default:
+							LogLevel = atoi(optarg);
+					}
+				}
+				break;
+			case 'd':
+				DebugOpt = 1;
+				LogLevel = LOG_DEBUG;
+				/* fall through to include f too */
+			case 'f':
+				ForegroundOpt = 1;
+				break;
+			case 'b':
+				ForegroundOpt = 0;
+				break;
+			case 'S':			/* log through syslog */
+				SyslogOpt = 1;
+				break;
+			case 'L':			/* use internal log formatter */
+				SyslogOpt = 0;
+				LogFile = optarg;
+				/* if LC_TIME is defined, we use it for logging to file instead of compiled-in TIMESTAMP_FMT */
+				if (getenv("LC_TIME") != NULL) {
+					LogHeader = LOCALE_LOGHEADER;
+				}
+				break;
+			case 'c':
+				if (*optarg != 0) CDir = optarg;
+				break;
+			case 's':
+				if (*optarg != 0) SCDir = optarg;
+				break;
+			case 't':
+				if (*optarg != 0) TSDir = optarg;
+				break;
+			case 'M':
+				if (*optarg != 0) SendMail = optarg;
+				break;
+			case 'm':
+				if (*optarg != 0) Mailto = optarg;
+				break;
+			default:
+				/*
+				 * check for parse error
+				 */
+				printf("dillon's cron daemon " VERSION "\n");
+				printf("crond [-s dir] [-c dir] [-t dir] [-m user@host] [-M mailer] [-S|-L [file]] [-l level] [-b|-f|-d]\n");
+				printf("-s            directory of system crontabs (defaults to %s)\n", SCRONTABS);
+				printf("-c            directory of per-user crontabs (defaults to %s)\n", CRONTABS);
+				printf("-t            directory of timestamps (defaults to %s)\n", CRONSTAMPS);
+				printf("-m user@host  where should cron output be directed? (defaults to local user)\n");
+				printf("-M mailer     (defaults to %s)\n", SENDMAIL);
+				printf("-S            log to syslog using identity '%s' (default)\n", LOG_IDENT);
+				printf("-L file       log to specified file instead of syslog\n");
+				printf("-l loglevel   log events <= this level (defaults to %s (level %d))\n", LevelAry[LOG_LEVEL], LOG_LEVEL);
+				printf("-b            run in background (default)\n");
+				printf("-f            run in foreground\n");
+				printf("-d            run in debugging mode\n");
+				exit(2);
+		}
+	}
+
+	/*
+	 * close stdin and stdout.
+	 * close unused descriptors -  don't need.
+	 * optional detach from controlling terminal
+	 */
+
+	fclose(stdin);
+	fclose(stdout);
+
+	i = open("/dev/null", O_RDWR);
+	if (i < 0) {
+		perror("open: /dev/null");
+		exit(1);
+	}
+	dup2(i, 0);
+	dup2(i, 1);
+
+	/* create tempdir with permissions 0755 for cron output */
+	TempDir = strdup(TMPDIR "/cron.XXXXXX");
+	if (mkdtemp(TempDir) == NULL) {
+		perror("mkdtemp");
+		exit(1);
+	}
+	if (chmod(TempDir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) {
+		perror("chmod");
+		exit(1);
+	}
+	if (!(TempFileFmt = concat(TempDir, "/cron.%s.%d", NULL))) {
+		errno = ENOMEM;
+		perror("main");
+		exit(1);
+	}
+
+	if (ForegroundOpt == 0) {
+
+		int fd;
+		int pid;
+
+		if ((pid = fork()) < 0) {
+			/* fork failed */
+			perror("fork");
+			exit(1);
+		} else if (pid > 0) {
+			/* parent */
+			exit(0);
+		}
+		/* child continues */
+
+		/* become session leader, detach from terminal */
+
+		if (setsid() < 0)
+			perror("setsid");
+		if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
+			ioctl(fd, TIOCNOTTY, 0);
+			close(fd);
+		}
+
+		/* setup logging for backgrounded daemons */
+
+		if (SyslogOpt) {
+			/* start SIGHUP and SIGCHLD handling while stderr still open */
+			initsignals();
+			/* 2> /dev/null */
+			fclose(stderr);
+			dup2(1, 2);
+
+			/* open syslog */
+			openlog(LOG_IDENT, LOG_CONS|LOG_PID, LOG_CRON);
+
+		} else {
+			/* open logfile */
+			if ((fd = open(LogFile, O_WRONLY|O_CREAT|O_APPEND, 0600)) >= 0) {
+				/* start SIGHUP ignoring, SIGCHLD handling while stderr still open */
+				initsignals();
+				/* 2> LogFile */
+				fclose(stderr);
+				dup2(fd, 2);
+			} else {
+				int n = errno;
+				fdprintf(2, "failed to open logfile '%s', reason: %s", LogFile, strerror(n));
+				exit(n);
+			}
+		}
+	} else {
+		/* daemon in foreground */
+
+		/* stay in existing session, but start a new process group */
+		if (setpgid(0,0)) {
+			perror("setpgid");
+			exit(1);
+		}
+
+		/* stderr stays open, start SIGHUP ignoring, SIGCHLD handling */
+		initsignals();
+	}
+
+	/* close all other fds, including the ones we opened as /dev/null and LogFile */
+	for (i = 3; i < MAXOPEN; ++i) {
+        close(i);
+    }
+
+
+	/*
+	 * main loop - synchronize to 1 second after the minute, minimum sleep
+	 *             of 1 second.
+	 */
+
+	printlogf(LOG_NOTICE,"%s " VERSION " dillon's cron daemon, started with loglevel %s\n", av[0], LevelAry[LogLevel]);
+	SynchronizeDir(CDir, NULL, 1);
+	SynchronizeDir(SCDir, "root", 1);
+	ReadTimestamps(NULL);
+	TestStartupJobs(); /* @startup jobs only run when crond is started, not when their crontab is loaded */
+
+	{
+		time_t t1 = time(NULL);
+		time_t t2;
+		long dt;
+		short rescan = 60;
+		short stime = 60;
+
+		for (;;) {
+			sleep((stime + 1) - (short)(time(NULL) % stime));
+
+			t2 = time(NULL);
+			dt = t2 - 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 disparity.  Disparities over an hour either way
+			 * result in resynchronization.  A reverse-indexed disparity
+			 * less then 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 forward-indexed disparity less then
+			 * 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) {
+				/*
+				 * If we resynchronize while jobs are running, we'll clobber
+				 * the job pids, so we won't know what's already running.
+				 */
+				if (CheckJobs() > 0) {
+					rescan = 1;
+				} else {
+					rescan = 60;
+					SynchronizeDir(CDir, NULL, 0);
+					SynchronizeDir(SCDir, "root", 0);
+					ReadTimestamps(NULL);
+				}
+			}
+			if (rescan < 60) {
+				CheckUpdates(CDir, NULL, t1, t2);
+				CheckUpdates(SCDir, "root", t1, t2);
+			}
+			if (DebugOpt)
+				printlogf(LOG_DEBUG, "Wakeup dt=%d\n", dt);
+			if (dt < -60*60 || dt > 60*60) {
+				t1 = t2;
+				printlogf(LOG_NOTICE,"time disparity of %d minutes detected\n", dt / 60);
+			} else if (dt > 0) {
+				TestJobs(t1, t2);
+				RunJobs();
+				sleep(5);
+				if (CheckJobs() > 0)
+					stime = 10;
+				else
+					stime = 60;
+				t1 = t2;
+			}
+		}
+	}
+	/* not reached */
+}
+