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:
parent
353d4d9637
commit
acb1415e3c
@ -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
5
usr.bin/ts/Makefile
Normal 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
92
usr.bin/ts/ts.1
Normal 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
164
usr.bin/ts/ts.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user