- char buf[SHORT_STRING];
- time_t now;
- struct tm *tm;
- const char *fqdn;
-
- now = time (NULL);
- tm = gmtime (&now);
- if(!(fqdn = mutt_fqdn(0)))
- fqdn = NONULL(Hostname);
-
- snprintf (buf, sizeof (buf), "<%d%02d%02d%02d%02d%02d.G%c%u@%s>",
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
- tm->tm_min, tm->tm_sec, MsgIdPfx, (unsigned int)getpid (), fqdn);
- MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
- return (safe_strdup (buf));
+#define APPEND_FMT(fmt, arg) \
+ if (len > 1) { \
+ int snlen = snprintf(buf, len, fmt, arg); \
+ buf += snlen; \
+ len -= snlen; \
+ }
+
+#define APPEND_BYTE(c) \
+ if (len > 1) { \
+ *buf++ = c; \
+ *buf = '\0'; \
+ len--; \
+ }
+
+ time_t now;
+ struct tm *tm;
+
+ now = time (NULL);
+ tm = gmtime (&now);
+
+ while (*fmt) {
+ static char MsgIdPfx = 'A';
+ int c = *fmt++;
+
+ if (c != '%') {
+ /* normalized character (we're stricter than RFC2822, 3.6.4) */
+ APPEND_BYTE((isalnum(c) || strchr(".!#$%&'*+-/=?^_`{|}~", c)) ? c : '.');
+ continue;
+ }
+
+ switch (*fmt++) {
+ case 0:
+ return;
+ case 'd':
+ APPEND_FMT("%02d", tm->tm_mday);
+ break;
+ case 'h':
+ APPEND_FMT("%02d", tm->tm_hour);
+ break;
+ case 'm':
+ APPEND_FMT("%02d", tm->tm_mon + 1);
+ break;
+ case 'M':
+ APPEND_FMT("%02d", tm->tm_min);
+ break;
+ case 'O':
+ APPEND_FMT("%lo", (unsigned long)now);
+ break;
+ case 'p':
+ APPEND_FMT("%u", (unsigned int)getpid());
+ break;
+ case 'P':
+ APPEND_FMT("%c", MsgIdPfx);
+ MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1;
+ break;
+ case 'r':
+ APPEND_FMT("%u", (unsigned int)rand());
+ break;
+ case 'R':
+ APPEND_FMT("%x", (unsigned int)rand());
+ break;
+ case 's':
+ APPEND_FMT("%02d", tm->tm_sec);
+ break;
+ case 'T':
+ APPEND_FMT("%u", (unsigned int) now);
+ break;
+ case 'X':
+ APPEND_FMT("%x", (unsigned int) now);
+ break;
+ case 'Y': /* this will break in the year 10000 ;-) */
+ APPEND_FMT("%04d", tm->tm_year + 1900);
+ break;
+ case '%':
+ APPEND_BYTE('%');
+ break;
+ default: /* invalid formats are replaced by '.' */
+ APPEND_BYTE('.');
+ }
+ }
+
+ *buf = '\0';
+
+#undef APPEND_BYTE
+#undef APPEND_FMT
+}
+
+static char *mutt_gen_msgid (void)
+{
+ char buf[SHORT_STRING];
+ char localpart[SHORT_STRING];
+ const char *fqdn;
+
+ if (!(fqdn = mutt_fqdn(0)))
+ fqdn = NONULL(Hostname);
+
+ mutt_gen_localpart(localpart, sizeof(localpart), MsgIdFormat);
+ snprintf(buf, sizeof(buf), "<%s@%s>", localpart, fqdn);
+ return m_strdup(buf);