dwmblocks.c (4331B) - raw


      1 #include<stdlib.h>
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<unistd.h>
      5 #include<signal.h>
      6 #ifndef NO_X
      7 #include<X11/Xlib.h>
      8 #endif
      9 #ifdef __OpenBSD__
     10 #define SIGPLUS                 SIGUSR1+1
     11 #define SIGMINUS                SIGUSR1-1
     12 #else
     13 #define SIGPLUS                 SIGRTMIN
     14 #define SIGMINUS                SIGRTMIN
     15 #endif
     16 #define LENGTH(X)               (sizeof(X) / sizeof (X[0]))
     17 #define CMDLENGTH               50
     18 #define MIN( a, b ) ( ( a < b) ? a : b )
     19 #define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1)
     20 
     21 typedef struct {
     22 	char* command;
     23 	unsigned int interval;
     24 	unsigned int signal;
     25 } Block;
     26 #ifndef __OpenBSD__
     27 void dummysighandler(int num);
     28 #endif
     29 void sighandler(int num);
     30 void getcmds(int time);
     31 void getsigcmds(unsigned int signal);
     32 void setupsignals();
     33 void sighandler(int signum);
     34 int getstatus(char *str, char *last);
     35 void statusloop();
     36 void termhandler();
     37 void pstdout();
     38 #ifndef NO_X
     39 void setroot();
     40 static void (*writestatus) () = setroot;
     41 static int setupX();
     42 static Display *dpy;
     43 static int screen;
     44 static Window root;
     45 #else
     46 static void (*writestatus) () = pstdout;
     47 #endif
     48 
     49 #include "config.h"
     50 
     51 static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
     52 static char statusstr[2][STATUSLENGTH];
     53 static int statusContinue = 1;
     54 static int returnStatus = 0;
     55 
     56 /* opens process *cmd and stores output in *output */
     57 void getcmd(const Block *block, char *output)
     58 {
     59 	int i;
     60 	FILE *cmdf = popen(block->command, "r");
     61 	if (!cmdf)
     62 		return;
     63 	if (fgets(output, CMDLENGTH-strlen(delim), cmdf) == NULL)
     64 		output[0] = '\0';
     65 	pclose(cmdf);
     66 
     67 	i = strlen(output);
     68 	i = (i && output[i-1] == '\n') ? i-1 : i;   /* delete trailing newline */
     69 	if (i == 0)     /* ensure length 0 in case the string was "\n" */
     70 		output[0] = '\0';   /* ensure length 0 in case the string was "\n" */
     71 	else            /* only add delimiter if output not empty */
     72 		strcpy(output+i, delim);
     73 }
     74 
     75 void getcmds(int time)
     76 {
     77 	const Block* current;
     78 	for (unsigned int i = 0; i < LENGTH(blocks); i++) {
     79 		current = blocks + i;
     80 		if ((current->interval != 0 && time % current->interval == 0) || time == -1)
     81 			getcmd(current, statusbar[i]);
     82 	}
     83 }
     84 
     85 void getsigcmds(unsigned int signal)
     86 {
     87 	const Block *current;
     88 	for (unsigned int i = 0; i < LENGTH(blocks); i++) {
     89 		current = blocks + i;
     90 		if (current->signal == signal)
     91 			getcmd(current, statusbar[i]);
     92 	}
     93 }
     94 
     95 void setupsignals()
     96 {
     97 #ifndef __OpenBSD__
     98 	/* initialize all real time signals with dummy handler */
     99 	for (int i = SIGRTMIN; i <= SIGRTMAX; i++)
    100 		signal(i, dummysighandler);
    101 #endif
    102 
    103 	for (unsigned int i = 0; i < LENGTH(blocks); i++) {
    104 		if (blocks[i].signal > 0)
    105 			signal(SIGMINUS+blocks[i].signal, sighandler);
    106 	}
    107 }
    108 
    109 int getstatus(char *str, char *last)
    110 {
    111 	strcpy(last, str);
    112 	strcpy(str, " ");       /* add leading space to status bar */
    113 	for (unsigned int i = 0; i < LENGTH(blocks); i++)
    114 		strcat(str, statusbar[i]);
    115 	str[strlen(str)-strlen(delim)] = '\0';
    116 	return strcmp(str, last);       /* 0 if they are the same */
    117 }
    118 
    119 #ifndef NO_X
    120 void setroot()
    121 {
    122 	/* only set root if text has changed */
    123 	if (!getstatus(statusstr[0], statusstr[1]))
    124 		return;
    125 	XStoreName(dpy, root, statusstr[0]);
    126 	XFlush(dpy);
    127 }
    128 
    129 int setupX()
    130 {
    131 	dpy = XOpenDisplay(NULL);
    132 	if (!dpy) {
    133 		fprintf(stderr, "dwmblocks: Failed to open display\n");
    134 		return 0;
    135 	}
    136 	screen = DefaultScreen(dpy);
    137 	root = RootWindow(dpy, screen);
    138 	return 1;
    139 }
    140 #endif
    141 
    142 void pstdout()
    143 {
    144 	/* only write out if text has changed */
    145 	if (!getstatus(statusstr[0], statusstr[1]))
    146 		return;
    147 	printf("%s\n", statusstr[0]);
    148 	fflush(stdout);
    149 }
    150 
    151 void statusloop()
    152 {
    153 	setupsignals();
    154 	int i = 0;
    155 	getcmds(-1);
    156 	while (1) {
    157 		getcmds(i++);
    158 		writestatus();
    159 		if (!statusContinue)
    160 			break;
    161 		sleep(1.0);
    162 	}
    163 }
    164 
    165 #ifndef __OpenBSD__
    166 /* this signal handler should do nothing */
    167 void dummysighandler(int signum)
    168 {
    169 	return;
    170 }
    171 #endif
    172 
    173 void sighandler(int signum)
    174 {
    175 	getsigcmds(signum-SIGPLUS);
    176 	writestatus();
    177 }
    178 
    179 void termhandler()
    180 {
    181 	statusContinue = 0;
    182 }
    183 
    184 int main(int argc, char** argv)
    185 {
    186 	/* handle command line arguments */
    187 	for (int i = 0; i < argc; i++) {
    188 		if (!strcmp("-d", argv[i]))
    189 			strcpy(delim, argv[++i]);
    190 		else if (!strcmp("-p", argv[i]))
    191 			writestatus = pstdout;
    192 	}
    193 #ifndef NO_X
    194 	if (!setupX())
    195 		return 1;
    196 #endif
    197 	signal(SIGTERM, termhandler);
    198 	signal(SIGINT, termhandler);
    199 	statusloop();
    200 #ifndef NO_X
    201 	XCloseDisplay(dpy);
    202 #endif
    203 	return 0;
    204 }