sistema_progs

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

dwmblocks_gerard.c (5272B)


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