<commit_before>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

#include "libvarnish.h"
#include "event.h"


/*--------------------------------------------------------------------
 * stubs to survice linkage
 */
 
#include "cli_priv.h"

struct cli;

void cli_out(struct cli *cli, const char *fmt, ...) { (void)cli; (void)fmt; abort(); }
void cli_param(struct cli *cli) { (void)cli; abort(); }
void cli_result(struct cli *cli, unsigned res) { (void)cli; (void)res; abort(); }

/*--------------------------------------------------------------------*/

static struct event_base *eb;
static struct bufferevent *e_cmd;
static struct bufferevent *e_pipe2;
static int pipe1[2];
static int pipe2[2];
static pid_t child;

/*--------------------------------------------------------------------*/

static void
rd_pipe2(struct bufferevent *bev, void *arg)
{
	char *p;

	(void)arg;
	p = evbuffer_readline(bev->input);
	if (p == NULL)
		return;
	printf("V: <<%s>>\n", p);
}

static void
ex_pipe2(struct bufferevent *bev, short what, void *arg)
{
	int i, status;

	(void)arg;
	printf("%s(%p, 0x%x, %p)\n", __func__, bev, what, arg);
	bufferevent_disable(e_pipe2, EV_READ);

	i = wait4(child, &status, 0, NULL);
	printf("stopped i %d status 0x%x\n", i, status);
	child = 0;
	close(pipe1[1]);
	close(pipe2[0]);
}

/*--------------------------------------------------------------------*/

static void
cmd_start(char **av)
{

	printf("%s()\n", __func__);
	(void)av;
	assert(pipe(pipe1) == 0);
	assert(pipe(pipe2) == 0);

	e_pipe2 = bufferevent_new(pipe2[0], rd_pipe2, NULL, ex_pipe2, NULL);
	assert(e_pipe2 != NULL);
	bufferevent_base_set(eb, e_pipe2);
	bufferevent_enable(e_pipe2, EV_READ);

	child = fork();
	if (!child) {
		dup2(pipe1[0], 0);
		dup2(pipe2[1], 1);
		dup2(pipe2[1], 2);
		close(pipe1[0]);
		close(pipe1[1]);
		close(pipe2[0]);
		close(pipe2[1]);
		write(2, "Forked\n", 7);
		assert(chdir("../varnishd") == 0);
		execl(
		    "./varnishd",
		    "varnishd",
		    "-blocalhost:8081",
		    "-sfile,/tmp/,10m",
		    NULL);
		perror("execl");
		exit (2);
	}
	close(pipe1[0]);
	close(pipe2[1]);
}


/*--------------------------------------------------------------------*/

static void
cmd_stop(char **av)
{

	(void)av;
	if (child == 0) {
		fprintf(stderr, "No child running\n");
		exit (2);
	}
	write(pipe1[1], "exit\r", 5);
	/* XXX: arm timeout */
}

/*--------------------------------------------------------------------*/

static void
rd_cmd(struct bufferevent *bev, void *arg)
{
	char *p;
	char **av;

	(void)bev;
	(void)arg;
	p = evbuffer_readline(bev->input);
	if (p == NULL)
		return;
	av = ParseArgv(p, 0);
	if (av[0] != NULL) {
		fprintf(stderr, "%s\n", av[0]);
		exit (1);
	}
	if (av[1] == NULL)
		return;
	if (!strcmp(av[1], "start"))
		cmd_start(av + 2);
	else if (!strcmp(av[1], "stop"))
		cmd_stop(av + 2);
	else {
		fprintf(stderr, "Unknown command \"%s\"\n", av[1]);
		exit (2);
	}
	FreeArgv(av);
}

/*--------------------------------------------------------------------*/

int
main(int argc, char **argv)
{

	setbuf(stdout, NULL);
	(void)argc;
	(void)argv;

	eb = event_init();
	assert(eb != NULL);

	e_cmd = bufferevent_new(0, rd_cmd, NULL, NULL, NULL);
	assert(e_cmd != NULL);
	bufferevent_base_set(eb, e_cmd);
	bufferevent_enable(e_cmd, EV_READ);

	event_base_loop(eb, 0);
	return (2);
}
<commit_msg>Add a server facility to act as backend for varnish<commit_after>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>

#include "libvarnish.h"
#include "event.h"
#include "queue.h"


/*--------------------------------------------------------------------
 * stubs to survice linkage
 */
 
#include "cli_priv.h"

struct cli;

void cli_out(struct cli *cli, const char *fmt, ...) { (void)cli; (void)fmt; abort(); }
void cli_param(struct cli *cli) { (void)cli; abort(); }
void cli_result(struct cli *cli, unsigned res) { (void)cli; (void)res; abort(); }

/*--------------------------------------------------------------------*/

static struct event_base *eb;

/*--------------------------------------------------------------------*/

static int serv_sock = -1;
static struct event e_acc;
static int sock_acc = -1;
static struct bufferevent *e_racc;

struct serv {
	TAILQ_ENTRY(serv)	list;
	char			*data;
};

static TAILQ_HEAD(,serv) serv_head = TAILQ_HEAD_INITIALIZER(serv_head);

static void
rd_acc(struct bufferevent *bev, void *arg)
{
	char *p;
	struct serv *sp;
	int *ip;

	ip = arg;
	while (1) {
		p = evbuffer_readline(bev->input);
		if (p == NULL)
			return;
		printf("A: <<%s>>\n", p);
		if (*p == '\0') {
			sp = TAILQ_FIRST(&serv_head);
			assert(sp != NULL);
			write(*ip, sp->data, strlen(sp->data));
			if (TAILQ_NEXT(sp, list) != NULL) {
				TAILQ_REMOVE(&serv_head, sp, list);
				free(sp->data);	
				free(sp);
			}
		}
	}
}

static void
ex_acc(struct bufferevent *bev, short what, void *arg)
{
	int *ip;

	ip = arg;
	printf("%s(%p, 0x%x, %p)\n", __func__, bev, what, arg);
	bufferevent_disable(bev, EV_READ);
	bufferevent_free(bev);
	close(*ip);
	free(ip);
}

static void
acc_sock(int fd, short event, void *arg)
{
	struct sockaddr addr[2];	/* XXX: IPv6 hack */
	socklen_t l;
	struct linger linger;
	int *ip;

	ip = calloc(sizeof *ip, 1);
	(void)event;
	(void)arg;
	l = sizeof addr;
	fd = accept(fd, addr, &l);
	if (fd < 0) {
		perror("accept");
		exit (2);
	}
#ifdef SO_LINGER /* XXX Linux ? */
	linger.l_onoff = 0;
	linger.l_linger = 0;
	assert(setsockopt(fd, SOL_SOCKET, SO_LINGER,
	   &linger, sizeof linger) == 0);
#endif
	*ip = fd;
	e_racc = bufferevent_new(fd, rd_acc, NULL, ex_acc, ip);
	assert(e_racc != NULL);
	bufferevent_base_set(eb, e_racc);
	bufferevent_enable(e_racc, EV_READ);
}

static void
open_serv_sock(void)
{
	struct addrinfo ai, *r0, *r1;
	int i, j, s = -1;

	memset(&ai, 0, sizeof ai);
	ai.ai_family = PF_UNSPEC;
	ai.ai_socktype = SOCK_STREAM;
	ai.ai_flags = AI_PASSIVE;
	i = getaddrinfo("localhost", "8081", &ai, &r0);

	if (i) {
		fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(i));
		return;
	}

	for (r1 = r0; r1 != NULL; r1 = r1->ai_next) {
		s = socket(r1->ai_family, r1->ai_socktype, r1->ai_protocol);
		if (s < 0)
			continue;
		j = 1;
		i = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &j, sizeof j);
		assert(i == 0);

		i = bind(s, r1->ai_addr, r1->ai_addrlen);
		if (i != 0) {
			perror("bind");
			continue;
		}
		assert(i == 0);
		serv_sock = s;
		break;
	}
	freeaddrinfo(r0);
	if (s < 0) {
		perror("bind");
		exit (2);
	}

	listen(s, 16);

	event_set(&e_acc, s, EV_READ | EV_PERSIST, acc_sock, NULL);
	event_base_set(eb, &e_acc);
	event_add(&e_acc, NULL);
}

static void
cmd_serve(char **av)
{
	struct serv *sp;
	int i;

	for (i = 0; av[i] != NULL; i++) {
		sp = calloc(sizeof *sp, 1);
		assert(sp != NULL);
		sp->data = strdup(av[i]);
		assert(sp->data != NULL);
		TAILQ_INSERT_TAIL(&serv_head, sp, list);
	}
}

/*--------------------------------------------------------------------*/

static struct bufferevent *e_pipe2;
static int pipe1[2];
static int pipe2[2];
static pid_t child;

/*--------------------------------------------------------------------*/

static void
rd_pipe2(struct bufferevent *bev, void *arg)
{
	char *p;

	(void)arg;
	while (1) {
		p = evbuffer_readline(bev->input);
		if (p == NULL)
			return;
		printf("V: <<%s>>\n", p);
	}
}

static void
ex_pipe2(struct bufferevent *bev, short what, void *arg)
{
	int i, status;

	(void)arg;
	printf("%s(%p, 0x%x, %p)\n", __func__, bev, what, arg);
	bufferevent_disable(e_pipe2, EV_READ);

	i = wait4(child, &status, 0, NULL);
	printf("stopped i %d status 0x%x\n", i, status);
	child = 0;
	close(pipe1[1]);
	close(pipe2[0]);
}

/*--------------------------------------------------------------------*/

static void
cmd_start(char **av)
{

	printf("%s()\n", __func__);
	(void)av;
	assert(pipe(pipe1) == 0);
	assert(pipe(pipe2) == 0);

	e_pipe2 = bufferevent_new(pipe2[0], rd_pipe2, NULL, ex_pipe2, NULL);
	assert(e_pipe2 != NULL);
	bufferevent_base_set(eb, e_pipe2);
	bufferevent_enable(e_pipe2, EV_READ);

	child = fork();
	if (!child) {
		dup2(pipe1[0], 0);
		dup2(pipe2[1], 1);
		dup2(pipe2[1], 2);
		close(pipe1[0]);
		close(pipe1[1]);
		close(pipe2[0]);
		close(pipe2[1]);
		write(2, "Forked\n", 7);
		assert(chdir("../varnishd") == 0);
		execl(
		    "./varnishd",
		    "varnishd",
		    "-blocalhost:8081",
		    "-sfile,/tmp/,10m",
		    NULL);
		perror("execl");
		exit (2);
	}
	close(pipe1[0]);
	close(pipe2[1]);
}


/*--------------------------------------------------------------------*/

static void
cmd_stop(char **av)
{

	(void)av;
	if (child == 0) {
		fprintf(stderr, "No child running\n");
		exit (2);
	}
	write(pipe1[1], "exit\r", 5);
	/* XXX: arm timeout */
}

/*--------------------------------------------------------------------*/

static void
rd_cmd(struct bufferevent *bev, void *arg)
{
	char *p;
	char **av;

	(void)bev;
	(void)arg;
	p = evbuffer_readline(bev->input);
	if (p == NULL)
		return;
	av = ParseArgv(p, 0);
	if (av[0] != NULL) {
		fprintf(stderr, "%s\n", av[0]);
		exit (1);
	}
	if (av[1] == NULL)
		return;
	if (!strcmp(av[1], "start"))
		cmd_start(av + 2);
	else if (!strcmp(av[1], "stop"))
		cmd_stop(av + 2);
	else if (!strcmp(av[1], "serve"))
		cmd_serve(av + 2);
	else {
		fprintf(stderr, "Unknown command \"%s\"\n", av[1]);
		exit (2);
	}
	FreeArgv(av);
}

/*--------------------------------------------------------------------*/

static struct bufferevent *e_cmd;

int
main(int argc, char **argv)
{

	setbuf(stdout, NULL);
	(void)argc;
	(void)argv;

	eb = event_init();
	assert(eb != NULL);

	open_serv_sock();

	e_cmd = bufferevent_new(0, rd_cmd, NULL, NULL, NULL);
	assert(e_cmd != NULL);
	bufferevent_base_set(eb, e_cmd);
	bufferevent_enable(e_cmd, EV_READ);

	event_base_loop(eb, 0);
	return (2);
}

{'fraction_non_alphanumeric': 0.28614488094041995, 'fraction_numerical': 0.021199638300010048, 'mean_word_length': 2.485294117647059, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 43, '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': '7567929', 'n_tokens_mistral': 4216, 'n_tokens_neox': 3968, 'n_words': 890}