Index: configure
===================================================================
--- configure	(revision 4696)
+++ configure	(revision 4705)
@@ -1419,4 +1419,6 @@
 test_func_defmake ROAR_HAVE_POPEN     popen     'popen("", "")'              -- stdio.h
 test_func_defmake ROAR_HAVE_PCLOSE    pclose    'pclose(0)'                  -- stdio.h
+test_func_defmake ROAR_HAVE_GETSOCKNAME getsockname 'getsockname(0, 0, 0)'   -- sys/socket.h
+test_func_defmake ROAR_HAVE_GETPEERNAME getpeername 'getpeername(0, 0, 0)'   -- sys/socket.h
 test_func_defmake ROAR_HAVE_RAND      rand      'rand()'                     -- stdlib.h
 test_func_defmake ROAR_HAVE_RAND_R    rand_r    'rand_r((unsigned int*)0)'   -- stdlib.h
Index: include/libroar/vio_ctl.h
===================================================================
--- include/libroar/vio_ctl.h	(revision 4530)
+++ include/libroar/vio_ctl.h	(revision 4705)
@@ -81,4 +81,6 @@
                                                                                         /* struct roar_vio_sysio_ioctl* */
 #define ROAR_VIO_CTL_FSTAT               (ROAR_VIO_CTL_GENERIC|ROAR_VIO_CTL_GET|0x0184) /* fstat() */
+#define ROAR_VIO_CTL_GET_SOCKNAME        (ROAR_VIO_CTL_GENERIC|ROAR_VIO_CTL_GET|0x0188) /* getsockname() */
+#define ROAR_VIO_CTL_GET_PEERNAME        (ROAR_VIO_CTL_GENERIC|ROAR_VIO_CTL_GET|0x018C) /* getpeername() */
 
 // more about network based protocols:
@@ -185,4 +187,12 @@
 };
 
+// for ROAR_VIO_CTL_GET_SOCKNAME and ROAR_VIO_CTL_GET_PEERNAME
+struct roar_sockname {
+ int flags;
+ int type;
+ char * addr;
+ int port;
+};
+
 #endif
 
Index: libroar/vio.c
===================================================================
--- libroar/vio.c	(revision 4692)
+++ libroar/vio.c	(revision 4705)
@@ -369,4 +369,26 @@
  int tmp;
  int s_r = 0, s_w = 0;
+#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
+ union {
+  struct sockaddr     sa;
+#if defined(ROAR_HAVE_IPV4) || defined(ROAR_HAVE_IPV6)
+  struct sockaddr_in  in;
+#endif
+#ifdef ROAR_HAVE_UNIX
+  struct sockaddr_un  un;
+#endif
+#ifdef ROAR_HAVE_LIBDNET
+  struct sockaddr_dn  dn;
+#endif
+#ifdef ROAR_HAVE_IPV6
+  struct sockaddr_in6 in6;
+#endif
+#ifdef ROAR_HAVE_IPX
+  struct sockaddr_ipx ipx;
+#endif
+ } sockaddr;
+ socklen_t socklen;
+ struct roar_sockname * rsockname;
+#endif
 
  if ( vio == NULL || cmd == -1 )
@@ -442,4 +464,91 @@
     return ROAR_SHUTDOWN(roar_vio_get_fh(vio), tmp);
    break;
+#if defined(ROAR_HAVE_GETSOCKNAME) || defined(ROAR_HAVE_GETPEERNAME)
+  case ROAR_VIO_CTL_GET_SOCKNAME:
+  case ROAR_VIO_CTL_GET_PEERNAME:
+    if ( data == NULL )
+     return -1;
+
+    rsockname = data;
+
+    socklen = sizeof(sockaddr);
+
+    if ( cmd == ROAR_VIO_CTL_GET_SOCKNAME ) {
+#ifdef ROAR_HAVE_GETSOCKNAME
+     tmp = getsockname(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
+#else
+     return -1;
+#endif
+    } else if ( cmd == ROAR_VIO_CTL_GET_PEERNAME ) {
+#ifdef ROAR_HAVE_GETPEERNAME
+     tmp = getpeername(roar_vio_get_fh(vio), &(sockaddr.sa), &socklen);
+#else
+     return -1;
+#endif
+    } else {
+     return -1;
+    }
+
+    if ( tmp == -1 )
+     return -1;
+
+    memset(rsockname, 0, sizeof(struct roar_sockname));
+
+    switch (sockaddr.sa.sa_family) {
+#ifdef AF_UNIX
+     case AF_UNIX:
+       rsockname->type = ROAR_SOCKET_TYPE_UNIX;
+       if ( sockaddr.un.sun_path[0] == 0 ) {
+        rsockname->addr = roar_mm_malloc(sizeof(sockaddr.un.sun_path));
+        if ( rsockname->addr == NULL )
+         return -1;
+        memcpy(rsockname->addr, sockaddr.un.sun_path, sizeof(sockaddr.un.sun_path));
+       } else {
+        rsockname->addr = roar_mm_strdup(sockaddr.un.sun_path);
+       }
+      break;
+#endif
+#ifdef AF_DECnet
+     case AF_DECnet:
+       rsockname->type = ROAR_SOCKET_TYPE_DECNET;
+
+       if ( sockaddr.dn.sdn_add.a_len != 2 )
+        return -1;
+
+       rsockname->addr = roar_mm_malloc(28);
+       if ( rsockname->addr == NULL )
+        return -1;
+
+       snprintf(rsockname->addr, 28, "%i.%i::",
+                 sockaddr.dn.sdn_add.a_addr[1] >> 2,
+                 sockaddr.dn.sdn_add.a_addr[0] + ((sockaddr.dn.sdn_add.a_addr[1] & 0x03) << 8));
+
+       rsockname->port = sockaddr.dn.sdn_objnum;
+       if ( sockaddr.dn.sdn_objnum == 0 ) {
+        tmp = strlen(rsockname->addr);
+        memcpy(rsockname->addr + tmp, sockaddr.dn.sdn_objname, sockaddr.dn.sdn_objnamel);
+        rsockname->addr[tmp + sockaddr.dn.sdn_objnamel] = 0;
+       }
+      break;
+#endif
+#ifdef AF_INET
+     case AF_INET:
+       rsockname->type = ROAR_SOCKET_TYPE_INET;
+       rsockname->port = ntohs(sockaddr.in.sin_port);
+       rsockname->addr = roar_mm_strdup(inet_ntoa(sockaddr.in.sin_addr));
+      break;
+#endif
+#ifdef AF_INET6
+     case AF_INET6:
+       rsockname->type = ROAR_SOCKET_TYPE_INET6;
+       rsockname->port = ntohs(sockaddr.in6.sin6_port);
+      break;
+#endif
+     default:
+       return -1;
+    }
+    return 0;
+#endif
+   break;
 #ifdef ROAR_HAVE_H_SYS_IOCTL
   case ROAR_VIO_CTL_SYSIO_IOCTL:
Index: plugins/roard/protocol-gopher.c
===================================================================
--- plugins/roard/protocol-gopher.c	(revision 4704)
+++ plugins/roard/protocol-gopher.c	(revision 4705)
@@ -71,5 +71,5 @@
 }
 
-static int send_menu (int client, struct roar_gopher_menu * menu) {
+static int send_menu (int client, struct roar_gopher_menu * menu, struct roar_vio_calls * vio) {
  struct roar_buffer * buf;
  struct roar_gopher_menu_item * item;
@@ -78,11 +78,19 @@
  void * data;
  char * chardata;
- char * host;
+ const char * host;
  unsigned int port;
+ struct roar_sockname sockaddr;
+
+ if ( roar_vio_ctl(vio, ROAR_VIO_CTL_GET_SOCKNAME, &sockaddr) == -1 ) {
+  memset(&sockaddr, 0, sizeof(sockaddr));
+ }
 
  for (i = 0; i < menu->items_len; i++) {
   item = &(menu->items[i]);
-  if ( roar_buffer_new_data(&buf, len, &data) == -1 )
-   return -1;
+  if ( roar_buffer_new_data(&buf, len, &data) == -1 ) {
+   if ( sockaddr.addr != NULL )
+    roar_mm_free(sockaddr.addr);
+   return -1;
+  } 
 
   chardata = data;
@@ -93,6 +101,6 @@
     break;
    default:
-     host = item->host;
-     port = item->port;
+     host = item->host == NULL ? sockaddr.addr : item->host;
+     port = item->port ==    0 ? sockaddr.port : item->port;
      snprintf(data, len-1, "%c%s\t%s\t%s\t%u\r\n", item->type, item->name, item->selector, host, port);
     break;
@@ -106,8 +114,11 @@
  }
 
- return 0;
-}
-
-static int send_text (int client, const char * text) {
+ if ( sockaddr.addr != NULL )
+  roar_mm_free(sockaddr.addr);
+
+ return 0;
+}
+
+static int send_text (int client, const char * text, struct roar_vio_calls * vio) {
  struct roar_buffer * buf;
  void * data;
@@ -199,8 +210,8 @@
  switch (c->type) {
   case _DIR:
-    funcret = send_menu(client, &(c->menu));
+    funcret = send_menu(client, &(c->menu), vio);
    break;
   case _FILE:
-    funcret = send_text(client, c->text);
+    funcret = send_text(client, c->text, vio);
    break;
   default:
