dwmblocks

I use polybar now
Log | Files | Refs | README | LICENSE

dwmblocks.c (4656B)


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