summaryrefslogtreecommitdiff
path: root/src/tai64nfrac.c
diff options
context:
space:
mode:
authorJannis Hoffmann <jannis@fehcom.de>2024-07-03 15:48:04 +0200
committerJannis Hoffmann <jannis@fehcom.de>2024-07-03 15:48:04 +0200
commit89b7b67a13ebb7965cc7f13ad0595e2194a2d34c (patch)
tree25efd77a90ae87236e6730d8ea3846bbe0fd126f /src/tai64nfrac.c
add sqmail-4.2.29asqmail-4.2
Diffstat (limited to 'src/tai64nfrac.c')
-rw-r--r--src/tai64nfrac.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/tai64nfrac.c b/src/tai64nfrac.c
new file mode 100644
index 0000000..f3db977
--- /dev/null
+++ b/src/tai64nfrac.c
@@ -0,0 +1,85 @@
+#include "buffer.h"
+#include "stralloc.h"
+#include "exit.h"
+#include "readwrite.h"
+#include "open.h"
+#include "scan.h"
+#include "fmt.h"
+#include "getln.h"
+
+#define TAI64NLEN 24
+
+/** @file tai64nfrac
+ @brief Read a TAI64N external format timestamp from stdin and
+ write fractional seconds since epoch (TAI, not UTC) to stdout.
+ Return the characters after the timestamp.
+ */
+
+char outbuf[64];
+buffer bo = BUFFER_INIT(write,1,outbuf,sizeof(outbuf));
+
+static void outs(char *s)
+{
+ if (buffer_puts(&bo,s) == -1) _exit(1);
+ if (buffer_flush(&bo) == -1) _exit(1);
+}
+
+static void outi(int i)
+{
+ char num[FMT_ULONG];
+
+ if (buffer_put(&bo,num,fmt_ulong(num,(unsigned long) i)) == -1) _exit(1);
+ if (buffer_flush(&bo) == -1) _exit(1);
+}
+
+char inbuf[1024];
+buffer bi = BUFFER_INIT(read,0,inbuf,sizeof(inbuf));
+
+int main(void)
+{
+ int c;
+ int i;
+ int match;
+ unsigned long u;
+ unsigned long seconds;
+ unsigned long nanoseconds;
+ stralloc line = {0};
+
+/* Read from stdin */
+
+ buffer_init(&bi,read,0,inbuf,sizeof(inbuf));
+
+ for (;;) {
+ if (getln(&bi,&line,&match,'\n') != 0) _exit(1);
+ if (!match) break;
+ if (!stralloc_0(&line)) _exit(1);
+
+ seconds = 0;
+ nanoseconds = 0;
+
+ if (line.s[0] == '@') { /* tai64 timestamp */
+ for (i = 1; i <= TAI64NLEN; i++) {
+ c = (int)line.s[i];
+ u = c - '0';
+ if (u >= 10) {
+ u = c - 'a';
+ if (u >= 6) break;
+ u += 10;
+ }
+ seconds <<= 4;
+ seconds += nanoseconds >> 28;
+ nanoseconds &= 0xfffffff;
+ nanoseconds <<= 4;
+ nanoseconds += u;
+ }
+ seconds -= 4611686018427387914ULL;
+ seconds = seconds > 0 ? seconds : 0;
+ outi(seconds); outs("."); outi(nanoseconds); outs(line.s + i); outs("\n");
+ } else {
+ outs("tai64nfrac: fatal: Wrong TAI64N input format."); outs("\n");
+ _exit(1);
+ }
+ }
+
+ _exit(0);
+}