Index: libroar/basic.c
===================================================================
--- libroar/basic.c	(revision 5369)
+++ libroar/basic.c	(revision 5373)
@@ -64,7 +64,14 @@
  }
 
- // TODO: FIXME: we should move this into the config structure.
  if ( daemonimage == NULL )
+  daemonimage = roar_libroar_get_config()->daemonimage;
+
+ // we keep this step to be compatible with older versions.
+ if ( daemonimage == NULL || *daemonimage == 0 ) {
   daemonimage = getenv("ROAR_DAEMONIMAGE");
+  if ( daemonimage != NULL ) {
+   ROAR_WARN("_start_server(*): Usage of $ROAR_DAEMONIMAGE is obsolete. Use ROAR_OPTIONS=daemonimage:...");
+  }
+ }
 
  if ( daemonimage == NULL || *daemonimage == 0 )
@@ -76,9 +83,8 @@
  }
 
- r = fork();
+ r = roar_fork(NULL);
 
  if ( r == -1 ) { // error!
-  roar_err_from_errno();
-  ROAR_ERR("roar_socket_open_fork(*): Can not fork: %s", strerror(errno));
+  ROAR_ERR("_start_server(*): Can not fork: %s", roar_error2str(roar_error));
   close(socks[0]);
   close(socks[1]);
@@ -106,5 +112,5 @@
 
   // we are still alive?
-  ROAR_ERR("roar_socket_open_fork(*): alive after exec(), that's bad!");
+  ROAR_ERR("_start_server(*): alive after exec(), that's bad!");
   _exit(1);
  } else { // we are the parent
@@ -121,7 +127,26 @@
  return -1;
 #else
- ROAR_ERR("roar_socket_open_fork(*): There is no UNIX Domain Socket support in win32, download a real OS.");
+ ROAR_ERR("_start_server(*): There is no UNIX Domain Socket support in win32, download a real OS.");
  return -1;
 #endif
+}
+
+static int _connect_internal(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout) {
+ struct roar_libroar_config * config = roar_libroar_get_config();
+ struct roar_vio_calls * vio;
+
+ if ( config->connect_internal != NULL ) {
+  vio = config->connect_internal(con, server, type, flags, timeout);
+  if ( vio == NULL )
+   return -1;
+
+  con->viocon = vio;
+  con->flags |= ROAR_CON_FLAGS_VIO;
+
+  return 0;
+ }
+
+ roar_err_set(ROAR_ERROR_BADHOST);
+ return -1;
 }
 
@@ -153,4 +178,6 @@
  } else if ( !strcmp(server, "+fork") || !strncmp(server, "+fork=", 6) ) {
   return _start_server(con, server, type, flags, timeout);
+ } else if ( !strcmp(server, "+internal") || !strncmp(server, "+internal=", 10) ) {
+  return _connect_internal(con, server, type, flags, timeout);
  }
 
@@ -346,5 +373,6 @@
 #ifdef ROAR_HAVE_LIBSLP
  if ( !(config->workaround.workarounds & ROAR_LIBROAR_CONFIG_WAS_NO_SLP) &&
-      !(flags & ROAR_ENUM_FLAG_NONBLOCK)
+      !(flags & ROAR_ENUM_FLAG_NONBLOCK) &&
+      !(flags & ROAR_ENUM_FLAG_LOCALONLY)
     ) {
   if ( (server = roar_slp_find_roard(0)) != NULL ) {
@@ -391,4 +419,6 @@
 
 int roar_connect     (struct roar_connection * con, const char * server, int flags, uint_least32_t timeout) {
+ struct roar_libroar_config * config = roar_libroar_get_config();
+
  if ( con == NULL ) {
   roar_err_set(ROAR_ERROR_FAULT);
@@ -400,7 +430,8 @@
 
  roar_err_set(ROAR_ERROR_UNKNOWN);
- if ( roar_connect_raw(con, server, flags, timeout) == -1 )
-  return -1;
-
+ if ( roar_connect_raw(con, server, flags | config->serverflags, timeout) == -1 )
+  return -1;
+
+ // TODO: this should be moved to be within _connect_server() so it also stores server names of auto located servers.
  if ( server != NULL ) {
   con->server_name = roar_mm_strdup(server);
Index: libroar/cdrom.c
===================================================================
--- libroar/cdrom.c	(revision 5289)
+++ libroar/cdrom.c	(revision 5373)
@@ -64,5 +64,5 @@
  }
 
- if ( (pid = fork()) == -1 ) {
+ if ( (pid = roar_fork(NULL)) == (pid_t)-1 ) {
   return -1;
  }
Index: libroar/config.c
===================================================================
--- libroar/config.c	(revision 5357)
+++ libroar/config.c	(revision 5373)
@@ -50,13 +50,16 @@
 
 #ifdef ROAR_SUPPORT_TRAP
-  config.trap_policy = ROAR_TRAP_IGNORE;
+  config.trap_policy      = ROAR_TRAP_IGNORE;
 #endif
-  config.opmode      = ROAR_LIBROAR_CONFIG_OPMODE_NORMAL;
-  config.server   = NULL;
-  config.authfile = NULL;
+  config.opmode           = ROAR_LIBROAR_CONFIG_OPMODE_NORMAL;
+  config.server           = NULL;
+  config.authfile         = NULL;
+  config.forkapi          = NULL;
+  config.connect_internal = NULL;
+  config.daemonimage      = NULL;
 
   if ( home != NULL ) {
-   snprintf(authfile, 1023, "%s/.roarauth", home);
-   authfile[1023]     = 0;
+   snprintf(authfile, sizeof(authfile)-1, "%s/.roarauth", home);
+   authfile[sizeof(authfile)-1] = 0;
    config.authfile    = authfile;
    config.serversfile = NULL;
@@ -304,4 +307,16 @@
   } else if ( !strcmp(k, "x11-display") ) {
    config->x11.display = v;
+  } else if ( !strcmp(k, "daemonimage") ) {
+   config->daemonimage = v;
+  } else if ( !strcmp(k, "serverflags") ) {
+   if ( !strcmp(v, "nonblock") ) {
+    config->serverflags |= ROAR_ENUM_FLAG_NONBLOCK;
+   } else if ( !strcmp(v, "hardnonblock") ) {
+    config->serverflags |= ROAR_ENUM_FLAG_HARDNONBLOCK;
+   } else if ( !strcmp(v, "localonly") ) {
+    config->serverflags |= ROAR_ENUM_FLAG_LOCALONLY;
+   } else {
+    ROAR_WARN("roar_libroar_config_parse(*): Unknown serverflag: %s", v);
+   }
   } else {
    ROAR_WARN("roar_libroar_config_parse(*): Unknown option: %s", k);
@@ -389,4 +404,14 @@
 }
 
+int    roar_libroar_set_forkapi(struct roar_libroar_forkapi * api) {
+ roar_libroar_get_config_ptr()->forkapi = api;
+ return 0;
+}
+
+int    roar_libroar_set_connect_internal(struct roar_vio_calls * (*func)(struct roar_connection * con, const char * server, int type, int flags, uint_least32_t timeout)) {
+ roar_libroar_get_config_ptr()->connect_internal = func;
+ return 0;
+}
+
 void   roar_libroar_nowarn(void) {
  roar_libroar_get_config_ptr()->nowarncounter++;
Index: libroar/enumdev.c
===================================================================
--- libroar/enumdev.c	(revision 5324)
+++ libroar/enumdev.c	(revision 5373)
@@ -105,45 +105,50 @@
  (void)flags, (void)dir, (void)socktype;
 
- if ( maxlen < 11 )
-  return -1;
-
- new = roar_libroar_get_server();
- _add(new);
-
- new = getenv("ROAR_SERVER");
- _add(new);
+ if ( maxlen < 12 )
+  return -1;
+
+ // We can not yet test if those servers are local or reachable via network so
+ // we skip them for now.
+ // TODO: test those servers.
+ if ( !(flags & ROAR_ENUM_FLAG_LOCALONLY) ) {
+  new = roar_libroar_get_server();
+  _add(new);
+
+  new = getenv("ROAR_SERVER");
+  _add(new);
 
 #ifdef ROAR_HAVE_LIBX11
- if ( (x11con = roar_x11_connect(NULL)) != NULL ) {
-  new = roar_x11_get_prop(x11con, "ROAR_SERVER");
-  _add(new);
-  roar_x11_disconnect(x11con);
- }
-#endif
-
- new = getenv("SSH_CLIENT");
- if ( new == NULL )
-  new = getenv("SSH_CONNECTION");
-
- if ( new != NULL ) {
-  ssh_buf = roar_mm_strdup(new);
-  if ( ssh_buf != NULL ) {
-   tmp = strstr(ssh_buf, " ");
-   if ( tmp == NULL ) {
-    // invalid format.
-    roar_mm_free(ssh_buf);
-   } else {
-    *tmp = 0;
-    servers[ret++] = ssh_buf;
+  if ( (x11con = roar_x11_connect(NULL)) != NULL ) {
+   new = roar_x11_get_prop(x11con, "ROAR_SERVER");
+   _add(new);
+   roar_x11_disconnect(x11con);
+  }
+#endif
+
+  new = getenv("SSH_CLIENT");
+  if ( new == NULL )
+   new = getenv("SSH_CONNECTION");
+
+  if ( new != NULL ) {
+   ssh_buf = roar_mm_strdup(new);
+   if ( ssh_buf != NULL ) {
+    tmp = strstr(ssh_buf, " ");
+    if ( tmp == NULL ) {
+     // invalid format.
+     roar_mm_free(ssh_buf);
+    } else {
+     *tmp = 0;
+     servers[ret++] = ssh_buf;
+    }
    }
   }
- }
 
 #if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
- if ( (i = readlink("/etc/roarserver", buf, sizeof(buf)-1)) != -1 ) {
-   buf[i] = 0;
-   _add(buf);
- }
-#endif
+  if ( (i = readlink("/etc/roarserver", buf, sizeof(buf)-1)) != -1 ) {
+    buf[i] = 0;
+    _add(buf);
+  }
+#endif
+ }
 
  if ( (new = roar_env_get_home(0)) != NULL ) {
@@ -158,4 +163,5 @@
  servers[ret++] = roar_mm_strdup("+abstract");
  servers[ret++] = roar_mm_strdup("/tmp/muroard");
+ servers[ret++] = roar_mm_strdup("/dev/roar");
 
  return ret;
@@ -290,12 +296,13 @@
 
 static struct locmed _libroar_locmod[] = {
- {ROAR_ENUM_FLAG_NONBLOCK|ROAR_ENUM_FLAG_HARDNONBLOCK, _esl_defaults},
- {ROAR_ENUM_FLAG_NONE,                                 _esl_slp},
+ {ROAR_ENUM_FLAG_NONBLOCK|ROAR_ENUM_FLAG_HARDNONBLOCK|ROAR_ENUM_FLAG_LOCALONLY, _esl_defaults},
+ {ROAR_ENUM_FLAG_NONE,                                                          _esl_slp},
 #ifdef ROAR_HAVE_FOPEN
- {ROAR_ENUM_FLAG_NONBLOCK,                             _esl_neighbours}
+ {ROAR_ENUM_FLAG_NONBLOCK,                                                      _esl_neighbours}
 #endif
 };
 
 struct roar_server * roar_enum_servers(int flags, int dir, int socktype) {
+ struct roar_libroar_config * config = roar_libroar_get_config();
  struct roar_server * ret = NULL;
  struct roar_server * c;
@@ -304,6 +311,9 @@
  size_t i, cp, unic;
  ssize_t r;
- int testflags = flags;
+ int testflags;
  int is_uniq;
+
+ flags     |= config->serverflags;
+ testflags  = flags;
 
  if ( flags & ROAR_ENUM_FLAG_HARDNONBLOCK )
Index: libroar/libroar.c
===================================================================
--- libroar/libroar.c	(revision 5270)
+++ libroar/libroar.c	(revision 5373)
@@ -154,4 +154,78 @@
 }
 
+static pid_t _libroar_fork(void ** context, void * userdata) {
+ pid_t ret;
+ (void)context, (void)userdata;
+ ret = fork();
+ if ( ret == -1 )
+  roar_err_from_errno();
+ return ret;
+}
+
+static const struct roar_libroar_forkapi _libroar_forkapi = {
+ .prefork   = NULL,
+ .fork      = _libroar_fork,
+ .failed    = NULL,
+ .parent    = NULL,
+ .child     = NULL,
+ .userdata  = NULL
+};
+
+pid_t roar_fork(const struct roar_libroar_forkapi * api) {
+ void * context = NULL;
+ int err;
+ pid_t ret;
+
+ if ( api == NULL )
+  api = &_libroar_forkapi;
+
+ if ( api->fork == NULL ) {
+  roar_err_set(ROAR_ERROR_INVAL);
+  return -1;
+ }
+
+ if ( api->prefork != NULL ) {
+  if ( api->prefork(&context, api->userdata) != 0 ) {
+   if ( api->failed != NULL )
+    api->failed(&context, api->userdata);
+
+   if ( context != NULL ) {
+    err = roar_error;
+    roar_mm_free(context);
+    roar_error = err;
+   }
+   return (pid_t)-1;
+  }
+ }
+
+ if ( (ret = api->fork(&context, api->userdata)) == (pid_t)-1 ) {
+  if ( api->failed != NULL )
+   api->failed(&context, api->userdata);
+
+  if ( context != NULL ) {
+   err = roar_error;
+   roar_mm_free(context);
+   roar_error = err;
+  }
+  return (pid_t)-1;
+ }
+
+ if ( ret == (pid_t)0 ) {
+  if ( api->child != NULL )
+   api->child(&context, api->userdata);
+ } else {
+  if ( api->parent != NULL )
+   api->parent(&context, api->userdata, ret);
+ }
+
+ if ( context != NULL ) {
+  err = roar_error;
+  roar_mm_free(context);
+  roar_error = err;
+ }
+
+ return ret;
+}
+
 int roar_reset(enum roar_reset what) {
  char c;
Index: libroar/pinentry.c
===================================================================
--- libroar/pinentry.c	(revision 5270)
+++ libroar/pinentry.c	(revision 5373)
@@ -88,5 +88,5 @@
  }
 
- pe->pid = fork();
+ pe->pid = roar_fork(NULL);
 
  switch (pe->pid) {
Index: libroar/socket.c
===================================================================
--- libroar/socket.c	(revision 5369)
+++ libroar/socket.c	(revision 5373)
@@ -1154,5 +1154,5 @@
 #endif
 
- r = fork();
+ r = roar_fork(NULL);
 
  if ( r == -1 ) { // error!
Index: libroar/vio_cmd.c
===================================================================
--- libroar/vio_cmd.c	(revision 5364)
+++ libroar/vio_cmd.c	(revision 5373)
@@ -159,5 +159,5 @@
  }
 
- child->pid = fork();
+ child->pid = roar_fork(NULL);
 
  switch (child->pid) {
