From: Christian Kastner <ckk@kvr.at>
Date: Sun, 20 Dec 2015 19:03:04 +0100
Subject: cron: report missing newline before EOF

A missing newline before EOF caused the daemon to silently ignore the last line
of a crontab. Print a warning instead.

Bug-Debian: https://bugs.debian.org/79037
Forwarded: no
Last-Update: 2015-12-20
---
 crontab.1 |  5 +++++
 crontab.5 |  6 ++++++
 entry.c   |  4 ++++
 user.c    | 17 +++++++++++++----
 4 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/crontab.1 b/crontab.1
index 8dee61d..a948c46 100644
--- a/crontab.1
+++ b/crontab.1
@@ -116,6 +116,11 @@ SVR3 syntax.
 .SH DIAGNOSTICS
 A fairly informative usage message appears if you run it with a bad command
 line.
+
+cron requires that each entry in a crontab end in a newline character. If the
+last entry in a crontab is missing the newline, cron will consider the crontab
+(at least partially) broken and refuse to install it.
+
 .SH AUTHOR
 .nf
 Paul Vixie <paul@vix.com>
diff --git a/crontab.5 b/crontab.5
index d094699..ad2c6d2 100644
--- a/crontab.5
+++ b/crontab.5
@@ -326,6 +326,12 @@ the following wrapper code:
 .fi
 
 
+.SH DIAGNOSTICS
+cron requires that each entry in a crontab end in a newline character.  If the
+last entry in a crontab is missing a newline (i.e.\& terminated by EOF),
+cron will consider the crontab (at least partially) broken.
+A warning will be written to syslog.
+
 .SH AUTHOR
 .nf
 Paul Vixie <paul@vix.com>
diff --git a/entry.c b/entry.c
index 84ccac4..429d8c0 100644
--- a/entry.c
+++ b/entry.c
@@ -313,6 +313,10 @@ load_entry(file, error_func, pw, envp)
 	ch = get_string(cmd, MAX_COMMAND, file, "\n");
 
 	/* a file without a \n before the EOF is rude, so we'll complain...
+
+	   CK 2010-04-14: this code will never be reached. All calls to
+	   load_entry are proceeded by calls to load_env, which aborts on EOF, and
+	   where load_env fails, the code bails out.
 	 */
 	if (ch == EOF) {
 		ecode = e_cmd;
diff --git a/user.c b/user.c
index 3e36b86..221eb9e 100644
--- a/user.c
+++ b/user.c
@@ -87,11 +87,20 @@ load_user(crontab_fd, pw, name)
 	 * load the crontab
 	 */
 	Set_LineNum(1)
-	while ((status = load_env(envstr, file)) >= OK) {
+	do {
+		status = load_env(envstr, file);
 		switch (status) {
 		case ERR:
-			free_user(u);
-			u = NULL;
+			/* If envstr has no content, we reached a proper EOF
+			 * and we can return to continue regular processing.
+			 *
+			 * If it does have content, we reached EOF without a
+			 * newline, so we bail out
+			 */
+			if (envstr[0] != '\0') {
+				log_it(u->name, getpid(), "ERROR", "Missing "
+				"newline before EOF");
+			}
 			goto done;
 		case FALSE:
 			e = load_entry(file, NULL, pw, envp);
@@ -110,7 +119,7 @@ load_user(crontab_fd, pw, name)
 			}
 			break;
 		}
-	}
+	} while (status >= OK);
 
  done:
 	env_free(envp);
