---
.gitignore | 1 +
Makefile | 1 +
README | 1 +
ts.1 | 38 +++++++++++++++++++++++
ts.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 132 insertions(+)
create mode 100644 ts.1
create mode 100644 ts.c
diff --git a/.gitignore b/.gitignore
index e591886..001b055 100644
--- a/.gitignore
+++ b/.gitignore
_AT_@ -88,6 +88,7 @@
/touch
/tr
/true
+/ts
/tsort
/tty
/uname
diff --git a/Makefile b/Makefile
index 55e00d9..7bd9626 100644
--- a/Makefile
+++ b/Makefile
_AT_@ -177,6 +177,7 @@ BIN =\
touch\
tr\
true\
+ ts\
tsort\
tty\
uname\
diff --git a/README b/README
index 91a60f9..5555f8b 100644
--- a/README
+++ b/README
_AT_@ -129,6 +129,7 @@ The following tools are implemented:
0=*|o touch .
0#*|o tr .
0=*|o true .
+0=* x ts .
0=* o tsort .
0=*|o tty .
0=*|o uname .
diff --git a/ts.1 b/ts.1
new file mode 100644
index 0000000..dcc04ac
--- /dev/null
+++ b/ts.1
_AT_@ -0,0 +1,38 @@
+.Dd 2024-02-25
+.Dt TS 1
+.Os sbase
+.Sh NAME
+.Nm ts
+.Nd timestamp input
+.Sh SYNOPSIS
+.Nm
+.Op Fl i | Fl s
+.Op Fl m Ar n
+.Op Ar format
+.Sh DESCRIPTION
+.Nm
+prepends a timestamp to each line of standard input and
+writes it to standard output.
+The timestamp is formatted using
+.Ar format ,
+according to the conversion specifications described in
+.Xf strftime 3 .
+The default format is "%b %d %H:%M:%S"; or "%H:%M:%S"
+if one of the
+.Fl i
+or
+.Fl s
+options is used.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl i
+Display time elapsed since the last timestamp.
+.It Fl m
+Append to the timestamp
+.Ar n
+digits (up to 9) of nanoseconds.
+.It Fl s
+Display time elapsed since the start of the program.
+.El
+.Sh SEE ALSO
+.Xr strftime 3
diff --git a/ts.c b/ts.c
new file mode 100644
index 0000000..d419660
--- /dev/null
+++ b/ts.c
_AT_@ -0,0 +1,91 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "util.h"
+
+#define timespecsub(tsp, usp, vsp) \
+ do { \
+ (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
+ (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
+ if ((vsp)->tv_nsec < 0) { \
+ (vsp)->tv_sec--; \
+ (vsp)->tv_nsec += 1000000000L; \
+ } \
+ } while (0)
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-i | -s] [-m] [format]\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int iflag, mflag, sflag, div;
+ ssize_t len;
+ size_t n;
+ char *fmt, *line = NULL, buf[256], mm[11];
+ struct tm *tm;
+ struct timespec start, now, ts;
+ clockid_t clock = CLOCK_REALTIME;
+
+ fmt = "%b %d %H:%M:%S";
+ *mm = '\0';
+ iflag = mflag = sflag = 0;
+
+ ARGBEGIN {
+ case 'i':
+ iflag = 1;
+ fmt = "%H:%M:%S";
+ clock = CLOCK_MONOTONIC;
+ break;
+ case 'm':
+ mflag = estrtonum(EARGF(usage()), 1, 9);
+ break;
+ case 's':
+ sflag = 1;
+ fmt = "%H:%M:%S";
+ clock = CLOCK_MONOTONIC;
+ break;
+ default:
+ usage();
+ } ARGEND
+
+ /* divisor factor for nanosecs */
+ div = 1000000000;
+ for (int i = mflag; i > 0; i--)
+ div /= 10;
+
+ setvbuf(stdout, NULL, _IOLBF, 0);
+
+ clock_gettime(clock, &start);
+
+ if (argc > 1)
+ usage();
+ else if (argc == 1)
+ fmt = *argv;
+
+ while ((len = getline(&line, &n, stdin)) > 0) {
+ clock_gettime(clock, &now);
+ if (iflag || sflag)
+ timespecsub(&now, &start, &ts);
+ else
+ ts = now;
+ if (mflag)
+ sprintf(mm, ".%0*ld", mflag, ts.tv_nsec/div);
+
+ tm = (iflag || sflag) ? gmtime(&ts.tv_sec) : localtime(&ts.tv_sec);
+
+ strftime(buf, sizeof(buf), fmt, tm);
+ printf("%s%s ", buf, mm);
+ fwrite(line, 1, len, stdout);
+
+ if (iflag)
+ start = now;
+ }
+ free(line);
+
+ return 0;
+}
--
2.43.0
Received on Sun Feb 25 2024 - 19:35:54 CET
This archive was generated by hypermail 2.3.0 : Mon Feb 26 2024 - 23:48:38 CET