My personal build for dwm statusbar.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

228 lines
4.3 KiB

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