From: Walter Alejandro Iglesias Subject: Re: mail(1) patches (UPDATE) To: tech@openbsd.org Date: Wed, 7 Aug 2024 10:39:35 +0200 Yesterday I ran into a problem that I didn't remember, that under Linux gethostname() returns only the hostname. This means that the diff below as well as the second from the three versions I posted before, since the idea was to make them portable, are useless. So, to generate Message-ID and Date headers, OpenSMTP uses "hand written" functions. Using libc (strftime()) wasn't convenient in this case because of OpenBSD limitation with locales. Is detecting UTF-8 characters a different case in this matter? This is what I was suggested to use instead of my hand written UTF-8 parser: https://marc.info/?l=openbsd-tech&m=169530140424607&w=2 But mblen(3) also depends on locales. So far, at least under Linux, using mblen(3) I got the same behavior that under OpenBSD but given my short experience as a C programmer, hence my limited knowledge of the "context", contrary to my hand written function which I'm sure is 100% portable and do NOT depend on locales, I'm not sure to which extent I can trust on the "portability" of the code using mblen(3). At least, this is how things look from my ignorant point of view. Years ago I used to write web applications in PHP for my clients. I didn't use already written functions, I wrote my own code, trying to use the most basics. To filter user input I wrote my own regular expressions. This way my applications were secure, portable and *I didn't have to rewrite them for each new version of PHP*. I understand that this worked for me because I worked alone, and that PHP is not C, but the analogy is still valid to some extent. > > > Index: extern.h > =================================================================== > RCS file: /cvs/src/usr.bin/mail/extern.h,v > diff -u -p -r1.30 extern.h > --- extern.h 21 May 2024 05:00:48 -0000 1.30 > +++ extern.h 6 Aug 2024 06:51:15 -0000 > @@ -176,6 +176,7 @@ void mesedit(FILE *, int); > void mespipe(FILE *, char *); > int messize(void *); > int metamess(int, int); > +const char* month(int num); > int more(void *); > int newfileinfo(int); > int next(void *); > @@ -253,7 +254,9 @@ void vfree(char *); > int visual(void *); > int wait_child(pid_t); > int wait_command(int); > +const char* wday(int num); > int writeback(FILE *); > +const char* zone(int num); > > extern char *__progname; > extern char *tmpdir; > Index: send.c > =================================================================== > RCS file: /cvs/src/usr.bin/mail/send.c,v > diff -u -p -r1.26 send.c > --- send.c 8 Mar 2023 04:43:11 -0000 1.26 > +++ send.c 6 Aug 2024 06:51:15 -0000 > @@ -516,15 +516,28 @@ puthead(struct header *hp, FILE *fo, int > { > int gotcha; > char *from; > + time_t t = time(NULL); > + struct tm lt = *localtime(&t); > + char host[1024]; > + int h = gethostname(host, 1023); > > gotcha = 0; > from = hp->h_from ? hp->h_from : value("from"); > if (from != NULL) > fprintf(fo, "From: %s\n", from), gotcha++; > + if (fo != stdout) > + fprintf(fo, "Date: %s, %d %s %d %02d:%02d:%02d %s\n", > + wday(lt.tm_wday), lt.tm_mday, month(lt.tm_mon), > + lt.tm_year + 1900, lt.tm_hour, lt.tm_min, lt.tm_sec, > + zone(lt.tm_gmtoff)), gotcha++; > if (hp->h_to != NULL && w & GTO) > fmt("To:", hp->h_to, fo, w&GCOMMA), gotcha++; > if (hp->h_subject != NULL && w & GSUBJECT) > fprintf(fo, "Subject: %s\n", hp->h_subject), gotcha++; > + if (fo != stdout && h == 0) > + fprintf(fo, "Message-ID: <%d%02d%02d.%02d%02d%02d@%s>\n", > + lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, > + lt.tm_min, lt.tm_sec, host), gotcha++; > if (hp->h_cc != NULL && w & GCC) > fmt("Cc:", hp->h_cc, fo, w&GCOMMA), gotcha++; > if (hp->h_bcc != NULL && w & GBCC) > Index: util.c > =================================================================== > RCS file: /cvs/src/usr.bin/mail/util.c,v > diff -u -p -r1.2 util.c > --- util.c 26 Dec 2022 19:16:01 -0000 1.2 > +++ util.c 6 Aug 2024 06:51:15 -0000 > @@ -641,3 +641,34 @@ clearnew(void) > } > } > } > + > +const char* > +wday(int num) > +{ > + const char *week[] = {"Sun", "Mon", "Tue", "Wed", "Thu", > + "Fri", "Sat"}; > + return(week[num]); > +} > + > +const char* > +month(int num) > +{ > + const char *month[] = {"Jan","Feb","Mar","Apr","May","Jun", > + "Jul","Aug","Sep","Oct","Nov","Dec"}; > + return(month[num]); > +} > + > +const char* > +zone(int num) > +{ > + static char buf[6]; > + size_t r; > + > + r = snprintf(buf, sizeof(buf), "%c%02d%02d", num >= 0 ? '+' : '-', > + abs((int)num / 3600), abs((int)num % 3600) / 60); > + > + if (r < 0 || r >= sizeof(buf)) > + errx(1, "zone: snprintf"); > + > + return(buf); > +} > -- Walter