dwmblocks

fork of dwmblocks
git clone git://popovic.xyz/dwmblocks.git
Log | Files | Refs | README | LICENSE

dwmblocks.c (4830B)


      1 #include<stdlib.h>
      2 #include<stdio.h>
      3 #include<string.h>
      4 #include<unistd.h>
      5 #include<signal.h>
      6 #include <time.h>
      7 #include<X11/Xlib.h>
      8 #define LENGTH(X)               (sizeof(X) / sizeof (X[0]))
      9 #define CMDLENGTH		50
     10 
     11 typedef struct {
     12 	char* icon;
     13 	char* command;
     14 	unsigned int interval;
     15 	unsigned int signal;
     16 } Block;
     17 void sighandler(int num);
     18 void buttonhandler(int sig, siginfo_t *si, void *ucontext);
     19 void replace(char *str, char old, char new);
     20 void remove_all(char *str, char to_remove);
     21 void getcmds(int time);
     22 #ifndef __OpenBSD__
     23 void getsigcmds(int signal);
     24 void setupsignals();
     25 void sighandler(int signum);
     26 #endif
     27 int getstatus(char *str, char *last);
     28 void setroot();
     29 void statusloop();
     30 void termhandler(int signum);
     31 
     32 
     33 #include "config.h"
     34 
     35 static Display *dpy;
     36 static int screen;
     37 static Window root;
     38 static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
     39 static char statusstr[2][256];
     40 static int statusContinue = 1;
     41 static void (*writestatus) () = setroot;
     42 
     43 void replace(char *str, char old, char new)
     44 {
     45 	int N = strlen(str);
     46 	for(int i = 0; i < N; i++)
     47 		if(str[i] == old)
     48 			str[i] = new;
     49 }
     50 
     51 void remove_all(char *str, char to_remove) {
     52 	char *read = str;
     53 	char *write = str;
     54 	while (*read) {
     55 		if (*read == to_remove) {
     56 			read++;
     57 			*write = *read;
     58 		}
     59 		read++;
     60 		write++;
     61 	}
     62 }
     63 
     64 //opens process *cmd and stores output in *output
     65 void getcmd(const Block *block, char *output)
     66 {
     67     nanosleep((const struct timespec[]){{0, 50000000L}}, NULL);
     68 
     69 	if (block->signal)
     70 	{
     71 		output[0] = block->signal;
     72 		output++;
     73 	}
     74 	strcpy(output, block->icon);
     75 	char *cmd = block->command;
     76 	FILE *cmdf = popen(cmd,"r");
     77 	if (!cmdf)
     78 		return;
     79 	char c;
     80 	int i = strlen(block->icon);
     81 	fgets(output+i, CMDLENGTH-(strlen(delim)+1), cmdf);
     82 	remove_all(output, '\n');
     83 	i = strlen(output);
     84     if ((i > 0 && block != &blocks[LENGTH(blocks) - 1]))
     85         strcat(output, delim);
     86     i+=strlen(delim);
     87 	output[i++] = '\0';
     88 	pclose(cmdf);
     89 }
     90 
     91 void getcmds(int time)
     92 {
     93 	const Block* current;
     94 	for(int i = 0; i < LENGTH(blocks); i++)
     95 	{
     96 		current = blocks + i;
     97 		if ((current->interval != 0 && time % current->interval == 0) || time == -1)
     98 			getcmd(current,statusbar[i]);
     99 	}
    100 }
    101 
    102 #ifndef __OpenBSD__
    103 void getsigcmds(int signal)
    104 {
    105 	const Block *current;
    106 	for (int i = 0; i < LENGTH(blocks); i++)
    107 	{
    108 		current = blocks + i;
    109 		if (current->signal == signal)
    110 			getcmd(current,statusbar[i]);
    111 	}
    112 }
    113 
    114 void setupsignals()
    115 {
    116 	struct sigaction sa;
    117 	for(int i = 0; i < LENGTH(blocks); i++)
    118 	{
    119 		if (blocks[i].signal > 0)
    120 		{
    121 			signal(SIGRTMIN+blocks[i].signal, sighandler);
    122 			sigaddset(&sa.sa_mask, SIGRTMIN+blocks[i].signal);
    123 		}
    124 	}
    125 	sa.sa_sigaction = buttonhandler;
    126 	sa.sa_flags = SA_SIGINFO;
    127 	sigaction(SIGUSR1, &sa, NULL);
    128 	struct sigaction sigchld_action = {
    129   		.sa_handler = SIG_DFL,
    130   		.sa_flags = SA_NOCLDWAIT
    131 	};
    132 	sigaction(SIGCHLD, &sigchld_action, NULL);
    133 
    134 }
    135 #endif
    136 
    137 int getstatus(char *str, char *last)
    138 {
    139 	strcpy(last, str);
    140 	str[0] = '\0';
    141     for(int i = 0; i < LENGTH(blocks); i++) {
    142 		strcat(str, statusbar[i]);
    143         if (i == LENGTH(blocks) - 1)
    144             strcat(str, " ");
    145     }
    146 	str[strlen(str)-1] = '\0';
    147 	return strcmp(str, last);//0 if they are the same
    148 }
    149 
    150 void setroot()
    151 {
    152 	if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed.
    153 		return;
    154 	Display *d = XOpenDisplay(NULL);
    155 	if (d) {
    156 		dpy = d;
    157 	}
    158 	screen = DefaultScreen(dpy);
    159 	root = RootWindow(dpy, screen);
    160 	XStoreName(dpy, root, statusstr[0]);
    161 	XCloseDisplay(dpy);
    162 }
    163 
    164 void pstdout()
    165 {
    166 	if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed.
    167 		return;
    168 	printf("%s\n",statusstr[0]);
    169 	fflush(stdout);
    170 }
    171 
    172 
    173 void statusloop()
    174 {
    175 #ifndef __OpenBSD__
    176 	setupsignals();
    177 #endif
    178 	int i = 0;
    179 	getcmds(-1);
    180 	while(statusContinue)
    181 	{
    182 		getcmds(i);
    183 		writestatus();
    184 		sleep(1.0);
    185 		i++;
    186 	}
    187 }
    188 
    189 #ifndef __OpenBSD__
    190 void sighandler(int signum)
    191 {
    192 	getsigcmds(signum-SIGRTMIN);
    193 	writestatus();
    194 }
    195 
    196 void buttonhandler(int sig, siginfo_t *si, void *ucontext)
    197 {
    198 	char button[2] = {'0' + si->si_value.sival_int & 0xff, '\0'};
    199 	pid_t process_id = getpid();
    200 	sig = si->si_value.sival_int >> 8;
    201 	if (fork() == 0)
    202 	{
    203 		const Block *current;
    204 		for (int i = 0; i < LENGTH(blocks); i++)
    205 		{
    206 			current = blocks + i;
    207 			if (current->signal == sig)
    208 				break;
    209 		}
    210 		char shcmd[1024];
    211 		sprintf(shcmd,"%s && kill -%d %d",current->command, current->signal+34,process_id);
    212 		char *command[] = { "/bin/sh", "-c", shcmd, NULL };
    213 		setenv("BLOCK_BUTTON", button, 1);
    214 		setsid();
    215 		execvp(command[0], command);
    216 		exit(EXIT_SUCCESS);
    217 	}
    218 }
    219 
    220 #endif
    221 
    222 void termhandler(int signum)
    223 {
    224 	statusContinue = 0;
    225 	exit(0);
    226 }
    227 
    228 int main(int argc, char** argv)
    229 {
    230 	for(int i = 0; i < argc; i++)
    231 	{
    232 		if (!strcmp("-d",argv[i]))
    233 			delim = argv[++i];
    234 		else if(!strcmp("-p",argv[i]))
    235 			writestatus = pstdout;
    236 	}
    237 	signal(SIGTERM, termhandler);
    238 	signal(SIGINT, termhandler);
    239 	statusloop();
    240 }