1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-21 23:18:00 -08:00

Import ts(1) - a timestamp utility

A from scratch & pledged implementation of the perl 'ts' utility found
in the moreutils collection.

With help from florian@, tb@, and deraadt@

OK deraadt@
This commit is contained in:
job 2022-06-29 08:39:49 +00:00
parent 353d4d9637
commit acb1415e3c
4 changed files with 263 additions and 2 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.167 2022/04/19 01:32:06 dlg Exp $
# $OpenBSD: Makefile,v 1.168 2022/06/29 08:39:49 job Exp $
.include <bsd.own.mk>
@ -26,7 +26,7 @@ SUBDIR= apply arch at aucat audioctl awk banner \
skeyaudit skeyinfo skeyinit sndioctl sndiod snmp \
sort spell split ssh stat su systat \
tail talk tcpbench tee telnet tftp tic time timeout \
tmux top touch tput tr true tset tsort tty usbhidaction usbhidctl \
tmux top touch tput tr true ts tset tsort tty usbhidaction usbhidctl \
ul uname unexpand unifdef uniq units \
unvis users uudecode uuencode vacation vi vis vmstat w wall wc \
what which who whois write x99token xargs xinstall \

5
usr.bin/ts/Makefile Normal file
View File

@ -0,0 +1,5 @@
# $OpenBSD: Makefile,v 1.1 2022/06/29 08:39:49 job Exp $
PROG= ts
.include <bsd.prog.mk>

92
usr.bin/ts/ts.1 Normal file
View File

@ -0,0 +1,92 @@
.\" $OpenBSD: ts.1,v 1.1 2022/06/29 08:39:49 job Exp $
.\"
.\" Copyright (c) 2022 Job Snijders <job@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: June 29 2022 $
.Dt TS 1
.Os
.Sh NAME
.Nm ts
.Nd timestamp input
.Sh SYNOPSIS
.Nm ts
.Op Fl i | s
.Op Ar format
.Sh DESCRIPTION
When invoked, the
.Nm
utility adds a timestamp to the beginning of each line of input.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl i
Display time elapsed since the last timestamp.
.It Fl s
Display time elapsed since the start of the program.
.El
.Pp
The optional
.Ar format
argument controls how the timestamp is displayed, according to the conversion
specifications described in the
.Xr strftime 3
manual page.
The default format is
.Qq %b %d %H:%M:%S ,
or
.Qq %H:%M:%S
if an option is used.
.Pp
The following non-standard conversion specifications append microsecond
resolution:
.Cm \&%.S ,
.Cm \&%.s ,
and
.Cm \&%.T ;
which are similar to
.Cm \&%S ,
.Cm \&%s ,
and
.Cm \&%T .
Examples:
.Qq 10.00001 ,
.Qq 1656427781.00001 ,
and
.Qq 4:20:00.00001 .
.Sh EXAMPLES
.Bd -literal -offset indent
$ (echo foo; sleep 2; echo bar) | ts
Jun 28 12:13:38 foo
Jun 28 12:13:40 bar
$ ls | ts -i %.S
00.000452 CVS
00.000595 Makefile
00.000004 ts.1
00.000004 ts.c
.Ed
.Sh HISTORY
A
.Nm
utility first appeared in the moreutils collection by Joey Hess, and was
rewritten from scratch for
.Ox 7.2 .
.Sh AUTHORS
This
.Nm
utility was written by
.An Job Snijders Aq Mt job@openbsd.org
and
.An Claudio Jeker Aq Mt claudio@openbsd.org .

164
usr.bin/ts/ts.c Normal file
View File

@ -0,0 +1,164 @@
/* $OpenBSD: ts.c,v 1.1 2022/06/29 08:39:49 job Exp $ */
/*
* Copyright (c) 2022 Job Snijders <job@openbsd.org>
* Copyright (c) 2022 Claudio Jeker <claudio@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
#include <sys/time.h>
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
static char *format = "%b %d %H:%M:%S";
static char *buf;
static char *outbuf;
static size_t bufsize;
static void fmtfmt(struct tm *, long);
static void __dead usage(void);
int
main(int argc, char *argv[])
{
int iflag, sflag;
int ch, prev;
struct timespec start, now, elapsed;
struct tm *lt, tm;
if (pledge("stdio", NULL) == -1)
err(1, "pledge");
iflag = sflag = 0;
while ((ch = getopt(argc, argv, "is")) != -1) {
switch (ch) {
case 'i':
iflag = 1;
format = "%H:%M:%S";
break;
case 's':
sflag = 1;
format = "%H:%M:%S";
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if ((iflag && sflag) || argc > 1)
usage();
if (argc == 1)
format = *argv;
bufsize = strlen(format);
if (bufsize > SIZE_MAX / 10)
errx(1, "format string too big");
bufsize *= 10;
if ((buf = calloc(1, bufsize)) == NULL)
err(1, NULL);
if ((outbuf = calloc(1, bufsize)) == NULL)
err(1, NULL);
clock_gettime(CLOCK_MONOTONIC, &start);
for (prev = '\n'; (ch = getchar()) != EOF; prev = ch) {
if (prev == '\n') {
if (iflag || sflag) {
if (clock_gettime(CLOCK_MONOTONIC, &now))
err(1, "clock_gettime");
timespecsub(&now, &start, &elapsed);
if (gmtime_r(&elapsed.tv_sec, &tm) == NULL)
err(1, "gmtime_r");
if (iflag)
clock_gettime(CLOCK_MONOTONIC, &start);
fmtfmt(&tm, elapsed.tv_nsec);
} else {
if (clock_gettime(CLOCK_REALTIME, &now))
err(1, "clock_gettime");
lt = localtime(&now.tv_sec);
if (lt == NULL)
err(1, "localtime");
fmtfmt(lt, now.tv_nsec);
}
}
if (putchar(ch) == EOF)
break;
}
if (fclose(stdout))
err(1, "stdout");
return 0;
}
static void __dead
usage(void)
{
fprintf(stderr, "usage: %s [-i | -s] [format]\n", getprogname());
exit(1);
}
/*
* yo dawg, i heard you like format strings
* so i put format strings in your user supplied input
* so you can format while you format
*/
static void
fmtfmt(struct tm *tm, long tv_nsec)
{
char *f, ms[7];
snprintf(ms, sizeof(ms), "%06ld", tv_nsec / 1000);
strlcpy(buf, format, bufsize);
f = buf;
do {
while ((f = strchr(f, '%')) != NULL && f[1] == '%')
f += 2;
if (f == NULL)
break;
f++;
if (f[0] == '.' &&
(f[1] == 'S' || f[1] == 's' || f[1] == 'T')) {
size_t l;
f[0] = f[1];
f[1] = '.';
f += 2;
l = strlen(f);
memmove(f + 6, f, l + 1);
memcpy(f, ms, 6);
f += 6;
}
} while (*f != '\0');
if (strftime(outbuf, bufsize, buf, tm) == 0)
errx(1, "strftime");
fprintf(stdout, "%s ", outbuf);
if (ferror(stdout))
exit(1);
}