2 * Copyright (C) 2007 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
18 #include <sys/types.h>
28 * instances of dumm, used to deliver signals
30 static linked_list_t
*instances
= NULL
;
32 typedef struct private_dumm_t private_dumm_t
;
34 struct private_dumm_t
{
35 /** public dumm interface */
39 /** list of managed guests */
40 linked_list_t
*guests
;
41 /** list of managed bridges */
42 linked_list_t
*bridges
;
43 /** do not catch signals if we are destroying */
48 * Implementation of dumm_t.create_guest.
50 static guest_t
* create_guest(private_dumm_t
*this, char *name
, char *kernel
,
51 char *master
, int mem
)
55 guest
= guest_create(this->dir
, name
, kernel
, master
, mem
);
58 this->guests
->insert_last(this->guests
, guest
);
64 * Implementation of dumm_t.create_guest_iterator.
66 static iterator_t
* create_guest_iterator(private_dumm_t
*this)
68 return this->guests
->create_iterator(this->guests
, TRUE
);
72 * Implementation of dumm_t.create_bridge.
74 static bridge_t
* create_bridge(private_dumm_t
*this, char *name
)
78 bridge
= bridge_create(name
);
81 this->bridges
->insert_last(this->bridges
, bridge
);
87 * Implementation of dumm_t.create_bridge_iterator.
89 static iterator_t
* create_bridge_iterator(private_dumm_t
*this)
91 return this->bridges
->create_iterator(this->bridges
, TRUE
);
97 void signal_handler(int sig
, siginfo_t
*info
, void *ucontext
)
101 iterator_t
*iterator
, *guests
;
105 iterator
= instances
->create_iterator(instances
, TRUE
);
106 while (iterator
->iterate(iterator
, (void**)&this))
108 if (this->destroying
)
112 switch (info
->si_code
)
118 guests
= this->guests
->create_iterator(this->guests
, TRUE
);
119 while (guests
->iterate(guests
, (void**)&guest
))
121 if (guest
->get_pid(guest
) == info
->si_pid
)
123 guest
->sigchild(guest
);
127 guests
->destroy(guests
);
134 iterator
->destroy(iterator
);
136 /* SIGHUP is currently just ignored */
140 * add a dumm instance
142 static void add_instance(private_dumm_t
*this)
144 if (instances
== NULL
)
146 struct sigaction action
;
148 instances
= linked_list_create();
150 memset(&action
, 0, sizeof(action
));
151 action
.sa_sigaction
= signal_handler
;
152 action
.sa_flags
= SA_SIGINFO
;
154 if (sigaction(SIGCHLD
, &action
, NULL
) != 0 ||
155 sigaction(SIGHUP
, &action
, NULL
) != 0)
157 DBG1("installing signal handler failed!");
160 instances
->insert_last(instances
, this);
164 * remove a dumm instance
166 static void remove_instance(private_dumm_t
*this)
168 iterator_t
*iterator
;
169 private_dumm_t
*current
;
171 iterator
= instances
->create_iterator(instances
, TRUE
);
172 while (iterator
->iterate(iterator
, (void**)¤t
))
176 iterator
->remove(iterator
);
180 iterator
->destroy(iterator
);
181 if (instances
->get_count(instances
) == 0)
183 instances
->destroy(instances
);
189 * Implementation of dumm_t.destroy
191 static void destroy(private_dumm_t
*this)
193 iterator_t
*iterator
;
196 this->bridges
->destroy_offset(this->bridges
, offsetof(bridge_t
, destroy
));
198 iterator
= this->guests
->create_iterator(this->guests
, TRUE
);
199 while (iterator
->iterate(iterator
, (void**)&guest
))
203 iterator
->destroy(iterator
);
205 this->destroying
= TRUE
;
206 this->guests
->destroy_offset(this->guests
, offsetof(guest_t
, destroy
));
208 remove_instance(this);
213 * load all guests in our working dir
215 static void load_guests(private_dumm_t
*this)
221 dir
= opendir(this->dir
);
227 while ((ent
= readdir(dir
)))
229 if (streq(ent
->d_name
, ".") || streq(ent
->d_name
, ".."))
233 guest
= guest_load(this->dir
, ent
->d_name
);
236 this->guests
->insert_last(this->guests
, guest
);
240 DBG1("loading guest in directory '%s' failed, skipped", ent
->d_name
);
247 * create a dumm instance
249 dumm_t
*dumm_create(char *dir
)
252 private_dumm_t
*this = malloc_thing(private_dumm_t
);
254 this->public.create_guest
= (guest_t
*(*)(dumm_t
*,char*,char*,char*,int))create_guest
;
255 this->public.create_guest_iterator
= (iterator_t
*(*)(dumm_t
*))create_guest_iterator
;
256 this->public.create_bridge
= (bridge_t
*(*)(dumm_t
*, char *name
))create_bridge
;
257 this->public.create_bridge_iterator
= (iterator_t
*(*)(dumm_t
*))create_bridge_iterator
;
258 this->public.destroy
= (void(*)(dumm_t
*))destroy
;
260 this->destroying
= FALSE
;
261 if (*dir
== '/' || getcwd(cwd
, sizeof(cwd
)) == 0)
263 this->dir
= strdup(dir
);
267 asprintf(&this->dir
, "%s/%s", cwd
, dir
);
269 this->guests
= linked_list_create();
270 this->bridges
= linked_list_create();
275 return &this->public;