Add support for -n
option in crontab entries
Resolves: RHEL-5372
This commit is contained in:
parent
5bfb0297b0
commit
eb373fda1e
@ -6,7 +6,7 @@
|
||||
Summary: Cron daemon for executing programs at set times
|
||||
Name: cronie
|
||||
Version: 1.5.7
|
||||
Release: 8%{?dist}
|
||||
Release: 9%{?dist}
|
||||
License: MIT and BSD and ISC and GPLv2+
|
||||
URL: https://github.com/cronie-crond/cronie
|
||||
Source0: https://github.com/cronie-crond/cronie/releases/download/cronie-%{version}/cronie-%{version}.tar.gz
|
||||
@ -17,6 +17,9 @@ Patch: 0002-Add-random-within-range-operator.patch
|
||||
Patch: 0003-get_number-Add-missing-NUL-termination-for-the-scann.patch
|
||||
Patch: 0004-Fix-regression-in-handling-x-crontab-entries.patch
|
||||
Patch: 0005-Fix-regression-in-handling-1-5-crontab-entries.patch
|
||||
# Add support for `-n` option in crontab entries
|
||||
# https://github.com/cronie-crond/cronie/commit/ce7d5bf0a43d147f8502e6424cd523b56adf5599
|
||||
Patch: n_option.patch
|
||||
|
||||
Requires: dailyjobs
|
||||
|
||||
@ -211,6 +214,10 @@ exit 0
|
||||
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/cron.d/dailyjobs
|
||||
|
||||
%changelog
|
||||
* Fri Nov 10 2023 Ondřej Pohořelský <opohorel@redhat.com> - 1.5.7-9
|
||||
- Add support for `-n` option in crontab entries
|
||||
- Resolves: RHEL-5372
|
||||
|
||||
* Mon Jul 11 2022 Jan Staněk <jstanek@redhat.com> - 1.5.7-8
|
||||
- Set 'missingok' for /etc/cron.deny to not recreate it on update
|
||||
|
||||
|
205
n_option.patch
Normal file
205
n_option.patch
Normal file
@ -0,0 +1,205 @@
|
||||
From ce7d5bf0a43d147f8502e6424cd523b56adf5599 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ond=C5=99ej=20Poho=C5=99elsk=C3=BD?= <opohorel@redhat.com>
|
||||
Date: Mon, 26 Sep 2022 16:51:41 +0200
|
||||
Subject: [PATCH] Add -n option for crontab entries
|
||||
|
||||
The -n option causes no mail to be sent
|
||||
when the command finishes successfully.
|
||||
|
||||
These kind of options are already supported in *BSD;
|
||||
in fact, this is a port of a patch from NetBSD [1].
|
||||
|
||||
This was requested in [2].
|
||||
|
||||
[1]: NetBSD/src@666eac5
|
||||
[2]: https://bugzilla.redhat.com/show_bug.cgi?id=1591763
|
||||
---
|
||||
src/do_command.c | 32 +++++++++++++++++++++++++++++---
|
||||
src/entry.c | 31 +++++++++++++++++++++++++++++++
|
||||
src/funcs.h | 1 +
|
||||
src/popen.c | 33 ++++++++++++++++++++++++++++++---
|
||||
src/structs.h | 1 +
|
||||
5 files changed, 92 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/do_command.c b/src/do_command.c
|
||||
index 87f996f..6a3886a 100644
|
||||
--- a/src/do_command.c
|
||||
+++ b/src/do_command.c
|
||||
@@ -94,6 +94,7 @@ static int child_process(entry * e, char **jobenv) {
|
||||
char mailfrom_expanded[MAX_EMAILSTR];
|
||||
int children = 0;
|
||||
pid_t pid = getpid();
|
||||
+ pid_t jobpid = -1;
|
||||
struct sigaction sa;
|
||||
|
||||
/* Ignore SIGPIPE as we will be writing to pipes and do not want to terminate
|
||||
@@ -199,7 +200,7 @@ static int child_process(entry * e, char **jobenv) {
|
||||
|
||||
/* fork again, this time so we can exec the user's command.
|
||||
*/
|
||||
- switch (fork()) {
|
||||
+ switch (jobpid = fork()) {
|
||||
case -1:
|
||||
log_it("CRON", pid, "CAN'T FORK", "child_process", errno);
|
||||
return ERROR_EXIT;
|
||||
@@ -552,10 +553,35 @@ static int child_process(entry * e, char **jobenv) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
- /* only close pipe if we opened it -- i.e., we're
|
||||
- * mailing...
|
||||
+ /* if -n option was specified, abort the sending
|
||||
+ * now when we read all of the command output
|
||||
+ * and thus can wait for it's exit status
|
||||
*/
|
||||
+ if (mail && e->flags & MAIL_WHEN_ERR) {
|
||||
+ int jobstatus = -1;
|
||||
+ if (jobpid > 0) {
|
||||
+ while (waitpid(jobpid, &jobstatus, WNOHANG) == -1) {
|
||||
+ if (errno == EINTR) continue;
|
||||
+ log_it("CRON", getpid(), "error", "invalid job pid", errno);
|
||||
+ break;
|
||||
+ }
|
||||
+ } else {
|
||||
+ log_it("CRON", getpid(), "error", "invalid job pid", 0);
|
||||
+ }
|
||||
|
||||
+ /* if everything went well, -n is set, and we have mail,
|
||||
+ * we won't be mailing – so shoot the messenger!
|
||||
+ */
|
||||
+ if (WIFEXITED(jobstatus) && WEXITSTATUS(jobstatus) == EXIT_SUCCESS) {
|
||||
+ Debug(DPROC, ("[%ld] aborting pipe to mail\n", (long)getpid()));
|
||||
+ status = cron_pabort(mail);
|
||||
+ mail = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* only close pipe if we opened it -- i.e., we're (still)
|
||||
+ * mailing...
|
||||
+ */
|
||||
if (mail) {
|
||||
Debug(DPROC, ("[%ld] closing pipe to mail\n", (long) getpid()));
|
||||
/* Note: the pclose will probably see
|
||||
diff --git a/src/entry.c b/src/entry.c
|
||||
index bb7cb62..9e199fe 100644
|
||||
--- a/src/entry.c
|
||||
+++ b/src/entry.c
|
||||
@@ -417,6 +417,37 @@ entry *load_entry(FILE * file, void (*error_func) (), struct passwd *pw,
|
||||
|
||||
Debug(DPARS, ("load_entry()...about to parse command\n"));
|
||||
|
||||
+ /* If the first character of the command is '-', it is a cron option. */
|
||||
+ ch = get_char(file);
|
||||
+ while (ch == '-') {
|
||||
+ switch (ch = get_char(file)) {
|
||||
+ case 'n':
|
||||
+ /* only allow user to set the option once */
|
||||
+ if ((e->flags & MAIL_WHEN_ERR) == MAIL_WHEN_ERR) {
|
||||
+ ecode = e_option;
|
||||
+ goto eof;
|
||||
+ }
|
||||
+ e->flags |= MAIL_WHEN_ERR;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ ecode = e_option;
|
||||
+ goto eof;
|
||||
+ }
|
||||
+
|
||||
+ ch = get_char(file);
|
||||
+ if (ch != '\t' && ch != ' ') {
|
||||
+ ecode = e_option;
|
||||
+ goto eof;
|
||||
+ }
|
||||
+ Skip_Blanks(ch, file);
|
||||
+ if (ch == EOF || ch == '\n') {
|
||||
+ ecode = e_cmd;
|
||||
+ goto eof;
|
||||
+ }
|
||||
+ }
|
||||
+ unget_char(ch, file);
|
||||
+
|
||||
/* Everything up to the next \n or EOF is part of the command...
|
||||
* too bad we don't know in advance how long it will be, since we
|
||||
* need to malloc a string for it... so, we limit it to MAX_COMMAND.
|
||||
diff --git a/src/funcs.h b/src/funcs.h
|
||||
index dea737e..427e027 100644
|
||||
--- a/src/funcs.h
|
||||
+++ b/src/funcs.h
|
||||
@@ -67,6 +67,7 @@ int load_database(cron_db *),
|
||||
swap_uids_back(void),
|
||||
load_env(char *, FILE *),
|
||||
env_set_from_environ(char ***envpp),
|
||||
+ cron_pabort(FILE *),
|
||||
cron_pclose(FILE *),
|
||||
glue_strings(char *, size_t, const char *, const char *, char),
|
||||
strcmp_until(const char *, const char *, char),
|
||||
diff --git a/src/popen.c b/src/popen.c
|
||||
index 4397264..3043eb6 100644
|
||||
--- a/src/popen.c
|
||||
+++ b/src/popen.c
|
||||
@@ -167,7 +167,7 @@ FILE *cron_popen(char *program, const char *type, struct passwd *pw, char **jobe
|
||||
return (iop);
|
||||
}
|
||||
|
||||
-int cron_pclose(FILE * iop) {
|
||||
+static int cron_finalize(FILE * iop, int sig) {
|
||||
int fdes;
|
||||
sigset_t oset, nset;
|
||||
WAIT_T stat_loc;
|
||||
@@ -180,7 +180,12 @@ int cron_pclose(FILE * iop) {
|
||||
fdes = fileno(iop);
|
||||
if (pids == NULL || fdes >= fds || pids[fdes] == 0L)
|
||||
return (-1);
|
||||
- (void) fclose(iop);
|
||||
+
|
||||
+ if (!sig) {
|
||||
+ (void) fclose(iop);
|
||||
+ } else if (kill(pids[fdes], sig) == -1) {
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
sigemptyset(&nset);
|
||||
sigaddset(&nset, SIGINT);
|
||||
@@ -189,6 +194,28 @@ int cron_pclose(FILE * iop) {
|
||||
(void) sigprocmask(SIG_BLOCK, &nset, &oset);
|
||||
while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1) ;
|
||||
(void) sigprocmask(SIG_SETMASK, &oset, NULL);
|
||||
+
|
||||
+ if (sig) {
|
||||
+ (void) fclose(iop);
|
||||
+ }
|
||||
pids[fdes] = 0;
|
||||
- return (pid == -1 ? -1 : WEXITSTATUS(stat_loc));
|
||||
+
|
||||
+ if (pid < 0) {
|
||||
+ return pid;
|
||||
+ }
|
||||
+
|
||||
+ if (WIFEXITED(stat_loc)) {
|
||||
+ return WEXITSTATUS(stat_loc);
|
||||
+ } else {
|
||||
+ return WTERMSIG(stat_loc);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int cron_pclose(FILE * iop) {
|
||||
+ return cron_finalize(iop, 0);
|
||||
+}
|
||||
+
|
||||
+int cron_pabort(FILE * iop) {
|
||||
+ int esig = cron_finalize(iop, SIGKILL);
|
||||
+ return esig == SIGKILL ? 0 : esig;
|
||||
}
|
||||
diff --git a/src/structs.h b/src/structs.h
|
||||
index 6d3c15b..d930da5 100644
|
||||
--- a/src/structs.h
|
||||
+++ b/src/structs.h
|
||||
@@ -48,6 +48,7 @@ typedef struct _entry {
|
||||
#define DOW_STAR 0x08
|
||||
#define WHEN_REBOOT 0x10
|
||||
#define DONT_LOG 0x20
|
||||
+#define MAIL_WHEN_ERR 0x40
|
||||
} entry;
|
||||
|
||||
/* the crontab database will be a list of the
|
Loading…
Reference in New Issue
Block a user