diff src/ushare.c @ 125:e413158cae13

Add ushare project files.
author naoyan@johnstown.minaminoshima.org
date Sun, 03 Oct 2010 11:35:19 +0900
parents
children 5dcaf3785ebe
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ushare.c	Sun Oct 03 11:35:19 2010 +0900
@@ -0,0 +1,911 @@
+/*
+ * ushare.c : GeeXboX uShare UPnP Media Server.
+ * Originally developped for the GeeXboX project.
+ * Parts of the code are originated from GMediaServer from Oskar Liljeblad.
+ * Copyright (C) 2005-2007 Benjamin Zores <ben@geexbox.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+
+#if (defined(BSD) || defined(__FreeBSD__) || defined(__APPLE__))
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/if_dl.h>
+#endif
+
+#if (defined(__APPLE__))
+#include <net/route.h>
+#endif
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <fcntl.h>
+
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#endif
+
+#if (defined(__unix__) || defined(unix)) && !defined(USG)
+#include <sys/param.h>
+#endif
+
+#include <upnp/upnp.h>
+#include <upnp/upnptools.h>
+
+#if (defined(HAVE_SETLOCALE) && defined(CONFIG_NLS))
+# include <locale.h>
+#endif
+
+#include "config.h"
+#include "ushare.h"
+#include "services.h"
+#include "http.h"
+#include "metadata.h"
+#include "util_iconv.h"
+#include "content.h"
+#include "cfgparser.h"
+#include "gettext.h"
+#include "trace.h"
+#include "buffer.h"
+#include "ctrl_telnet.h"
+#include "recpt1.h"
+
+struct ushare_t *ut = NULL;
+
+static struct ushare_t * ushare_new (void)
+    __attribute__ ((malloc));
+
+static struct ushare_t *
+ushare_new (void)
+{
+  struct ushare_t *ut = (struct ushare_t *) malloc (sizeof (struct ushare_t));
+  if (!ut)
+    return NULL;
+
+  ut->name = strdup (DEFAULT_USHARE_NAME);
+  ut->interface = strdup (DEFAULT_USHARE_IFACE);
+  ut->model_name = strdup (DEFAULT_USHARE_NAME);
+  ut->contentlist = NULL;
+  ut->rb = rbinit (rb_compare, NULL);
+  ut->root_entry = NULL;
+  ut->nr_entries = 0;
+  ut->starting_id = STARTING_ENTRY_ID_DEFAULT;
+  ut->init = 0;
+  ut->dev = 0;
+  ut->udn = NULL;
+  ut->ip = NULL;
+  ut->port = 0; /* Randomly attributed by libupnp */
+  ut->telnet_port = CTRL_TELNET_PORT;
+  ut->presentation = NULL;
+  ut->use_presentation = true;
+  ut->use_telnet = true;
+#ifdef HAVE_DLNA
+  ut->dlna_enabled = false;
+  ut->dlna = NULL;
+  ut->dlna_flags = DLNA_ORG_FLAG_STREAMING_TRANSFER_MODE |
+                   DLNA_ORG_FLAG_BACKGROUND_TRANSFERT_MODE |
+                   DLNA_ORG_FLAG_CONNECTION_STALL |
+                   DLNA_ORG_FLAG_DLNA_V15;
+#endif /* HAVE_DLNA */
+  ut->xbox360 = false;
+  ut->verbose = false;
+  ut->daemon = false;
+  ut->override_iconv_err = false;
+  ut->cfg_file = NULL;
+
+  pthread_mutex_init (&ut->termination_mutex, NULL);
+  pthread_cond_init (&ut->termination_cond, NULL);
+
+  return ut;
+}
+
+static void
+ushare_free (struct ushare_t *ut)
+{
+  if (!ut)
+    return;
+
+  if (ut->name)
+    free (ut->name);
+  if (ut->interface)
+    free (ut->interface);
+  if (ut->model_name)
+    free (ut->model_name);
+  if (ut->contentlist)
+    content_free (ut->contentlist);
+  if (ut->rb)
+    rbdestroy (ut->rb);
+  if (ut->root_entry)
+    upnp_entry_free (ut, ut->root_entry);
+  if (ut->udn)
+    free (ut->udn);
+  if (ut->ip)
+    free (ut->ip);
+  if (ut->presentation)
+    buffer_free (ut->presentation);
+#ifdef HAVE_DLNA
+  if (ut->dlna_enabled)
+  {
+    if (ut->dlna)
+      dlna_uninit (ut->dlna);
+    ut->dlna = NULL;
+  }
+#endif /* HAVE_DLNA */
+  if (ut->cfg_file)
+    free (ut->cfg_file);
+
+  pthread_cond_destroy (&ut->termination_cond);
+  pthread_mutex_destroy (&ut->termination_mutex);
+
+  free (ut);
+}
+
+static void
+ushare_signal_exit (void)
+{
+  pthread_mutex_lock (&ut->termination_mutex);
+  pthread_cond_signal (&ut->termination_cond);
+  pthread_mutex_unlock (&ut->termination_mutex);
+}
+
+static void
+handle_action_request (struct Upnp_Action_Request *request)
+{
+  struct service_t *service;
+  struct service_action_t *action;
+  char val[256];
+  uint32_t ip;
+
+  if (!request || !ut)
+    return;
+
+  if (request->ErrCode != UPNP_E_SUCCESS)
+    return;
+
+  if (strcmp (request->DevUDN + 5, ut->udn))
+    return;
+
+  ip = request->CtrlPtIPAddr.s_addr;
+  ip = ntohl (ip);
+  sprintf (val, "%d.%d.%d.%d",
+           (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
+
+  if (ut->verbose)
+  {
+    DOMString str = ixmlPrintDocument (request->ActionRequest);
+    log_verbose ("***************************************************\n");
+    log_verbose ("**             New Action Request                **\n");
+    log_verbose ("***************************************************\n");
+    log_verbose ("ServiceID: %s\n", request->ServiceID);
+    log_verbose ("ActionName: %s\n", request->ActionName);
+    log_verbose ("CtrlPtIP: %s\n", val);
+    log_verbose ("Action Request:\n%s\n", str);
+    ixmlFreeDOMString (str);
+  }
+  
+  if (find_service_action (request, &service, &action))
+    {
+      struct action_event_t event;
+
+      event.request = request;
+      event.status = true;
+      event.service = service;
+
+      if (action->function (&event) && event.status)
+        request->ErrCode = UPNP_E_SUCCESS;
+
+      if (ut->verbose)
+      {
+        DOMString str = ixmlPrintDocument (request->ActionResult);
+        log_verbose ("Action Result:\n%s", str);
+        log_verbose ("***************************************************\n");
+        log_verbose ("\n");
+        ixmlFreeDOMString (str);
+      }
+      
+      return;
+    }
+
+  if (service) /* Invalid Action name */
+    strcpy (request->ErrStr, "Unknown Service Action");
+  else /* Invalid Service name */
+    strcpy (request->ErrStr, "Unknown Service ID");
+
+  request->ActionResult = NULL;
+  request->ErrCode = UPNP_SOAP_E_INVALID_ACTION;
+}
+
+static int
+device_callback_event_handler (Upnp_EventType type, void *event,
+                               void *cookie __attribute__((unused)))
+{
+  switch (type)
+    {
+    case UPNP_CONTROL_ACTION_REQUEST:
+      handle_action_request ((struct Upnp_Action_Request *) event);
+      break;
+    case UPNP_CONTROL_ACTION_COMPLETE:
+    case UPNP_EVENT_SUBSCRIPTION_REQUEST:
+    case UPNP_CONTROL_GET_VAR_REQUEST:
+      break;
+    default:
+      break;
+    }
+
+  return 0;
+}
+
+static int
+finish_upnp (struct ushare_t *ut)
+{
+  if (!ut)
+    return -1;
+
+  log_info (_("Stopping UPnP Service ...\n"));
+  UpnpUnRegisterRootDevice (ut->dev);
+  UpnpFinish ();
+
+  return UPNP_E_SUCCESS;
+}
+
+static int
+init_upnp (struct ushare_t *ut)
+{
+  char *description = NULL;
+  int res;
+  size_t len;
+
+  if (!ut || !ut->name || !ut->udn || !ut->ip)
+    return -1;
+
+#ifdef HAVE_DLNA
+  if (ut->dlna_enabled)
+  {
+    len = 0;
+    description =
+      dlna_dms_description_get (ut->name,
+                                "GeeXboX Team",
+                                "http://ushare.geexbox.org/",
+                                "uShare : DLNA Media Server",
+                                ut->model_name,
+                                "001",
+                                "http://ushare.geexbox.org/",
+                                "USHARE-01",
+                                ut->udn,
+                                "/web/ushare.html",
+                                "/web/cms.xml",
+                                "/web/cms_control",
+                                "/web/cms_event",
+                                "/web/cds.xml",
+                                "/web/cds_control",
+                                "/web/cds_event");
+    if (!description)
+      return -1;
+  }
+  else
+  {
+#endif /* HAVE_DLNA */ 
+  len = strlen (UPNP_DESCRIPTION) + strlen (ut->name)
+    + strlen (ut->model_name) + strlen (ut->udn) + 1;
+  description = (char *) malloc (len * sizeof (char));
+  memset (description, 0, len);
+  sprintf (description, UPNP_DESCRIPTION, ut->name, ut->model_name, ut->udn);
+#ifdef HAVE_DLNA
+  }
+#endif /* HAVE_DLNA */
+
+  log_info (_("Initializing UPnP subsystem ...\n"));
+  res = UpnpInit (ut->ip, ut->port);
+  if (res != UPNP_E_SUCCESS)
+  {
+    log_error (_("Cannot initialize UPnP subsystem\n"));
+    return -1;
+  }
+
+  if (UpnpSetMaxContentLength (UPNP_MAX_CONTENT_LENGTH) != UPNP_E_SUCCESS)
+    log_info (_("Could not set Max content UPnP\n"));
+
+  if (ut->xbox360)
+    log_info (_("Starting in XboX 360 compliant profile ...\n"));
+
+#ifdef HAVE_DLNA
+  if (ut->dlna_enabled)
+  {
+    log_info (_("Starting in DLNA compliant profile ...\n"));
+    ut->dlna = dlna_init ();
+    dlna_set_verbosity (ut->dlna, ut->verbose ? 1 : 0);
+    dlna_set_extension_check (ut->dlna, 1);
+    dlna_register_all_media_profiles (ut->dlna);
+  }
+#endif /* HAVE_DLNA */
+  
+  ut->port = UpnpGetServerPort();
+  log_info (_("UPnP MediaServer listening on %s:%d\n"),
+            UpnpGetServerIpAddress (), ut->port);
+
+  UpnpEnableWebserver (TRUE);
+
+  res = UpnpSetVirtualDirCallbacks (&virtual_dir_callbacks);
+  if (res != UPNP_E_SUCCESS)
+  {
+    log_error (_("Cannot set virtual directory callbacks\n"));
+    free (description);
+    return -1;
+  }
+
+  res = UpnpAddVirtualDir (VIRTUAL_DIR);
+  if (res != UPNP_E_SUCCESS)
+  {
+    log_error (_("Cannot add virtual directory for web server\n"));
+    free (description);
+    return -1;
+  }
+
+  res = UpnpRegisterRootDevice2 (UPNPREG_BUF_DESC, description, 0, 1,
+                                 device_callback_event_handler,
+                                 NULL, &(ut->dev));
+  if (res != UPNP_E_SUCCESS)
+  {
+    log_error (_("Cannot register UPnP device\n"));
+    free (description);
+    return -1;
+  }
+
+  res = UpnpUnRegisterRootDevice (ut->dev);
+  if (res != UPNP_E_SUCCESS)
+  {
+    log_error (_("Cannot unregister UPnP device\n"));
+    free (description);
+    return -1;
+  }
+
+  res = UpnpRegisterRootDevice2 (UPNPREG_BUF_DESC, description, 0, 1,
+                                 device_callback_event_handler,
+                                 NULL, &(ut->dev));
+  if (res != UPNP_E_SUCCESS)
+  {
+    log_error (_("Cannot register UPnP device\n"));
+    free (description);
+    return -1;
+  }
+
+  log_info (_("Sending UPnP advertisement for device ...\n"));
+  UpnpSendAdvertisement (ut->dev, 1800);
+
+  log_info (_("Listening for control point connections ...\n"));
+
+  if (description)
+    free (description);
+
+  return 0;
+}
+
+static bool
+has_iface (char *interface)
+{
+#ifdef HAVE_IFADDRS_H
+  struct ifaddrs *itflist, *itf;
+
+  if (!interface)
+    return false;
+
+  if (getifaddrs (&itflist) < 0)
+  {
+    perror ("getifaddrs");
+    return false;
+  }
+
+  itf = itflist;
+  while (itf)
+  {
+    if ((itf->ifa_flags & IFF_UP)
+        && !strncmp (itf->ifa_name, interface, IFNAMSIZ))
+    {
+      log_error (_("Interface %s is down.\n"), interface);
+      log_error (_("Recheck uShare's configuration and try again !\n"));
+      freeifaddrs (itflist);
+      return true;
+    }
+    itf = itf->ifa_next;
+  }
+
+  freeifaddrs (itf);
+#else  
+  int sock, i, n;
+  struct ifconf ifc;
+  struct ifreq ifr;
+  char buff[8192];
+
+  if (!interface)
+    return false;
+
+  /* determine UDN according to MAC address */
+  sock = socket (AF_INET, SOCK_STREAM, 0);
+  if (sock < 0)
+  {
+    perror ("socket");
+    return false;
+  }
+
+  /* get list of available interfaces */
+  ifc.ifc_len = sizeof (buff);
+  ifc.ifc_buf = buff;
+
+  if (ioctl (sock, SIOCGIFCONF, &ifc) < 0)
+  {
+    perror ("ioctl");
+    close (sock);
+    return false;
+  }
+
+  n = ifc.ifc_len / sizeof (struct ifreq);
+  for (i = n - 1 ; i >= 0 ; i--)
+  {
+    ifr = ifc.ifc_req[i];
+
+    if (strncmp (ifr.ifr_name, interface, IFNAMSIZ))
+      continue;
+
+    if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)
+    {
+      perror ("ioctl");
+      close (sock);
+      return false;
+    }
+
+    if (!(ifr.ifr_flags & IFF_UP))
+    {
+      /* interface is down */
+      log_error (_("Interface %s is down.\n"), interface);
+      log_error (_("Recheck uShare's configuration and try again !\n"));
+      close (sock);
+      return false;
+    }
+
+    /* found right interface */
+    close (sock);
+    return true;
+  }
+  close (sock);
+#endif
+  
+  log_error (_("Can't find interface %s.\n"),interface);
+  log_error (_("Recheck uShare's configuration and try again !\n"));
+
+  return false;
+}
+
+static char *
+create_udn (char *interface)
+{
+  int sock = -1;
+  char *buf;
+  unsigned char *ptr;
+
+#if (defined(BSD) || defined(__FreeBSD__) || defined(__APPLE__))
+  int mib[6];
+  size_t len;
+  struct if_msghdr *ifm;
+  struct sockaddr_dl *sdl;
+#else /* Linux */
+  struct ifreq ifr;
+#endif
+
+  if (!interface)
+    return NULL;
+
+#if (defined(BSD) || defined(__FreeBSD__) || defined(__APPLE__))
+  mib[0] = CTL_NET;
+  mib[1] = AF_ROUTE;
+  mib[2] = 0;
+  mib[3] = AF_LINK;
+  mib[4] = NET_RT_IFLIST;
+
+  mib[5] = if_nametoindex (interface);
+  if (mib[5] == 0)
+  {
+    perror ("if_nametoindex");
+    return NULL;
+  }
+
+  if (sysctl (mib, 6, NULL, &len, NULL, 0) < 0)
+  {
+    perror ("sysctl");
+    return NULL;
+  }
+
+  buf = malloc (len);
+  if (sysctl (mib, 6, buf, &len, NULL, 0) < 0)
+  {
+    perror ("sysctl");
+    return NULL;
+  }
+
+  ifm = (struct if_msghdr *) buf;
+  sdl = (struct sockaddr_dl*) (ifm + 1);
+  ptr = (unsigned char *) LLADDR (sdl);
+#else /* Linux */
+  /* determine UDN according to MAC address */
+  sock = socket (AF_INET, SOCK_STREAM, 0);
+  if (sock < 0)
+  {
+    perror ("socket");
+    return NULL;
+  }
+
+  strcpy (ifr.ifr_name, interface);
+  strcpy (ifr.ifr_hwaddr.sa_data, "");
+
+  if (ioctl (sock, SIOCGIFHWADDR, &ifr) < 0)
+  {
+    perror ("ioctl");
+    return NULL;
+  }
+
+  buf = (char *) malloc (64 * sizeof (char));
+  memset (buf, 0, 64);
+  ptr = (unsigned char *) ifr.ifr_hwaddr.sa_data;
+#endif /* (defined(BSD) || defined(__FreeBSD__)) */
+
+  snprintf (buf, 64, "%s-%02x%02x%02x%02x%02x%02x", DEFAULT_UUID,
+            (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
+            (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377));
+
+  if (sock)
+    close (sock);
+
+  return buf;
+}
+
+static char *
+get_iface_address (char *interface)
+{
+  int sock;
+  uint32_t ip;
+  struct ifreq ifr;
+  char *val;
+
+  if (!interface)
+    return NULL;
+
+  /* determine UDN according to MAC address */
+  sock = socket (AF_INET, SOCK_STREAM, 0);
+  if (sock < 0)
+  {
+    perror ("socket");
+    return NULL;
+  }
+
+  strcpy (ifr.ifr_name, interface);
+  ifr.ifr_addr.sa_family = AF_INET;
+
+  if (ioctl (sock, SIOCGIFADDR, &ifr) < 0)
+  {
+    perror ("ioctl");
+    close (sock);
+    return NULL;
+  }
+
+  val = (char *) malloc (16 * sizeof (char));
+  ip = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr;
+  ip = ntohl (ip);
+  sprintf (val, "%d.%d.%d.%d",
+           (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
+
+  close (sock);
+
+  return val;
+}
+
+static int
+restart_upnp (struct ushare_t *ut)
+{
+  finish_upnp (ut);
+
+  if (ut->udn)
+    free (ut->udn);
+  ut->udn = create_udn (ut->interface);
+  if (!ut->udn)
+    return -1;
+
+  if (ut->ip)
+    free (ut->ip);
+  ut->ip = get_iface_address (ut->interface);
+  if (!ut->ip)
+    return -1;
+
+  return (init_upnp (ut));
+}
+
+static void
+UPnPBreak (int s __attribute__ ((unused)))
+{
+  ushare_signal_exit ();
+}
+
+static void
+reload_config (int s __attribute__ ((unused)))
+{
+  struct ushare_t *ut2;
+  bool reload = false;
+
+  log_info (_("Reloading configuration...\n"));
+
+  ut2 = ushare_new ();
+  if (!ut || !ut2)
+    return;
+
+  if (parse_config_file (ut2) < 0)
+    return;
+
+  if (ut->name && strcmp (ut->name, ut2->name))
+  {
+    free (ut->name);
+    ut->name = ut2->name;
+    ut2->name = NULL;
+    reload = true;
+  }
+
+  if (ut->interface && strcmp (ut->interface, ut2->interface))
+  {
+    if (!has_iface (ut2->interface))
+    {
+      ushare_free (ut2);
+      raise (SIGINT);
+    }
+    else
+    {
+      free (ut->interface);
+      ut->interface = ut2->interface;
+      ut2->interface = NULL;
+      reload = true;
+    }
+  }
+
+  if (ut->port != ut2->port)
+  {
+    ut->port = ut2->port;
+    reload = true;
+  }
+
+  if (reload)
+  {
+    if (restart_upnp (ut) < 0)
+    {
+      ushare_free (ut2);
+      raise (SIGINT);
+    }
+  }
+
+  if (ut->contentlist)
+    content_free (ut->contentlist);
+  ut->contentlist = ut2->contentlist;
+  ut2->contentlist = NULL;
+  ushare_free (ut2);
+
+  if (ut->contentlist)
+  {
+    free_metadata_list (ut);
+    build_metadata_list (ut);
+  }
+  else
+  {
+    log_error (_("Error: no content directory to be shared.\n"));
+    raise (SIGINT);
+  }
+}
+
+inline void
+display_headers (void)
+{
+  printf (_("%s (version %s), a lightweight UPnP A/V and DLNA Media Server.\n"),
+          PACKAGE_NAME, VERSION);
+  printf (_("Benjamin Zores (C) 2005-2007, for GeeXboX Team.\n"));
+  printf (_("See http://ushare.geexbox.org/ for updates.\n"));
+}
+
+inline static void
+setup_i18n(void)
+{
+#ifdef CONFIG_NLS
+#ifdef HAVE_SETLOCALE
+  setlocale (LC_ALL, "");
+#endif
+#if (!defined(BSD) && !defined(__FreeBSD__))
+  bindtextdomain (PACKAGE, LOCALEDIR);
+#endif
+  textdomain (PACKAGE);
+#endif
+}
+
+#define SHUTDOWN_MSG _("Server is shutting down: other clients will be notified soon, Bye bye ...\n")
+
+static void
+ushare_kill (ctrl_telnet_client *client,
+             int argc __attribute__((unused)),
+             char **argv __attribute__((unused)))
+{
+  if (ut->use_telnet)
+  {
+    ctrl_telnet_client_send (client, SHUTDOWN_MSG);
+    client->exiting = true;
+  }
+  ushare_signal_exit ();
+}
+
+//main (int argc, char **argv)
+void *
+dlna_startup (void *p)
+{
+  ut = ushare_new ();
+  log_verbose ("dlna_startup() start\n");
+
+  if (!ut)
+    return NULL;
+
+  setup_i18n ();
+  setup_iconv ();
+
+#if 0
+  /* Parse args before cfg file, as we may override the default file */
+  if (parse_command_line (ut, argc, argv) < 0)
+  {
+    ushare_free (ut);
+    return NULL;
+  }
+#endif
+
+  if (parse_config_file (ut) < 0)
+  {
+    /* fprintf here, because syslog not yet ready */
+    fprintf (stderr, _("Warning: can't parse file \"%s\".\n"),
+             ut->cfg_file ? ut->cfg_file : SYSCONFDIR "/" USHARE_CONFIG_FILE);
+  }
+  ut->verbose = true;
+  ut->port = 0;
+  ut->use_presentation = false;
+  ut->use_telnet = false;
+  ut->dlna_enabled = true;
+  ut->override_iconv_err = false;
+  ut->xbox360 = true;
+  ut->daemon = false;
+  //ut->interface = "192.168.1.34";
+  ut->contentlist = "/tmp";
+
+  if (ut->xbox360)
+  {
+    char *name;
+
+    name = malloc (strlen (XBOX_MODEL_NAME) + strlen (ut->model_name) + 4);
+    sprintf (name, "%s (%s)", XBOX_MODEL_NAME, ut->model_name);
+    free (ut->model_name);
+    ut->model_name = strdup (name);
+    free (name);
+
+    ut->starting_id = STARTING_ENTRY_ID_XBOX360;
+  }
+
+  if (ut->daemon)
+  {
+    /* starting syslog feature as soon as possible */
+    start_log ();
+  }
+
+  if (!ut->contentlist)
+  {
+    log_error (_("Error: no content directory to be shared.\n"));
+    ushare_free (ut);
+    return NULL;
+  }
+
+  if (!has_iface (ut->interface))
+  {
+    ushare_free (ut);
+    return NULL;
+  }
+
+  ut->udn = create_udn (ut->interface);
+  if (!ut->udn)
+  {
+    ushare_free (ut);
+    return NULL;
+  }
+
+  ut->ip = get_iface_address (ut->interface);
+  if (!ut->ip)
+  {
+    ushare_free (ut);
+    return NULL;
+  }
+
+  if (ut->daemon)
+  {
+    int err;
+    err = daemon (0, 0);
+    if (err == -1)
+    {
+      log_error (_("Error: failed to daemonize program : %s\n"),
+                 strerror (err));
+      ushare_free (ut);
+      return NULL;
+    }
+  }
+  else
+  {
+    display_headers ();
+  }
+
+#if 0
+  signal (SIGINT, UPnPBreak);
+  signal (SIGTERM, UPnPBreak);
+  signal (SIGUSR1, UPnPBreak);
+  signal (SIGUSR2, UPnPBreak);
+  signal (SIGPIPE, UPnPBreak);
+  signal (SIGHUP, reload_config);
+#endif
+
+  if (ut->use_telnet)
+  {
+    if (ctrl_telnet_start (ut->telnet_port) < 0)
+    {
+      ushare_free (ut);
+      return NULL;
+    }
+    
+    ctrl_telnet_register ("kill", ushare_kill,
+                          _("Terminates the uShare server"));
+  }
+  log_verbose ("init_upnp() start\n");
+  
+  if (init_upnp (ut) < 0)
+  {
+    finish_upnp (ut);
+    ushare_free (ut);
+    return NULL;
+  }
+
+  build_metadata_list (ut);
+
+  log_verbose ("uShare mutex lock.\n");
+  /* Let main sleep until it's time to die... */
+  pthread_mutex_lock (&ut->termination_mutex);
+  log_verbose ("uShare cond wait.\n");
+  pthread_cond_wait (&ut->termination_cond, &ut->termination_mutex);
+  pthread_mutex_unlock (&ut->termination_mutex);
+  log_verbose ("uShare finish.\n");
+
+  if (ut->use_telnet)
+    ctrl_telnet_stop ();
+  finish_upnp (ut);
+  free_metadata_list (ut);
+  ushare_free (ut);
+  finish_iconv ();
+
+  log_verbose ("dlna_start() finish\n");
+  /* it should never be executed */
+  return NULL;
+}