Some sample status scripts 0.02
authorStiletto <blasux@blasux.ru>
Mon, 20 Oct 2014 22:59:08 +0400
changeset 1 3e9290bf7249
parent 0 a22a319f5129
child 2 f303b1affcff
Some sample status scripts
.hgignore
LICENSE
Makefile
Makefile.status.inc
README
config.def.h
config.mk
dpoke.c
status-loadavg/Makefile
status-loadavg/config.def.h
status-loadavg/config.mk
status-loadavg/loadavg.c
status-mem/Makefile
status-mem/config.def.h
status-mem/config.mk
status-mem/mem.c
status-time/Makefile
status-time/config.def.h
status-time/config.mk
status-time/time.c
--- 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-.*/.*$
--- /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 <blasux@blasux.ru>
+
+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.
--- 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
--- /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
--- /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.
--- 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 <X11/Xlib.h>
+
+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
--- 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
--- 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;
 }
 /*
--- /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
--- /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
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#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("<span %s>%.2f</span> <span %s>%.2f</span> <span %s>%.2f</span>\n",
+            cols[0], avgs[0], cols[1], avgs[1], cols[2], avgs[2]);
+        fflush(stdout);
+        sleep(UPDATE_PERIOD);
+    }
+}
--- /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
--- /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
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#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("<span %s>%d/%d</span>\n", color, used/1024, total/1024);
+        fflush(stdout);
+	sleep(UPDATE_PERIOD);
+    }
+}
--- /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
--- /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
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <time.h>
+
+#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);
+    }
+}