diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/cron/cron.c | 3 | ||||
-rw-r--r-- | usr.sbin/cron/crontab.5 | 11 | ||||
-rw-r--r-- | usr.sbin/cron/do_command.c | 12 | ||||
-rw-r--r-- | usr.sbin/cron/entry.c | 10 | ||||
-rw-r--r-- | usr.sbin/cron/funcs.h | 7 | ||||
-rw-r--r-- | usr.sbin/cron/job.c | 65 | ||||
-rw-r--r-- | usr.sbin/cron/structs.h | 3 | ||||
-rw-r--r-- | usr.sbin/cron/user.c | 3 |
8 files changed, 98 insertions, 16 deletions
diff --git a/usr.sbin/cron/cron.c b/usr.sbin/cron/cron.c index 69952932812..6fe8916141d 100644 --- a/usr.sbin/cron/cron.c +++ b/usr.sbin/cron/cron.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cron.c,v 1.78 2020/02/11 12:42:01 schwarze Exp $ */ +/* $OpenBSD: cron.c,v 1.79 2020/04/16 17:51:56 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -497,6 +497,7 @@ sigchld_reaper(void) case 0: break; default: + job_exit(pid); break; } } while (pid > 0); diff --git a/usr.sbin/cron/crontab.5 b/usr.sbin/cron/crontab.5 index ef9ac0a6672..756d0656872 100644 --- a/usr.sbin/cron/crontab.5 +++ b/usr.sbin/cron/crontab.5 @@ -17,9 +17,9 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT .\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.\" $OpenBSD: crontab.5,v 1.38 2020/04/15 01:59:34 millert Exp $ +.\" $OpenBSD: crontab.5,v 1.39 2020/04/16 17:51:56 millert Exp $ .\" -.Dd $Mdocdate: April 15 2020 $ +.Dd $Mdocdate: April 16 2020 $ .Dt CRONTAB 5 .Os .Sh NAME @@ -217,6 +217,13 @@ option is an attempt to cure potentially copious volumes of mail coming from .Xr cron 8 . .It Fl q Ar command Execution will not be logged. +.It Fl s Ar command +Only a single instance of +.Ar command +will be run concurrently. +Additional instances of +.Ar command +will not be scheduled until the earlier one completes. .El .Pp Commands are executed by diff --git a/usr.sbin/cron/do_command.c b/usr.sbin/cron/do_command.c index c0e6c5dcc90..6ec98dd0c7d 100644 --- a/usr.sbin/cron/do_command.c +++ b/usr.sbin/cron/do_command.c @@ -1,4 +1,4 @@ -/* $OpenBSD: do_command.c,v 1.60 2019/06/28 13:32:47 deraadt Exp $ */ +/* $OpenBSD: do_command.c,v 1.61 2020/04/16 17:51:56 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -47,9 +47,10 @@ static void child_process(entry *, user *); -void +pid_t do_command(entry *e, user *u) { + pid_t pid; /* fork to become asynchronous -- parent process is done immediately, * and continues to run the normal cron code, which means return to @@ -58,7 +59,7 @@ do_command(entry *e, user *u) * vfork() is unsuitable, since we have much to do, and the parent * needs to be able to run off and fork other processes. */ - switch (fork()) { + switch ((pid = fork())) { case -1: syslog(LOG_ERR, "(CRON) CAN'T FORK (%m)"); break; @@ -69,8 +70,13 @@ do_command(entry *e, user *u) break; default: /* parent process */ + if ((e->flags & SINGLE_JOB) == 0) + pid = -1; break; } + + /* only return pid if a singleton */ + return (pid); } static void diff --git a/usr.sbin/cron/entry.c b/usr.sbin/cron/entry.c index e3f919a86e3..caeb5ba620e 100644 --- a/usr.sbin/cron/entry.c +++ b/usr.sbin/cron/entry.c @@ -1,4 +1,4 @@ -/* $OpenBSD: entry.c,v 1.50 2020/04/15 01:59:34 millert Exp $ */ +/* $OpenBSD: entry.c,v 1.51 2020/04/16 17:51:56 millert Exp $ */ /* * Copyright 1988,1990,1993,1994 by Paul Vixie @@ -354,6 +354,14 @@ load_entry(FILE *file, void (*error_func)(const char *), struct passwd *pw, } e->flags |= DONT_LOG; break; + case 's': + /* only allow the user to set the option once */ + if ((e->flags & SINGLE_JOB) == SINGLE_JOB) { + ecode = e_option; + goto eof; + } + e->flags |= SINGLE_JOB; + break; default: ecode = e_option; goto eof; diff --git a/usr.sbin/cron/funcs.h b/usr.sbin/cron/funcs.h index ee42477007d..4696852b1cf 100644 --- a/usr.sbin/cron/funcs.h +++ b/usr.sbin/cron/funcs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: funcs.h,v 1.29 2018/02/05 03:52:37 millert Exp $ */ +/* $OpenBSD: funcs.h,v 1.30 2020/04/16 17:51:56 millert Exp $ */ /* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -24,7 +24,8 @@ void load_database(cron_db **), job_add(entry *, user *), - do_command(entry *, user *), + job_remove(entry *, user *), + job_exit(pid_t), free_user(user *), env_free(char **), unget_char(int, FILE *), @@ -33,6 +34,8 @@ void load_database(cron_db **), poke_daemon(unsigned char), atrun(at_db *, double, time_t); +pid_t do_command(entry *, user *); + int job_runqueue(void), get_char(FILE *), get_string(char *, int, FILE *, char *), diff --git a/usr.sbin/cron/job.c b/usr.sbin/cron/job.c index b67b74d5ce1..fde35e7a5ca 100644 --- a/usr.sbin/cron/job.c +++ b/usr.sbin/cron/job.c @@ -1,4 +1,4 @@ -/* $OpenBSD: job.c,v 1.13 2015/11/09 01:12:27 millert Exp $ */ +/* $OpenBSD: job.c,v 1.14 2020/04/16 17:51:56 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -22,6 +22,7 @@ #include <bitstring.h> /* for structs.h */ #include <stdio.h> #include <stdlib.h> +#include <syslog.h> #include <time.h> /* for structs.h */ #include "macros.h" @@ -32,6 +33,7 @@ typedef struct _job { SIMPLEQ_ENTRY(_job) entries; entry *e; user *u; + pid_t pid; } job; @@ -43,31 +45,84 @@ job_add(entry *e, user *u) job *j; /* if already on queue, keep going */ - SIMPLEQ_FOREACH(j, &jobs, entries) + SIMPLEQ_FOREACH(j, &jobs, entries) { if (j->e == e && j->u == u) return; + } /* build a job queue element */ if ((j = malloc(sizeof(job))) == NULL) return; j->e = e; j->u = u; + j->pid = -1; /* add it to the tail */ SIMPLEQ_INSERT_TAIL(&jobs, j, entries); } +void +job_remove(entry *e, user *u) +{ + job *j, *prev = NULL; + + SIMPLEQ_FOREACH(j, &jobs, entries) { + if (j->e == e && j->u == u) { + if (prev == NULL) + SIMPLEQ_REMOVE_HEAD(&jobs, entries); + else + SIMPLEQ_REMOVE_AFTER(&jobs, prev, entries); + free(j); + break; + } + prev = j; + } +} + +void +job_exit(pid_t jobpid) +{ + job *j, *prev = NULL; + + /* If a singleton exited, remove and free it. */ + SIMPLEQ_FOREACH(j, &jobs, entries) { + if (jobpid == j->pid) { + if (prev == NULL) + SIMPLEQ_REMOVE_HEAD(&jobs, entries); + else + SIMPLEQ_REMOVE_AFTER(&jobs, prev, entries); + free(j); + break; + } + prev = j; + } +} + int job_runqueue(void) { + struct job_queue singletons = SIMPLEQ_HEAD_INITIALIZER(singletons); job *j; int run = 0; while ((j = SIMPLEQ_FIRST(&jobs))) { SIMPLEQ_REMOVE_HEAD(&jobs, entries); - do_command(j->e, j->u); - free(j); - run++; + + /* Only start the job if it is not a running singleton. */ + if (j->pid == -1) { + j->pid = do_command(j->e, j->u); + run++; + } else if ((j->e->flags & DONT_LOG) == 0) { + syslog(LOG_INFO, "(%s) SKIPPING (%s)", + j->u->name, j->e->cmd); + } + + /* Singleton jobs persist in the queue until they exit. */ + if (j->pid != -1) + SIMPLEQ_INSERT_TAIL(&singletons, j, entries); + else + free(j); } + SIMPLEQ_CONCAT(&jobs, &singletons); return (run); } diff --git a/usr.sbin/cron/structs.h b/usr.sbin/cron/structs.h index c380b14f90d..159f8ce1e68 100644 --- a/usr.sbin/cron/structs.h +++ b/usr.sbin/cron/structs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: structs.h,v 1.9 2018/06/13 11:27:30 job Exp $ */ +/* $OpenBSD: structs.h,v 1.10 2020/04/16 17:51:56 millert Exp $ */ /* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -39,6 +39,7 @@ typedef struct _entry { #define WHEN_REBOOT 0x10 #define DONT_LOG 0x20 #define MAIL_WHEN_ERR 0x40 +#define SINGLE_JOB 0x80 } entry; /* the crontab database will be a list of the diff --git a/usr.sbin/cron/user.c b/usr.sbin/cron/user.c index 0c0d25642da..ee2a32694c9 100644 --- a/usr.sbin/cron/user.c +++ b/usr.sbin/cron/user.c @@ -1,4 +1,4 @@ -/* $OpenBSD: user.c,v 1.21 2018/02/05 03:52:37 millert Exp $ */ +/* $OpenBSD: user.c,v 1.22 2020/04/16 17:51:56 millert Exp $ */ /* Copyright 1988,1990,1993,1994 by Paul Vixie * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") @@ -41,6 +41,7 @@ free_user(user *u) while ((e = SLIST_FIRST(&u->crontab))) { SLIST_REMOVE_HEAD(&u->crontab, entries); + job_remove(e, u); free_entry(e); } free(u->name); |