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.

185 lines
3.6 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. char *cmd = block->command;
  49. FILE *cmdf = popen(cmd,"r");
  50. if (!cmdf)
  51. return;
  52. char c;
  53. int i = strlen(block->icon);
  54. fgets(output+i, CMDLENGTH-i-delimLen, cmdf);
  55. i = strlen(output);
  56. if (delim[0] != '\0' && --i)
  57. strncpy(output+i, delim, delimLen);
  58. else
  59. output[i++] = '\0';
  60. pclose(cmdf);
  61. }
  62. void getcmds(int time)
  63. {
  64. const Block* current;
  65. for(unsigned int i = 0; i < LENGTH(blocks); i++)
  66. {
  67. current = blocks + i;
  68. if ((current->interval != 0 && time % current->interval == 0) || time == -1)
  69. getcmd(current,statusbar[i]);
  70. }
  71. }
  72. void getsigcmds(unsigned int signal)
  73. {
  74. const Block *current;
  75. for (unsigned int i = 0; i < LENGTH(blocks); i++)
  76. {
  77. current = blocks + i;
  78. if (current->signal == signal)
  79. getcmd(current,statusbar[i]);
  80. }
  81. }
  82. void setupsignals()
  83. {
  84. #ifndef __OpenBSD__
  85. /* initialize all real time signals with dummy handler */
  86. for(int i = SIGRTMIN; i <= SIGRTMAX; i++)
  87. signal(i, dummysighandler);
  88. #endif
  89. for(unsigned int i = 0; i < LENGTH(blocks); i++)
  90. {
  91. if (blocks[i].signal > 0)
  92. signal(SIGMINUS+blocks[i].signal, sighandler);
  93. }
  94. }
  95. int getstatus(char *str, char *last)
  96. {
  97. strcpy(last, str);
  98. str[0] = '\0';
  99. for(unsigned int i = 0; i < LENGTH(blocks); i++)
  100. strcat(str, statusbar[i]);
  101. str[strlen(str)-strlen(delim)] = '\0';
  102. return strcmp(str, last);//0 if they are the same
  103. }
  104. void setroot()
  105. {
  106. if (!getstatus(statusstr[0], statusstr[1]))//Only set root if text has changed.
  107. return;
  108. Display *d = XOpenDisplay(NULL);
  109. if (d) {
  110. dpy = d;
  111. }
  112. screen = DefaultScreen(dpy);
  113. root = RootWindow(dpy, screen);
  114. XStoreName(dpy, root, statusstr[0]);
  115. XCloseDisplay(dpy);
  116. }
  117. void pstdout()
  118. {
  119. if (!getstatus(statusstr[0], statusstr[1]))//Only write out if text has changed.
  120. return;
  121. printf("%s\n",statusstr[0]);
  122. fflush(stdout);
  123. }
  124. void statusloop()
  125. {
  126. setupsignals();
  127. int i = 0;
  128. getcmds(-1);
  129. while(statusContinue)
  130. {
  131. getcmds(i);
  132. writestatus();
  133. sleep(1.0);
  134. i++;
  135. }
  136. }
  137. #ifndef __OpenBSD__
  138. /* this signal handler should do nothing */
  139. void dummysighandler(int signum)
  140. {
  141. return;
  142. }
  143. #endif
  144. void sighandler(int signum)
  145. {
  146. getsigcmds(signum-SIGPLUS);
  147. writestatus();
  148. }
  149. void termhandler()
  150. {
  151. statusContinue = 0;
  152. }
  153. int main(int argc, char** argv)
  154. {
  155. for(int i = 0; i < argc; i++)
  156. {
  157. if (!strcmp("-d",argv[i]))
  158. strncpy(delim, argv[++i], delimLen);
  159. else if(!strcmp("-p",argv[i]))
  160. writestatus = pstdout;
  161. }
  162. delim[MIN(delimLen, strlen(delim))] = '\0';
  163. signal(SIGTERM, termhandler);
  164. signal(SIGINT, termhandler);
  165. statusloop();
  166. }