summary refs log tree commit diff
path: root/mgenmid.c
blob: a9b878b7e536e64d562f1e8b8c4509de42e3a68e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#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("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"
		    " ${MBLAZE:-$HOME/.mblaze}/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;
}