dwmblocks.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. typedef struct {
  21. char* icon;
  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. #include "blocks.h"
  49. static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
  50. static char statusstr[2][STATUSLENGTH];
  51. static int statusContinue = 1;
  52. static int returnStatus = 0;
  53. //opens process *cmd and stores output in *output
  54. void getcmd(const Block *block, char *output)
  55. {
  56. strcpy(output, block->icon);
  57. FILE *cmdf = popen(block->command, "r");
  58. if (!cmdf)
  59. return;
  60. int i = strlen(block->icon);
  61. fgets(output+i, CMDLENGTH-i-delimLen, cmdf);
  62. i = strlen(output);
  63. if (i == 0) {
  64. //return if block and command output are both empty
  65. pclose(cmdf);
  66. return;
  67. }
  68. if (delim[0] != '\0') {
  69. //only chop off newline if one is present at the end
  70. i = output[i-1] == '\n' ? i-1 : i;
  71. strncpy(output+i, delim, delimLen);
  72. }
  73. else
  74. output[i++] = '\0';
  75. pclose(cmdf);
  76. }
  77. void getcmds(int time)
  78. {
  79. const Block* current;
  80. for (unsigned int i = 0; i < LENGTH(blocks); i++) {
  81. current = blocks + i;
  82. if ((current->interval != 0 && time % current->interval == 0) || time == -1)
  83. getcmd(current,statusbar[i]);
  84. }
  85. }
  86. void getsigcmds(unsigned int signal)
  87. {
  88. const Block *current;
  89. for (unsigned int i = 0; i < LENGTH(blocks); i++) {
  90. current = blocks + i;
  91. if (current->signal == signal)
  92. getcmd(current,statusbar[i]);
  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. for (unsigned int i = 0; i < LENGTH(blocks); i++) {
  103. if (blocks[i].signal > 0)
  104. signal(SIGMINUS+blocks[i].signal, sighandler);
  105. }
  106. }
  107. int getstatus(char *str, char *last)
  108. {
  109. strcpy(last, str);
  110. str[0] = '\0';
  111. for (unsigned int i = 0; i < LENGTH(blocks); i++)
  112. strcat(str, statusbar[i]);
  113. str[strlen(str)-strlen(delim)] = '\0';
  114. return strcmp(str, last);//0 if they are the same
  115. }
  116. #ifndef NO_X
  117. void setroot()
  118. {
  119. if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed.
  120. return;
  121. XStoreName(dpy, root, statusstr[0]);
  122. XFlush(dpy);
  123. }
  124. int setupX()
  125. {
  126. dpy = XOpenDisplay(NULL);
  127. if (!dpy) {
  128. fprintf(stderr, "dwmblocks: Failed to open display\n");
  129. return 0;
  130. }
  131. screen = DefaultScreen(dpy);
  132. root = RootWindow(dpy, screen);
  133. return 1;
  134. }
  135. #endif
  136. void pstdout()
  137. {
  138. if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed.
  139. return;
  140. printf("%s\n",statusstr[0]);
  141. fflush(stdout);
  142. }
  143. void statusloop()
  144. {
  145. setupsignals();
  146. int i = 0;
  147. getcmds(-1);
  148. while (1) {
  149. getcmds(i++);
  150. writestatus();
  151. if (!statusContinue)
  152. break;
  153. sleep(1.0);
  154. }
  155. }
  156. #ifndef __OpenBSD__
  157. /* this signal handler should do nothing */
  158. void dummysighandler(int signum)
  159. {
  160. return;
  161. }
  162. #endif
  163. void sighandler(int signum)
  164. {
  165. getsigcmds(signum-SIGPLUS);
  166. writestatus();
  167. }
  168. void termhandler()
  169. {
  170. statusContinue = 0;
  171. }
  172. int main(int argc, char** argv)
  173. {
  174. for (int i = 0; i < argc; i++) {//Handle command line arguments
  175. if (!strcmp("-d",argv[i]))
  176. strncpy(delim, argv[++i], delimLen);
  177. else if (!strcmp("-p",argv[i]))
  178. writestatus = pstdout;
  179. }
  180. #ifndef NO_X
  181. if (!setupX())
  182. return 1;
  183. #endif
  184. delimLen = MIN(delimLen, strlen(delim));
  185. delim[delimLen++] = '\0';
  186. signal(SIGTERM, termhandler);
  187. signal(SIGINT, termhandler);
  188. statusloop();
  189. #ifndef NO_X
  190. XCloseDisplay(dpy);
  191. #endif
  192. return 0;
  193. }