tfirst commit - stopwatch - simple timer for console or x root window
git clone git://src.adamsgaard.dk/stopwatch
Log
Files
Refs
README
LICENSE
---
commit 3390af26250ccad0fd7e796c2325c94f5dbe538c
Author: Anders Damsgaard 
Date:   Wed,  4 Nov 2020 14:56:30 +0100

first commit

Diffstat:
  A LICENSE                             |      15 +++++++++++++++
  A Makefile                            |      63 +++++++++++++++++++++++++++++++
  A README                              |      18 ++++++++++++++++++
  A stopwatch.1                         |      45 +++++++++++++++++++++++++++++++
  A stopwatch.c                         |     105 +++++++++++++++++++++++++++++++

5 files changed, 246 insertions(+), 0 deletions(-)
---
diff --git a/LICENSE b/LICENSE
t@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2020 Anders Damsgaard 
+
+Permission to use, copy, modify, and/or 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.
diff --git a/Makefile b/Makefile
t@@ -0,0 +1,63 @@
+.POSIX:
+
+NAME = stopwatch
+VERSION = 0.1
+
+# paths
+PREFIX = /usr/local
+MANPREFIX = ${PREFIX}/share/man
+DOCPREFIX = ${PREFIX}/share/doc/${NAME}
+
+BIN = ${NAME}
+SRC = ${BIN:=.c}
+MAN1 = ${BIN:=.1}
+DOC = \
+        LICENSE\
+        README
+
+all: ${BIN}
+
+CFLAGS = -DVERSION=\"${VERSION}\" -I/usr/X11R6/include
+LDFLAGS = -L/usr/X11R6/lib -lX11
+
+${BIN}: ${@:=.o}
+
+.o:
+        ${CC} ${LDFLAGS} -o $@ $<
+
+.c.o:
+        ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ -c $<
+
+dist:
+        rm -rf "${NAME}-${VERSION}"
+        mkdir -p "${NAME}-${VERSION}"
+        cp -f ${MAN1} ${DOC} ${SRC} Makefile "${NAME}-${VERSION}"
+        tar cf - "${NAME}-${VERSION}" | gzip -c > "${NAME}-${VERSION}.tar.gz"
+        rm -rf "${NAME}-${VERSION}"
+
+clean:
+        rm -f ${BIN} ${OBJ}
+
+install:
+        # installing executable files.
+        mkdir -p "${DESTDIR}${PREFIX}/bin"
+        cp -f ${BIN} "${DESTDIR}${PREFIX}/bin"
+        for f in ${BIN}; do chmod 755 "${DESTDIR}${PREFIX}/bin/$$f"; done
+        # installing documentation files.
+        mkdir -p "${DESTDIR}${DOCPREFIX}"
+        cp -f ${DOC} "${DESTDIR}${DOCPREFIX}"
+        # installing manual pages for general commands: section 1.
+        mkdir -p "${DESTDIR}${DOCPREFIX}/man1"
+        cp -f ${MAN1} "${DESTDIR}${MANPREFIX}/man1"
+        for m in ${MAN1}; do chmod 644 "${DESTDIR}${MANPREFIX}/man1/$$m"; done
+
+uninstall:
+        # removing executable files.
+        for f in ${BIN}; do rm -f "${DESTDIR}${PREFIX}/bin/$$f"; done
+        # removing documentation files.
+        for d in ${DOC}; do rm -f "${DESTDIR}${DOCPREFIX}/$$d"; done
+        -rmdir "${DESTDIR}${DOCPREFIX}"
+        # removing manual pages.
+        for m in ${MAN1}; do rm -f "${DESTDIR}${MANPREFIX}/man1/$$m"; done
+
+.PHONY: all clean dist install uninstall
diff --git a/README b/README
t@@ -0,0 +1,18 @@
+# stopwatch
+
+About: A simple stopwatch which can print the output to the terminal or
+       the X root window parameter.  The latter is used for setting the
+       dwm(1) title bar.
+
+Compiling: `make && make install`
+           (optionally prefix the install comman with sudo(1) or doas(1))
+
+Compatibility: Tested on OpenBSD 6.8
+
+Documentation: `man 1 stopwatch`
+
+Copyright: See LICENSE
+
+Author: Anders Damsgaard 
+        git://src.adamsgaard.dk/stopwatch
+        https://src.adamsgaard.dk/stopwatch
diff --git a/stopwatch.1 b/stopwatch.1
t@@ -0,0 +1,45 @@
+.Dd $Mdocdate$
+.Dt STOPWATCH 1
+.Os
+.Sh NAME
+.Nm stopwatch
+.Nd reports elapsed time after launch.
+.Sh SYNOPSIS
+.Nm
+.Op Fl p Ar prefix
+.Op Fl P Ar postfix
+.Op Fl i Ar interval
+.Op Fl x
+.Sh DESCRIPTION
+The
+.Nm
+prints the elapsed time to standard output by default.  The time
+is written in the format "%S s" for elapsed durations less than one
+minute long, "%M:%SS" for durations less than one hour, and
+"%H:%MM:%SS" for all longer durations.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl p Ar prefix
+Print the
+.Ar prefix
+string before the time stamp.
+.It Fl P Ar postfix
+Print the
+.Ar postfix
+string after the time stamp.
+.It Fl i Ar interval
+update the elapsed time with this interval in seconds.
+.It Fl x
+write the output to the X root window parameter, which
+.Xr dwm 1
+uses as status line.
+.Sh EXIT STATUS
+.Nm
+exits with 0 on success, and >0 if a a runtime error occurs.
+.Sh SEE ALSO
+.Xr dwm 1
+.Xr spoon 1
+.Xr xsetroot 1
+.Sh AUTHORS
+.An Anders Damsgaard Aq Mt anders@adamsgaard.dk
diff --git a/stopwatch.c b/stopwatch.c
t@@ -0,0 +1,105 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+void
+usage(char *argv0)
+{
+        errx(1, "usage: %s [-p prefix] [-P postfix] [-i interval] [-x]", argv0);
+}
+
+void
+format_time(char *out, size_t outsiz, time_t t_elapsed, char *prefix, char *postfix)
+{
+        time_t h = 0, m = 0, s = 0;
+
+        h = t_elapsed / 3600;
+        m = (t_elapsed % 3600) / 60;
+        s = t_elapsed % 60;
+
+        if (h > 0)
+                snprintf(out, outsiz, "%s%lld:%02lld:%02lld%s",
+                         prefix, h, m, s, postfix);
+        else if (m > 0)
+                snprintf(out, outsiz, "%s%lld:%02lld%s", prefix, m, s, postfix);
+        else
+                snprintf(out, outsiz, "%s%lld s%s", prefix, s, postfix);
+}
+
+void
+print_loop(unsigned int interval, char *prefix, char *postfix)
+{
+        char buf[LINE_MAX];
+        time_t t_start = time(NULL);
+
+        while (1) {
+                format_time(buf, sizeof(buf), time(NULL) - t_start, prefix, postfix);
+                printf("\r%s\n", buf);
+                fflush(stdout);
+                sleep(interval);
+        }
+}
+
+void
+xroot_loop(unsigned int interval, char *prefix, char *postfix)
+{
+        Display *dpy;
+        char buf[LINE_MAX];
+        time_t t_start = time(NULL);
+
+        dpy = XOpenDisplay(NULL);
+        if (dpy == NULL)
+                errx(1, "cannot open display");
+        while (1) {
+                format_time(buf, sizeof(buf), time(NULL) - t_start, prefix, postfix);
+                XStoreName(dpy, DefaultRootWindow(dpy), buf);
+                XSync(dpy, False);
+                sleep(interval);
+        }
+}
+
+int
+main(int argc, char *argv[])
+{
+        int ch, xflag = 0;
+        unsigned int interval = 1;
+        char prefix[LINE_MAX] = "", postfix[LINE_MAX] = "";
+        const char *errstr;
+
+        while ((ch = getopt(argc, argv, "p:P:i:x")) != -1) {
+                switch (ch) {
+                case 'p':
+                        strlcpy(prefix, optarg, sizeof(prefix));
+                        break;
+                case 'P':
+                        strlcpy(postfix, optarg, sizeof(postfix));
+                        break;
+                case 'i':
+                        interval = strtonum(optarg, 1, UINT_MAX, &errstr);
+                        if (errstr != NULL)
+                                errx(1, "interval is %s: %s", errstr, optarg);
+                        break;
+                case 'x':
+                        xflag = 1;
+                        break;
+                default:
+                        usage(argv[0]);
+                }
+        }
+        argc -= optind;
+        argv += optind;
+        if (argc > 0)
+                usage(argv[0]);
+
+        if (xflag)
+                xroot_loop(interval, prefix, postfix);
+        else
+                print_loop(interval, prefix, postfix);
+
+        return 0;
+}