Implement asynchronous block execution
This commit is contained in:
parent
060a64bfce
commit
f4a1a63485
30
config.h
30
config.h
|
@ -1,22 +1,14 @@
|
||||||
#define CMDLENGTH 50
|
#define CMDLENGTH 50 + 1 // 1 character used to encoding the signal
|
||||||
#define DELIMITER "<"
|
#define DELIMITER "<"
|
||||||
|
|
||||||
typedef struct {
|
const Block blocks[] = {
|
||||||
char* command;
|
BLOCK("sb-mail", 1800, 17)
|
||||||
unsigned int interval;
|
BLOCK("sb-music", 0, 18)
|
||||||
unsigned int signal;
|
BLOCK("sb-disk", 1800, 19)
|
||||||
char output[CMDLENGTH];
|
BLOCK("sb-memory", 1800, 20)
|
||||||
int pipe[2];
|
BLOCK("sb-loadavg", 1800, 21)
|
||||||
} Block;
|
BLOCK("sb-volume", 1800, 22)
|
||||||
|
BLOCK("sb-battery", 5, 23)
|
||||||
static Block blocks[] = {
|
BLOCK("sb-date", 5, 24)
|
||||||
{"sb-mail", 1800, 17},
|
BLOCK("sb-network", 5, 25)
|
||||||
{"sb-music", 0, 18},
|
|
||||||
{"sb-disk", 1800, 19},
|
|
||||||
{"sb-memory", 10, 20},
|
|
||||||
{"sb-loadavg", 10, 21},
|
|
||||||
{"sb-volume", 0, 22},
|
|
||||||
{"sb-battery", 5, 23},
|
|
||||||
{"sb-date", 20, 24},
|
|
||||||
{"sb-network", 5, 25}
|
|
||||||
};
|
};
|
||||||
|
|
108
main.c
108
main.c
|
@ -1,5 +1,4 @@
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -8,6 +7,14 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define STR2(a) #a
|
||||||
|
#define STRINGIFY(a) STR2(a)
|
||||||
|
#define BLOCK(cmd, interval, signal) { .command = "echo \"" STR(__COUNTER__) "$(" cmd ")\"", interval, signal },
|
||||||
|
typedef struct {
|
||||||
|
const char *command;
|
||||||
|
const unsigned int interval;
|
||||||
|
const unsigned int signal;
|
||||||
|
} Block;
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define LEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
#define LEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
@ -16,9 +23,11 @@
|
||||||
static Display *dpy;
|
static Display *dpy;
|
||||||
static int screen;
|
static int screen;
|
||||||
static Window root;
|
static Window root;
|
||||||
|
static char outputs[LEN(blocks)][CMDLENGTH];
|
||||||
static char statusBar[2][LEN(blocks) * (CMDLENGTH + LEN(DELIMITER) - 1) + 1];
|
static char statusBar[2][LEN(blocks) * (CMDLENGTH + LEN(DELIMITER) - 1) + 1];
|
||||||
static int statusContinue = 1;
|
static int statusContinue = 1;
|
||||||
void (*writeStatus)();
|
void (*writeStatus)();
|
||||||
|
static int pipeFD[2];
|
||||||
|
|
||||||
int gcd(int a, int b) {
|
int gcd(int a, int b) {
|
||||||
int temp;
|
int temp;
|
||||||
|
@ -37,21 +46,14 @@ void replace(char *str, char old, char new) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void getCommand(int i, const char *button) {
|
void getCommand(int i, const char *button) {
|
||||||
Block *block = blocks + i;
|
const Block *block = blocks + i;
|
||||||
|
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
dup2(block->pipe[1], STDOUT_FILENO);
|
dup2(pipeFD[1], STDOUT_FILENO);
|
||||||
close(block->pipe[0]);
|
close(pipeFD[0]);
|
||||||
close(block->pipe[1]);
|
|
||||||
|
|
||||||
// Temporary hack
|
if (button)
|
||||||
char cmd[1024];
|
setenv("BLOCK_BUTTON", button, 1);
|
||||||
sprintf(cmd, "echo \"_$(%s)\"", block->command);
|
execl("/bin/sh", "sh", "-c", block->command);
|
||||||
|
|
||||||
char *command[] = {"/bin/sh", "-c", cmd, NULL};
|
|
||||||
if (button) setenv("BLOCK_BUTTON", button, 1);
|
|
||||||
setsid();
|
|
||||||
execvp(command[0], command);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,20 +71,21 @@ void getSignalCommand(int signal) {
|
||||||
|
|
||||||
int getStatus(char *new, char *old) {
|
int getStatus(char *new, char *old) {
|
||||||
strcpy(old, new);
|
strcpy(old, new);
|
||||||
new[0] = '\0';
|
new[0] = 0;
|
||||||
for (int i = 0; i < LEN(blocks); i++) {
|
for (int i = 0; i < LEN(blocks); i++) {
|
||||||
Block *block = blocks + i;
|
const Block *block = blocks + i;
|
||||||
if (strlen(block->output) > (block->signal != 0))
|
if (strlen(outputs[i]) > 0)
|
||||||
strcat(new, DELIMITER);
|
strcat(new, DELIMITER);
|
||||||
strcat(new, block->output);
|
strcat(new, outputs[i]);
|
||||||
}
|
}
|
||||||
new[strlen(new)] = '\0';
|
new[strlen(new)] = 0;
|
||||||
return strcmp(new, old);
|
return strcmp(new, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug() {
|
void debug() {
|
||||||
// Only write out if text has changed
|
// Only write out if text has changed
|
||||||
if (!getStatus(statusBar[0], statusBar[1])) return;
|
if (!getStatus(statusBar[0], statusBar[1]))
|
||||||
|
return;
|
||||||
|
|
||||||
write(STDOUT_FILENO, statusBar[0], strlen(statusBar[0]));
|
write(STDOUT_FILENO, statusBar[0], strlen(statusBar[0]));
|
||||||
write(STDOUT_FILENO, "\n", 1);
|
write(STDOUT_FILENO, "\n", 1);
|
||||||
|
@ -90,10 +93,12 @@ void debug() {
|
||||||
|
|
||||||
void setRoot() {
|
void setRoot() {
|
||||||
// Only set root if text has changed
|
// Only set root if text has changed
|
||||||
if (!getStatus(statusBar[0], statusBar[1])) return;
|
if (!getStatus(statusBar[0], statusBar[1]))
|
||||||
|
return;
|
||||||
|
|
||||||
Display *d = XOpenDisplay(NULL);
|
Display *d = XOpenDisplay(NULL);
|
||||||
if (d) dpy = d;
|
if (d)
|
||||||
|
dpy = d;
|
||||||
screen = DefaultScreen(dpy);
|
screen = DefaultScreen(dpy);
|
||||||
root = RootWindow(dpy, screen);
|
root = RootWindow(dpy, screen);
|
||||||
XStoreName(dpy, root, statusBar[0]);
|
XStoreName(dpy, root, statusBar[0]);
|
||||||
|
@ -103,8 +108,9 @@ void setRoot() {
|
||||||
void signalHandler(int sig, siginfo_t *si, void *ucontext) {
|
void signalHandler(int sig, siginfo_t *si, void *ucontext) {
|
||||||
sig -= SIGRTMIN;
|
sig -= SIGRTMIN;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (blocks[i].signal != sig) i++;
|
while (blocks[i].signal != sig)
|
||||||
const char button[2] = {'0' + si->si_value.sival_int & 0xff, '\0'};
|
i++;
|
||||||
|
const char button[2] = {'0' + si->si_value.sival_int & 0xff, 0};
|
||||||
getCommand(i, button);
|
getCommand(i, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,22 +120,29 @@ void termHandler(int signal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void childHandler() {
|
void childHandler() {
|
||||||
for (int i = 0; i < LEN(blocks); i++) {
|
char i;
|
||||||
Block *block = blocks + i;
|
read(pipeFD[0], &i, 1);
|
||||||
|
i -= '0';
|
||||||
|
|
||||||
int bytesToRead = CMDLENGTH;
|
char ch;
|
||||||
char *output = block->output;
|
char buffer[LEN(outputs[0]) - 1];
|
||||||
if (block->signal) output++, bytesToRead--;
|
int j = 0;
|
||||||
|
while (j < LEN(buffer) && read(pipeFD[0], &ch, 1) == 1) {
|
||||||
char placebo;
|
buffer[j++] = ch;
|
||||||
if (read(block->pipe[0], &placebo, 1) == 1) {
|
if (ch == '\n')
|
||||||
char buffer[PIPE_BUF];
|
|
||||||
read(block->pipe[0], buffer, PIPE_BUF);
|
|
||||||
replace(buffer, '\n', '\0');
|
|
||||||
strncpy(output, buffer, bytesToRead);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
buffer[j - 1] = 0;
|
||||||
|
|
||||||
|
const Block *block = blocks + i;
|
||||||
|
char *output = outputs[i];
|
||||||
|
|
||||||
|
if (block->signal > 0) {
|
||||||
|
output[0] = block->signal;
|
||||||
|
output++;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(output, buffer);
|
||||||
writeStatus();
|
writeStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,11 +160,7 @@ void setupSignals() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle exit of forks
|
// Handle exit of forks
|
||||||
struct sigaction sigchld_action = {
|
signal(SIGCHLD, childHandler);
|
||||||
.sa_handler = childHandler,
|
|
||||||
.sa_flags = SA_NOCLDWAIT,
|
|
||||||
};
|
|
||||||
sigaction(SIGCHLD, &sigchld_action, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void statusLoop() {
|
void statusLoop() {
|
||||||
|
@ -168,7 +177,8 @@ void statusLoop() {
|
||||||
|
|
||||||
while (statusContinue) {
|
while (statusContinue) {
|
||||||
// Sleep for `sleepTime` even on being interrupted
|
// Sleep for `sleepTime` even on being interrupted
|
||||||
if (nanosleep(&toSleep, &toSleep) == -1) continue;
|
if (nanosleep(&toSleep, &toSleep) == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
// Write to status after sleeping
|
// Write to status after sleeping
|
||||||
getCommands(i);
|
getCommands(i);
|
||||||
|
@ -180,17 +190,11 @@ void statusLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
pipe(pipeFD);
|
||||||
writeStatus = setRoot;
|
writeStatus = setRoot;
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
if (!strcmp("-d", argv[i])) writeStatus = debug;
|
if (!strcmp("-d", argv[i]))
|
||||||
|
writeStatus = debug;
|
||||||
for (int i = 0; i < LEN(blocks); i++) {
|
|
||||||
Block *block = blocks + i;
|
|
||||||
pipe(block->pipe);
|
|
||||||
fcntl(block->pipe[0], F_SETFL, O_NONBLOCK);
|
|
||||||
|
|
||||||
if (block->signal) block->output[0] = block->signal;
|
|
||||||
}
|
|
||||||
|
|
||||||
setupSignals();
|
setupSignals();
|
||||||
statusLoop();
|
statusLoop();
|
||||||
|
|
Loading…
Reference in New Issue