Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Dec 2012 15:37:32 +0100 (CET)
From:      Thierry Thomas <thierry@FreeBSD.org>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/174715: calendar: define Content-Type / charset when sending periodic mails
Message-ID:  <20121226143732.D45351147F@graf.pompo.net>
Resent-Message-ID: <201212261440.qBQEe0Q3062275@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         174715
>Category:       bin
>Synopsis:       calendar: define Content-Type / charset when sending periodic mails
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Dec 26 14:40:00 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Thierry Thomas
>Release:        FreeBSD 9.1-PRERELEASE i386
>Organization:
Kabbale Eros
>Environment:
System: FreeBSD graf.pompo.net 9.1-PRERELEASE FreeBSD 9.1-PRERELEASE #0 r243502: Sun Nov 25 18:43:08 CET 2012 thierry@graf.pompo.net:/usr/obj/usr/src/sys/GRAF120125 i386


	
>Description:
	When daily_calendar_enable is set (periodic.conf), `calenidar -a'
	is run, and sends mails with the content of calendar files.
	These calendar files may be encoded with non-ASCII character
	sets, defined by the variable LANG.
	Unfortunately, calendar always sends mails without defining any
	charset.

	If your MUA is set for the same default charset that the one
	used by your calendar files, it may seem working, and you won't
	notice anything strange. Else, the non-ASCII strings won't be
	displayed correctly.

>How-To-Repeat:
	- include some non-ASCII calendar files in your ~/calendar
	  (e.g. #include <calendar.french>)
	- set your MUA to a different default charset
	  (e.g. for mutt: set charset="utf-8")
	- run `calendar -a' or wait for periodic.

>Fix:
	Please check the hereunder patch. I'm not sure that this is the
	best way to do it, but you got the idea - and it works for me!

--- io.c.diff begins here ---
--- usr.bin/calendar/io.c.orig	2012-12-18 21:09:21.000000000 +0100
+++ usr.bin/calendar/io.c	2012-12-24 10:47:13.000000000 +0100
@@ -64,6 +64,9 @@
 static const char *calendarNoMail = "nomail";/* don't sent mail if file exist */
 
 static char path[MAXPATHLEN];
+#define MAXLANGLEN 31
+static char lang[MAXLANGLEN];
+static char xcharset[MAXLANGLEN];
 
 struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
 struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
@@ -77,6 +80,17 @@
 			struct_.len = strlen(buf + (slen));		      \
 			continue;					      \
 		}
+
+static void str_tolower(char *s)
+{
+	size_t i, l;
+	l = strlen(s);
+	for (i = 0; i < l; i++)
+	{
+		s[i] = tolower(s[i]);
+	}
+}
+
 void
 cal(void)
 {
@@ -127,7 +141,8 @@
 
 		/* Parse special definitions: LANG, Easter, Paskha etc */
 		if (strncmp(buf, "LANG=", 5) == 0) {
-			(void)setlocale(LC_ALL, buf + 5);
+			(void)strncpy(lang, buf + 5, sizeof(lang));
+			(void)setlocale(LC_ALL, lang);
 			d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
 			setnnames();
 			continue;
@@ -301,6 +316,8 @@
 	struct stat sbuf;
 	int nread, pdes[2], status;
 	char buf[1024];
+	char *charset, *char_set;
+	char iso[MAXLANGLEN] = "iso-";
 
 	if (!doall)
 		return;
@@ -310,7 +327,7 @@
 		goto done;
 	if (pipe(pdes) < 0)
 		goto done;
-	switch (fork()) {
+	switch (vfork()) {
 	case -1:			/* error */
 		(void)close(pdes[0]);
 		(void)close(pdes[1]);
@@ -335,8 +352,28 @@
 			warnx("setuid failed");
 			_exit(1);
 		}
-		execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
-		    "\"Reminder Service\"", (char *)NULL);
+		if (lang == NULL)
+			execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
+		    	"\"Reminder Service\"", (char *)NULL);
+		else {
+			charset = strchr(lang, '.');
+			if (charset == NULL) {
+				warnx("Invalid LANG: %s", lang);
+				_exit(1);
+			}
+			else {
+				str_tolower(charset);
+				char_set = strstr(charset, "iso");
+				if (char_set != NULL) {
+					(void)strncat(iso, char_set + 3, sizeof(lang));
+					(void)strncpy(xcharset, iso, sizeof(lang));
+				}
+				else
+					(void)strncpy(xcharset, charset, sizeof(lang));
+				execl(_PATH_SENDMAIL, "sendmail", "-i", "-t",
+				"-B", "8BITMIME", "-F", "\"Reminder Service\"", (char *)NULL);
+			}
+		}
 		warn(_PATH_SENDMAIL);
 		_exit(1);
 	}
@@ -349,7 +386,14 @@
 	write(pdes[1], pw->pw_name, strlen(pw->pw_name));
 	write(pdes[1], ">\nSubject: ", 11);
 	write(pdes[1], dayname, strlen(dayname));
-	write(pdes[1], "'s Calendar\nPrecedence: bulk\n\n", 30);
+	write(pdes[1], "'s Calendar\nPrecedence: bulk\n", 29);
+	if (xcharset[0] != '\0') {
+		write(pdes[1], "Mime-Version: 1.0\n", 18);
+		write(pdes[1], "Content-Type: text/plain; charset=", 34);
+		write(pdes[1], xcharset, strlen(xcharset));
+		write(pdes[1], "\n", 1);
+	}
+	write(pdes[1], "\n", 1);
 
 	while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
 		(void)write(pdes[1], buf, nread);
--- io.c.diff ends here ---

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20121226143732.D45351147F>