--- /dev/null
+#define WITH_C99 /* For ul_gsa.h iterators */
+#include <getopt.h>
+#include <forb.h>
+#include <error.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ul_log.h>
+#include <stdbool.h>
+#include <dlfcn.h>
+#include <forb/forb-internal.h>
+#include <pthread.h>
+
+static struct option long_opts[] = {
+ { "daemon", optional_argument, NULL, 'd' },
+ { "id", required_argument, NULL, 'i' },
+/* { "loglevel", required_argument, NULL, 'l' }, */
+ { "port", required_argument, NULL, 'p' },
+ { 0, 0, 0, 0}
+};
+
+static void
+usage(void)
+{
+ printf("usage: forbrun [ options ] <forb-server>.so ... [-- <options for forb_main()>] \n");
+ printf(" -d, --daemon [pid-file] go to background after initialization of servers\n");
+ printf(" -i, --id <orb id> \n");
+/* printf(" -l, --loglevel <number>|<domain>=<number>,...\n"); */
+ printf(" -p, --port <number> listen on a fixed port number\n");
+}
+
+int print_log_domain(ul_log_domain_t *domain, void *context)
+{
+ printf("%s = %d\n", domain->name, domain->level);
+ return 0;
+}
+
+struct forb_main_data {
+ char *filename;
+ forb_orb orb;
+ int (*forb_main)(forb_orb orb, int argc, char *argv[]);
+ int argc;
+ char **argv;
+};
+
+void *forb_main_thread(void *arg)
+{
+ struct forb_main_data *data = arg;
+ int ret;
+ ret = data->forb_main(data->orb, data->argc, data->argv);
+ if (ret != 0)
+ fprintf(stderr, "forb_main() in %s returned %d\n",
+ data->filename, ret);
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ forb_orb orb;
+ bool opt_daemon = false;
+ char *opt_pidfile = NULL;
+ int i;
+ forb_init_attr_t attr = {
+ .orb_id = "org.frescor.fcb",
+ .peer_discovery_callback = NULL, /* TODO */
+ .peer_dead_callback = NULL, /* TODO */
+ .fixed_tcp_port = 0,
+#ifdef CONFIG_FORB_PROTO_INET_DEFAULT
+ .fixed_server_id = 0, /* TODO */
+ .redistribute_hellos = false , /* TODO */
+#endif
+ };
+ int opt;
+
+ while ((opt = getopt_long(argc, argv, "d::hil:p:", &long_opts[0], NULL)) != EOF) {
+ switch (opt) {
+#if 0
+ case 'l':
+ if (*optarg == '?') {
+ ul_logreg_for_each_domain(print_log_domain, NULL);
+ exit(0);
+ }
+ {
+ int ret;
+ ret = ul_log_domain_arg2levels(optarg);
+ if (ret)
+ error(1, EINVAL, "Error parsing -l argument at char %d\n", ret);
+ }
+ break;
+#endif
+ case 'd':
+ opt_daemon = true;
+ opt_pidfile = optarg;
+ break;
+ case 'i':
+ attr.orb_id = optarg;
+ break;
+ case 'h':
+ /*default:*/
+ usage();
+ exit(opt == 'h' ? 0 : 1);
+ break;
+ case 'p':
+ attr.fixed_tcp_port = atol(optarg);
+ break;
+ }
+ }
+
+ if (opt_daemon)
+ forb_daemon_prepare(opt_pidfile); /* == fork() */
+
+ orb = forb_init(&argc, &argv, &attr);
+ if (!orb) error(1, errno, "FORB initialization failed");
+
+#if CONFIG_FCB_INET && !CONFIG_FORB_PROTO_INET_DEFAULT
+ ret = register_inet_port(orb);
+ if (ret) error(0, errno, "INET port registration failed");
+#endif
+
+ for (i = optind; i < argc; i++) {
+ void *handle;
+ fosa_thread_id_t tid;
+ struct forb_main_data data;
+
+ data.filename = argv[i];
+ handle = dlopen(data.filename, RTLD_LOCAL|RTLD_LAZY);
+ if (!handle)
+ error(1, errno, "dlopen(\"%s\") failed", data.filename);
+ data.forb_main = dlsym(handle, "forb_main");
+ if (!data.forb_main)
+ error(1, errno, "Cannot find forb_main() in %s", data.filename);
+
+ data.orb = orb;
+ data.argc = 0; /* TODO argc and argv after "--" */
+ data.argv = NULL; /* TODO argc and argv after "--" */
+ fosa_thread_create(&tid, NULL, forb_main_thread, &data);
+
+ forb_wait_for_server_ready(orb);
+ }
+
+ if (opt_daemon)
+ forb_daemon_ready();
+
+ /* Allow other threads to continue execution, but exit
+ * ourselves (without exit()ing the whole process. */
+ pthread_exit(NULL);
+
+ return 0;
+}