mirror of https://github.com/leahneukirchen/mblaze
add mgenmid
parent
400c6793d6
commit
78fec302cb
@ -0,0 +1,58 @@
|
|||||||
|
.Dd August 1, 2016
|
||||||
|
.Dt MGENMID 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm mgenmid
|
||||||
|
.Nd generate a Message-ID
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
generates a fresh Message-ID and prints it.
|
||||||
|
The Message-ID consists of a timestamp,
|
||||||
|
a random value,
|
||||||
|
and a fully qualified domain name.
|
||||||
|
.Pp
|
||||||
|
The fully qualified domain name is computed by:
|
||||||
|
.Bl -enum
|
||||||
|
.It
|
||||||
|
Using
|
||||||
|
.Sq Li "FQDN:"
|
||||||
|
from
|
||||||
|
.Pa "~/.santoku/profile"
|
||||||
|
(if set).
|
||||||
|
.It
|
||||||
|
Resolving the current hostname.
|
||||||
|
.It
|
||||||
|
Using the host part of the address in
|
||||||
|
.Sq Li "Local-Mailbox:"
|
||||||
|
from
|
||||||
|
.Pa "~/.santoku/profile"
|
||||||
|
(if set).
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If these steps don't result in a fully qualified domain name,
|
||||||
|
.Nm
|
||||||
|
fails.
|
||||||
|
.Sh EXIT STATUS
|
||||||
|
.Ex -std
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Rs
|
||||||
|
.%A M. Curtin
|
||||||
|
.%A J. Zawinski
|
||||||
|
.%D July 1998
|
||||||
|
.%R draft-ietf-usefor-message-id-01.txt
|
||||||
|
.%T Recommendations for generating Message IDs
|
||||||
|
.Re
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An Christian Neukirchen Aq Mt chneukirchen@gmail.com
|
||||||
|
.Sh LICENSE
|
||||||
|
.Nm
|
||||||
|
is in the public domain.
|
||||||
|
.Pp
|
||||||
|
To the extent possible under law,
|
||||||
|
the creator of this work
|
||||||
|
has waived all copyright and related or
|
||||||
|
neighboring rights to this work.
|
||||||
|
.Pp
|
||||||
|
.Lk http://creativecommons.org/publicdomain/zero/1.0/
|
@ -0,0 +1,115 @@
|
|||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "blaze822.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
printb36(uint64_t x)
|
||||||
|
{
|
||||||
|
static char const base36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
|
char outbuf[16];
|
||||||
|
char *o = outbuf + sizeof outbuf;
|
||||||
|
*o = 0;
|
||||||
|
|
||||||
|
do { *--o = base36[x % 36]; } while (x /= 36);
|
||||||
|
fputs(o, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
char hostbuf[1024];
|
||||||
|
char *host = 0;
|
||||||
|
|
||||||
|
char *f = blaze822_home_file(".santoku/profile");
|
||||||
|
struct message *config = blaze822(f);
|
||||||
|
|
||||||
|
if (config) // try FQDN: first
|
||||||
|
host = blaze822_hdr(config, "fqdn");
|
||||||
|
|
||||||
|
if (!host && gethostname(hostbuf, sizeof hostbuf) == 0) {
|
||||||
|
// termination not posix guaranteed
|
||||||
|
hostbuf[sizeof hostbuf - 1] = 0;
|
||||||
|
|
||||||
|
struct addrinfo hints = { .ai_family = AF_UNSPEC,
|
||||||
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
.ai_flags = AI_CANONNAME };
|
||||||
|
struct addrinfo *info;
|
||||||
|
if (getaddrinfo(hostbuf, 0, &hints, &info) == 0) {
|
||||||
|
// sanity checks: no (null), at least one dot,
|
||||||
|
// doesn't start with localhost.
|
||||||
|
|
||||||
|
if (info &&
|
||||||
|
info->ai_canonname &&
|
||||||
|
strchr(info->ai_canonname, '.') &&
|
||||||
|
strncmp(info->ai_canonname, "localhost.", 10) != 0)
|
||||||
|
host = info->ai_canonname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!host && config) {
|
||||||
|
// get address part of Local-Mailbox:
|
||||||
|
char *disp, *addr;
|
||||||
|
char *from = blaze822_hdr(config, "local-mailbox");
|
||||||
|
while (from && (from = blaze822_addr(from, &disp, &addr)))
|
||||||
|
if (addr) {
|
||||||
|
host = strchr(addr, '@');
|
||||||
|
if (host) {
|
||||||
|
host++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!host) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"mgenmid: failed to find a FQDN for the Message-ID.\n"
|
||||||
|
" Define 'FQDN:' or 'Local-Mailbox:' in ~/.santoku/profile\n"
|
||||||
|
" or add a FQDN to /etc/hosts.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timespec tp;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &tp);
|
||||||
|
|
||||||
|
uint64_t rnd;
|
||||||
|
|
||||||
|
int rndfd = open("/dev/urandom", O_RDONLY);
|
||||||
|
if (rndfd >= 0) {
|
||||||
|
unsigned char rndb[8];
|
||||||
|
if (read(rndfd, rndb, sizeof rndb) != sizeof rndb)
|
||||||
|
goto fallback;
|
||||||
|
close(rndfd);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0, rnd = 0; i < 8; i++)
|
||||||
|
rnd = rnd*256 + rndb[i];
|
||||||
|
} else {
|
||||||
|
fallback:
|
||||||
|
srand48(tp.tv_sec ^ tp.tv_nsec/1000 ^ getpid());
|
||||||
|
rnd = (lrand48() << 32) + lrand48();
|
||||||
|
}
|
||||||
|
|
||||||
|
rnd |= (1LL << 63); // set highest bit to force full width
|
||||||
|
|
||||||
|
putchar('<');
|
||||||
|
printb36(((uint64_t)tp.tv_sec << 16) + (tp.tv_nsec >> 16));
|
||||||
|
putchar('.');
|
||||||
|
printb36(rnd);
|
||||||
|
putchar('@');
|
||||||
|
fputs(host, stdout);
|
||||||
|
putchar('>');
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue