# HG changeset patch # User Stiletto # Date 1413831548 -14400 # Node ID 3e9290bf7249e715935a1a160d5d4bf962ccd23e # Parent a22a319f5129ce0ce7fa0b453480f80489164b24 Some sample status scripts diff -r a22a319f5129 -r 3e9290bf7249 .hgignore --- a/.hgignore Sat Mar 16 00:03:51 2013 +0400 +++ b/.hgignore Mon Oct 20 22:59:08 2014 +0400 @@ -3,4 +3,6 @@ ^shi_buftest$ ^shi_dietest$ ^config.h$ - +^status-.*/status-.*$ +^status-.*/config.h$ +^dpoke-.*/.*$ diff -r a22a319f5129 -r 3e9290bf7249 LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,21 @@ +MIT/X Consortium License + +© 2013-2014 Stiletto + +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 -r a22a319f5129 -r 3e9290bf7249 Makefile --- a/Makefile Sat Mar 16 00:03:51 2013 +0400 +++ b/Makefile Mon Oct 20 22:59:08 2014 +0400 @@ -1,22 +1,22 @@ -# dwm - dynamic window manager # See LICENSE file for copyright and license details. +# Build system is based on build system of dwm. include config.mk SRC = dpoke.c OBJ = ${SRC:.c=.o} -all: options dpoke +all: options dpoke status options: @echo dpoke build options: - @echo "CFLAGS = ${CFLAGS}" - @echo "LDFLAGS = ${LDFLAGS}" + @echo "CFLAGS = ${DPOKE_CFLAGS}" + @echo "LDFLAGS = ${DPOKE_LDFLAGS}" @echo "CC = ${CC}" .c.o: @echo CC $< - @${CC} -c ${CFLAGS} $< + @${CC} -c ${DPOKE_CFLAGS} $< ${OBJ}: config.h config.mk @@ -26,19 +26,23 @@ dpoke: ${OBJ} @echo CC -o $@ - @${CC} -o $@ ${OBJ} ${LDFLAGS} + @${CC} -o $@ ${OBJ} ${DPOKE_LDFLAGS} clean: @echo cleaning @rm -f dpoke ${OBJ} dpoke-${VERSION}.tar.gz + @for dir in $(STATUS); do make -C $$dir clean; done dist: clean @echo creating dist tarball @mkdir -p dpoke-${VERSION} - @cp -R LICENSE Makefile README config.def.h config.mk \ - ${SRC} dpoke-${VERSION} + @cp -R LICENSE Makefile* README config.def.h config.mk \ + ${SRC} status-* dpoke-${VERSION} @tar -cf dpoke-${VERSION}.tar dpoke-${VERSION} @gzip dpoke-${VERSION}.tar @rm -rf dpoke-${VERSION} +status: + for dir in $(STATUS); do make -C $$dir; done + .PHONY: all options clean dist diff -r a22a319f5129 -r 3e9290bf7249 Makefile.status.inc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile.status.inc Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,28 @@ +all: options ${OUT} + +options: + @echo ${OUT} build options: + @echo "CFLAGS = ${STATUS_CFLAGS}" + @echo "LDFLAGS = ${STATUS_LDFLAGS}" + @echo "CC = ${CC}" + + +${OBJ}: ${CONFIG} config.mk + +%.o: %.c + @echo CC $< + @${CC} -c ${STATUS_CFLAGS} $< + +${OUT}: ${OBJ} + @echo CC -o $@ + @${CC} -o $@ ${OBJ} ${STATUS_LDFLAGS} + +${CONFIG}: + @echo creating $@ from default + @cp config.def.h config.h + +clean: + @echo cleaning ${OUT} + @rm -f ${OUT} ${OBJ} ${CONFIG} + +.PHONY: all clean diff -r a22a319f5129 -r 3e9290bf7249 README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,26 @@ +dpoke - dynamic status bar updater +================================== +dpoke is a simple application for updating dwm status bar. +It is kinda Unix-way and extensible. + + +Requirements +------------ +In order to build dpoke and use it with dwm you need the Xlib header files. +However, dpoke can be configured not to use X11 and Xlib and output to console. + + +Installation +------------ +Edit config.mk to match your local setup. + + +Running dpoke +------------- +Start dpoke from your session manager or xinitrc. + + +Configuration +------------- +The configuration of dpoke is done by creating a custom config.h +and (re)compiling the source code. diff -r a22a319f5129 -r 3e9290bf7249 config.def.h --- a/config.def.h Sat Mar 16 00:03:51 2013 +0400 +++ b/config.def.h Mon Oct 20 22:59:08 2014 +0400 @@ -1,8 +1,7 @@ static DPokeSource sources[] = { - { DPOKE_PROGRAM, "./shi_date.sh" }, - { DPOKE_PROGRAM, "./shi_buftest" }, - { DPOKE_PROGRAM, "./shi_dietest" }, - { DPOKE_PROGRAM, "/bin/true" }, + { DPOKE_PROGRAM, "./status-mem/status-mem" }, + { DPOKE_PROGRAM, "./status-loadavg/status-loadavg" }, + { DPOKE_PROGRAM, "./status-time/status-time" }, }; #define FAILURE_MSG "FAILURE" @@ -10,6 +9,40 @@ #define MINTIME 1.0 //#define DEBUG +#include + +Display *dpy; +Window rootwin; +int scr; + +void display(char* v[], size_t vc) { + char *new_title = smprintf("%s | %s | %s",v[0],v[1],v[2]); + XStoreName(dpy, rootwin, new_title); + //printf("set: %s\n", new_title); + XSync(dpy, False); + free(new_title); +} + +void setup() { + if(!(dpy=XOpenDisplay(NULL))) { + fprintf(stderr, "ERROR: could not open display\n"); + exit(21); + } + scr = DefaultScreen(dpy); + rootwin = RootWindow(dpy, scr); +} + +void cleanup(int exitcode) { + XCloseDisplay(dpy); +} + +#if 0 +// no-X11 variant: void display() { printf("%s | <%s> | %s | %s\n",v[0],v[1],v[2],v[3]); } +void setup() { +} +void cleanup(int exitcode) { +} +#endif diff -r a22a319f5129 -r 3e9290bf7249 config.mk --- a/config.mk Sat Mar 16 00:03:51 2013 +0400 +++ b/config.mk Mon Oct 20 22:59:08 2014 +0400 @@ -1,19 +1,21 @@ -# dwm version -VERSION = 0.01 +# dpoke version +VERSION = 0.02 # Customize below to fit your system # includes and libs -#INCS = -I. -I/usr/include -I${X11INC} `pkg-config --cflags xft pango pangoxft` -#LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS} `pkg-config --libs xft pango pangoxft` -LIBS = -L/usr/lib -lc -lrt -lm +DPOKE_LIBS = -L/usr/lib -lm -lX11 +DPOKE_INCS = +DPOKE_CPPFLAGS = -DVERSION=\"${VERSION}\" +DPOKE_CFLAGS = -g -std=c99 -pedantic -Wall -Os ${DPOKE_INCS} ${DPOKE_CPPFLAGS} +DPOKE_LDFLAGS = -g ${DPOKE_LIBS} -# flags -CPPFLAGS = -DVERSION=\"${VERSION}\" -CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -#CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} -LDFLAGS = -g ${LIBS} -#LDFLAGS = -s ${LIBS} +STATUS_LIBS = -L/usr/lib +STATUS_INCS = +STATUS_CPPFLAGS = -DVERSION=\"${VERSION}\" +STATUS_CFLAGS = -std=c99 -pedantic -Wall -Os ${STATUS_INCS} ${STATUS_CPPFLAGS} +STATUS_LDFLAGS = ${STATUS_LIBS} -static +STATUS = status-time status-mem status-loadavg # compiler and linker CC = cc diff -r a22a319f5129 -r 3e9290bf7249 dpoke.c --- a/dpoke.c Sat Mar 16 00:03:51 2013 +0400 +++ b/dpoke.c Mon Oct 20 22:59:08 2014 +0400 @@ -21,7 +21,7 @@ }; typedef enum DPokeSourceType_en DPokeSourceType; -#define DPOKE_BUFFER 32 +#define DPOKE_BUFFER 128 struct DPokeSource_st { DPokeSourceType type; char *path; @@ -48,35 +48,38 @@ #define LENGTH(X) (sizeof X / sizeof X[0]) -char* smprintf(char *fmt, ...) { - va_list fmtargs; - char *ret; - int len; +char * +smprintf(char *fmt, ...) +{ + va_list fmtargs; + char *ret; + int len; - va_start(fmtargs, fmt); - len = vsnprintf(NULL, 0, fmt, fmtargs); - va_end(fmtargs); + va_start(fmtargs, fmt); + len = vsnprintf(NULL, 0, fmt, fmtargs); + va_end(fmtargs); - ret = malloc(++len); - if (ret == NULL) { - perror("malloc"); - exit(1); - } + ret = malloc(++len); + if (ret == NULL) { + perror("malloc"); + exit(1); + } - va_start(fmtargs, fmt); - vsnprintf(ret, len, fmt, fmtargs); - va_end(fmtargs); + va_start(fmtargs, fmt); + vsnprintf(ret, len, fmt, fmtargs); + va_end(fmtargs); - return ret; + return ret; } - -void display(); +void display(char *v[], size_t vc); +void setup(void); +void cleanup(int exitcode); extern char* v[]; #include "config.h" #ifdef DEBUG -#define errprintf(...) fprintf(stderr,...) +#define errprintf(...) fprintf(stderr,__VA_ARGS__) #else #define errprintf(...) #endif @@ -85,6 +88,12 @@ static struct pollfd source_fds[LENGTH(sources)]; +void die(int exitcode) { + fprintf(stderr, "Dying with exit code %d\n", exitcode); + cleanup(exitcode); + exit(exitcode); +} + void source_open(int source_id) { DPokeSource *src = &sources[source_id]; //FILE* stream; @@ -94,12 +103,12 @@ //stream = popen(src->path, "r"); if (pipe(p_stdout)!=0) { perror("pipe"); - exit(7); + die(7); } pid_t pid = fork(); if (pid < 0) { perror("fork"); - exit(7); + die(7); } else if (pid == 0) { dup2(open("/dev/null",O_RDONLY),0); close(p_stdout[0]); @@ -113,7 +122,7 @@ break; default: errprintf("Don't know how to handle source type %d.\n",src->type); - exit(2); + die(2); } //src->stream = stream; //src->fd = fileno(stream); @@ -138,7 +147,7 @@ sources[i].status = DPOKE_DIED; break; default: errprintf("#%d died in state %d. Whaddafuck?!\n",i,sources[i].status); - exit(8); + die(8); } } } @@ -155,19 +164,20 @@ struct timespec tp; if (clock_gettime(CLOCK_MONOTONIC,&tp)) { perror("clock_gettime"); - exit(5); + die(5); } return tp.tv_sec + tp.tv_nsec*1E-9; } int main(int argc, char* argv[]) { + setup(); struct sigaction act; memset (&act, 0, sizeof(act)); act.sa_handler = sigchld_hdl; if (sigaction(SIGCHLD, &act, 0)) { perror ("sigaction"); - exit(6); + die(6); } for (int i = 0; i < LENGTH(sources); i++ ) { @@ -186,11 +196,13 @@ for (int i = 0; i < LENGTH(sources); i++) { DPokeSource *src = sources+i; if (source_fds[i].revents & POLLIN) { + errprintf("Event: %d\n", source_fds[i].revents); int data_read = read(src->fd,src->buffer+src->buffer_usage,DPOKE_BUFFER-src->buffer_usage); if (data_read>0) { src->buffer_usage += data_read; - if (src->buffer_usage==DPOKE_BUFFER) { - errprintf("Buffer is full for #%d.\n",i); + if (src->buffer_usage>=DPOKE_BUFFER) { + fprintf(stderr, "Buffer is full for #%d. Resetting.\n",i); + src->buffer_usage = 0; } src->buffer[src->buffer_usage] = '\0'; char* eolpos = strchr(src->buffer + src->buffer_usage - data_read,'\n'); @@ -203,8 +215,9 @@ if (src->status == DPOKE_STARTED) src->status = DPOKE_RUNNING; } else { + fprintf(stderr, "Buffer usage: %d\n", src->buffer_usage); perror("read"); - exit(3); + die(3); } } else if ((source_fds[i].revents & POLLHUP)||(src->status==DPOKE_DIED)) { errprintf("#%d HUP\n",i); @@ -224,7 +237,7 @@ } double curtime = dpoke_time(); if ((curtime-prevtime)>MINTIME) { - display(); + display(v,LENGTH(sources)); prevtime = curtime; sleeptime = 10000; } else { @@ -234,6 +247,7 @@ } errprintf("Will sleep for %d\n",sleeptime); } + cleanup(0); return 0; } /* diff -r a22a319f5129 -r 3e9290bf7249 status-loadavg/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-loadavg/Makefile Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,12 @@ +# dwm - dynamic window manager +# See LICENSE file for copyright and license details. + +include ../config.mk +include config.mk + +OUT = status-loadavg +SRC = loadavg.c +OBJ = ${SRC:.c=.o} +CONFIG = config.h + +include ../Makefile.status.inc diff -r a22a319f5129 -r 3e9290bf7249 status-loadavg/config.def.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-loadavg/config.def.h Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,4 @@ +#define GREEN 1.0 +#define ORANGE 4.0 + +#define UPDATE_PERIOD 15 diff -r a22a319f5129 -r 3e9290bf7249 status-loadavg/config.mk diff -r a22a319f5129 -r 3e9290bf7249 status-loadavg/loadavg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-loadavg/loadavg.c Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,35 @@ +#define _DEFAULT_SOURCE +#include +#include +#include +#include +#include + +#include "config.h" + +int +main(void) +{ + while (1) { + double avgs[3]; + char *cols[3]; + + if (getloadavg(avgs, 3) < 0) { + perror("getloadavg"); + exit(1); + } + for ( int i = 0; i < 3; i++ ) { + if ( avgs[i] <= GREEN ) + cols[i] = "color='green'"; + else if ( avgs[i] <= ORANGE ) + cols[i] = "color='orange'"; + else + cols[i] = "color='red'"; + } + + printf("%.2f %.2f %.2f\n", + cols[0], avgs[0], cols[1], avgs[1], cols[2], avgs[2]); + fflush(stdout); + sleep(UPDATE_PERIOD); + } +} diff -r a22a319f5129 -r 3e9290bf7249 status-mem/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-mem/Makefile Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,12 @@ +# dwm - dynamic window manager +# See LICENSE file for copyright and license details. + +include ../config.mk +include config.mk + +OUT = status-mem +SRC = mem.c +OBJ = ${SRC:.c=.o} +CONFIG = config.h + +include ../Makefile.status.inc diff -r a22a319f5129 -r 3e9290bf7249 status-mem/config.def.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-mem/config.def.h Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,4 @@ +#define GREEN 0.7 +#define ORANGE 0.8 +#define RED 0.9 +#define UPDATE_PERIOD 15 diff -r a22a319f5129 -r 3e9290bf7249 status-mem/config.mk diff -r a22a319f5129 -r 3e9290bf7249 status-mem/mem.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-mem/mem.c Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,58 @@ +#define _DEFAULT_SOURCE +#include +#include +#include +#include +#include + +#include "config.h" + +int +main(void) +{ + while (1) { + char line[513]; + FILE *fd; + + fd = fopen("/proc/meminfo", "r"); + if (fd == NULL) { + perror("fopen"); + exit(1); + } + + int free = 0; + int total = 0; + int sub; + while (!feof(fd)) { + if (fgets(line, sizeof(line)-1, fd) == NULL) + break; + + if (!strncmp(line, "MemTotal", 8)) + sscanf(line+9, "%*[ ]%d%*[^\n]", &total); + + if (!strncmp(line, "MemFree", 7)) + sscanf(line+8, "%*[ ]%d%*[^\n]", &free); + + if (!strncmp(line, "Buffers", 7)) { + sscanf(line+8, "%*[ ]%d%*[^\n]", &sub); + free += sub; + } + if (!strncmp(line, "Cached", 6)) { + sscanf(line+7, "%*[ ]%d%*[^\n]", &sub); + free += sub; + } + } + fclose(fd); + + int used = total - free; + + char *color; + if (used*1.0/total < GREEN) color = "color='green'"; + else if (used*1.0/total > RED) color = "color='red'"; + else if (used*1.0/total > ORANGE) color = "color='orange'"; + else color = ""; + printf("%d/%d\n", color, used/1024, total/1024); + fflush(stdout); + sleep(UPDATE_PERIOD); + } +} diff -r a22a319f5129 -r 3e9290bf7249 status-time/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-time/Makefile Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,11 @@ +# dwm - dynamic window manager +# See LICENSE file for copyright and license details. + +include ../config.mk + +OUT = status-time +SRC = time.c +OBJ = ${SRC:.c=.o} +CONFIG = config.h + +include ../Makefile.status.inc diff -r a22a319f5129 -r 3e9290bf7249 status-time/config.def.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-time/config.def.h Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,3 @@ +#define TIMEZONE "Europe/Moscow" +#define TIMEFORMAT "%d.%m.%Y %H:%M" +#define UPDATE_PERIOD 1 diff -r a22a319f5129 -r 3e9290bf7249 status-time/config.mk diff -r a22a319f5129 -r 3e9290bf7249 status-time/time.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/status-time/time.c Mon Oct 20 22:59:08 2014 +0400 @@ -0,0 +1,38 @@ +#define _DEFAULT_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +int +main(void) +{ + char buf[129]; + time_t tim; + struct tm *timtm; + + setenv("TZ", TIMEZONE, 1); + + while (1) { + bzero(buf, sizeof(buf)); + tim = time(NULL); + timtm = localtime(&tim); + if (timtm == NULL) { + perror("localtime"); + exit(1); + } + + if (!strftime(buf, sizeof(buf)-1, TIMEFORMAT, timtm)) { + fprintf(stderr, "strftime == 0\n"); + exit(1); + } + printf("%s\n", buf); + fflush(stdout); + sleep(UPDATE_PERIOD); + } +}