summaryrefslogtreecommitdiff
path: root/frontends/monkey/dispatch.c
blob: 08bd352d5f001ddc0b8697b66504c3aea2dc1eff (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
113
114
115
116
/*
 * Copyright 2011 Daniel Silverstone <dsilvers@digital-scurf.org>
 *
 * This file is part of NetSurf, http://www.netsurf-browser.org/
 *
 * NetSurf is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * NetSurf is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "utils/log.h"
#include "utils/utils.h"
#include "utils/ring.h"

#include "monkey/dispatch.h"

typedef struct cmdhandler {
	struct cmdhandler *r_next, *r_prev;
	char *cmd;
	handle_command_fn fn;
} monkey_cmdhandler_t;

static monkey_cmdhandler_t *handler_ring = NULL;

nserror
monkey_register_handler(const char *cmd, handle_command_fn fn)
{
	monkey_cmdhandler_t *ret = calloc(sizeof(*ret), 1);
	if (ret == NULL) {
		NSLOG(netsurf, INFO, "Unable to allocate handler");
		return NSERROR_NOMEM;
	}
	ret->cmd = strdup(cmd);
	ret->fn = fn;
	RING_INSERT(handler_ring, ret);
	return NSERROR_OK;
}

void
monkey_free_handlers(void)
{
	while (handler_ring != NULL) {
		monkey_cmdhandler_t *handler = handler_ring;
		RING_REMOVE(handler_ring, handler);
		free(handler->cmd);
		free(handler);
	}
}

void
monkey_process_command(void)
{
	char buffer[PATH_MAX];
	int argc = 0;
	char **argv = NULL;
	char *p, *r = NULL;
	handle_command_fn fn = NULL;
	char **nargv;
  
	if (fgets(buffer, PATH_MAX, stdin) == NULL) {
		/* end of input or read error so issue QUIT */
		sprintf(buffer, "QUIT\n");
	}

	/* remove newline */
	buffer[strlen(buffer) - 1] = '\0';
  
	argv = malloc(sizeof *argv);
	if (argv == NULL) {
		return;
	}
	argc = 1;
	*argv = buffer;
  
	for (p = r = buffer; *p != '\0'; p++) {
		if (*p == ' ') {
			nargv = realloc(argv, sizeof(*argv) * (argc + 1));
			if (nargv == NULL) {
				/* reallocation of argument vector failed, try using what is
				 * already processed.
				 */
				break;
			} else {
				argv = nargv;
			}
			argv[argc++] = r = p + 1;
			*p = '\0';
		}
	}
  
	RING_ITERATE_START(monkey_cmdhandler_t, handler_ring, handler) {
		if (strcmp(argv[0], handler->cmd) == 0) {
			fn = handler->fn;
			RING_ITERATE_STOP(handler_ring, handler);
		}
	} RING_ITERATE_END(handler_ring, handler);
  
	if (fn != NULL) {
		fn(argc, argv);
	}

	free(argv);
}