summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorjob <job@cvs.openbsd.org>2018-06-13 11:27:31 +0000
committerjob <job@cvs.openbsd.org>2018-06-13 11:27:31 +0000
commitffebb6c34c09a29f5b265d36ca12f1d79278c089 (patch)
treeefc7fb01609ac59ecd75e1b03e22bc64eec44824 /usr.sbin
parent442a17b8b75aa93a5dbb58b2d44f69df11dbfc3c (diff)
Add crontab entry option -n for "No mail when run successful"
OK jmc@ millert@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/cron/crontab.529
-rw-r--r--usr.sbin/cron/do_command.c101
-rw-r--r--usr.sbin/cron/entry.c22
-rw-r--r--usr.sbin/cron/structs.h3
4 files changed, 95 insertions, 60 deletions
diff --git a/usr.sbin/cron/crontab.5 b/usr.sbin/cron/crontab.5
index 9c2e651980a..cdda7bb40dd 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.34 2016/10/12 17:27:08 schwarze Exp $
+.\" $OpenBSD: crontab.5,v 1.35 2018/06/13 11:27:30 job Exp $
.\"
-.Dd $Mdocdate: October 12 2016 $
+.Dd $Mdocdate: June 13 2018 $
.Dt CRONTAB 5
.Os
.Sh NAME
@@ -193,14 +193,20 @@ will be changed into newline characters, and all data
after the first
.Ql %
will be sent to the command as standard input.
-If the
-.Ar command
-field begins with
-.Ql -q ,
-execution will not be logged.
-Use whitespace to separate
-.Ql -q
-from the command.
+.Pp
+Commands may be modified as follows:
+.Bl -tag -width Ds
+.It Fl n Ar command
+No mail is sent after a successful run.
+The execution output will only be mailed if the command exits with a non-zero
+exit code.
+The
+.Fl -n
+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.
+.El
.Pp
Commands are executed by
.Xr cron 8
@@ -329,6 +335,9 @@ Ranges may include
.It
Months or days of the week can be specified by name.
.It
+Mailing after a successful run can be suppressed with
+.Fl n .
+.It
Logging can be suppressed with
.Ql -q .
.It
diff --git a/usr.sbin/cron/do_command.c b/usr.sbin/cron/do_command.c
index 6a4022fcc9a..0e711b636bb 100644
--- a/usr.sbin/cron/do_command.c
+++ b/usr.sbin/cron/do_command.c
@@ -1,8 +1,9 @@
-/* $OpenBSD: do_command.c,v 1.57 2017/10/23 08:39:26 friehm Exp $ */
+/* $OpenBSD: do_command.c,v 1.58 2018/06/13 11:27:30 job Exp $ */
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1997,2000 by Internet Software Consortium, Inc.
+ * Copyright (c) 2018 Job Snijders <job@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -80,7 +81,6 @@ child_process(entry *e, user *u)
char **p, *input_data, *usernm;
auth_session_t *as;
login_cap_t *lc;
- int children = 0;
extern char **environ;
/* mark ourselves as different to PS command watchers */
@@ -146,7 +146,9 @@ child_process(entry *e, user *u)
/* fork again, this time so we can exec the user's command.
*/
- switch (fork()) {
+
+ pid_t jobpid;
+ switch (jobpid = fork()) {
case -1:
syslog(LOG_ERR, "(CRON) CAN'T FORK (%m)");
_exit(EXIT_FAILURE);
@@ -260,8 +262,6 @@ child_process(entry *e, user *u)
break;
}
- children++;
-
/* middle process, child of original cron, parent of process running
* the user's command.
*/
@@ -283,7 +283,8 @@ child_process(entry *e, user *u)
* we would block here. thus we must fork again.
*/
- if (*input_data && fork() == 0) {
+ pid_t stdinjob;
+ if (*input_data && (stdinjob = fork()) == 0) {
FILE *out = fdopen(stdin_pipe[WRITE_PIPE], "w");
int need_newline = FALSE;
int escaped = FALSE;
@@ -331,8 +332,6 @@ child_process(entry *e, user *u)
*/
close(stdin_pipe[WRITE_PIPE]);
- children++;
-
/*
* read output from the grandchild. it's stderr has been redirected to
* it's stdout, which has been redirected to our pipe. if there is any
@@ -342,15 +341,17 @@ child_process(entry *e, user *u)
(void) signal(SIGPIPE, SIG_IGN);
in = fdopen(stdout_pipe[READ_PIPE], "r");
+
+ char *mailto;
+ FILE *mail = NULL;
+ int status = 0;
+ pid_t mailpid;
+ size_t bytes = 1;
+
if (in != NULL) {
int ch = getc(in);
if (ch != EOF) {
- FILE *mail = NULL;
- char *mailto;
- size_t bytes = 1;
- int status = 0;
- pid_t mailpid;
/* get name of recipient. this is MAILTO if set to a
* valid local username; USER otherwise.
@@ -415,30 +416,6 @@ child_process(entry *e, user *u)
fputc(ch, mail);
}
- /* only close pipe if we opened it -- i.e., we're
- * mailing...
- */
-
- if (mail) {
- /* Note: the pclose will probably see
- * the termination of the grandchild
- * in addition to the mail process, since
- * it (the grandchild) is likely to exit
- * after closing its stdout.
- */
- status = cron_pclose(mail, mailpid);
- }
-
- /* if there was output and we could not mail it,
- * log the facts so the poor user can figure out
- * what's going on.
- */
- if (mail && status) {
- syslog(LOG_NOTICE, "(%s) MAIL (mailed %zu byte"
- "%s of output but got status 0x%04x)", usernm,
- bytes, (bytes == 1) ? "" : "s", status);
- }
-
} /*if data from grandchild*/
fclose(in); /* also closes stdout_pipe[READ_PIPE] */
@@ -446,20 +423,50 @@ child_process(entry *e, user *u)
/* wait for children to die.
*/
- for (; children > 0; children--) {
- int waiter;
- pid_t pid;
-
- while ((pid = wait(&waiter)) < 0 && errno == EINTR)
+ int waiter;
+ if (jobpid > 0) {
+ ;
+ while (waitpid(jobpid, &waiter, 0) < 0 && errno == EINTR)
;
- if (pid < 0) {
- break;
+
+ /* If everything went well, and -n was set, _and_ we have mail,
+ * we won't be mailing... so shoot the messenger!
+ */
+ if (WIFEXITED(waiter) && WEXITSTATUS(waiter) == 0
+ && (e->flags & MAIL_WHEN_ERR) == MAIL_WHEN_ERR
+ && mail) {
+ kill(mailpid, SIGKILL);
+ (void)fclose(mail);
+ mail = NULL;
}
- /*
- if (WIFSIGNALED(waiter) && WCOREDUMP(waiter))
- Debug(DPROC, (", dumped core"))
+
+ /* only close pipe if we opened it -- i.e., we're
+ * mailing...
*/
+ if (mail) {
+ /*
+ * Note: the pclose will probably see the termination
+ * of the grandchild in addition to the mail process,
+ * since it (the grandchild) is likely to exit after
+ * closing its stdout.
+ */
+ status = cron_pclose(mail, mailpid);
+ }
+
+ /* if there was output and we could not mail it,
+ * log the facts so the poor user can figure out
+ * what's going on.
+ */
+ if (mail && status) {
+ syslog(LOG_NOTICE, "(%s) MAIL (mailed %zu byte"
+ "%s of output but got status 0x%04x)", usernm,
+ bytes, (bytes == 1) ? "" : "s", status);
+ }
}
+
+ if (stdinjob > 0)
+ while (waitpid(stdinjob, &waiter, 0) < 0 && errno == EINTR)
+ ;
}
int
diff --git a/usr.sbin/cron/entry.c b/usr.sbin/cron/entry.c
index 761f01d3d6f..bb0221bffb6 100644
--- a/usr.sbin/cron/entry.c
+++ b/usr.sbin/cron/entry.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: entry.c,v 1.48 2015/11/14 13:09:14 millert Exp $ */
+/* $OpenBSD: entry.c,v 1.49 2018/06/13 11:27:30 job Exp $ */
/*
* Copyright 1988,1990,1993,1994 by Paul Vixie
@@ -338,14 +338,32 @@ load_entry(FILE *file, void (*error_func)(const char *), struct passwd *pw,
ch = get_char(file);
while (ch == '-') {
switch (ch = get_char(file)) {
+ case 'n':
+ /* only allow the 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;
case 'q':
+ /* only allow the user to set the option once */
+ if ((e->flags & DONT_LOG) == DONT_LOG) {
+ ecode = e_option;
+ goto eof;
+ }
e->flags |= DONT_LOG;
- Skip_Nonblanks(ch, file)
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;
diff --git a/usr.sbin/cron/structs.h b/usr.sbin/cron/structs.h
index af0d75c3b55..c380b14f90d 100644
--- a/usr.sbin/cron/structs.h
+++ b/usr.sbin/cron/structs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: structs.h,v 1.8 2016/01/11 14:23:50 millert Exp $ */
+/* $OpenBSD: structs.h,v 1.9 2018/06/13 11:27:30 job Exp $ */
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
@@ -38,6 +38,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