-/* $OpenBSD: atrun.c,v 1.43 2016/01/11 14:23:50 millert Exp $ */
+/* $OpenBSD: atrun.c,v 1.44 2017/06/07 17:59:36 millert Exp $ */
/*
* Copyright (c) 2002-2003 Todd C. Miller <Todd.Miller@courtesan.com>
#include "funcs.h"
#include "globals.h"
-static void run_job(atjob *, char *);
+static void run_job(const atjob *, int, const char *);
static int
strtot(const char *nptr, char **endptr, time_t *tp)
char atfile[PATH_MAX];
struct stat sb;
double la;
+ int dfd, len;
atjob *job, *tjob, *batch = NULL;
if (db == NULL)
return;
+ if ((dfd = open(_PATH_AT_SPOOL, O_RDONLY|O_DIRECTORY)) == -1) {
+ syslog(LOG_ERR, "(CRON) OPEN FAILED (%s)", _PATH_AT_SPOOL);
+ return;
+ }
+
TAILQ_FOREACH_SAFE(job, &db->jobs, entries, tjob) {
/* Skip jobs in the future */
if (job->run_time > now)
continue;
- snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL,
+ len = snprintf(atfile, sizeof(atfile), "%lld.%c",
(long long)job->run_time, job->queue);
+ if (len >= sizeof(atfile)) {
+ TAILQ_REMOVE(&db->jobs, job, entries);
+ free(job);
+ continue;
+ }
- if (lstat(atfile, &sb) != 0 || !S_ISREG(sb.st_mode)) {
+ if (fstatat(dfd, atfile, &sb, AT_SYMLINK_NOFOLLOW) != 0 ||
+ !S_ISREG(sb.st_mode)) {
TAILQ_REMOVE(&db->jobs, job, entries);
free(job);
continue; /* disapeared or not a file */
batch = job;
} else {
/* normal at job */
- run_job(job, atfile);
+ run_job(job, dfd, atfile);
TAILQ_REMOVE(&db->jobs, job, entries);
free(job);
}
&& (batch_maxload == 0.0 ||
((getloadavg(&la, 1) == 1) && la <= batch_maxload))
) {
- snprintf(atfile, sizeof(atfile), "%s/%lld.%c", _PATH_AT_SPOOL,
+ len = snprintf(atfile, sizeof(atfile), "%lld.%c",
(long long)batch->run_time, batch->queue);
- run_job(batch, atfile);
+ if (len < sizeof(atfile))
+ run_job(batch, dfd, atfile);
TAILQ_REMOVE(&db->jobs, batch, entries);
free(job);
}
+
+ close(dfd);
}
/*
* Run the specified job contained in atfile.
*/
static void
-run_job(atjob *job, char *atfile)
+run_job(const atjob *job, int dfd, const char *atfile)
{
struct stat sb;
struct passwd *pw;
char *nargv[2], *nenvp[1];
/* Open the file and unlink it so we don't try running it again. */
- if ((fd = open(atfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) {
+ if ((fd = openat(dfd, atfile, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) {
syslog(LOG_ERR, "(CRON) CAN'T OPEN (%s)", atfile);
return;
}
- unlink(atfile);
-
- /* We don't want the atjobs dir in the log messages. */
- if ((cp = strrchr(atfile, '/')) != NULL)
- atfile = cp + 1;
+ unlinkat(dfd, atfile, 0);
/* Fork so other pending jobs don't have to wait for us to finish. */
switch (fork()) {