521311f618c4b83b8f43eea3e11231ba2ee4f99d
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 #undef PACKAGE_TARNAME
30 #undef PACKAGE_VERSION
36 static VALUE rbm_dumm
;
37 static VALUE rbc_guest
;
38 static VALUE rbc_bridge
;
39 static VALUE rbc_iface
;
40 static VALUE rbc_template
;
43 * Guest invocation callback
45 static pid_t
invoke(void *null
, guest_t
*guest
, char *args
[], int argc
)
49 args
[argc
++] = "con0=xterm";
50 args
[argc
++] = "xterm=gnome-terminal,-t,-x";
56 /* create a new process group in order to prevent signals (e.g.
57 * SIGINT) sent to the parent from terminating the child */
59 dup2(open("/dev/null", 0), 1);
60 dup2(open("/dev/null", 0), 2);
61 execvp(args
[0], args
);
71 * SIGCHLD signal handler
73 static void sigchld_handler(int signal
, siginfo_t
*info
, void* ptr
)
75 enumerator_t
*enumerator
;
78 enumerator
= dumm
->create_guest_enumerator(dumm
);
79 while (enumerator
->enumerate(enumerator
, &guest
))
81 if (guest
->get_pid(guest
) == info
->si_pid
)
83 guest
->sigchild(guest
);
87 enumerator
->destroy(enumerator
);
95 static VALUE
guest_find(VALUE
class, VALUE key
)
97 enumerator_t
*enumerator
;
98 guest_t
*guest
, *found
= NULL
;
99 if (TYPE(key
) == T_SYMBOL
) {
100 key
= rb_convert_type(key
, T_STRING
, "String", "to_s");
102 enumerator
= dumm
->create_guest_enumerator(dumm
);
103 while (enumerator
->enumerate(enumerator
, &guest
))
105 if (streq(guest
->get_name(guest
), StringValuePtr(key
)))
111 enumerator
->destroy(enumerator
);
116 return Data_Wrap_Struct(class, NULL
, NULL
, found
);
119 static VALUE
guest_get(VALUE
class, VALUE key
)
121 VALUE guest
= guest_find(class, key
);
124 rb_raise(rb_eRuntimeError
, "guest not found");
129 static VALUE
guest_each(int argc
, VALUE
*argv
, VALUE
class)
131 enumerator_t
*enumerator
;
134 if (!rb_block_given_p())
136 rb_raise(rb_eArgError
, "must be called with a block");
138 enumerator
= dumm
->create_guest_enumerator(dumm
);
139 while (enumerator
->enumerate(enumerator
, &guest
))
141 rb_yield(Data_Wrap_Struct(class, NULL
, NULL
, guest
));
143 enumerator
->destroy(enumerator
);
147 static VALUE
guest_new(VALUE
class, VALUE name
, VALUE kernel
,
148 VALUE master
, VALUE mem
)
152 guest
= dumm
->create_guest(dumm
, StringValuePtr(name
), StringValuePtr(kernel
),
153 StringValuePtr(master
), FIX2INT(mem
));
156 rb_raise(rb_eRuntimeError
, "creating guest failed");
158 return Data_Wrap_Struct(class, NULL
, NULL
, guest
);
161 static VALUE
guest_to_s(VALUE self
)
165 Data_Get_Struct(self
, guest_t
, guest
);
166 return rb_str_new2(guest
->get_name(guest
));
169 static VALUE
guest_start(VALUE self
)
173 Data_Get_Struct(self
, guest_t
, guest
);
175 if (!guest
->start(guest
, invoke
, NULL
, NULL
))
177 rb_raise(rb_eRuntimeError
, "starting guest failed");
182 static VALUE
guest_stop(VALUE self
)
186 Data_Get_Struct(self
, guest_t
, guest
);
187 guest
->stop(guest
, NULL
);
191 static VALUE
guest_running(VALUE self
)
195 Data_Get_Struct(self
, guest_t
, guest
);
196 return guest
->get_pid(guest
) ? Qtrue
: Qfalse
;
199 static void exec_cb(void *data
, char *buf
)
201 rb_yield(rb_str_new2(buf
));
204 static VALUE
guest_exec(VALUE self
, VALUE cmd
)
210 block
= rb_block_given_p();
211 Data_Get_Struct(self
, guest_t
, guest
);
212 if ((ret
= guest
->exec_str(guest
, block ?
(void*)exec_cb
: NULL
, TRUE
, NULL
,
213 "%s", StringValuePtr(cmd
))) != 0)
215 rb_raise(rb_eRuntimeError
, "executing command failed (%d)", ret
);
220 static VALUE
guest_add_iface(VALUE self
, VALUE name
)
225 Data_Get_Struct(self
, guest_t
, guest
);
226 iface
= guest
->create_iface(guest
, StringValuePtr(name
));
229 rb_raise(rb_eRuntimeError
, "adding interface failed");
231 return Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
);
234 static VALUE
guest_find_iface(VALUE self
, VALUE key
)
236 enumerator_t
*enumerator
;
237 iface_t
*iface
, *found
= NULL
;
239 if (TYPE(key
) == T_SYMBOL
) {
240 key
= rb_convert_type(key
, T_STRING
, "String", "to_s");
242 Data_Get_Struct(self
, guest_t
, guest
);
243 enumerator
= guest
->create_iface_enumerator(guest
);
244 while (enumerator
->enumerate(enumerator
, &iface
))
246 if (streq(iface
->get_guestif(iface
), StringValuePtr(key
)))
252 enumerator
->destroy(enumerator
);
257 return Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
);
260 static VALUE
guest_get_iface(VALUE self
, VALUE key
)
262 VALUE iface
= guest_find_iface(self
, key
);
265 rb_raise(rb_eRuntimeError
, "interface not found");
270 static VALUE
guest_each_iface(int argc
, VALUE
*argv
, VALUE self
)
272 enumerator_t
*enumerator
;
276 if (!rb_block_given_p())
278 rb_raise(rb_eArgError
, "must be called with a block");
280 Data_Get_Struct(self
, guest_t
, guest
);
281 enumerator
= guest
->create_iface_enumerator(guest
);
282 while (enumerator
->enumerate(enumerator
, &iface
))
284 rb_yield(Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
));
286 enumerator
->destroy(enumerator
);
290 static VALUE
guest_delete(VALUE self
)
294 Data_Get_Struct(self
, guest_t
, guest
);
295 dumm
->delete_guest(dumm
, guest
);
299 static void guest_init()
301 rbc_guest
= rb_define_class_under(rbm_dumm
, "Guest", rb_cObject
);
302 rb_include_module(rb_class_of(rbc_guest
), rb_mEnumerable
);
303 rb_include_module(rbc_guest
, rb_mEnumerable
);
305 rb_define_singleton_method(rbc_guest
, "[]", guest_get
, 1);
306 rb_define_singleton_method(rbc_guest
, "each", guest_each
, -1);
307 rb_define_singleton_method(rbc_guest
, "new", guest_new
, 4);
308 rb_define_singleton_method(rbc_guest
, "include?", guest_find
, 1);
309 rb_define_singleton_method(rbc_guest
, "guest?", guest_find
, 1);
311 rb_define_method(rbc_guest
, "to_s", guest_to_s
, 0);
312 rb_define_method(rbc_guest
, "start", guest_start
, 0);
313 rb_define_method(rbc_guest
, "stop", guest_stop
, 0);
314 rb_define_method(rbc_guest
, "running?", guest_running
, 0);
315 rb_define_method(rbc_guest
, "exec", guest_exec
, 1);
316 rb_define_method(rbc_guest
, "add", guest_add_iface
, 1);
317 rb_define_method(rbc_guest
, "[]", guest_get_iface
, 1);
318 rb_define_method(rbc_guest
, "each", guest_each_iface
, -1);
319 rb_define_method(rbc_guest
, "include?", guest_find_iface
, 1);
320 rb_define_method(rbc_guest
, "iface?", guest_find_iface
, 1);
321 rb_define_method(rbc_guest
, "delete", guest_delete
, 0);
327 static VALUE
bridge_get(VALUE
class, VALUE key
)
329 enumerator_t
*enumerator
;
330 bridge_t
*bridge
, *found
= NULL
;
332 enumerator
= dumm
->create_bridge_enumerator(dumm
);
333 while (enumerator
->enumerate(enumerator
, &bridge
))
335 if (streq(bridge
->get_name(bridge
), StringValuePtr(key
)))
341 enumerator
->destroy(enumerator
);
344 rb_raise(rb_eRuntimeError
, "bridge not found");
346 return Data_Wrap_Struct(class, NULL
, NULL
, found
);
349 static VALUE
bridge_each(int argc
, VALUE
*argv
, VALUE
class)
351 enumerator_t
*enumerator
;
354 if (!rb_block_given_p())
356 rb_raise(rb_eArgError
, "must be called with a block");
358 enumerator
= dumm
->create_bridge_enumerator(dumm
);
359 while (enumerator
->enumerate(enumerator
, &bridge
))
361 rb_yield(Data_Wrap_Struct(class, NULL
, NULL
, bridge
));
363 enumerator
->destroy(enumerator
);
367 static VALUE
bridge_new(VALUE
class, VALUE name
)
372 bridge
= dumm
->create_bridge(dumm
, StringValuePtr(name
));
375 rb_raise(rb_eRuntimeError
, "creating bridge failed");
377 return Data_Wrap_Struct(class, NULL
, NULL
, bridge
);
380 static VALUE
bridge_to_s(VALUE self
)
384 Data_Get_Struct(self
, bridge_t
, bridge
);
385 return rb_str_new2(bridge
->get_name(bridge
));
388 static VALUE
bridge_each_iface(int argc
, VALUE
*argv
, VALUE self
)
390 enumerator_t
*enumerator
;
394 if (!rb_block_given_p())
396 rb_raise(rb_eArgError
, "must be called with a block");
398 Data_Get_Struct(self
, bridge_t
, bridge
);
399 enumerator
= bridge
->create_iface_enumerator(bridge
);
400 while (enumerator
->enumerate(enumerator
, &iface
))
402 rb_yield(Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
));
404 enumerator
->destroy(enumerator
);
408 static VALUE
bridge_delete(VALUE self
)
412 Data_Get_Struct(self
, bridge_t
, bridge
);
413 dumm
->delete_bridge(dumm
, bridge
);
417 static void bridge_init()
419 rbc_bridge
= rb_define_class_under(rbm_dumm
, "Bridge", rb_cObject
);
420 rb_include_module(rb_class_of(rbc_bridge
), rb_mEnumerable
);
421 rb_include_module(rbc_bridge
, rb_mEnumerable
);
423 rb_define_singleton_method(rbc_bridge
, "[]", bridge_get
, 1);
424 rb_define_singleton_method(rbc_bridge
, "each", bridge_each
, -1);
425 rb_define_singleton_method(rbc_bridge
, "new", bridge_new
, 1);
427 rb_define_method(rbc_bridge
, "to_s", bridge_to_s
, 0);
428 rb_define_method(rbc_bridge
, "each", bridge_each_iface
, -1);
429 rb_define_method(rbc_bridge
, "delete", bridge_delete
, 0);
435 static VALUE
iface_to_s(VALUE self
)
439 Data_Get_Struct(self
, iface_t
, iface
);
440 return rb_str_new2(iface
->get_hostif(iface
));
443 static VALUE
iface_connect(VALUE self
, VALUE vbridge
)
448 Data_Get_Struct(self
, iface_t
, iface
);
449 Data_Get_Struct(vbridge
, bridge_t
, bridge
);
450 if (!bridge
->connect_iface(bridge
, iface
))
452 rb_raise(rb_eRuntimeError
, "connecting iface failed");
457 static VALUE
iface_disconnect(VALUE self
)
462 Data_Get_Struct(self
, iface_t
, iface
);
463 bridge
= iface
->get_bridge(iface
);
464 if (!bridge
|| !bridge
->disconnect_iface(bridge
, iface
))
466 rb_raise(rb_eRuntimeError
, "disconnecting iface failed");
471 static VALUE
iface_add_addr(VALUE self
, VALUE name
)
476 addr
= host_create_from_string(StringValuePtr(name
), 0);
479 rb_raise(rb_eArgError
, "invalid IP address");
481 Data_Get_Struct(self
, iface_t
, iface
);
482 if (!iface
->add_address(iface
, addr
))
485 rb_raise(rb_eRuntimeError
, "adding address failed");
487 if (rb_block_given_p()) {
489 iface
->delete_address(iface
, addr
);
495 static VALUE
iface_each_addr(int argc
, VALUE
*argv
, VALUE self
)
497 enumerator_t
*enumerator
;
502 if (!rb_block_given_p())
504 rb_raise(rb_eArgError
, "must be called with a block");
506 Data_Get_Struct(self
, iface_t
, iface
);
507 enumerator
= iface
->create_address_enumerator(iface
);
508 while (enumerator
->enumerate(enumerator
, &addr
))
510 snprintf(buf
, sizeof(buf
), "%H", addr
);
511 rb_yield(rb_str_new2(buf
));
513 enumerator
->destroy(enumerator
);
517 static VALUE
iface_del_addr(VALUE self
, VALUE vaddr
)
522 addr
= host_create_from_string(StringValuePtr(vaddr
), 0);
525 rb_raise(rb_eArgError
, "invalid IP address");
527 Data_Get_Struct(self
, iface_t
, iface
);
528 if (!iface
->delete_address(iface
, addr
))
531 rb_raise(rb_eRuntimeError
, "address not found");
533 if (rb_block_given_p()) {
535 iface
->add_address(iface
, addr
);
541 static VALUE
iface_delete(VALUE self
)
546 Data_Get_Struct(self
, iface_t
, iface
);
547 guest
= iface
->get_guest(iface
);
548 guest
->destroy_iface(guest
, iface
);
552 static void iface_init()
554 rbc_iface
= rb_define_class_under(rbm_dumm
, "Iface", rb_cObject
);
555 rb_include_module(rbc_iface
, rb_mEnumerable
);
557 rb_define_method(rbc_iface
, "to_s", iface_to_s
, 0);
558 rb_define_method(rbc_iface
, "connect", iface_connect
, 1);
559 rb_define_method(rbc_iface
, "disconnect", iface_disconnect
, 0);
560 rb_define_method(rbc_iface
, "add", iface_add_addr
, 1);
561 rb_define_method(rbc_iface
, "del", iface_del_addr
, 1);
562 rb_define_method(rbc_iface
, "each", iface_each_addr
, -1);
563 rb_define_method(rbc_iface
, "delete", iface_delete
, 0);
566 static VALUE
template_load(VALUE
class, VALUE dir
)
568 if (!dumm
->load_template(dumm
, StringValuePtr(dir
)))
570 rb_raise(rb_eRuntimeError
, "loading template failed");
575 static VALUE
template_unload(VALUE
class)
577 if (!dumm
->load_template(dumm
, NULL
))
579 rb_raise(rb_eRuntimeError
, "unloading template failed");
584 static void template_init()
586 rbc_template
= rb_define_class_under(rbm_dumm
, "Template", rb_cObject
);
588 rb_define_singleton_method(rbc_template
, "load", template_load
, 1);
589 rb_define_singleton_method(rbc_template
, "unload", template_unload
, 0);
593 * extension finalization
597 struct sigaction action
;
601 sigemptyset(&action
.sa_mask
);
602 action
.sa_handler
= SIG_DFL
;
604 sigaction(SIGCHLD
, &action
, NULL
);
610 * extension initialization
614 struct sigaction action
;
616 /* there are too many to report, rubyruby... */
617 setenv("LEAK_DETECTIVE_DISABLE", "1", 1);
621 dumm
= dumm_create(NULL
);
623 rbm_dumm
= rb_define_module("Dumm");
630 sigemptyset(&action
.sa_mask
);
631 action
.sa_sigaction
= sigchld_handler
;
632 action
.sa_flags
= SA_SIGINFO
;
633 sigaction(SIGCHLD
, &action
, NULL
);
635 rb_set_end_proc(Final_dumm
, 0);