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.

188 lines
3.8 KiB

  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. #ifdef __OpenBSD__
  8. #define SIGPLUS SIGUSR1+1
  9. #define SIGMINUS SIGUSR1-1
  10. #else
  11. #define SIGPLUS SIGRTMIN
  12. #define SIGMINUS SIGRTMIN
  13. #endif
  14. #define LENGTH(X) (sizeof(X) / sizeof (X[0]))
  15. #define CMDLENGTH 50
  16. #define MIN( a, b ) ( ( a < b) ? a : b )
  17. #define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1)
  18. typedef struct {
  19. char* icon;
  20. char* command;
  21. unsigned int interval;
  22. unsigned int signal;
  23. } Block;
  24. #ifndef __OpenBSD__
  25. void dummysighandler(int num);
  26. #endif
  27. void sighandler(int num);
  28. void getcmds(int time);
  29. void getsigcmds(unsigned int signal);
  30. void setupsignals();
  31. void sighandler(int signum);
  32. int getstatus(char *str, char *last);
  33. void setroot();
  34. void statusloop();
  35. void termhandler();
  36. #include "blocks.h"
  37. static Display *dpy;
  38. static int screen;
  39. static Window root;
  40. static char statusbar[LENGTH(blocks)][CMDLENGTH] = {0};
  41. static char statusstr[2][STATUSLENGTH];
  42. static int statusContinue = 1;
  43. static void (*writestatus) () = setroot;
  44. //opens process *cmd and stores output in *output
  45. void getcmd(const Block *block, char *output)
  46. {
  47. strcpy(output, block->icon);
  48. FILE *cmdf = popen(block->command, "r");
  49. if (!cmdf)
  50. return;
  51. int i = strlen(block->icon);
  52. fgets(output+i, CMDLENGTH-i-delimLen, cmdf);
  53. i = strlen(output);
  54. if (i == 0)//return if block and command output are both empty
  55. return;
  56. if (delim[0] != '\0') {
  57. //only chop off newline if one is present at the end
  58. i = output[i-1] == '\n' ? i-1 : i;
  59. strncpy(output+i, delim, delimLen);
  60. }
  61. else
  62. output[i++] = '\0';
  63. pclose(cmdf);
  64. }
  65. void getcmds(int time)
  66. {
  67. const Block* current;
  68. for (unsigned int i = 0; i < LENGTH(blocks); i++)
  69. {
  70. current = blocks + i;
  71. if ((current->interval != 0 && time % current->interval == 0) || time == -1)
  72. getcmd(current,statusbar[i]);
  73. }
  74. }
  75. void getsigcmds(unsigned int signal)
  76. {
  77. const Block *current;
  78. for (unsigned int i = 0; i < LENGTH(blocks); i++)
  79. {
  80. current = blocks + i;
  81. if (current->signal == signal)
  82. getcmd(current,statusbar[i]);
  83. }
  84. }
  85. void setupsignals()
  86. {
  87. #ifndef __OpenBSD__
  88. /* initialize all real time signals with dummy handler */
  89. for (int i = SIGRTMIN; i <= SIGRTMAX; i++)
  90. signal(i, dummysighandler);
  91. #endif
  92. for (unsigned int i = 0; i < LENGTH(blocks); i++)
  93. {
  94. if (blocks[i].signal > 0)
  95. signal(SIGMINUS+blocks[i].signal, sighandler);
  96. }
  97. }
  98. int getstatus(char *str, char *last)
  99. {
  100. strcpy(last, str);
  101. str[0] = '\0';
  102. for (unsigned int i = 0; i < LENGTH(blocks); i++)
  103. strcat(str, statusbar[i]);
  104. str[strlen(str)-strlen(delim)] = '\0';
  105. return strcmp(str, last);//0 if they are the same
  106. }
  107. void setroot()
  108. {
  109. if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed.
  110. return;
  111. Display *d = XOpenDisplay(NULL);
  112. if (d) {
  113. dpy = d;
  114. }
  115. screen = DefaultScreen(dpy);
  116. root = RootWindow(dpy, screen);
  117. XStoreName(dpy, root, statusstr[0]);
  118. XCloseDisplay(dpy);
  119. }
  120. void pstdout()
  121. {
  122. if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed.
  123. return;
  124. printf("%s\n",statusstr[0]);
  125. fflush(stdout);
  126. }
  127. void statusloop()
  128. {
  129. setupsignals();
  130. int i = 0;
  131. getcmds(-1);
  132. while (statusContinue)
  133. {
  134. getcmds(i++);
  135. writestatus();
  136. sleep(1.0);
  137. }
  138. }
  139. #ifndef __OpenBSD__
  140. /* this signal handler should do nothing */
  141. void dummysighandler(int signum)
  142. {
  143. return;
  144. }
  145. #endif
  146. void sighandler(int signum)
  147. {
  148. getsigcmds(signum-SIGPLUS);
  149. writestatus();
  150. }
  151. void termhandler()
  152. {
  153. statusContinue = 0;
  154. }
  155. int main(int argc, char** argv)
  156. {
  157. for (int i = 0; i < argc; i++) //Handle command line arguments
  158. {
  159. if (!strcmp("-d",argv[i]))
  160. strncpy(delim, argv[++i], delimLen);
  161. else if (!strcmp("-p",argv[i]))
  162. writestatus = pstdout;
  163. }
  164. delimLen = MIN(delimLen, strlen(delim));
  165. delim[delimLen++] = '\0';
  166. signal(SIGTERM, termhandler);
  167. signal(SIGINT, termhandler);
  168. statusloop();
  169. }