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