2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #undef PACKAGE_TARNAME
27 #undef PACKAGE_VERSION
39 * Guest invocation callback
41 static pid_t
invoke(void *null
, guest_t
*guest
, char *args
[], int argc
)
45 args
[argc
] = "con0=xterm";
51 dup2(open("/dev/null", 0), 1);
52 dup2(open("/dev/null", 0), 2);
53 execvp(args
[0], args
);
63 * SIGCHLD signal handler
65 static void sigchld_handler(int signal
, siginfo_t
*info
, void* ptr
)
67 enumerator_t
*enumerator
;
70 enumerator
= dumm
->create_guest_enumerator(dumm
);
71 while (enumerator
->enumerate(enumerator
, &guest
))
73 if (guest
->get_pid(guest
) == info
->si_pid
)
75 guest
->sigchild(guest
);
79 enumerator
->destroy(enumerator
);
83 * SIGINT/SEGV/TERM signal handler
85 static void sigint_handler(int signal
, siginfo_t
*info
, void* ptr
)
87 struct sigaction action
;
91 action
.sa_handler
= SIG_DFL
;
93 sigaction(SIGCHLD
, &action
, NULL
);
102 static VALUE
guest_get(VALUE
class, VALUE key
)
104 enumerator_t
*enumerator
;
105 guest_t
*guest
, *found
= NULL
;
107 enumerator
= dumm
->create_guest_enumerator(dumm
);
108 while (enumerator
->enumerate(enumerator
, &guest
))
110 if (streq(guest
->get_name(guest
), StringValuePtr(key
)))
116 enumerator
->destroy(enumerator
);
119 rb_raise(rb_eRuntimeError
, "guest not found");
121 return Data_Wrap_Struct(class, NULL
, NULL
, found
);
124 static VALUE
guest_each(int argc
, VALUE
*argv
, VALUE
class)
126 enumerator_t
*enumerator
;
129 if (!rb_block_given_p())
131 rb_raise(rb_eArgError
, "must be called with a block");
133 enumerator
= dumm
->create_guest_enumerator(dumm
);
134 while (enumerator
->enumerate(enumerator
, &guest
))
136 rb_yield(Data_Wrap_Struct(class, NULL
, NULL
, guest
));
138 enumerator
->destroy(enumerator
);
142 static VALUE
guest_new(VALUE
class, VALUE name
, VALUE kernel
,
143 VALUE master
, VALUE mem
)
147 guest
= dumm
->create_guest(dumm
, StringValuePtr(name
), StringValuePtr(kernel
),
148 StringValuePtr(master
), FIX2INT(mem
));
151 rb_raise(rb_eRuntimeError
, "creating guest failed");
153 return Data_Wrap_Struct(class, NULL
, NULL
, guest
);
156 static VALUE
guest_to_s(VALUE self
)
160 Data_Get_Struct(self
, guest_t
, guest
);
161 return rb_str_new2(guest
->get_name(guest
));
164 static VALUE
guest_start(VALUE self
)
168 Data_Get_Struct(self
, guest_t
, guest
);
170 if (!guest
->start(guest
, invoke
, NULL
, NULL
))
172 rb_raise(rb_eRuntimeError
, "starting guest failed");
177 static VALUE
guest_stop(VALUE self
)
181 Data_Get_Struct(self
, guest_t
, guest
);
183 if (!guest
->stop(guest
, NULL
))
185 rb_raise(rb_eRuntimeError
, "stopping guest failed");
195 static void exec_cb(exec_t
*exec
, char *buf
, size_t len
)
202 to_copy
= min(len
, sizeof(exec
->buf
) - (exec
->top
- exec
->buf
));
203 memcpy(exec
->top
, buf
, to_copy
);
204 exec
->top
+= to_copy
;
210 nl
= memchr(exec
->buf
, '\n', exec
->top
- exec
->buf
);
217 rb_yield(rb_str_new(exec
->buf
, nl
- exec
->buf
));
220 to_copy
= exec
->top
- nl
;
221 memmove(exec
->buf
, nl
, to_copy
);
222 exec
->top
= exec
->buf
+ to_copy
;
224 if (exec
->top
>= exec
->buf
+ sizeof(exec
->buf
))
226 rb_yield(rb_str_new(exec
->buf
, sizeof(exec
->buf
)));
227 exec
->top
= exec
->buf
;
232 static VALUE
guest_exec(VALUE self
, VALUE cmd
)
238 block
= rb_block_given_p();
240 Data_Get_Struct(self
, guest_t
, guest
);
241 if (guest
->exec(guest
, block ?
(void*)exec_cb
: NULL
, &exec
,
242 "%s", StringValuePtr(cmd
)) != 0)
244 rb_raise(rb_eRuntimeError
, "executing command failed");
246 if (exec
.top
!= exec
.buf
&& block
)
248 rb_yield(rb_str_new(exec
.buf
, exec
.top
- exec
.buf
));
253 static VALUE
guest_add_iface(VALUE self
, VALUE name
)
258 Data_Get_Struct(self
, guest_t
, guest
);
259 iface
= guest
->create_iface(guest
, StringValuePtr(name
));
262 rb_raise(rb_eRuntimeError
, "adding interface failed");
264 return Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
);
267 static VALUE
guest_get_iface(VALUE self
, VALUE key
)
269 enumerator_t
*enumerator
;
270 iface_t
*iface
, *found
= NULL
;
273 Data_Get_Struct(self
, guest_t
, guest
);
274 enumerator
= guest
->create_iface_enumerator(guest
);
275 while (enumerator
->enumerate(enumerator
, &iface
))
277 if (streq(iface
->get_guestif(iface
), StringValuePtr(key
)))
283 enumerator
->destroy(enumerator
);
286 rb_raise(rb_eRuntimeError
, "interface not found");
288 return Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
);
291 static VALUE
guest_each_iface(int argc
, VALUE
*argv
, VALUE self
)
293 enumerator_t
*enumerator
;
297 if (!rb_block_given_p())
299 rb_raise(rb_eArgError
, "must be called with a block");
301 Data_Get_Struct(self
, guest_t
, guest
);
302 enumerator
= guest
->create_iface_enumerator(guest
);
303 while (enumerator
->enumerate(enumerator
, &iface
))
305 rb_yield(Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
));
307 enumerator
->destroy(enumerator
);
311 static VALUE
guest_delete(VALUE self
)
315 Data_Get_Struct(self
, guest_t
, guest
);
316 dumm
->delete_guest(dumm
, guest
);
320 static void guest_init()
322 rbc_guest
= rb_define_class_under(rbm_dumm
, "Guest", rb_cObject
);
323 rb_define_singleton_method(rbc_guest
, "[]", guest_get
, 1);
324 rb_define_singleton_method(rbc_guest
, "each", guest_each
, -1);
325 rb_define_singleton_method(rbc_guest
, "new", guest_new
, 4);
326 rb_define_method(rbc_guest
, "to_s", guest_to_s
, 0);
327 rb_define_method(rbc_guest
, "start", guest_start
, 0);
328 rb_define_method(rbc_guest
, "stop", guest_stop
, 0);
329 rb_define_method(rbc_guest
, "exec", guest_exec
, 1);
330 rb_define_method(rbc_guest
, "add", guest_add_iface
, 1);
331 rb_define_method(rbc_guest
, "[]", guest_get_iface
, 1);
332 rb_define_method(rbc_guest
, "each", guest_each_iface
, -1);
333 rb_define_method(rbc_guest
, "delete", guest_delete
, 0);
334 rb_include_module(rb_class_of(rbc_guest
), rb_mEnumerable
);
335 rb_include_module(rbc_guest
, rb_mEnumerable
);
341 static VALUE
bridge_get(VALUE
class, VALUE key
)
343 enumerator_t
*enumerator
;
344 bridge_t
*bridge
, *found
= NULL
;
346 enumerator
= dumm
->create_bridge_enumerator(dumm
);
347 while (enumerator
->enumerate(enumerator
, &bridge
))
349 if (streq(bridge
->get_name(bridge
), StringValuePtr(key
)))
355 enumerator
->destroy(enumerator
);
358 rb_raise(rb_eRuntimeError
, "bridgne not found");
360 return Data_Wrap_Struct(class, NULL
, NULL
, found
);
363 static VALUE
bridge_each(int argc
, VALUE
*argv
, VALUE
class)
365 enumerator_t
*enumerator
;
368 if (!rb_block_given_p())
370 rb_raise(rb_eArgError
, "must be called with a block");
372 enumerator
= dumm
->create_bridge_enumerator(dumm
);
373 while (enumerator
->enumerate(enumerator
, &bridge
))
375 rb_yield(Data_Wrap_Struct(class, NULL
, NULL
, bridge
));
377 enumerator
->destroy(enumerator
);
381 static VALUE
bridge_new(VALUE
class, VALUE name
)
386 bridge
= dumm
->create_bridge(dumm
, StringValuePtr(name
));
389 rb_raise(rb_eRuntimeError
, "creating bridge failed");
391 return Data_Wrap_Struct(class, NULL
, NULL
, bridge
);
394 static VALUE
bridge_to_s(VALUE self
)
398 Data_Get_Struct(self
, bridge_t
, bridge
);
399 return rb_str_new2(bridge
->get_name(bridge
));
402 static VALUE
bridge_each_iface(int argc
, VALUE
*argv
, VALUE self
)
404 enumerator_t
*enumerator
;
408 if (!rb_block_given_p())
410 rb_raise(rb_eArgError
, "must be called with a block");
412 Data_Get_Struct(self
, bridge_t
, bridge
);
413 enumerator
= bridge
->create_iface_enumerator(bridge
);
414 while (enumerator
->enumerate(enumerator
, &iface
))
416 rb_yield(Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
));
418 enumerator
->destroy(enumerator
);
422 static VALUE
bridge_delete(VALUE self
)
426 Data_Get_Struct(self
, bridge_t
, bridge
);
427 dumm
->delete_bridge(dumm
, bridge
);
431 static void bridge_init()
433 rbc_bridge
= rb_define_class_under(rbm_dumm
, "Bridge", rb_cObject
);
434 rb_define_singleton_method(rbc_bridge
, "[]", bridge_get
, 1);
435 rb_define_singleton_method(rbc_bridge
, "each", bridge_each
, -1);
436 rb_define_singleton_method(rbc_bridge
, "new", bridge_new
, 1);
437 rb_define_method(rbc_bridge
, "to_s", bridge_to_s
, 0);
438 rb_define_method(rbc_bridge
, "each", bridge_each_iface
, -1);
439 rb_define_method(rbc_bridge
, "delete", bridge_delete
, 0);
440 rb_include_module(rb_class_of(rbc_bridge
), rb_mEnumerable
);
441 rb_include_module(rbc_bridge
, rb_mEnumerable
);
447 static VALUE
iface_to_s(VALUE self
)
451 Data_Get_Struct(self
, iface_t
, iface
);
452 return rb_str_new2(iface
->get_hostif(iface
));
455 static VALUE
iface_connect(VALUE self
, VALUE vbridge
)
460 Data_Get_Struct(self
, iface_t
, iface
);
461 Data_Get_Struct(vbridge
, bridge_t
, bridge
);
462 if (!bridge
->connect_iface(bridge
, iface
))
464 rb_raise(rb_eRuntimeError
, "connecting iface failed");
469 static VALUE
iface_disconnect(VALUE self
)
474 Data_Get_Struct(self
, iface_t
, iface
);
475 bridge
= iface
->get_bridge(iface
);
476 if (!bridge
|| !bridge
->disconnect_iface(bridge
, iface
))
478 rb_raise(rb_eRuntimeError
, "disconnecting iface failed");
483 static VALUE
iface_add_addr(VALUE self
, VALUE name
)
488 addr
= host_create_from_string(StringValuePtr(name
), 0);
491 rb_raise(rb_eRuntimeError
, "invalid IP address");
493 Data_Get_Struct(self
, iface_t
, iface
);
494 if (!iface
->add_address(iface
, addr
))
496 rb_raise(rb_eRuntimeError
, "adding address failed");
501 static VALUE
iface_each_addr(int argc
, VALUE
*argv
, VALUE self
)
503 enumerator_t
*enumerator
;
508 if (!rb_block_given_p())
510 rb_raise(rb_eArgError
, "must be called with a block");
512 Data_Get_Struct(self
, iface_t
, iface
);
513 enumerator
= iface
->create_address_enumerator(iface
);
514 while (enumerator
->enumerate(enumerator
, &addr
))
516 snprintf(buf
, sizeof(buf
), "%H", addr
);
517 rb_yield(rb_str_new2(buf
));
519 enumerator
->destroy(enumerator
);
523 static VALUE
iface_del_addr(VALUE self
, VALUE vaddr
)
528 addr
= host_create_from_string(StringValuePtr(vaddr
), 0);
529 Data_Get_Struct(self
, iface_t
, iface
);
530 if (!iface
->delete_address(iface
, addr
))
533 rb_raise(rb_eRuntimeError
, "address not found");
539 static VALUE
iface_delete(VALUE self
)
544 Data_Get_Struct(self
, iface_t
, iface
);
545 guest
= iface
->get_guest(iface
);
546 guest
->destroy_iface(guest
, iface
);
550 static void iface_init()
552 rbc_iface
= rb_define_class_under(rbm_dumm
, "Iface", rb_cObject
);
553 rb_define_method(rbc_iface
, "to_s", iface_to_s
, 0);
554 rb_define_method(rbc_iface
, "connect", iface_connect
, 1);
555 rb_define_method(rbc_iface
, "disconnect", iface_disconnect
, 0);
556 rb_define_method(rbc_iface
, "add", iface_add_addr
, 1);
557 rb_define_method(rbc_iface
, "del", iface_del_addr
, 1);
558 rb_define_method(rbc_iface
, "each", iface_each_addr
, -1);
559 rb_define_method(rbc_iface
, "delete", iface_delete
, 0);
560 rb_include_module(rbc_iface
, rb_mEnumerable
);
564 * main routine, parses args and reads from console
566 int main(int argc
, char *argv
[])
569 struct sigaction action
;
572 ruby_init_loadpath();
574 /* there are to many to report, rubyruby... */
575 setenv("LEAK_DETECTIVE_DISABLE", "1", 1);
579 dumm
= dumm_create(NULL
);
581 rbm_dumm
= rb_define_module("Dumm");
587 sigemptyset(&action
.sa_mask
);
588 action
.sa_flags
= SA_SIGINFO
;
589 action
.sa_sigaction
= sigchld_handler
;
590 sigaction(SIGCHLD
, &action
, NULL
);
591 action
.sa_sigaction
= sigint_handler
;
592 sigaction(SIGINT
, &action
, NULL
);
593 sigaction(SIGTERM
, &action
, NULL
);
594 sigaction(SIGSEGV
, &action
, NULL
);
595 sigaction(SIGHUP
, &action
, NULL
);
598 rb_eval_string_protect("include Dumm", &state
);
599 rb_eval_string_protect("IRB.start", &state
);
607 action
.sa_handler
= SIG_DFL
;
609 sigaction(SIGCHLD
, &action
, NULL
);