aboutsummaryrefslogtreecommitdiff
path: root/snag/src/build_db.c
blob: 01ff6bc4f7aa0b764aa657755fdbb19fe4efda12 (plain)
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
#include "build_db.h"
#include "util.h"

#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>

#define PKG_BUILD_CMD "./scripts/run_pkg_build.sh"

#define API_MESSAGE_NONE      0
#define API_MESSAGE_FINISHED  1
#define API_MESSAGE_TEST      2

void package_run_build(const package_info_t* info) {

    int api_from_sh[2] = {0};
    if (pipe(api_from_sh) < 0) die("failed to open api endpoint pipe: %s", strerror(errno));
    int api_to_sh[2] = {0};
    if (pipe(api_to_sh) < 0) die("failed to open api response pipe: %s", strerror(errno));

	// PIPE and FORK to run install script
    int child_output[2] = {0};
    if (pipe(child_output) < 0) die("failed to pipe: %s", strerror(errno));
    pid_t pid = fork();
    if (pid < 0) die("failed to fork: %s", strerror(errno));

    if (pid == 0) {
		// child proc
		// connect my stdout and stderr to the pipe
        close(child_output[0]);
        dup2(child_output[1], STDOUT_FILENO);
        dup2(child_output[1], STDERR_FILENO);
        close(child_output[1]);
        // close unused api pipes
        close(api_from_sh[0]);
        close(api_to_sh[1]);
        char buf1[1024];
        snprintf(buf1, sizeof(buf1), "%d", api_from_sh[1]);
        char buf2[1024];
        snprintf(buf2, sizeof(buf2), "%d", api_to_sh[0]);
		// exec into install script
        char* argv[] = { PKG_BUILD_CMD, buf1, buf2, info->script_path, NULL };
        char* envp[] = { NULL };
        execve(PKG_BUILD_CMD, argv, envp);
		// what are you still doing here?
		die("CHILD - execve to %s failed: %s", PKG_BUILD_CMD, strerror(errno));
    } else {
		// parent proc, close write end of pipe
		close(child_output[1]);
        // close unused api pipes
        close(api_from_sh[1]);
        close(api_to_sh[0]);
	}

    // all of this should be rewritten
	char buf[4096];
	ssize_t bytes_read = 0;
    struct pollfd pollfds[] = {
        { .fd = api_from_sh[0], .events = POLLIN, .revents = 0 },
        { .fd = child_output[0], .events = POLLIN, .revents = 0 }
    };
    bool finished = false;
    while (!finished) {
        if (poll(pollfds, sizeof(pollfds) / sizeof(*pollfds), 0) < 0) {
            die("polling child process fds failed %s", strerror(errno));
        }
        if (pollfds[1].revents == POLLIN) {
            bytes_read = read(child_output[0], buf, sizeof(buf));
            if (bytes_read < 0) die("failed to read from child output: %s", strerror(errno));
            // print build out, can log and stuff in future
            printf("%.*s", (int)bytes_read, buf);
        }
        if (pollfds[0].revents == POLLIN) {
            int api_call = 0;
            bytes_read = read(api_from_sh[0], &api_call, sizeof(api_call));
            if (bytes_read < 0) {
                print("reading from api pipe failed: %s\n", strerror(errno));
            }
            switch (api_call) {
            case API_MESSAGE_FINISHED:
                finished = true;
                break;
            case API_MESSAGE_TEST:
                printf("api test\n");
                write(api_to_sh[1], "api test\n", strlen("api test\n"));
                break;
            case API_MESSAGE_NONE:
            }
        }
    }
    while ((bytes_read = read(child_output[0], buf, sizeof(buf))) > 0) {
		// print build out, can log and stuff in future
		printf("%.*s", (int)bytes_read, buf);
	}
    if (bytes_read < 0) die("failed to read from pipe: %s", strerror(errno));
	close(child_output[0]);
    // close api pipes
	close(api_from_sh[0]);
	close(api_to_sh[1]);

	// reap the child to finish
    int wstatus;
    if (waitpid(pid, &wstatus, 0) < 0) die("waitpid failed: %s", strerror(errno));
	if (WEXITSTATUS(wstatus) != 0) die("the child failed to execute install script");
}