synthemesc-codex 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +8 -0
- data/Makefile.server +47 -0
- data/README.markdown +3 -0
- data/Rakefile +71 -0
- data/VERSION +1 -0
- data/build.h +11 -0
- data/codex.c +470 -0
- data/codex.gemspec +49 -0
- data/codex.h +58 -0
- data/codex_rb_ext.c +208 -0
- data/extconf.rb +2 -0
- data/format.h +126 -0
- data/lib/codex.rb +39 -0
- data/ptrn2mask +23 -0
- data/tpl.c +2449 -0
- data/tpl.h +119 -0
- data/vm.c +57 -0
- data/vm.h +35 -0
- metadata +71 -0
data/.gitignore
ADDED
data/Makefile.server
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- Mode: Makefile; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2
|
+
#
|
3
|
+
# Makefile for 'codex'.
|
4
|
+
#
|
5
|
+
# Type 'make' or 'make codex' to create the binary.
|
6
|
+
# Type 'make clean' to delete all temporaries.
|
7
|
+
# Type 'make run' to execute the binary.
|
8
|
+
# Type 'make debug' to debug the binary using gdb(1).
|
9
|
+
#
|
10
|
+
|
11
|
+
# build target specs
|
12
|
+
CC = cc
|
13
|
+
CFLAGS = -O3 -pipe -fPIC -fomit-frame-pointer -fno-common \
|
14
|
+
-Wall -Wshadow -Wpointer-arith \
|
15
|
+
# -march=native -mcpu=native -mtune=native
|
16
|
+
|
17
|
+
LIBS = -levent
|
18
|
+
|
19
|
+
# first target entry is the target invoked when typing 'make'
|
20
|
+
default: codex.c.o vm.c.o tpl.c.o
|
21
|
+
@echo -n 'Increasing build number in build.h... '
|
22
|
+
@awk '!/define CODEX_BUILD/ {print} /define CODEX_BUILD/ {print "#define CODEX_BUILD\t"$$3+1}' build.h > build.h~
|
23
|
+
@mv build.h~ build.h
|
24
|
+
@echo Done.
|
25
|
+
@echo -n 'Linking codex... '
|
26
|
+
@$(CC) $(CFLAGS) -o codex codex.c.o vm.c.o tpl.c.o $(LIBS)
|
27
|
+
@echo Done.
|
28
|
+
|
29
|
+
codex.c.o: codex.c
|
30
|
+
@echo -n 'Compiling codex.c... '
|
31
|
+
@$(CC) $(CFLAGS) -o codex.c.o -c codex.c
|
32
|
+
@echo Done.
|
33
|
+
|
34
|
+
vm.c.o: vm.c
|
35
|
+
@echo -n 'Compiling vm.c... '
|
36
|
+
@$(CC) $(CFLAGS) -o vm.c.o -c vm.c
|
37
|
+
@echo Done.
|
38
|
+
|
39
|
+
tpl.c.o: tpl.c
|
40
|
+
@echo -n 'Compiling tpl.c... '
|
41
|
+
@$(CC) $(CFLAGS) -o tpl.c.o -c tpl.c
|
42
|
+
@echo Done.
|
43
|
+
|
44
|
+
clean:
|
45
|
+
@echo -n 'Removing all temporary binaries... '
|
46
|
+
@rm -f codex *.o *.core *.map *.bundle
|
47
|
+
@echo Done.
|
data/README.markdown
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "codex"
|
8
|
+
gem.summary = %Q{Codex network machine}
|
9
|
+
gem.email = "josh@eksdyne.com"
|
10
|
+
gem.homepage = "http://github.com/synthemesc/codex"
|
11
|
+
gem.authors = ["Joshua Eckstein"]
|
12
|
+
# gem.rubyforge_project = "codex"
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
|
16
|
+
Jeweler::RubyforgeTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/*_test.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
task :default => :extconf
|
43
|
+
|
44
|
+
task :extconf do
|
45
|
+
ruby(File.join(File.dirname(__FILE__), 'extconf.rb'))
|
46
|
+
sh((PLATFORM =~ /win32/ ? 'nmake' : 'make') + ' -f Makefile.server')
|
47
|
+
sh(PLATFORM =~ /win32/ ? 'nmake' : 'make')
|
48
|
+
|
49
|
+
begin
|
50
|
+
require 'lib/codex'
|
51
|
+
File.new('VERSION', 'wb') << Codex::VERSION + "\n"
|
52
|
+
rescue LoadError
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
require 'rake/rdoctask'
|
57
|
+
Rake::RDocTask.new do |rdoc|
|
58
|
+
if File.exist?('VERSION.yml')
|
59
|
+
config = YAML.load(File.read('VERSION.yml'))
|
60
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
61
|
+
else
|
62
|
+
version = ""
|
63
|
+
end
|
64
|
+
|
65
|
+
rdoc.rdoc_dir = 'rdoc'
|
66
|
+
rdoc.title = "codex #{version}"
|
67
|
+
rdoc.rdoc_files.include('README*')
|
68
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
69
|
+
rdoc.options << '--accessor' << 'attr_xml=RW'
|
70
|
+
end
|
71
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/build.h
ADDED
data/codex.c
ADDED
@@ -0,0 +1,470 @@
|
|
1
|
+
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2
|
+
|
3
|
+
#include <sys/mman.h>
|
4
|
+
#include <sys/socket.h>
|
5
|
+
#include <sys/stat.h>
|
6
|
+
#include <sys/types.h>
|
7
|
+
|
8
|
+
#include <arpa/inet.h>
|
9
|
+
#include <assert.h>
|
10
|
+
#include <event.h>
|
11
|
+
#include <fcntl.h>
|
12
|
+
#include <inttypes.h>
|
13
|
+
#include <signal.h>
|
14
|
+
#include <stdint.h>
|
15
|
+
#include <stdio.h>
|
16
|
+
#include <stdlib.h>
|
17
|
+
#include <string.h>
|
18
|
+
#include <unistd.h>
|
19
|
+
#include <getopt.h>
|
20
|
+
|
21
|
+
#include "tpl.h"
|
22
|
+
#include "codex.h"
|
23
|
+
#include "format.h"
|
24
|
+
#include "vm.h"
|
25
|
+
|
26
|
+
static int verbose = VERBOSITY;
|
27
|
+
static int daemonize = FOREGROUND;
|
28
|
+
|
29
|
+
#if 0
|
30
|
+
static uint64_t CONSTANTS[] = { 0, 1 };
|
31
|
+
#endif
|
32
|
+
|
33
|
+
static struct codex sys;
|
34
|
+
static struct event event_handle;
|
35
|
+
static tpl_node *tpl_instructions = NULL;
|
36
|
+
static tpl_node *tpl_registers = NULL;
|
37
|
+
static struct sockaddr_in addr;
|
38
|
+
static socklen_t addr_size = sizeof(addr);
|
39
|
+
static struct instruction_word current;
|
40
|
+
|
41
|
+
static void codex_message(int socket_descriptor, short event, void* args)
|
42
|
+
{
|
43
|
+
static char buffer[PIPELINE_SIZE+1];
|
44
|
+
static int recv_length;
|
45
|
+
|
46
|
+
static uint64_t src;
|
47
|
+
static uint64_t arg;
|
48
|
+
static uint64_t result;
|
49
|
+
|
50
|
+
static uint64_t fetch_src;
|
51
|
+
static uint64_t fetch_arg;
|
52
|
+
|
53
|
+
#define NO_FLAGS 0
|
54
|
+
recv_length = recvfrom(socket_descriptor, buffer, PIPELINE_SIZE,
|
55
|
+
NO_FLAGS, (struct sockaddr*) &addr, (socklen_t*) &addr_size);
|
56
|
+
|
57
|
+
if (UNLIKELY(recv_length < 1))
|
58
|
+
{
|
59
|
+
if (UNLIKELY(verbose)) fprintf(stderr, "Got < 1 bytes: socket error or useless.\n");
|
60
|
+
return;
|
61
|
+
}
|
62
|
+
|
63
|
+
if (UNLIKELY(tpl_load(tpl_instructions, TPL_MEM | TPL_EXCESS_OK, buffer, recv_length) == -1))
|
64
|
+
{
|
65
|
+
if (UNLIKELY(verbose)) fprintf(stderr, "Got %d bytes, but they were invalid.\n", recv_length);
|
66
|
+
return;
|
67
|
+
}
|
68
|
+
|
69
|
+
while(tpl_unpack(tpl_instructions, 1) > 0)
|
70
|
+
{
|
71
|
+
current.opcode &= VALID_INSTRUCTION;
|
72
|
+
|
73
|
+
#define VALID_OFFSET(sys,off) (off>=sys.offset&&off<(sys.offset+sys.size))
|
74
|
+
|
75
|
+
/* Source decode */
|
76
|
+
switch(current.opcode & SRC_TYPE)
|
77
|
+
{
|
78
|
+
case SRC_TYPE_VAL:
|
79
|
+
fetch_src = current.src;
|
80
|
+
break;
|
81
|
+
|
82
|
+
case SRC_TYPE_REF:
|
83
|
+
if (VALID_OFFSET(sys, current.src))
|
84
|
+
fetch_src = sys.memory[current.src];
|
85
|
+
else
|
86
|
+
continue;
|
87
|
+
break;
|
88
|
+
|
89
|
+
default:
|
90
|
+
continue;
|
91
|
+
}
|
92
|
+
|
93
|
+
/* Argument decode */
|
94
|
+
switch(current.opcode & ARG_TYPE)
|
95
|
+
{
|
96
|
+
case ARG_TYPE_VAL:
|
97
|
+
fetch_arg = current.arg;
|
98
|
+
break;
|
99
|
+
|
100
|
+
case ARG_TYPE_REF:
|
101
|
+
if (VALID_OFFSET(sys, current.arg))
|
102
|
+
fetch_arg = sys.memory[current.arg];
|
103
|
+
else
|
104
|
+
continue;
|
105
|
+
break;
|
106
|
+
|
107
|
+
default:
|
108
|
+
continue;
|
109
|
+
}
|
110
|
+
|
111
|
+
/* Fetch src */
|
112
|
+
switch(current.opcode & SRC_MODE)
|
113
|
+
{
|
114
|
+
/* Source operand contains a hardcoded value. */
|
115
|
+
case SRC_MODE_IMM: src = fetch_src; break;
|
116
|
+
/* Source operand contains an address. */
|
117
|
+
case SRC_MODE_ADDR: src = sys.memory[fetch_src]; break;
|
118
|
+
/* Source operand contains a reference to a register. */
|
119
|
+
case SRC_MODE_REG: src = sys.registers[fetch_src & VALID_REGISTER]; break;
|
120
|
+
#if 0
|
121
|
+
/* Source operand contains a hardcoded constant. */
|
122
|
+
case SRC_MODE_CONST: src = CONSTANTS[fetch_src & CONSTANT_COUNT]; break;
|
123
|
+
#endif
|
124
|
+
|
125
|
+
default:
|
126
|
+
continue;
|
127
|
+
}
|
128
|
+
|
129
|
+
/* Fetch argument */
|
130
|
+
switch(current.opcode & ARG_MODE)
|
131
|
+
{
|
132
|
+
/* Source operand contains a hardcoded value. */
|
133
|
+
case ARG_MODE_IMM: arg = fetch_arg; break;
|
134
|
+
/* Source operand contains an address. */
|
135
|
+
case ARG_MODE_ADDR: arg = sys.memory[fetch_arg]; break;
|
136
|
+
/* Source operand contains a reference to a register. */
|
137
|
+
case ARG_MODE_REG: arg = sys.registers[fetch_arg & VALID_REGISTER]; break;
|
138
|
+
#if 0
|
139
|
+
/* Source operand contains a hardcoded constant. */
|
140
|
+
case ARG_MODE_CONST: arg = CONSTANTS[fetch_arg & CONSTANT_COUNT]; break;
|
141
|
+
#endif
|
142
|
+
|
143
|
+
default:
|
144
|
+
continue;
|
145
|
+
}
|
146
|
+
|
147
|
+
switch(current.opcode & OP_FULL)
|
148
|
+
{
|
149
|
+
/* clr %ax */
|
150
|
+
case OP_CLR:
|
151
|
+
result = 0;
|
152
|
+
break;
|
153
|
+
|
154
|
+
/* mov %ax, %bx */
|
155
|
+
case OP_MOV:
|
156
|
+
result = src;
|
157
|
+
break;
|
158
|
+
|
159
|
+
case OP_SORT:
|
160
|
+
if (src < arg)
|
161
|
+
result = -1;
|
162
|
+
else if (src > arg)
|
163
|
+
result = +1;
|
164
|
+
else
|
165
|
+
result = 0;
|
166
|
+
|
167
|
+
case OP_AVG:
|
168
|
+
result = (src + arg) / 2;
|
169
|
+
|
170
|
+
/*case OP_BE:*/
|
171
|
+
/*case OP_BNE:*/
|
172
|
+
/*case OP_BEZ:*/
|
173
|
+
/*case OP_BNEZ:*/
|
174
|
+
/*case OP_BLTEZ:*/
|
175
|
+
/*case OP_BGTEZ:*/
|
176
|
+
/*case OP_JMP:*/
|
177
|
+
/*case OP_SKP:*/
|
178
|
+
|
179
|
+
case OP_MIN:
|
180
|
+
if (src < arg)
|
181
|
+
result = src;
|
182
|
+
else
|
183
|
+
result = arg;
|
184
|
+
break;
|
185
|
+
|
186
|
+
case OP_MAX:
|
187
|
+
if (src > arg)
|
188
|
+
result = src;
|
189
|
+
else
|
190
|
+
result = arg;
|
191
|
+
break;
|
192
|
+
|
193
|
+
/*case OP_BLT:*/
|
194
|
+
/*case OP_BGT:*/
|
195
|
+
/*case OP_BLTZ:*/
|
196
|
+
/*case OP_BGTZ:*/
|
197
|
+
/*case OP_BLTE:*/
|
198
|
+
/*case OP_BGTE:*/
|
199
|
+
/*case OP_PUSH:*/
|
200
|
+
/*case OP_POP:*/
|
201
|
+
|
202
|
+
case OP_OR:
|
203
|
+
result = src | arg;
|
204
|
+
break;
|
205
|
+
|
206
|
+
case OP_NOR:
|
207
|
+
result = ~(src | arg);
|
208
|
+
break;
|
209
|
+
|
210
|
+
case OP_ADD:
|
211
|
+
result = src + arg;
|
212
|
+
break;
|
213
|
+
|
214
|
+
case OP_SUB:
|
215
|
+
result = src - arg;
|
216
|
+
break;
|
217
|
+
|
218
|
+
case OP_INC:
|
219
|
+
result = src + 1;
|
220
|
+
break;
|
221
|
+
|
222
|
+
case OP_DEC:
|
223
|
+
result = src - 1;
|
224
|
+
break;
|
225
|
+
|
226
|
+
case OP_GRY:
|
227
|
+
result = src ^ (src >> 1);
|
228
|
+
break;
|
229
|
+
|
230
|
+
/*case OP_HUE:*/
|
231
|
+
/*case OP_CALL:*/
|
232
|
+
/*case OP_RET:*/
|
233
|
+
|
234
|
+
case OP_AND:
|
235
|
+
result = src & arg;
|
236
|
+
break;
|
237
|
+
|
238
|
+
case OP_NAND:
|
239
|
+
result = ~(src & arg);
|
240
|
+
break;
|
241
|
+
|
242
|
+
case OP_MUL:
|
243
|
+
result = src * arg;
|
244
|
+
break;
|
245
|
+
|
246
|
+
case OP_DIV:
|
247
|
+
result = src / arg;
|
248
|
+
break;
|
249
|
+
|
250
|
+
case OP_SHL:
|
251
|
+
result = src << arg;
|
252
|
+
break;
|
253
|
+
|
254
|
+
case OP_SHR:
|
255
|
+
result = src >> arg;
|
256
|
+
break;
|
257
|
+
|
258
|
+
/*case OP_ROTL:*/
|
259
|
+
/*case OP_ROTR:*/
|
260
|
+
|
261
|
+
case OP_XOR:
|
262
|
+
result = src ^ arg;
|
263
|
+
break;
|
264
|
+
|
265
|
+
case OP_NOT:
|
266
|
+
result = ~src;
|
267
|
+
break;
|
268
|
+
|
269
|
+
case OP_SQR:
|
270
|
+
result = src * src;
|
271
|
+
break;
|
272
|
+
|
273
|
+
default:
|
274
|
+
continue;
|
275
|
+
}
|
276
|
+
|
277
|
+
if (UNLIKELY(verbose))
|
278
|
+
fprintf(stderr, "%llu <%x> %llu => %llu\n",
|
279
|
+
LLU current.src, current.opcode, LLU current.arg, LLU result);
|
280
|
+
|
281
|
+
switch(current.opcode & DST_TYPE)
|
282
|
+
{
|
283
|
+
case DST_MODE_ADDR:
|
284
|
+
if (VALID_OFFSET(sys, current.dst))
|
285
|
+
sys.memory[current.dst] = result;
|
286
|
+
else
|
287
|
+
continue;
|
288
|
+
break;
|
289
|
+
|
290
|
+
case DST_MODE_REG:
|
291
|
+
sys.registers[current.dst & VALID_REGISTER] = result;
|
292
|
+
break;
|
293
|
+
|
294
|
+
default:
|
295
|
+
continue;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
|
299
|
+
char *reply_buffer;
|
300
|
+
int reply_buffer_size;
|
301
|
+
#define NO_FLAGS 0
|
302
|
+
tpl_pack(tpl_registers, 0);
|
303
|
+
tpl_dump(tpl_registers, TPL_MEM, &reply_buffer, &reply_buffer_size);
|
304
|
+
sendto(socket_descriptor, reply_buffer, reply_buffer_size,
|
305
|
+
NO_FLAGS, (struct sockaddr*) &addr, addr_size);
|
306
|
+
free(reply_buffer);
|
307
|
+
}
|
308
|
+
|
309
|
+
static void codex_shutdown()
|
310
|
+
{
|
311
|
+
signal(SIGHUP, SIG_IGN);
|
312
|
+
signal(SIGINT, SIG_IGN);
|
313
|
+
signal(SIGQUIT, SIG_IGN);
|
314
|
+
signal(SIGABRT, SIG_IGN);
|
315
|
+
|
316
|
+
fprintf(stderr, "Got signal, cleaning up.. ");
|
317
|
+
|
318
|
+
if (event_initialized(&event_handle))
|
319
|
+
{
|
320
|
+
event_loopbreak();
|
321
|
+
fprintf(stderr, "event ");
|
322
|
+
}
|
323
|
+
|
324
|
+
if (sys.memory != NULL)
|
325
|
+
{
|
326
|
+
munmap(sys.memory, sys.size);
|
327
|
+
fprintf(stderr, "map ");
|
328
|
+
}
|
329
|
+
|
330
|
+
if (sys.descriptor > 0)
|
331
|
+
{
|
332
|
+
fsync(sys.descriptor); fprintf(stderr, "sync ");
|
333
|
+
close(sys.descriptor); fprintf(stderr, "close ");
|
334
|
+
fsync(sys.descriptor); fprintf(stderr, "sync ");
|
335
|
+
}
|
336
|
+
|
337
|
+
if (tpl_instructions != NULL)
|
338
|
+
{
|
339
|
+
tpl_free(tpl_instructions);
|
340
|
+
fprintf(stderr, "tpl ");
|
341
|
+
}
|
342
|
+
|
343
|
+
fprintf(stderr, "done.\n");
|
344
|
+
exit(0);
|
345
|
+
}
|
346
|
+
|
347
|
+
static void usage()
|
348
|
+
{
|
349
|
+
fprintf(stderr, "codex [--daemonize] [--verbose | --silent] [--range <offset+length>] [--file <filename>] [--port <port>]\n");
|
350
|
+
fprintf(stderr, "codex [-d] [-v | -s] [-r <offset+length>] [-f <filename>] [-p <port>]\n");
|
351
|
+
exit(EXIT_FAILURE);
|
352
|
+
}
|
353
|
+
|
354
|
+
int main(int argc, char *argv[])
|
355
|
+
{
|
356
|
+
signal(SIGHUP, codex_shutdown);
|
357
|
+
signal(SIGINT, codex_shutdown);
|
358
|
+
signal(SIGQUIT, codex_shutdown);
|
359
|
+
signal(SIGABRT, codex_shutdown);
|
360
|
+
|
361
|
+
static struct option long_options[] =
|
362
|
+
{
|
363
|
+
{ "verbose", no_argument, &verbose, VERBOSE },
|
364
|
+
{ "silent", no_argument, &verbose, SILENT },
|
365
|
+
{ "daemonize", no_argument, &daemonize, DAEMONIZE },
|
366
|
+
{ "range", required_argument, NULL, 'r' },
|
367
|
+
{ "file", required_argument, NULL, 'f' },
|
368
|
+
{ "port", required_argument, NULL, 'p' },
|
369
|
+
{ 0, 0, 0, 0 }
|
370
|
+
};
|
371
|
+
|
372
|
+
#define TO_STR(x) #x
|
373
|
+
|
374
|
+
char* range = TO_STR(DEFAULT_START+DEFAULT_SIZE);
|
375
|
+
|
376
|
+
int truth = 1;
|
377
|
+
uint16_t port = PORT;
|
378
|
+
sys.offset = DEFAULT_START;
|
379
|
+
sys.size = DEFAULT_SIZE;
|
380
|
+
|
381
|
+
if (argc < 2)
|
382
|
+
{
|
383
|
+
usage();
|
384
|
+
return(EXIT_FAILURE);
|
385
|
+
}
|
386
|
+
|
387
|
+
int c;
|
388
|
+
while ((c = getopt_long(argc, argv, "vsdr:f:p:", long_options, NULL)) != -1)
|
389
|
+
{
|
390
|
+
switch (c)
|
391
|
+
{
|
392
|
+
case 'r':
|
393
|
+
range = strdup(optarg);
|
394
|
+
/* Allocate a range string (0x0000+0xFFFF), copy safely */
|
395
|
+
sys.offset = strtoll(strsep(&range, "+"), (char **)NULL, 16);
|
396
|
+
sys.size = strtoll(range, (char **)NULL, 16);
|
397
|
+
break;
|
398
|
+
|
399
|
+
case 'f':
|
400
|
+
/* Allocate a filename, copy safely */
|
401
|
+
strncpy(sys.filename, optarg, sizeof(sys.filename)-1);
|
402
|
+
sys.filename[sizeof(sys.filename)-1] = '\0';
|
403
|
+
break;
|
404
|
+
|
405
|
+
case 'p':
|
406
|
+
port = atoi(optarg);
|
407
|
+
break;
|
408
|
+
|
409
|
+
default:
|
410
|
+
break;
|
411
|
+
}
|
412
|
+
}
|
413
|
+
|
414
|
+
if (daemonize == DAEMONIZE)
|
415
|
+
{
|
416
|
+
pid_t pid, sid;
|
417
|
+
|
418
|
+
fprintf(stderr, "Daemonizing.. ");
|
419
|
+
pid = fork();
|
420
|
+
|
421
|
+
if (pid < 0) exit(EXIT_FAILURE);
|
422
|
+
else if (pid > 0) exit(EXIT_SUCCESS);
|
423
|
+
umask(0);
|
424
|
+
|
425
|
+
sid = setsid();
|
426
|
+
if (sid < 0) exit(EXIT_FAILURE);
|
427
|
+
fprintf(stderr, "done.\n");
|
428
|
+
}
|
429
|
+
|
430
|
+
assert(port > 0);
|
431
|
+
assert(port < 65535);
|
432
|
+
|
433
|
+
codex_init(&sys);
|
434
|
+
|
435
|
+
#define NO_PROTOCOL 0
|
436
|
+
int socket_descriptor;
|
437
|
+
assert((socket_descriptor = socket(AF_INET, SOCK_DGRAM, NO_PROTOCOL)) > 0);
|
438
|
+
|
439
|
+
fprintf(stderr, "Setting socket options.. ");
|
440
|
+
assert(setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, &truth, sizeof(truth)) == 0);
|
441
|
+
assert(setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEPORT, &truth, sizeof(truth)) == 0);
|
442
|
+
fprintf(stderr, "done.\n");
|
443
|
+
|
444
|
+
addr.sin_family = AF_INET;
|
445
|
+
addr.sin_port = htons(port);
|
446
|
+
addr.sin_addr.s_addr = INADDR_ANY;
|
447
|
+
|
448
|
+
fprintf(stderr, "Binding to interface on port %d.. ", port);
|
449
|
+
assert(bind(socket_descriptor, (struct sockaddr*) &addr, addr_size) == 0);
|
450
|
+
fprintf(stderr, "done.\n");
|
451
|
+
|
452
|
+
fprintf(stderr, "Constructing serializer.. ");
|
453
|
+
tpl_instructions = tpl_map(TPL_INSTRUCTION_FORMAT, ¤t);
|
454
|
+
tpl_registers = tpl_map(TPL_REGISTER_FORMAT, sys.registers, REGISTER_COUNT);
|
455
|
+
assert(tpl_instructions != NULL);
|
456
|
+
assert(tpl_registers != NULL);
|
457
|
+
fprintf(stderr, "done.\n");
|
458
|
+
|
459
|
+
#define NO_CALLBACK_ARGS 0
|
460
|
+
#define NO_TIMEOUT NULL
|
461
|
+
#define NO_FLAGS 0
|
462
|
+
event_init();
|
463
|
+
event_set(&event_handle, socket_descriptor, EV_READ | EV_PERSIST, codex_message, NO_CALLBACK_ARGS);
|
464
|
+
event_add(&event_handle, NO_TIMEOUT);
|
465
|
+
event_loop(NO_FLAGS);
|
466
|
+
|
467
|
+
codex_shutdown();
|
468
|
+
return (EXIT_SUCCESS);
|
469
|
+
}
|
470
|
+
|