A better version of dwmblock (i think)...
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.

164 lines
2.6KB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <signal.h>
  6. #include <errno.h>
  7. #include <unistd.h>
  8. #include <sys/select.h>
  9. #include <sys/fcntl.h>
  10. #include <sys/wait.h>
  11. typedef struct Process Process;
  12. struct Process {
  13. pid_t pid;
  14. int fd;
  15. char str[64];
  16. Process *next;
  17. };
  18. static Process *list = NULL;
  19. int
  20. max(int a, int b)
  21. {
  22. return (a > b ? a : b);
  23. }
  24. Process *
  25. newproc(const char *command)
  26. {
  27. Process *p;
  28. int pipes[2];
  29. pid_t pid;
  30. if(pipe(pipes) < 0) {
  31. perror("pipe()");
  32. exit(EXIT_FAILURE);
  33. }
  34. switch((pid = fork())) {
  35. case -1:
  36. perror("fork()");
  37. exit(EXIT_FAILURE);
  38. case 0:
  39. close(0);
  40. close(1);
  41. dup2(pipes[1], 1);
  42. close(pipes[0]);
  43. close(pipes[1]);
  44. execl("/bin/sh", "/bin/sh", "-c", command, NULL);
  45. exit(EXIT_SUCCESS);
  46. return NULL;
  47. default:
  48. close(pipes[1]);
  49. p = malloc(sizeof *p);
  50. if(!p) {
  51. perror("malloc()");
  52. exit(EXIT_FAILURE);
  53. }
  54. memset(p, 0, sizeof *p);
  55. p->pid = pid;
  56. p->fd = pipes[0];
  57. return p;
  58. }
  59. }
  60. static void
  61. sigtrap(int sig)
  62. {
  63. if(sig != SIGINT)
  64. return;
  65. for(Process *p = list; p; p = p->next) {
  66. killpg(p->pid, sig);
  67. }
  68. while(wait(NULL) != -1 || errno == EINTR);
  69. /* let the operating take care of the memory leak, fuck it */
  70. exit(EXIT_SUCCESS);
  71. }
  72. int
  73. linerd(int fd, char *line, int linesize)
  74. {
  75. int i;
  76. for(i = 0; i < linesize; i++) {
  77. char c;
  78. if(read(fd, &c, sizeof c) <= 0) {
  79. break;
  80. }
  81. if(c == '\n') {
  82. line[i] = 0;
  83. break;
  84. }
  85. line[i] = c;
  86. }
  87. line[linesize - 1] = 0;
  88. return i;
  89. }
  90. int
  91. main(int argc, char *argv[])
  92. {
  93. int maxfd = 0, i, c;
  94. fd_set rdset;
  95. Process *p;
  96. signal(SIGINT, sigtrap);
  97. signal(SIGTERM, sigtrap);
  98. signal(SIGKILL, sigtrap);
  99. FD_ZERO(&rdset);
  100. while((c = getopt(argc, argv, "c:")) > 0) {
  101. switch(c) {
  102. case 'c':
  103. p = newproc(optarg);
  104. FD_SET(p->fd, &rdset);
  105. maxfd = max(maxfd, p->fd);
  106. p->next = list;
  107. list = p;
  108. break;
  109. default:
  110. fprintf(stderr, "Unknown option: %c\n", c);
  111. exit(EXIT_FAILURE);
  112. }
  113. }
  114. if(!list) {
  115. fprintf(stderr, "usage: %s -c command [-c command2 ]...\n", argv[0]);
  116. exit(EXIT_FAILURE);
  117. }
  118. for(;;) {
  119. int n;
  120. fd_set copy;
  121. FD_ZERO(&copy);
  122. memcpy(&copy, &rdset, sizeof rdset);
  123. n = select(maxfd + 1, &copy, NULL, NULL, NULL);
  124. if(n < 0) {
  125. perror("select()");
  126. continue;
  127. }
  128. for(Process *p = list; p; p = p->next)
  129. if(FD_ISSET(p->fd, &copy)) {
  130. if(linerd(p->fd, p->str, sizeof p->str) <= 0) {
  131. FD_CLR(p->fd, &rdset);
  132. close(p->fd);
  133. }
  134. }
  135. for(Process *p = list; p; p = p->next)
  136. printf("%s%s", p->str, p->next ? " | " : "");
  137. printf("\n");
  138. fflush(stdout);
  139. }
  140. return 0;
  141. }