5 * crond [-l#] [-L logfile | -S ] [-M mailer] [-m mailto] [-d|-f|-b] [-c crondir] [-s systemdir] [-t timestamps]
7 * run as root, but NOT setuid root
9 * Copyright 1994 Matthew Dillon (dillon@apollo.backplane.com)
10 * Copyright 2009 James Pryor <profjim@jimpryor.net>
11 * May be distributed under the GNU General Public License
16 Prototype
short DebugOpt
;
17 Prototype
short LogLevel
;
18 Prototype
short ForegroundOpt
;
19 Prototype
short LoggerOpt
;
20 Prototype
const char *CDir
;
21 Prototype
const char *SCDir
;
22 Prototype
const char *TSDir
;
23 Prototype
const char *LogFile
;
24 Prototype uid_t DaemonUid
;
25 Prototype
int InSyncFileRoot
;
26 Prototype
const char *SendMail
;
27 Prototype
const char *Mailto
;
28 Prototype
char *TempDir
;
29 Prototype
char *TempFileFmt
;
32 short LogLevel
= LOG_NOTICE
;
33 short ForegroundOpt
= 0;
35 const char *CDir
= CRONTABS
;
36 const char *SCDir
= SCRONTABS
;
37 const char *TSDir
= TIMESTAMPS
;
38 const char *LogFile
= LOG_FILE
; /* opened with mode 0600 */
39 const char *SendMail
= NULL
;
40 const char *Mailto
= NULL
;
48 main(int ac
, char **av
)
50 const char *LevelAry
[] = {
74 while ((i
= getopt(ac
,av
,"dl:L:fbSc:s:m:M:t:")) != EOF
) {
81 for (j
= 0; LevelAry
[j
]; ++j
) {
82 if (strncmp(ptr
, LevelAry
[j
], strlen(LevelAry
[j
])) == 0) {
89 /* #define LOG_EMERG 0 [* system is unusable *] */
93 /* #define LOG_ALERT 1 [* action must be taken immediately *] */
97 /* #define LOG_CRIT 2 [* critical conditions *] */
102 /* #define LOG_ERR 3 [* error conditions *] */
107 /* #define LOG_WARNING 4 [* warning conditions *] */
108 LogLevel
= LOG_WARNING
;
111 /* #define LOG_NOTICE 5 [* normal but significant condition *] */
112 LogLevel
= LOG_NOTICE
;
115 /* #define LOG_INFO 6 [* informational *] */
119 /* #define LOG_DEBUG 7 [* debug-level messages *] */
120 LogLevel
= LOG_DEBUG
;
123 LogLevel
= atoi(optarg
);
129 LogLevel
= LOG_DEBUG
;
130 /* fall through to include f too */
137 case 'S': /* log through syslog */
140 case 'L': /* use internal log formatter */
147 if (*optarg
!= 0) CDir
= optarg
;
150 if (*optarg
!= 0) SCDir
= optarg
;
153 if (*optarg
!= 0) TSDir
= optarg
;
156 if (*optarg
!= 0) SendMail
= optarg
;
159 if (*optarg
!= 0) Mailto
= optarg
;
163 * check for parse error
165 printf("dcron " VERSION
"\n");
166 printf("crond [-l#] [-L logfile | -S ] [-M mailer] [-m mailto] [-d|-f|-b] [-c crondir] [-s systemdir] [-t timestamps]\n");
167 printf("-l num\tlogging level (default <= LOG_NOTICE = 5)\n");
168 printf("-L file\tlog to file (default %s)\n-S\tlog to syslogd (default)\n", LOG_FILE
);
169 printf("-M mailer\tprogram to mail output (default %s)\n-m mailto\taddress to mail cron output to (default to user)\n", SENDMAIL
);
170 printf("-d\tdebugging\n-f\trun in foreground\n-b\trun in background (default)\n");
171 printf("-c crondir\tcrontab spool dir (default %s)\n-s systemdir\tsystem cron.d dir (default %s)\n-t timestamps\ttimestamp dir (default %s)\n",
172 CRONTABS
, SCRONTABS
, TIMESTAMPS
);
178 * close stdin and stdout.
179 * close unused descriptors - don't need.
180 * optional detach from controlling terminal
186 for (i
= 3; i
< OPEN_MAX
; ++i
) {
190 i
= open("/dev/null", O_RDWR
);
192 perror("open: /dev/null");
198 if (ForegroundOpt
== 0) {
208 if ((fd
= open("/dev/tty", O_RDWR
)) >= 0) {
209 ioctl(fd
, TIOCNOTTY
, 0);
223 (void)startlogger(); /* need if syslog mode selected */
224 (void)initsignals(); /* set some signal handlers */
226 /* create tempdir with permissions 755 for cron output */
227 TempDir
= strdup(TMPDIR
"/cron.XXXXXX");
228 if (mkdtemp(TempDir
) == NULL
) {
232 if (chmod(TempDir
, S_IRWXU
|S_IRGRP
|S_IXGRP
|S_IROTH
|S_IXOTH
)) {
236 asprintf(&TempFileFmt
, "%s/cron.%%s.%%d", TempDir
);
239 * main loop - synchronize to 1 second after the minute, minimum sleep
243 logn(LOG_INFO
,"%s " VERSION
" yacron, started with loglevel %s\n", av
[0], LevelAry
[LogLevel
]);
244 SynchronizeDir(CDir
, NULL
, 1);
245 SynchronizeDir(SCDir
, "root", 1);
246 ReadTimestamps(NULL
);
247 TestStartupJobs(); /* @startup jobs only run when crond is started, not when their crontab is loaded */
250 time_t t1
= time(NULL
);
257 sleep((stime
+ 1) - (short)(time(NULL
) % stime
));
263 * The file 'cron.update' is checked to determine new cron
264 * jobs. The directory is rescanned once an hour to deal
267 * check for disparity. Disparities over an hour either way
268 * result in resynchronization. A reverse-indexed disparity
269 * less then an hour causes us to effectively sleep until we
270 * match the original time (i.e. no re-execution of jobs that
271 * have just been run). A forward-indexed disparity less then
272 * an hour causes intermediate jobs to be run, but only once
275 * when running jobs, the inequality used is greater but not
276 * equal to t1, and less then or equal to t2.
281 SynchronizeDir(CDir
, NULL
, 0);
282 SynchronizeDir(SCDir
, "root", 0);
283 ReadTimestamps(NULL
);
285 CheckUpdates(CDir
, NULL
, t1
, t2
);
286 CheckUpdates(SCDir
, "root", t1
, t2
);
289 logn(LOG_DEBUG
, "Wakeup dt=%d\n", dt
);
290 if (dt
< -60*60 || dt
> 60*60) {
292 logn(LOG_NOTICE
,"time disparity of %d minutes detected\n", dt
/ 60);