--- /dev/null
+/* vi: set sw=4 ts=4: */
+/*
+ * Copyright (C) 2006 Michael Opdenacker <michael@free-electrons.com>
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+//config:config TS
+//config: bool "ts (450 bytes)"
+//config: default y
+
+//applet:IF_TS(APPLET(ts, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_TS) += ts.o
+
+//usage:#define ts_trivial_usage
+//usage: "[-is] [STRFTIME]"
+//usage:#define ts_full_usage ""
+
+#include "libbb.h"
+#include "common_bufsiz.h"
+# include <sys/syscall.h>
+
+int ts_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int ts_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
+{
+ struct timespec base;
+ unsigned opt;
+ char *frac;
+ char *fmt_dt2str;
+ char *line;
+
+ opt = getopt32(argv, "^" "is" "\0" "?1" /*max one arg*/);
+ if (opt) {
+ putenv((char*)"TZ=UTC0");
+ tzset();
+ }
+ /*argc -= optind;*/
+ argv += optind;
+ fmt_dt2str = argv[0] ? argv[0]
+ : (char*)(opt ? "%b %d %H:%M:%S"+6 : "%b %d %H:%M:%S");
+ frac = is_suffixed_with(fmt_dt2str, "%.S");
+ if (!frac)
+ frac = is_suffixed_with(fmt_dt2str, "%.s");
+ if (frac) {
+ frac++;
+ strcpy(frac, frac + 1);
+ }
+
+#define date_buf bb_common_bufsiz1
+ setup_common_bufsiz();
+ syscall(__NR_clock_gettime, CLOCK_REALTIME, &base);
+
+ while ((line = xmalloc_fgets(stdin)) != NULL) {
+ struct timespec ts;
+ struct tm tm_time;
+
+ /* libc has incredibly messy way of doing this,
+ * typically requiring -lrt. We just skip all this mess
+ */
+ syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts);
+ if (opt) {
+ /* -i and/or -s */
+ struct timespec ts1 = ts1;
+ if (opt & 1) /* -i */
+ ts1 = ts;
+//printf("%d %d\n", ts.tv_sec, base.tv_sec);
+ ts.tv_sec -= base.tv_sec;
+//printf("%d %d\n", ts.tv_sec, base.tv_sec);
+ ts.tv_nsec -= base.tv_nsec;
+ if ((int32_t)(ts.tv_nsec) < 0) {
+ ts.tv_sec--;
+ ts.tv_nsec += 1000*1000*1000;
+ }
+ if (opt & 1) /* -i */
+ base = ts1;
+ localtime_r(&ts.tv_sec, &tm_time);
+ }
+ strftime(date_buf, COMMON_BUFSIZE, fmt_dt2str, &tm_time);
+ if (!frac) {
+ printf("%s %s", date_buf, line);
+ } else {
+ printf("%s.%06u %s", date_buf, (unsigned)ts.tv_nsec / 1000u, line);
+ }
+ free(line);
+ }
+
+ return EXIT_SUCCESS;
+}