summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/cron/cron.c3
-rw-r--r--usr.sbin/cron/crontab.511
-rw-r--r--usr.sbin/cron/do_command.c12
-rw-r--r--usr.sbin/cron/entry.c10
-rw-r--r--usr.sbin/cron/funcs.h7
-rw-r--r--usr.sbin/cron/job.c65
-rw-r--r--usr.sbin/cron/structs.h3
-rw-r--r--usr.sbin/cron/user.c3
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);