[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

vixie-cron small patch



Hello everybody!
I've added new environment support to vixie-cron which is used by default cron in Debian. This environment is adding oppotunity to set mail subject for cron's report. It looks like this:
MAILSUBJECT="CRON at the %hostname% (fqdn: %fqdn%): User %user% ran command %cmd% which was executed with status %status%. Cron fork status: %forkstatus%"
* * * * * root echo test

It can be useful for many users. I've attached the patch for vixie cron. Could the patch be included to Debian release?

Thanks!

---
Site Reliability Engineer
Stan E. Putrya

/"\
\ / ASCII Ribbon Campaign
 X against HTML email & vCards
/ \
--- a/compat.c
+++ b/compat.c
@@ -236,3 +236,18 @@ setenv(name, value, overwrite)
 	return putenv(tmp);	/* intentionally orphan 'tmp' storage */
 }
 #endif
+
+void
+replace_str(char *str, int len, char *origin, char *replace) {
+	char *p;
+	char buf[len];
+	memset(buf, 0, len);
+	if (strnlen(str, len+1) > len)
+		return;
+	if (!(p=strstr(str, origin)))
+		return;
+	strncpy(buf, str, p-str);
+	sprintf(buf+(p-str), "%s%s", replace, p+strlen(origin));
+	strncpy(str, buf, strlen(buf));
+	memset(str+strlen(buf), 0, len-strlen(buf));
+}
--- a/compat.h
+++ b/compat.h
@@ -135,3 +135,5 @@
 #if !defined(UNICOS) && !defined(UNIXPC)
 # define HAS_FCHMOD
 #endif
+
+#define MAXREPLACEBUF 4028 /* max length for string origin replace */
--- a/cron.h
+++ b/cron.h
@@ -98,6 +98,14 @@
 #define	DTEST		0x0040	/* test mode: don't execute any commands */
 #define	DBIT		0x0080	/* bit twiddling shown (long) */
 
+// Templates
+#define	CRONUSER 	"%user%"	/* tag for cron's user */
+#define	HOSTNAME	"%hostname%"	/* tag for cron's hostname*/
+#define	FQDN		"%fqdn%"	/* tag for cron's fqdn*/
+#define	CMD		"%cmd%"		/* extend flag for other debug masks */
+#define	STATUS 		"%status%"	/* extend flag for other debug masks */
+#define	FORKSTATUS 	"%forkstatus%"	/* extend flag for other debug masks */
+
 #define	CRON_TAB(u)	"%s/%s", SPOOL_DIR, u
 #define	REG		register
 #define	PPC_NULL	((char **)NULL)
--- a/do_command.c
+++ b/do_command.c
@@ -129,7 +129,7 @@ child_process(e, u)
 	int		stdin_pipe[2];
 	FILE		*tmpout;
 	register char	*input_data;
-	char		*usernm, *mailto;
+	char		*usernm, *mailto, *mailsubject, *p;
 	int		children = 0;
 	pid_t		job_pid;
 
@@ -153,6 +153,7 @@ child_process(e, u)
 	 */
 	usernm = env_get("LOGNAME", e->envp);
 	mailto = env_get("MAILTO", e->envp);
+	mailsubject = env_get("MAILSUBJECT", e->envp);
 
 	/* Check for arguments */
 	if (mailto) {
@@ -474,6 +475,7 @@ child_process(e, u)
 	/* wait for children to die.
 	 */
 	int status = 0;
+	int execstatus = 0;
 	for (;  children > 0;  children--)
 	{
 		char		msg[256];
@@ -489,6 +491,7 @@ child_process(e, u)
 		}
 		Debug(DPROC, ("[%d] grandchild #%d finished, status=%04x\n",
 			getpid(), pid, WEXITSTATUS(waiter)))
+                execstatus = WEXITSTATUS(waiter);
 
 		if (log_level & CRON_LOG_JOBFAILED) {
 			if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) {
@@ -560,9 +563,37 @@ child_process(e, u)
 	}
 	fprintf(mail, "From: root (Cron Daemon)\n");
 	fprintf(mail, "To: %s\n", mailto);
-	fprintf(mail, "Subject: Cron <%s@%s> %s%s\n",
+	
+	// Generate subject
+	if (mailsubject == NULL) {
+		fprintf(mail, "Subject: Cron <%s@%s> %s%s\n",
 			usernm, first_word(hostname, "."),
 			e->cmd, status?" (failed)":"");
+	} else {
+		char buffer[MAXREPLACEBUF];
+		memset(buffer, 0, MAXREPLACEBUF);
+		if (strnlen(mailsubject, MAXREPLACEBUF+1) > MAXREPLACEBUF) {
+			fprintf(mail, "Subject: Cron <%s@%s> %s%s\n",
+				usernm, first_word(hostname, "."),
+				e->cmd, status?" (failed)":"");
+		} else {
+			strncpy(buffer, mailsubject, strlen(mailsubject));
+			if (strstr(buffer, CRONUSER))
+				replace_str(buffer, MAXREPLACEBUF, CRONUSER, usernm);
+			if (strstr(buffer, HOSTNAME))
+				replace_str(buffer, MAXREPLACEBUF, HOSTNAME, first_word(hostname, "."));
+			if (strstr(buffer, CMD))
+				replace_str(buffer, MAXREPLACEBUF, CMD, e->cmd);
+			if (strstr(buffer, STATUS))
+				replace_str(buffer, MAXREPLACEBUF, STATUS, execstatus?"failed":"success");
+			if (strstr(buffer, FORKSTATUS))
+				replace_str(buffer, MAXREPLACEBUF, FORKSTATUS, status?"failed":"success");
+			if (strstr(buffer, FQDN))
+				replace_str(buffer, MAXREPLACEBUF, FQDN, hostname);
+			fprintf(mail, "Subject: %s\n", buffer);
+		}
+	}
+	//
 # if defined(MAIL_DATE)
 	fprintf(mail, "Date: %s\n",
 			arpadate(&StartTime));

Reply to: