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
);
93 static VALUE
guest_get(VALUE
class, VALUE key
)
95 enumerator_t
*enumerator
;
96 guest_t
*guest
, *found
= NULL
;
98 enumerator
= dumm
->create_guest_enumerator(dumm
);
99 while (enumerator
->enumerate(enumerator
, &guest
))
101 if (streq(guest
->get_name(guest
), StringValuePtr(key
)))
107 enumerator
->destroy(enumerator
);
110 rb_raise(rb_eRuntimeError
, "guest not found");
112 return Data_Wrap_Struct(class, NULL
, NULL
, found
);
115 static VALUE
guest_each(int argc
, VALUE
*argv
, VALUE
class)
117 enumerator_t
*enumerator
;
120 if (!rb_block_given_p())
122 rb_raise(rb_eArgError
, "must be called with a block");
124 enumerator
= dumm
->create_guest_enumerator(dumm
);
125 while (enumerator
->enumerate(enumerator
, &guest
))
127 rb_yield(Data_Wrap_Struct(class, NULL
, NULL
, guest
));
129 enumerator
->destroy(enumerator
);
133 static VALUE
guest_new(VALUE
class, VALUE name
, VALUE kernel
,
134 VALUE master
, VALUE mem
)
138 guest
= dumm
->create_guest(dumm
, StringValuePtr(name
), StringValuePtr(kernel
),
139 StringValuePtr(master
), FIX2INT(mem
));
142 rb_raise(rb_eRuntimeError
, "creating guest failed");
144 return Data_Wrap_Struct(class, NULL
, NULL
, guest
);
147 static VALUE
guest_to_s(VALUE self
)
151 Data_Get_Struct(self
, guest_t
, guest
);
152 return rb_str_new2(guest
->get_name(guest
));
155 static VALUE
guest_start(VALUE self
)
159 Data_Get_Struct(self
, guest_t
, guest
);
161 if (!guest
->start(guest
, invoke
, NULL
, NULL
))
163 rb_raise(rb_eRuntimeError
, "starting guest failed");
168 static VALUE
guest_stop(VALUE self
)
172 Data_Get_Struct(self
, guest_t
, guest
);
173 guest
->stop(guest
, NULL
);
177 static void exec_cb(void *data
, char *buf
)
179 rb_yield(rb_str_new2(buf
));
182 static VALUE
guest_exec(VALUE self
, VALUE cmd
)
188 block
= rb_block_given_p();
189 Data_Get_Struct(self
, guest_t
, guest
);
190 if ((ret
= guest
->exec_str(guest
, block ?
(void*)exec_cb
: NULL
, TRUE
, NULL
,
191 "%s", StringValuePtr(cmd
))) != 0)
193 rb_raise(rb_eRuntimeError
, "executing command failed (%d)", ret
);
198 static VALUE
guest_add_iface(VALUE self
, VALUE name
)
203 Data_Get_Struct(self
, guest_t
, guest
);
204 iface
= guest
->create_iface(guest
, StringValuePtr(name
));
207 rb_raise(rb_eRuntimeError
, "adding interface failed");
209 return Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
);
212 static VALUE
guest_get_iface(VALUE self
, VALUE key
)
214 enumerator_t
*enumerator
;
215 iface_t
*iface
, *found
= NULL
;
218 Data_Get_Struct(self
, guest_t
, guest
);
219 enumerator
= guest
->create_iface_enumerator(guest
);
220 while (enumerator
->enumerate(enumerator
, &iface
))
222 if (streq(iface
->get_guestif(iface
), StringValuePtr(key
)))
228 enumerator
->destroy(enumerator
);
231 rb_raise(rb_eRuntimeError
, "interface not found");
233 return Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
);
236 static VALUE
guest_each_iface(int argc
, VALUE
*argv
, VALUE self
)
238 enumerator_t
*enumerator
;
242 if (!rb_block_given_p())
244 rb_raise(rb_eArgError
, "must be called with a block");
246 Data_Get_Struct(self
, guest_t
, guest
);
247 enumerator
= guest
->create_iface_enumerator(guest
);
248 while (enumerator
->enumerate(enumerator
, &iface
))
250 rb_yield(Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
));
252 enumerator
->destroy(enumerator
);
256 static VALUE
guest_delete(VALUE self
)
260 Data_Get_Struct(self
, guest_t
, guest
);
261 dumm
->delete_guest(dumm
, guest
);
265 static void guest_init()
267 rbc_guest
= rb_define_class_under(rbm_dumm
, "Guest", rb_cObject
);
268 rb_define_singleton_method(rbc_guest
, "[]", guest_get
, 1);
269 rb_define_singleton_method(rbc_guest
, "each", guest_each
, -1);
270 rb_define_singleton_method(rbc_guest
, "new", guest_new
, 4);
271 rb_define_method(rbc_guest
, "to_s", guest_to_s
, 0);
272 rb_define_method(rbc_guest
, "start", guest_start
, 0);
273 rb_define_method(rbc_guest
, "stop", guest_stop
, 0);
274 rb_define_method(rbc_guest
, "exec", guest_exec
, 1);
275 rb_define_method(rbc_guest
, "add", guest_add_iface
, 1);
276 rb_define_method(rbc_guest
, "[]", guest_get_iface
, 1);
277 rb_define_method(rbc_guest
, "each", guest_each_iface
, -1);
278 rb_define_method(rbc_guest
, "delete", guest_delete
, 0);
279 rb_include_module(rb_class_of(rbc_guest
), rb_mEnumerable
);
280 rb_include_module(rbc_guest
, rb_mEnumerable
);
286 static VALUE
bridge_get(VALUE
class, VALUE key
)
288 enumerator_t
*enumerator
;
289 bridge_t
*bridge
, *found
= NULL
;
291 enumerator
= dumm
->create_bridge_enumerator(dumm
);
292 while (enumerator
->enumerate(enumerator
, &bridge
))
294 if (streq(bridge
->get_name(bridge
), StringValuePtr(key
)))
300 enumerator
->destroy(enumerator
);
303 rb_raise(rb_eRuntimeError
, "bridge not found");
305 return Data_Wrap_Struct(class, NULL
, NULL
, found
);
308 static VALUE
bridge_each(int argc
, VALUE
*argv
, VALUE
class)
310 enumerator_t
*enumerator
;
313 if (!rb_block_given_p())
315 rb_raise(rb_eArgError
, "must be called with a block");
317 enumerator
= dumm
->create_bridge_enumerator(dumm
);
318 while (enumerator
->enumerate(enumerator
, &bridge
))
320 rb_yield(Data_Wrap_Struct(class, NULL
, NULL
, bridge
));
322 enumerator
->destroy(enumerator
);
326 static VALUE
bridge_new(VALUE
class, VALUE name
)
331 bridge
= dumm
->create_bridge(dumm
, StringValuePtr(name
));
334 rb_raise(rb_eRuntimeError
, "creating bridge failed");
336 return Data_Wrap_Struct(class, NULL
, NULL
, bridge
);
339 static VALUE
bridge_to_s(VALUE self
)
343 Data_Get_Struct(self
, bridge_t
, bridge
);
344 return rb_str_new2(bridge
->get_name(bridge
));
347 static VALUE
bridge_each_iface(int argc
, VALUE
*argv
, VALUE self
)
349 enumerator_t
*enumerator
;
353 if (!rb_block_given_p())
355 rb_raise(rb_eArgError
, "must be called with a block");
357 Data_Get_Struct(self
, bridge_t
, bridge
);
358 enumerator
= bridge
->create_iface_enumerator(bridge
);
359 while (enumerator
->enumerate(enumerator
, &iface
))
361 rb_yield(Data_Wrap_Struct(rbc_iface
, NULL
, NULL
, iface
));
363 enumerator
->destroy(enumerator
);
367 static VALUE
bridge_delete(VALUE self
)
371 Data_Get_Struct(self
, bridge_t
, bridge
);
372 dumm
->delete_bridge(dumm
, bridge
);
376 static void bridge_init()
378 rbc_bridge
= rb_define_class_under(rbm_dumm
, "Bridge", rb_cObject
);
379 rb_define_singleton_method(rbc_bridge
, "[]", bridge_get
, 1);
380 rb_define_singleton_method(rbc_bridge
, "each", bridge_each
, -1);
381 rb_define_singleton_method(rbc_bridge
, "new", bridge_new
, 1);
382 rb_define_method(rbc_bridge
, "to_s", bridge_to_s
, 0);
383 rb_define_method(rbc_bridge
, "each", bridge_each_iface
, -1);
384 rb_define_method(rbc_bridge
, "delete", bridge_delete
, 0);
385 rb_include_module(rb_class_of(rbc_bridge
), rb_mEnumerable
);
386 rb_include_module(rbc_bridge
, rb_mEnumerable
);
392 static VALUE
iface_to_s(VALUE self
)
396 Data_Get_Struct(self
, iface_t
, iface
);
397 return rb_str_new2(iface
->get_hostif(iface
));
400 static VALUE
iface_connect(VALUE self
, VALUE vbridge
)
405 Data_Get_Struct(self
, iface_t
, iface
);
406 Data_Get_Struct(vbridge
, bridge_t
, bridge
);
407 if (!bridge
->connect_iface(bridge
, iface
))
409 rb_raise(rb_eRuntimeError
, "connecting iface failed");
414 static VALUE
iface_disconnect(VALUE self
)
419 Data_Get_Struct(self
, iface_t
, iface
);
420 bridge
= iface
->get_bridge(iface
);
421 if (!bridge
|| !bridge
->disconnect_iface(bridge
, iface
))
423 rb_raise(rb_eRuntimeError
, "disconnecting iface failed");
428 static VALUE
iface_add_addr(VALUE self
, VALUE name
)
433 addr
= host_create_from_string(StringValuePtr(name
), 0);
436 rb_raise(rb_eArgError
, "invalid IP address");
438 Data_Get_Struct(self
, iface_t
, iface
);
439 if (!iface
->add_address(iface
, addr
))
441 rb_raise(rb_eRuntimeError
, "adding address failed");
447 static VALUE
iface_each_addr(int argc
, VALUE
*argv
, VALUE self
)
449 enumerator_t
*enumerator
;
454 if (!rb_block_given_p())
456 rb_raise(rb_eArgError
, "must be called with a block");
458 Data_Get_Struct(self
, iface_t
, iface
);
459 enumerator
= iface
->create_address_enumerator(iface
);
460 while (enumerator
->enumerate(enumerator
, &addr
))
462 snprintf(buf
, sizeof(buf
), "%H", addr
);
463 rb_yield(rb_str_new2(buf
));
465 enumerator
->destroy(enumerator
);
469 static VALUE
iface_del_addr(VALUE self
, VALUE vaddr
)
474 addr
= host_create_from_string(StringValuePtr(vaddr
), 0);
477 rb_raise(rb_eArgError
, "invalid IP address");
479 Data_Get_Struct(self
, iface_t
, iface
);
480 if (!iface
->delete_address(iface
, addr
))
483 rb_raise(rb_eRuntimeError
, "address not found");
489 static VALUE
iface_delete(VALUE self
)
494 Data_Get_Struct(self
, iface_t
, iface
);
495 guest
= iface
->get_guest(iface
);
496 guest
->destroy_iface(guest
, iface
);
500 static void iface_init()
502 rbc_iface
= rb_define_class_under(rbm_dumm
, "Iface", rb_cObject
);
503 rb_define_method(rbc_iface
, "to_s", iface_to_s
, 0);
504 rb_define_method(rbc_iface
, "connect", iface_connect
, 1);
505 rb_define_method(rbc_iface
, "disconnect", iface_disconnect
, 0);
506 rb_define_method(rbc_iface
, "add", iface_add_addr
, 1);
507 rb_define_method(rbc_iface
, "del", iface_del_addr
, 1);
508 rb_define_method(rbc_iface
, "each", iface_each_addr
, -1);
509 rb_define_method(rbc_iface
, "delete", iface_delete
, 0);
510 rb_include_module(rbc_iface
, rb_mEnumerable
);
513 static VALUE
template_load(VALUE
class, VALUE name
)
515 if (!dumm
->load_template(dumm
, StringValuePtr(name
)))
517 rb_raise(rb_eRuntimeError
, "loading template failed");
522 static VALUE
template_unload(VALUE
class)
524 if (!dumm
->load_template(dumm
, NULL
))
526 rb_raise(rb_eRuntimeError
, "unloading template failed");
531 static void template_init()
533 rbc_template
= rb_define_class_under(rbm_dumm
, "Template", rb_cObject
);
534 rb_define_singleton_method(rbc_template
, "load", template_load
, 1);
535 rb_define_singleton_method(rbc_template
, "unload", template_unload
, 0);
539 * extension finalization
543 struct sigaction action
;
547 sigemptyset(&action
.sa_mask
);
548 action
.sa_handler
= SIG_DFL
;
550 sigaction(SIGCHLD
, &action
, NULL
);
556 * extension initialization
560 struct sigaction action
;
562 /* there are too many to report, rubyruby... */
563 setenv("LEAK_DETECTIVE_DISABLE", "1", 1);
567 dumm
= dumm_create(NULL
);
569 rbm_dumm
= rb_define_module("Dumm");
576 sigemptyset(&action
.sa_mask
);
577 action
.sa_sigaction
= sigchld_handler
;
578 action
.sa_flags
= SA_SIGINFO
;
579 sigaction(SIGCHLD
, &action
, NULL
);
581 rb_set_end_proc(Final_dumm
, 0);