snore

sleep with feedback
git clone git://git.bitsmanent.org/snore
Log | Files | Refs | README | LICENSE

commit cb7e376b5ff3dda9002174183f9fe3b29f1359f6
Author: Claudio Alessi <smoppy@gmail.com>
Date:   Fri, 22 Jan 2016 20:03:06 +0100

init

Diffstat:
ALICENSE | 21+++++++++++++++++++++
AMakefile | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AREADME.md | 20++++++++++++++++++++
Aconfig.mk | 25+++++++++++++++++++++++++
Asnore.1 | 20++++++++++++++++++++
Asnore.c | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 256 insertions(+), 0 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -0,0 +1,21 @@ +MIT/X Consortium License + +© 2016 Claudio Alessi <smoppy at gmail dot com> + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile @@ -0,0 +1,56 @@ +# snore - simple executor +# See LICENSE file for copyright and license details. + +include config.mk + +SRC = snore.c +OBJ = ${SRC:.c=.o} + +all: options snore + +options: + @echo snore build options: + @echo "CFLAGS = ${CFLAGS}" + @echo "LDFLAGS = ${LDFLAGS}" + @echo "CC = ${CC}" + +.c.o: + @echo CC $< + @${CC} -c ${CFLAGS} $< + +${OBJ}: config.mk + +snore: ${OBJ} + @echo CC -o $@ + @${CC} -o $@ ${OBJ} ${LDFLAGS} + +clean: + @echo cleaning + @rm -f snore ${OBJ} snore-${VERSION}.tar.gz + +dist: clean + @echo creating dist tarball + @mkdir -p snore-${VERSION} + @cp -R LICENSE Makefile README config.mk \ + snore.1 ${SRC} snore-${VERSION} + @tar -cf snore-${VERSION}.tar snore-${VERSION} + @gzip snore-${VERSION}.tar + @rm -rf snore-${VERSION} + +install: all + @echo installing executable file to ${DESTDIR}${PREFIX}/bin + @mkdir -p ${DESTDIR}${PREFIX}/bin + @cp -f snore ${DESTDIR}${PREFIX}/bin + @chmod 755 ${DESTDIR}${PREFIX}/bin/snore + @echo installing manual page to ${DESTDIR}${MANPREFIX}/man1 + @mkdir -p ${DESTDIR}${MANPREFIX}/man1 + @sed "s/VERSION/${VERSION}/g" < snore.1 > ${DESTDIR}${MANPREFIX}/man1/snore.1 + @chmod 644 ${DESTDIR}${MANPREFIX}/man1/snore.1 + +uninstall: + @echo removing executable file from ${DESTDIR}${PREFIX}/bin + @rm -f ${DESTDIR}${PREFIX}/bin/snore + @echo removing manual page from ${DESTDIR}${MANPREFIX}/man1 + @rm -f ${DESTDIR}${MANPREFIX}/man1/snore.1 + +.PHONY: all options clean dist install uninstall diff --git a/README.md b/README.md @@ -0,0 +1,20 @@ +snore - sleep with feedback +=========================== +snore pause for NUMBER seconds. SUFFIX may be 's' for seconds, 'm' for minutes, +'h' four hours or 'd' for days. If the suffix is wrong or not given 's' is +default. Given two or more arguments, pause for the amount of time specified by +the sum of their values. A visual feedback is given by printing the flowing of +time in both ascending and descending order. + +Installation +------------ +Edit config.mk to match your local setup (snore is installed into the +/usr/local namespace by default). + +Afterwards enter the following command to build and install snore (if +necessary as root): + + make clean install + +If you are going to use the default bluegray color scheme it is highly +recommended to also install the bluegray files shipped in the dextra package. diff --git a/config.mk b/config.mk @@ -0,0 +1,25 @@ +# snore version +VERSION = 0.1 + +# Customize below to fit your system + +# paths +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +# includes and libs +INCS = +LIBS = + +# flags +CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" +#CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +LDFLAGS = -s ${LIBS} + +# Solaris +#CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" +#LDFLAGS = ${LIBS} + +# compiler and linker +CC = cc diff --git a/snore.1 b/snore.1 @@ -0,0 +1,20 @@ +.TH SNORE 1 snore\-VERSION +.SH NAME +snore \- sleep with feedback +.SH SYNOPSIS +.B snore +.RB [ \-v ] +.RI [ NUMBER ...] +.SH DESCRIPTION +.B snore +pause for NUMBER seconds. SUFFIX may be 's' for seconds, 'm' for minutes, 'h' +four hours or 'd' for days. If the suffix is wrong or not given 's' is default. +Given two or more arguments, pause for the amount of time specified by the sum +of their values. A visual feedback is given by printing the flowing of time in +both ascending and descending order. +.SH AUTHORS +See the LICENSE file for the authors. +.SH LICENSE +See the LICENSE file for the terms of redistribution. +.SH SEE ALSO +.BR sleep (1) diff --git a/snore.c b/snore.c @@ -0,0 +1,114 @@ +/* See LICENSE for license details. */ +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define TICK 0250000 +#define DELTA ((double)TICK / 1000000) +#define SCLEAR "\r \r" +#define LENGTH(X) (sizeof X / sizeof X[0]) + +typedef struct symbol_t { + char sym; + int mult; + int precision; +} Symbol; + +void die(const char *errstr, ...); +int time_to_sec(char *s); +void time_print(double tm); + +/* must be in ascending order */ +static Symbol symbols[] = { + /* symbol, multiplier, precision */ + { 's', 1, 3 }, /* first is default (if no suffix) */ + { 'm', 60, 0 }, + { 'h', 3600, 0 }, + { 'd', 86400, 0 }, +}; + +void +die(const char *errstr, ...) { + va_list ap; + + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); +} + +int +time_to_sec(char *s) { + int i, j, len; + char tmp[16]; + + len = strlen(s); + for(i = 0; i < len; ++i) { + if(s[i] < 'a' || s[i] > 'z') + continue; + for(j = 0; j < LENGTH(symbols); ++j) { + if(s[i] == symbols[j].sym) { + strncpy(tmp, s, i + 1); + return atoi(tmp) * symbols[j].mult; + } + } + + /* unsupported suffix */ + return -1; + } + + /* no suffix specified, use the first */ + strncpy(tmp, s, i + 1); + return atoi(tmp) * symbols[0].mult; +} + +void +time_print(double tm) { + double piece; + int i; + char buf[10], *p; + + /* high to low */ + for(i = LENGTH(symbols) - 1; i >= 0; --i) { + piece = tm / symbols[i].mult; + snprintf(buf, sizeof buf, "%f", piece); + p = strrchr(buf, '.'); + if(symbols[i].precision) + p += 1 + symbols[i].precision; /* truncate */ + *p = '\0'; + printf("%s%c%s", buf, symbols[i].sym, i ? " " : ""); + tm -= (int)piece * symbols[i].mult; + } +} + +int +main(int argc, char *argv[]) { + double tm, endtm; + int i; + + if(argc < 2) + die("Usage: %s [-v] [time ...]\n", *argv); + if(!strcmp("-v", argv[1])) + die("snore-"VERSION", © 2016 Claudio Alessi, see LICENSE for details\n"); + + endtm = 0; + for(i = 1; i < argc; ++i) { + tm = time_to_sec(argv[i]); + if(tm < 0) + die("%s: wrong time\n", argv[i]); + endtm += time_to_sec(argv[i]); + } + + for(tm = 0; tm < endtm; tm += DELTA) { + time_print(tm); /* ascending */ + printf(" | "); + time_print(endtm - tm); /* descending */ + fflush(stdout); + usleep(TICK); + printf("%s", SCLEAR); + } + printf("\a%s elapsed\n", argv[1]); + return 0; +}