--- .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.0Received 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