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 }