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