2 * i3bar - an xcb-based status- and ws-bar for i3
4 * © 2010 Axel Wagner and contributors
6 * See file LICNSE for license information
8 * src/child.c: Getting Input for the statusline
13 #include <sys/types.h>
23 /* stdin- and sigchild-watchers */
28 * Stop and free() the stdin- and sigchild-watchers
32 ev_io_stop(main_loop, stdin_io);
33 ev_child_stop(main_loop, child_sig);
40 * Since we don't use colors and stuff, we strip the dzen-formatstrings
43 void strip_dzen_formats(char *buffer) {
46 while (*src != '\0') {
47 /* ^ starts a format-string, ) ends it */
49 /* We replace the seperators from i3status by pipe-symbols */
50 if (!strncmp(src, "^ro", strlen("^ro"))) {
65 /* The last character is \n, which xcb cannot display */
70 * Callbalk for stdin. We read a line from stdin, strip dzen-formats and store
71 * the result in statusline
74 void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
78 int buffer_len = STDIN_CHUNK_SIZE;
79 char *buffer = malloc(buffer_len);
80 memset(buffer, '\0', buffer_len);
82 n = read(fd, buffer + rec, buffer_len - rec);
84 if (errno == EAGAIN) {
87 printf("ERROR: read() failed!");
91 if (rec == buffer_len) {
93 buffer = malloc(buffer_len + STDIN_CHUNK_SIZE);
94 memset(buffer, '\0', buffer_len);
95 strncpy(buffer, tmp, buffer_len);
96 buffer_len += STDIN_CHUNK_SIZE;
104 if (strlen(buffer) == 0) {
108 strip_dzen_formats(buffer);
111 printf("%s\n", buffer);
116 * We received a sigchild, meaning, that the child-process terminated.
117 * We simply free the respective data-structures and don't care for input
121 void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
122 printf("Child (pid: %d) unexpectedly exited with status %d\n",
129 * Start a child-process with the specified command and reroute stdin.
130 * We actually start a $SHELL to execute the command so we don't have to care
131 * about arguments and such
134 void start_child(char *command) {
136 if (command != NULL) {
142 printf("ERROR: Couldn't fork()");
147 dup2(fd[1], STDOUT_FILENO);
149 static const char *shell = NULL;
151 if ((shell = getenv("SHELL")) == NULL)
154 execl(shell, shell, "-c", command, (char*) NULL);
159 dup2(fd[0], STDIN_FILENO);
165 fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
167 stdin_io = malloc(sizeof(ev_io));
168 ev_io_init(stdin_io, &stdin_io_cb, STDIN_FILENO, EV_READ);
169 ev_io_start(main_loop, stdin_io);
171 /* We must cleanup, if the child unexpectedly terminates */
172 child_sig = malloc(sizeof(ev_io));
173 ev_child_init(child_sig, &child_sig_cb, child_pid, 0);
174 ev_child_start(main_loop, child_sig);
179 * kill()s the child-prozess (if existend) and closes and
180 * free()s the stdin- and sigchild-watchers
184 if (child_pid != 0) {
185 kill(child_pid, SIGQUIT);