-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrootblocks.c
193 lines (170 loc) · 4.37 KB
/
rootblocks.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifndef NO_X
#include <X11/Xlib.h>
#endif
#include "rootblocks.h"
#include "config.h"
#define STATUSLENGTH (LENGTH(blocks) * CMDLENGTH + 1)
static char statusbar[LENGTH(blocks)][CMDLENGTH] = { 0 };
static char statusstr[2][STATUSLENGTH]; // current and previous status string
static int statusContinue = 1;
FILE* subprocesses[LENGTH(blocks)];
// opens process for block's command and stores output in *output
void getcmd(const Block* block, char* output) {
FILE* cmdf = popen(block->command, "r");
if (!cmdf)
return;
fgets(output, CMDLENGTH - LENGTH(delim), cmdf);
long i = strlen(output);
if (i == 0) {
//return if block and command output are both empty
pclose(cmdf);
return;
}
//only chop off newline if one is present at the end
i = output[i - 1] == '\n' ? i - 1 : i;
if (LENGTH(delim) != 1)
strncpy(output + i, delim, LENGTH(delim));
else
output[i++] = '\0';
pclose(cmdf);
}
// update blocks in their time
void getcmds(int time) {
const Block* current;
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
current = blocks + i;
if ((current->interval != 0 && time % current->interval == 0) || time == -1)
getcmd(current, statusbar[i]);
}
}
// update blocks in their sigkills
void getsigcmds(unsigned int signal) {
const Block* current;
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
current = blocks + i;
if (current->signal == signal)
getcmd(current, statusbar[i]);
}
}
// setup signal handler
void setupsighandler() {
// initialize all real time signals with dummy handler
for (int i = SIGRTMIN; i <= SIGRTMAX; i++)
signal(i, dummysighandler);
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
if (blocks[i].signal > 0)
signal(SIGMINUS + blocks[i].signal, sighandler);
}
}
// compare prev to cur status
int statusupd(char* str, char* last) {
strcpy(last, str);
if (LENGTH(opening) != 1)
strncpy(str, opening, LENGTH(opening));
else
str[0] = '\0';
for (unsigned int i = 0; i < LENGTH(blocks); i++)
strcat(str, statusbar[i]);
str[strlen(str) - strlen(delim)] = '\0';
long i = strlen(str);
i = str[i - 1] == '\n' ? i - 1 : i;
if (LENGTH(ending) != 1)
strncpy(str + i, ending, LENGTH(ending));
return strcmp(str, last); // 0 if they are the same
}
#ifndef NO_X
// set root window name to status
void setroot() {
if (!statusupd(statusstr[0], statusstr[1])) //Only set root if text has changed.
return;
XStoreName(dpy, root, statusstr[0]);
XFlush(dpy);
}
// setup it on x display
int setupX() {
dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "rootblocks: Failed to open display\n");
return 0;
}
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
return 1;
}
#endif
// print status out in console
void pstdout() {
if (!statusupd(statusstr[0], statusstr[1])) //Only write out if text has changed.
return;
printf("%s\n", statusstr[0]);
fflush(stdout);
}
void subscribe() {
const Block* current;
for (unsigned int i = 0; i < LENGTH(blocks); i++) {
current = blocks + i;
subprocesses[i] = popen(current->sub, "r");
}
}
// da loop !!
void statusloop() {
setupsighandler();
int i = 0;
getcmds(-1);
while (1) {
getcmds(i++);
writestatus();
if (!statusContinue)
break;
sleep(1);
}
}
// this signal handler should do nothing
void dummysighandler(int signum) {
return;
}
// signal handler
void sighandler(int signum) {
getsigcmds(signum - SIGPLUS);
writestatus();
}
// terminate handler
void termhandler() {
statusContinue = 0;
}
int main(int argc, char** argv) {
if (argc > 1) {
if (!strcmp("-p", argv[1]))
writestatus = pstdout;
else if (!strcmp("-v", argv[1]) || !strcmp("-V", argv[1])) {
printf("v1.0");
return 0;
} else if (!strcmp("-h", argv[1]) || !strcmp("--help", argv[1])) {
printf("-v for version, -p for console output mode. That's it.");
return 0;
} else {
printf("Unknown option, try -h for help");
return 1;
}
}
#ifndef NO_X
if (!setupX())
return 1;
#endif
signal(SIGTERM, termhandler);
signal(SIGINT, termhandler);
subscribe();
statusloop();
#ifndef NO_X
XCloseDisplay(dpy);
#endif
for (unsigned int i = 0; i < LENGTH(blocks); i++)
pclose(subprocesses[i]);
return 0;
}