<commit_before>/*
 * i3bar - an xcb-based status- and ws-bar for i3
 *
 * © 2010 <NAME> and contributors
 *
 * See file LICNSE for license information
 *
 * src/child.c: Getting Input for the statusline
 *
 */
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <ev.h>

#include "common.h"

/* stdin- and sigchild-watchers */
ev_io    *stdin_io;
ev_child *child_sig;

/*
 * Stop and free() the stdin- and sigchild-watchers
 *
 */
void cleanup() {
    ev_io_stop(main_loop, stdin_io);
    ev_child_stop(main_loop, child_sig);
    FREE(stdin_io);
    FREE(child_sig);
    FREE(statusline);
}

/*
 * Since we don't use colors and stuff, we strip the dzen-formatstrings
 *
 */
void strip_dzen_formats(char *buffer) {
    char *src = buffer;
    char *dest = buffer;
    while (*src != '\0') {
        /* ^ starts a format-string, ) ends it */
        if (*src == '^') {
            /* We replace the seperators from i3status by pipe-symbols */
            if (!strncmp(src, "^ro", strlen("^ro"))) {
                *(dest++) = ' ';
                *(dest++) = '|';
                *(dest++) = ' ';
            }
            while (*src != ')') {
                src++;
            }
            src++;
        } else {
            *dest = *src;
            src++;
            dest++;
        }
    }
    /* The last character is \n, which xcb cannot display */
    *(--dest) = '\0';
}

/*
 * Callbalk for stdin. We read a line from stdin, strip dzen-formats and store
 * the result in statusline
 *
 */
void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
    int fd = watcher->fd;
    int n = 0;
    int rec = 0;
    int buffer_len = STDIN_CHUNK_SIZE;
    char *buffer = malloc(buffer_len);
    memset(buffer, '\0', buffer_len);
    while(1) {
        n = read(fd, buffer + rec, buffer_len - rec);
        if (n == -1) {
            if (errno == EAGAIN) {
                break;
            }
            printf("ERROR: read() failed!");
            exit(EXIT_FAILURE);
        }
        if (n == 0) {
            if (rec == buffer_len) {
                char *tmp = buffer;
                buffer = malloc(buffer_len + STDIN_CHUNK_SIZE);
                memset(buffer, '\0', buffer_len);
                strncpy(buffer, tmp, buffer_len);
                buffer_len += STDIN_CHUNK_SIZE;
                FREE(tmp);
            } else {
                break;
            }
        }
        rec += n;
    }
    if (strlen(buffer) == 0) {
        FREE(buffer);
        return;
    }
    strip_dzen_formats(buffer);
    FREE(statusline);
    statusline = buffer;
    printf("%s\n", buffer);
    draw_bars();
}

/*
 * We received a sigchild, meaning, that the child-process terminated.
 * We simply free the respective data-structures and don't care for input
 * anymore
 *
 */
void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
    printf("Child (pid: %d) unexpectedly exited with status %d\n",
           child_pid,
           watcher->rstatus);
    cleanup();
}

/*
 * Start a child-process with the specified command and reroute stdin.
 * We actually start a $SHELL to execute the command so we don't have to care
 * about arguments and such
 *
 */
void start_child(char *command) {
    child_pid = 0;
    if (command != NULL) {
        int fd[2];
        pipe(fd);
        child_pid = fork();
        switch (child_pid) {
            case -1:
                printf("ERROR: Couldn't fork()");
                exit(EXIT_FAILURE);
            case 0:
                close(fd[0]);

                dup2(fd[1], STDOUT_FILENO);

                static const char *shell = NULL;

                if ((shell = getenv("SHELL")) == NULL)
                    shell = "/bin/sh";

                execl(shell, shell, "-c", command, (char*) NULL);
                return;
            default:
                close(fd[1]);

                dup2(fd[0], STDIN_FILENO);

                break;
        }
    }

    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);

    stdin_io = malloc(sizeof(ev_io));
    ev_io_init(stdin_io, &stdin_io_cb, STDIN_FILENO, EV_READ);
    ev_io_start(main_loop, stdin_io);

    /* We must cleanup, if the child unexpectedly terminates */
    child_sig = malloc(sizeof(ev_io));
    ev_child_init(child_sig, &child_sig_cb, child_pid, 0);
    ev_child_start(main_loop, child_sig);

}

/*
 * kill()s the child-prozess (if existend) and closes and
 * free()s the stdin- and sigchild-watchers
 *
 */
void kill_child() {
    if (child_pid != 0) {
        kill(child_pid, SIGQUIT);
    }
    cleanup();
}<commit_msg>Allocate the right amount of memory for ev_child<commit_after>/*
 * i3bar - an xcb-based status- and ws-bar for i3
 *
 * © 2010 <NAME> and contributors
 *
 * See file LICNSE for license information
 *
 * src/child.c: Getting Input for the statusline
 *
 */
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <ev.h>

#include "common.h"

/* stdin- and sigchild-watchers */
ev_io    *stdin_io;
ev_child *child_sig;

/*
 * Stop and free() the stdin- and sigchild-watchers
 *
 */
void cleanup() {
    ev_io_stop(main_loop, stdin_io);
    ev_child_stop(main_loop, child_sig);
    FREE(stdin_io);
    FREE(child_sig);
    FREE(statusline);
}

/*
 * Since we don't use colors and stuff, we strip the dzen-formatstrings
 *
 */
void strip_dzen_formats(char *buffer) {
    char *src = buffer;
    char *dest = buffer;
    while (*src != '\0') {
        /* ^ starts a format-string, ) ends it */
        if (*src == '^') {
            /* We replace the seperators from i3status by pipe-symbols */
            if (!strncmp(src, "^ro", strlen("^ro"))) {
                *(dest++) = ' ';
                *(dest++) = '|';
                *(dest++) = ' ';
            }
            while (*src != ')') {
                src++;
            }
            src++;
        } else {
            *dest = *src;
            src++;
            dest++;
        }
    }
    /* The last character is \n, which xcb cannot display */
    *(--dest) = '\0';
}

/*
 * Callbalk for stdin. We read a line from stdin, strip dzen-formats and store
 * the result in statusline
 *
 */
void stdin_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) {
    int fd = watcher->fd;
    int n = 0;
    int rec = 0;
    int buffer_len = STDIN_CHUNK_SIZE;
    char *buffer = malloc(buffer_len);
    memset(buffer, '\0', buffer_len);
    while(1) {
        n = read(fd, buffer + rec, buffer_len - rec);
        if (n == -1) {
            if (errno == EAGAIN) {
                break;
            }
            printf("ERROR: read() failed!");
            exit(EXIT_FAILURE);
        }
        if (n == 0) {
            if (rec == buffer_len) {
                char *tmp = buffer;
                buffer = malloc(buffer_len + STDIN_CHUNK_SIZE);
                memset(buffer, '\0', buffer_len);
                strncpy(buffer, tmp, buffer_len);
                buffer_len += STDIN_CHUNK_SIZE;
                FREE(tmp);
            } else {
                break;
            }
        }
        rec += n;
    }
    if (strlen(buffer) == 0) {
        FREE(buffer);
        return;
    }
    strip_dzen_formats(buffer);
    FREE(statusline);
    statusline = buffer;
    printf("%s\n", buffer);
    draw_bars();
}

/*
 * We received a sigchild, meaning, that the child-process terminated.
 * We simply free the respective data-structures and don't care for input
 * anymore
 *
 */
void child_sig_cb(struct ev_loop *loop, ev_child *watcher, int revents) {
    printf("Child (pid: %d) unexpectedly exited with status %d\n",
           child_pid,
           watcher->rstatus);
    cleanup();
}

/*
 * Start a child-process with the specified command and reroute stdin.
 * We actually start a $SHELL to execute the command so we don't have to care
 * about arguments and such
 *
 */
void start_child(char *command) {
    child_pid = 0;
    if (command != NULL) {
        int fd[2];
        pipe(fd);
        child_pid = fork();
        switch (child_pid) {
            case -1:
                printf("ERROR: Couldn't fork()");
                exit(EXIT_FAILURE);
            case 0:
                close(fd[0]);

                dup2(fd[1], STDOUT_FILENO);

                static const char *shell = NULL;

                if ((shell = getenv("SHELL")) == NULL)
                    shell = "/bin/sh";

                execl(shell, shell, "-c", command, (char*) NULL);
                return;
            default:
                close(fd[1]);

                dup2(fd[0], STDIN_FILENO);

                break;
        }
    }

    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);

    stdin_io = malloc(sizeof(ev_io));
    ev_io_init(stdin_io, &stdin_io_cb, STDIN_FILENO, EV_READ);
    ev_io_start(main_loop, stdin_io);

    /* We must cleanup, if the child unexpectedly terminates */
    child_sig = malloc(sizeof(ev_child));
    ev_child_init(child_sig, &child_sig_cb, child_pid, 0);
    ev_child_start(main_loop, child_sig);

}

/*
 * kill()s the child-prozess (if existend) and closes and
 * free()s the stdin- and sigchild-watchers
 *
 */
void kill_child() {
    if (child_pid != 0) {
        kill(child_pid, SIGQUIT);
    }
    cleanup();
}
{'fraction_non_alphanumeric': 0.13493924536346194, 'fraction_numerical': 0.006182050735450863, 'mean_word_length': 1.8959876543209877, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3694908', 'n_tokens_mistral': 3181, 'n_tokens_neox': 3063, 'n_words': 805}