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 }