summaryrefslogtreecommitdiff
path: root/src/b98.c
blob: 2ca408f8b531a871a5798968f68b36778819d2d4 (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
110
111
112
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <unistd.h>

#include "b98.h"
#include "tls.h"

pid_t pid = 0;
int from_b98[2];
int to_b98[2];

#define PARENT_READ  from_b98[0]
#define CHILD_WRITE  from_b98[1]
#define CHILD_READ   to_b98[0]
#define PARENT_WRITE to_b98[1]

int bot_init(void)
{
    if (pipe (from_b98)) {
        perror("from_b98 pipe");
        return 1;
    }
    if (pipe (to_b98)) {
        perror("to_b98 pipe");
        return 1;
    }
    pid = fork ();
    if (pid == (pid_t) 0) {  // Child process
        close(PARENT_WRITE);
        close(PARENT_READ);

        dup2(CHILD_READ,  STDIN_FILENO);  close(CHILD_READ);
        dup2(CHILD_WRITE, STDOUT_FILENO);  close(CHILD_WRITE);

        execvp("fungi", (char *[]) { "fungi", "bot.b98" } );
        perror("execv");
        return 1;
    }
    else if (pid < (pid_t) 0) {
        fprintf (stderr, "Fork failed.\n");
        return 1;
    }
    else {  // Parent process
        close(CHILD_READ);
        close(CHILD_WRITE);
        return 0;
    }
}

int bot_loop(int socket_fd)
{
    fd_set rfds;
    while (1) {
        struct timeval timeout;
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;

        FD_ZERO(&rfds);
        FD_SET(PARENT_READ, &rfds);
        FD_SET(socket_fd, &rfds);
        select(20, &rfds, NULL, NULL, &timeout);
        if ( FD_ISSET(PARENT_READ, &rfds) ) {
            static char sbuf[512]; /* string buffer */
            static int n = 0; /* nition in buffer */
            ssize_t len = n + read(PARENT_READ, sbuf + n, 512 - n);
            while (n < len) {
                if ((n > 0 && sbuf[n] == '\n' && sbuf[n - 1] == '\r') ) { /* If we got a full message */
                    tls_send(sbuf, n);
                    sbuf[n - 1] = '\0';
                    printf(">>> %s\n", sbuf);
                    memmove(sbuf, sbuf + n + 1, len - n - 1);
                    len = len - n - 1;
                    if (len == 1)
                        len = 0;
                    n = 0; /* we reinitialise n for the next run */
                } else if (n == 512) { /* If we got a full buffer without finding a \r\n */
                    fprintf(stderr, "We got a full buffer without finding a \r\n");
                    return 2;
                } else { /* Nothing to do otherwise but roll the next char */
                    n++;
                }
            }
        } else if ( FD_ISSET(socket_fd, &rfds) ) {
            tls_read(&bot_handle_input);
        }
    }
}

int bot_handle_input(const char* const sbuf, int len)
{
    static char msg[512];
    static int pos = 0; /* position in msg buffer */
    for (int n = 0; n < len; n++) {
        msg[pos] = sbuf[n];
        if ((n > 0 && sbuf[n] == '\n' && sbuf[n - 1] == '\r') ) { /* If we got a full message */
            write(PARENT_WRITE, msg, n);
            msg[pos - 1] = '\0';
            printf("<<< %s\n", msg);
            pos = 0; /* we reinitialise pos for the next run */
        } else if (pos == sizeof(msg)) { /* If we got a full buffer without finding a \r\n */
            fprintf(stderr, "We got a full buffer without finding a \r\n");
            return 2;
        } else { /* Nothing to do otherwise but roll the next char */
            pos++;
        }
    }

    return 0;
}