sistema_progs

Programas para customizar o meu entorno de traballo nos meus equipos persoais
Log | Files | Refs

dwmblocks.c (5413B)


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