Example #1
0
static gboolean
on_shutdown (gpointer user_data)
{
	debug_enter ("liferea_shutdown");

	/* prevents signal handler from calling us a second time */
	if (runState == STATE_SHUTDOWN)
		return FALSE;
		
	runState = STATE_SHUTDOWN;

	/* order is important ! */
	itemlist_free ();
	update_deinit ();
	db_deinit ();
	social_free ();

	liferea_shell_destroy ();
#ifdef USE_SM
	/* unplug */
	session_end ();
#endif
	conf_deinit ();
	
	gtk_main_quit ();
	
	debug_exit ("liferea_shutdown");
	return FALSE;
}
Example #2
0
void sig_hup(int s)
{
	unsigned short dodb = 0;

	if (rundaemon) { syslog(LOG_INFO, "Received SIGHUP, reloading."); }
	if (DBhandle)
	{
		db_deinit();
		dodb = 1;
	}
	if (selectedconf && (selectedconf[0] != 0))
	{
		free_config(my_conf);
		my_conf = read_config(selectedconf);
		if (!my_conf)
		{
			if (rundaemon) { syslog(LOG_CRIT, "Could not read config file \"%s\" which was previously loaded.  Failing.", selectedconf); }
			else { fprintf(stdout, "Could not read config file \"%s\" which was previously loaded.  Failing.\n", selectedconf); }
			exit(1);
		}
	}
	if (dodb)
	{
		if (!db_init())
		{
			if (dlvl(1) && DBhandle)
			{
				if (rundaemon) { syslog(LOG_CRIT, "Database connection failed: %s", mysql_error(DBhandle)); }
				else { fprintf(stdout, "Database connection failed: %s\n", mysql_error(DBhandle)); }
				db_deinit();
			}
			else if (dlvl(1))
			{
				if (rundaemon) { syslog(LOG_CRIT, "Database connection failed: UNKNOWN"); }
				else { fprintf(stdout, "Database connection failed: UNKNOWN\n"); }
			}

			free_config(my_conf);
			exit(0);
		}
	}
}
Example #3
0
void core_deinit(Core* core)
{
    // Stop the DB thread and wait
    thread_send_stop_signal(B(core), T(&core->dbThread));
    thread_wait_until_stopped(T(&core->dbThread));
    
    // The DB thread tries to finish up any last pending queries before stopping,
    // so don't deinit the DB and DB thread until it finishes
    db_deinit(&core->database);
    db_thread_deinit(&core->dbThread);
    
    // Deinit the Basic object last
    basic_deinit(B(core));
}
Example #4
0
static void
migrate_from_14plus (const gchar *oldBaseDir, nodePtr node)
{
	GFile *sourceDbFile, *targetDbFile;
	gchar *newConfigDir, *newCacheDir, *newDataDir, *oldCacheDir, *filename;

	g_print("Performing %s -> XDG cache migration...\n", oldBaseDir);	
	
	/* 1.) Close already loaded DB */
	db_deinit ();

	/* 2.) Copy all files */
	newCacheDir	= g_build_filename (g_get_user_cache_dir(), "liferea", NULL);
	newConfigDir	= g_build_filename (g_get_user_config_dir(), "liferea", NULL);
	newDataDir	= g_build_filename (g_get_user_data_dir(), "liferea", NULL);
	oldCacheDir	= g_build_filename (oldBaseDir, "cache", NULL);

	migrate_copy_dir (oldBaseDir, newConfigDir, "");
	migrate_copy_dir (oldCacheDir, newCacheDir, G_DIR_SEPARATOR_S "favicons");
	migrate_copy_dir (oldCacheDir, newCacheDir, G_DIR_SEPARATOR_S "plugins");	

	/* 3.) Move DB to from new config dir to cache dir instead (this is
	       caused by the batch copy in step 2.) */
	sourceDbFile = g_file_new_for_path (g_build_filename (newConfigDir, "liferea.db", NULL));
	targetDbFile = g_file_new_for_path (g_build_filename (newDataDir, "liferea.db", NULL));
	g_file_move (sourceDbFile, targetDbFile, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL);
	g_object_unref (sourceDbFile);
	g_object_unref (targetDbFile);
	
	/* 3.) And reopen the copied DB */
	db_init ();

	/* 4.) Migrate file feed list into DB */
	filename = common_create_config_filename ("feedlist.opml");

	if (!import_OPML_feedlist (filename, node, FALSE, TRUE))
		g_error ("Fatal: Feed list migration failed!");

	g_free (filename);
	g_free (newConfigDir);
	g_free (newCacheDir);
	g_free (oldCacheDir);
}
Example #5
0
File: main.c Project: tiwoc/liferea
static gboolean
on_shutdown (gpointer user_data)
{
	debug_enter ("liferea_shutdown");

	/* prevents signal handler from calling us a second time */
	if (runState == STATE_SHUTDOWN)
		return FALSE;
		
	runState = STATE_SHUTDOWN;

	/* order is important ! */
	update_deinit ();

	liferea_shell_destroy ();

	db_deinit ();
	social_free ();
	conf_deinit ();
	
	debug_exit ("liferea_shutdown");
	return FALSE;
}
Example #6
0
int
main(int argc, char **argv)
{
  int option;
  char *configfile;
  int background;
  int mdns_no_rsp;
  int mdns_no_daap;
  int loglevel;
  char *logdomains;
  char *logfile;
  char *ffid;
  char *pidfile;
  const char *gcry_version;
  sigset_t sigs;
  int sigfd;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  struct kevent ke_sigs[4];
#endif
  int ret;

  struct option option_map[] =
    {
      { "ffid",         1, NULL, 'b' },
      { "debug",        1, NULL, 'd' },
      { "logdomains",   1, NULL, 'D' },
      { "foreground",   0, NULL, 'f' },
      { "config",       1, NULL, 'c' },
      { "pidfile",      1, NULL, 'P' },
      { "version",      0, NULL, 'v' },

      { "mdns-no-rsp",  0, NULL, 512 },
      { "mdns-no-daap", 0, NULL, 513 },

      { NULL,           0, NULL, 0 }
    };

  configfile = CONFFILE;
  pidfile = PIDFILE;
  loglevel = -1;
  logdomains = NULL;
  logfile = NULL;
  background = 1;
  ffid = NULL;
  mdns_no_rsp = 0;
  mdns_no_daap = 0;

  while ((option = getopt_long(argc, argv, "D:d:c:P:fb:v", option_map, NULL)) != -1)
    {
      switch (option)
	{
	  case 512:
	    mdns_no_rsp = 1;
	    break;

	  case 513:
	    mdns_no_daap = 1;
	    break;

	  case 'b':
            ffid = optarg;
            break;

	  case 'd':
	    ret = safe_atoi32(optarg, &option);
	    if (ret < 0)
	      fprintf(stderr, "Error: loglevel must be an integer in '-d %s'\n", optarg);
	    else
	      loglevel = option;
            break;

	  case 'D':
	    logdomains = optarg;
            break;

          case 'f':
            background = 0;
            break;

          case 'c':
            configfile = optarg;
            break;

          case 'P':
	    pidfile = optarg;
            break;

          case 'v':
	    version();
            return EXIT_SUCCESS;
            break;

          default:
            usage(argv[0]);
            return EXIT_FAILURE;
            break;
        }
    }

  ret = logger_init(NULL, NULL, (loglevel < 0) ? E_LOG : loglevel);
  if (ret != 0)
    {
      fprintf(stderr, "Could not initialize log facility\n");

      return EXIT_FAILURE;
    }

  ret = conffile_load(configfile);
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Config file errors; please fix your config\n");

      logger_deinit();
      return EXIT_FAILURE;
    }

  logger_deinit();

  /* Reinit log facility with configfile values */
  if (loglevel < 0)
    loglevel = cfg_getint(cfg_getsec(cfg, "general"), "loglevel");

  logfile = cfg_getstr(cfg_getsec(cfg, "general"), "logfile");

  ret = logger_init(logfile, logdomains, loglevel);
  if (ret != 0)
    {
      fprintf(stderr, "Could not reinitialize log facility with config file settings\n");

      conffile_unload();
      return EXIT_FAILURE;
    }

  /* Set up libevent logging callback */
  event_set_log_callback(logger_libevent);

  DPRINTF(E_LOG, L_MAIN, "Forked Media Server Version %s taking off\n", VERSION);

  ret = av_lockmgr_register(ffmpeg_lockmgr);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not register ffmpeg lock manager callback\n");

      ret = EXIT_FAILURE;
      goto ffmpeg_init_fail;
    }

  av_register_all();
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13)
  avformat_network_init();
#endif
  av_log_set_callback(logger_ffmpeg);

#ifdef LASTFM
  /* Initialize libcurl */
  curl_global_init(CURL_GLOBAL_DEFAULT);
#endif

  /* Initialize libgcrypt */
  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);

  gcry_version = gcry_check_version(GCRYPT_VERSION);
  if (!gcry_version)
    {
      DPRINTF(E_FATAL, L_MAIN, "libgcrypt version mismatch\n");

      ret = EXIT_FAILURE;
      goto gcrypt_init_fail;
    }

  /* We aren't handling anything sensitive, so give up on secure
   * memory, which is a scarce system resource.
   */
  gcry_control(GCRYCTL_DISABLE_SECMEM, 0);

  gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

  DPRINTF(E_DBG, L_MAIN, "Initialized with gcrypt %s\n", gcry_version);

  /* Block signals for all threads except the main one */
  sigemptyset(&sigs);
  sigaddset(&sigs, SIGINT);
  sigaddset(&sigs, SIGHUP);
  sigaddset(&sigs, SIGCHLD);
  sigaddset(&sigs, SIGTERM);
  sigaddset(&sigs, SIGPIPE);
  ret = pthread_sigmask(SIG_BLOCK, &sigs, NULL);
  if (ret != 0)
    {
      DPRINTF(E_LOG, L_MAIN, "Error setting signal set\n");

      ret = EXIT_FAILURE;
      goto signal_block_fail;
    }

  /* Daemonize and drop privileges */
  ret = daemonize(background, pidfile);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_MAIN, "Could not initialize server\n");

      ret = EXIT_FAILURE;
      goto daemon_fail;
    }

  /* Initialize libevent (after forking) */
  evbase_main = event_init();

  DPRINTF(E_LOG, L_MAIN, "mDNS init\n");
  ret = mdns_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "mDNS init failed\n");

      ret = EXIT_FAILURE;
      goto mdns_fail;
    }

  /* Initialize the database before starting */
  DPRINTF(E_INFO, L_MAIN, "Initializing database\n");
  ret = db_init();
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Database init failed\n");

      ret = EXIT_FAILURE;
      goto db_fail;
    }

  /* Open a DB connection for the main thread */
  ret = db_perthread_init();
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not perform perthread DB init for main\n");

      ret = EXIT_FAILURE;
      goto db_fail;
    }

  /* Spawn worker thread */
  ret = worker_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Worker thread failed to start\n");

      ret = EXIT_FAILURE;
      goto worker_fail;
    }

  /* Spawn cache thread */
  ret = cache_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Cache thread failed to start\n");

      ret = EXIT_FAILURE;
      goto cache_fail;
    }

  /* Spawn file scanner thread */
  ret = filescanner_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "File scanner thread failed to start\n");

      ret = EXIT_FAILURE;
      goto filescanner_fail;
    }

#ifdef HAVE_SPOTIFY_H
  /* Spawn Spotify thread */
  ret = spotify_init();
  if (ret < 0)
    {
      DPRINTF(E_INFO, L_MAIN, "Spotify thread not started\n");;
    }
#endif

  /* Spawn player thread */
  ret = player_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Player thread failed to start\n");

      ret = EXIT_FAILURE;
      goto player_fail;
    }

  /* Spawn HTTPd thread */
  ret = httpd_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "HTTPd thread failed to start\n");

      ret = EXIT_FAILURE;
      goto httpd_fail;
    }

#ifdef MPD
  /* Spawn MPD thread */
  ret = mpd_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "MPD thread failed to start\n");

      ret = EXIT_FAILURE;
      goto mpd_fail;
    }
#endif

  /* Start Remote pairing service */
  ret = remote_pairing_init();
  if (ret != 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Remote pairing service failed to start\n");

      ret = EXIT_FAILURE;
      goto remote_fail;
    }

  /* Register mDNS services */
  ret = register_services(ffid, mdns_no_rsp, mdns_no_daap);
  if (ret < 0)
    {
      ret = EXIT_FAILURE;
      goto mdns_reg_fail;
    }

#if defined(__linux__)
  /* Set up signal fd */
  sigfd = signalfd(-1, &sigs, SFD_NONBLOCK | SFD_CLOEXEC);
  if (sigfd < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not setup signalfd: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  event_set(&sig_event, sigfd, EV_READ, signal_signalfd_cb, NULL);

#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
  sigfd = kqueue();
  if (sigfd < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not setup kqueue: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  EV_SET(&ke_sigs[0], SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[1], SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[2], SIGHUP, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
  EV_SET(&ke_sigs[3], SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);

  ret = kevent(sigfd, ke_sigs, 4, NULL, 0, NULL);
  if (ret < 0)
    {
      DPRINTF(E_FATAL, L_MAIN, "Could not register signal events: %s\n", strerror(errno));

      ret = EXIT_FAILURE;
      goto signalfd_fail;
    }

  event_set(&sig_event, sigfd, EV_READ, signal_kqueue_cb, NULL);
#endif

  event_base_set(evbase_main, &sig_event);
  event_add(&sig_event, NULL);

  /* Run the loop */
  event_base_dispatch(evbase_main);

  DPRINTF(E_LOG, L_MAIN, "Stopping gracefully\n");
  ret = EXIT_SUCCESS;

  /*
   * On a clean shutdown, bring mDNS down first to give a chance
   * to the clients to perform a clean shutdown on their end
   */
  DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n");
  mdns_deinit();

 signalfd_fail:
 mdns_reg_fail:
  DPRINTF(E_LOG, L_MAIN, "Remote pairing deinit\n");
  remote_pairing_deinit();

 remote_fail:
  DPRINTF(E_LOG, L_MAIN, "HTTPd deinit\n");
  httpd_deinit();

 httpd_fail:
  DPRINTF(E_LOG, L_MAIN, "TCPd deinit\n");
#ifdef MPD
  DPRINTF(E_LOG, L_MAIN, "MPD deinit\n");
  mpd_deinit();
 mpd_fail:
#endif

  DPRINTF(E_LOG, L_MAIN, "Player deinit\n");
  player_deinit();

 player_fail:
#ifdef HAVE_SPOTIFY_H
  DPRINTF(E_LOG, L_MAIN, "Spotify deinit\n");
  spotify_deinit();
#endif
  DPRINTF(E_LOG, L_MAIN, "File scanner deinit\n");
  filescanner_deinit();

 filescanner_fail:
  DPRINTF(E_LOG, L_MAIN, "Cache deinit\n");
  cache_deinit();

 cache_fail:
  DPRINTF(E_LOG, L_MAIN, "Worker deinit\n");
  worker_deinit();

 worker_fail:
  DPRINTF(E_LOG, L_MAIN, "Database deinit\n");
  db_perthread_deinit();
  db_deinit();

 db_fail:
  if (ret == EXIT_FAILURE)
    {
      DPRINTF(E_LOG, L_MAIN, "mDNS deinit\n");
      mdns_deinit();
    }

 mdns_fail:
 daemon_fail:
  if (background)
    {
      ret = seteuid(0);
      if (ret < 0)
	DPRINTF(E_LOG, L_MAIN, "seteuid() failed: %s\n", strerror(errno));
      else
	{
	  ret = unlink(pidfile);
	  if (ret < 0)
	    DPRINTF(E_LOG, L_MAIN, "Could not unlink PID file %s: %s\n", pidfile, strerror(errno));
	}
    }

 signal_block_fail:
 gcrypt_init_fail:
#ifdef LASTFM
  curl_global_cleanup();
#endif
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 13)
  avformat_network_deinit();
#endif
  av_lockmgr_register(NULL);

 ffmpeg_init_fail:
  DPRINTF(E_LOG, L_MAIN, "Exiting.\n");
  conffile_unload();
  logger_deinit();

  return ret;
}
Example #7
0
int main(int argc, char **argv)
{
	time_t lastrun;
	char go;

	termsigs = 0;
	verbosity = 1;
	options = 0;
	my_conf = (Config *)NULL;
	DBhandle = (MYSQL *)NULL;
	LocalDB = (MYSQL *)NULL;
	selectedconf = (char *)NULL;

	signal(SIGTSTP, SIG_IGN);
	signal(SIGINT, sig_end);
	signal(SIGTERM, sig_end);
	signal(SIGQUIT, sig_end);
	signal(SIGHUP, sig_hup);

	stats = (struct dbstat *)malloc(sizeof(struct dbstat));
	if (!stats)
	{
		if (dlvl(1)) { fprintf(stdout, "malloc(stats): %s\n", strerror(errno)); }
		return(-1);
	}
	memset(stats, 0, sizeof(struct dbstat));
	stats->created = 0;
	stats->destroyed = 0;

	selectedconf = (char *)malloc(512);
	if (!selectedconf)
	{
		if (dlvl(1)) { fprintf(stdout, "malloc(selectedconf): %s\n", strerror(errno)); }
		return(-1);
	}
	memset(selectedconf, 0, 512);

	while ((go = getopt(argc, argv, "qvlhVc:")) >= 0)
	{
		switch (go)
		{
			case 'V':
			{
				fprintf(stdout, "Crimson Pyramid SQL Agent version %lu\n", VERSION);
				fflush(stdout);
				return(0);
				break;
			}
			case 'v':
			{
				if (verbosity < 5) { verbosity++; }
				break;
			}
			case 'q':
			{
				if (verbosity > 0) { verbosity--; }
				break;
			}
			case 'd':
			{
				options |= OPTION_DAEMON;
				break;
			}
			case 'c':
			{
				if (!optarg)
				{
					fprintf(stdout, "%s -c requires an argument.\n", argv[0]);
					return(-1);
				}
				my_conf = read_config(optarg);
				if (!my_conf)
				{
					fprintf(stdout, "%s -c %s: failed reading config file.\n", argv[0], optarg);
					return(-1);
				}
				else
				{
					if (dlvl(2)) { fprintf(stdout, "Loaded configuration file from: %s\n", optarg); }
					snprintf(selectedconf, 512, "%s", optarg);
				}
				break;
			}
			case 'h':
			default:
			{
				fprintf(stdout, "Crimson Pyramid sqlagent %lu\n", VERSION);
				fprintf(stdout, "\tusage: %s [-v|q] [-h] [-l] [-c <config file path>]\n", argv[0]);
				fflush(stdout);
				return(0);
				break;
			}
		}
	}

#ifdef CONFIG_FILE
	if (!my_conf)
	{
		my_conf = read_config(CONFIG_FILE);
		if (my_conf)
		{
			if (dlvl(2)) { fprintf(stdout, "Loaded configuration file from: %s\n", CONFIG_FILE); }
			snprintf(selectedconf, 512, "%s", CONFIG_FILE);
		}
	}
#endif

	if (!my_conf)
	{
		if (dlvl(1)) { fprintf(stdout, "Could not load configuration file.\n"); }
		return(1);
	}

	if (my_conf->svcdaemon)
	{
		options |= OPTION_DAEMON;
	}

	if (!db_init())
	{
		if (dlvl(1) && DBhandle) { fprintf(stdout, "Database connection failed: %s\n", mysql_error(DBhandle)); }
		else if (dlvl(1)) { fprintf(stdout, "Database connection failed: UNKNOWN\n"); }

		DBhandle = (MYSQL *)NULL;
		free_config(my_conf);
		return(1);
	}

	my_sid = db_getsrvid();
	if (my_sid < 0)
	{
		/* if (dlvl(4)) { fprintf(stdout, "Error getting server ID.\n"); } */
		free_config(my_conf);
		return(0);
	}

	if (rundaemon)
	{
		int fr;

		fr = fork();
		if (fr < 0)
		{
			fprintf(stdout, "Error with fork(): %s\n", strerror(errno));
			exit(1);
		}
		else if (fr > 0)
		{
			exit(0);
		}

		openlog("CP_sqlagent", LOG_NDELAY, LOG_DAEMON);

		run_updates(my_sid);
		lastrun = time(NULL);

		while (!(options & OPTION_TERMINATE))
		{
			if ((lastrun + my_conf->waittime) <= time(NULL))
			{
				if (DBhandle && mysql_stat(DBhandle))
				{
					run_updates(my_sid);
					lastrun = time(NULL);
				}
				else
				{
					if (!db_init())
					{
						if (dlvl(1) && DBhandle) { fprintf(stdout, "Database connection failed: %s\n", mysql_error(DBhandle)); }
						else if (dlvl(1)) { fprintf(stdout, "Database connection failed: UNKNOWN\n"); }
						DBhandle = (MYSQL *)NULL;
						sleep(30);
					}
				}
			}
			usleep(25000);	/* 1/4 of a second at a time */
		}
	}
	else
	{
		run_updates(my_sid);
	}

	if (DBhandle) { db_deinit(); }

	if (dlvl(3))
	{
		if (rundaemon)
		{
			syslog(LOG_INFO, "Created: %u", stats->created);
			syslog(LOG_INFO, "Dropped: %u", stats->destroyed);
		}
		else
		{
			fprintf(stdout, "Created: %u\n", stats->created);
			fprintf(stdout, "Dropped: %u\n", stats->destroyed);
		}
	}

	if (rundaemon) { closelog(); }
	free_config(my_conf);
	if (selectedconf) { free(selectedconf); }
	if (stats) { free(stats); }

	return(0);
}
Example #8
0
/**
 * Kick off the daap server and wait for events.
 *
 * This starts the initial db scan, sets up the signal
 * handling, starts the webserver, then sits back and waits
 * for events, as notified by the signal handler and the
 * web interface.  These events are communicated via flags
 * in the config structure.
 *
 * \param argc count of command line arguments
 * \param argv command line argument pointers
 * \returns 0 on success, -1 otherwise
 *
 * \todo split out a ws_init and ws_start, so that the
 * web space handlers can be registered before the webserver
 * starts.
 *
 */
int main(int argc, char *argv[]) {
    int option;
    char *configfile=CONFFILE;
    WSCONFIG ws_config;
    int reload=0;
    int start_time;
    int end_time;
    int rescan_counter=0;
    int old_song_count, song_count;
    int force_non_root=0;
    int skip_initial=1;
    int kill_server=0;
    int convert_conf=0;
    char *db_type,*db_parms,*web_root,*runas, *tmp;
    char **mp3_dir_array;
    char *servername, *iface;
    char *ffid = NULL;
    int appdir = 0;
    char *perr=NULL;
    char txtrecord[255];
    void *phandle;
    char *plugindir;

    int err;
    char *apppath;

    int debuglevel=0;
    int plugins_loaded = 0;

#ifdef ALPHA_CUSTOMIZE
    char *share_path;
    pthread_t thread1;
#endif

    config.use_mdns=1;
    err_setlevel(2);

    config.foreground=0;
    while((option=getopt(argc,argv,"D:d:c:P:mfrysiuvab:Vk")) != -1) {
        switch(option) {
        case 'a':
            appdir = 1;
            break;

        case 'b':
            ffid=optarg;
            break;

        case 'd':
            debuglevel = atoi(optarg);
            err_setlevel(debuglevel);
            break;

        case 'D':
            if(err_setdebugmask(optarg)) {
                usage(argv[0]);
                exit(EXIT_FAILURE);
            }
            break;

        case 'f':
            config.foreground=1;
            err_setdest(err_getdest() | LOGDEST_STDERR);
            break;

        case 'c':
            configfile=optarg;
            break;

        case 'm':
            config.use_mdns=0;
            break;

#ifndef WIN32
        case 'P':
            os_set_pidfile(optarg);
            break;
#endif
        case 'r':
            reload=1;
            break;

        case 's':
            skip_initial=0;
            break;

        case 'y':
            force_non_root=1;
            break;

#ifdef WIN32
        case 'i':
            os_register();
            exit(EXIT_SUCCESS);
            break;

        case 'u':
            os_unregister();
            exit(EXIT_SUCCESS);
            break;
#endif
        case 'v':
            convert_conf=1;
            break;

        case 'k':
            kill_server=1;
            break;

        case 'V':
            fprintf(stderr,"Firefly Media Server: Version %s\n",VERSION);
            exit(EXIT_SUCCESS);
            break;

        default:
            usage(argv[0]);
            exit(EXIT_FAILURE);
            break;
        }
    }

    if((getuid()) && (!force_non_root) && (!convert_conf)) {
        fprintf(stderr,"You are not root.  This is almost certainly wrong.  "
                "If you are\nsure you want to do this, use the -y "
                "command-line switch\n");
        exit(EXIT_FAILURE);
    }


    if(kill_server) {
        os_signal_server(S_STOP);
        exit(0);
    }

    io_init();
    io_set_errhandler(main_io_errhandler);
    ws_set_errhandler(main_ws_errhandler);

    /* read the configfile, if specified, otherwise
     * try defaults */
    config.stats.start_time=start_time=(int)time(NULL);
    config.stop=0;

    /* set appdir first, that way config resolves relative to appdir */
    if(appdir) {
        apppath = os_apppath(argv[0]);
        DPRINTF(E_INF,L_MAIN,"Changing cwd to %s\n",apppath);
        chdir(apppath);
        free(apppath);
        configfile="mt-daapd.conf";
    }

    if(CONF_E_SUCCESS != conf_read(configfile)) {
        fprintf(stderr,"Error reading config file (%s)\n",configfile);
        exit(EXIT_FAILURE);
    }

    if(debuglevel) /* was specified, should override the config file */
        err_setlevel(debuglevel);

    if(convert_conf) {
        fprintf(stderr,"Converting config file...\n");
        if(CONF_E_SUCCESS != conf_write()) {
            fprintf(stderr,"Error writing config file.\n");
            exit(EXIT_FAILURE);
        }
        exit(EXIT_SUCCESS);
    }

    DPRINTF(E_LOG,L_MAIN,"Firefly Version %s: Starting with debuglevel %d\n",
            VERSION,err_getlevel());


    /* load plugins before we drop privs?  Maybe... let the
     * plugins do stuff they might need to */
    plugin_init();
    if((plugindir=conf_alloc_string("plugins","plugin_dir",NULL)) != NULL) {
        /* instead of specifying plugins, let's walk through the directory
         * and load each of them */
        if(!load_plugin_dir(plugindir)) {
            DPRINTF(E_LOG,L_MAIN,"Warning: Could not load plugins\n");
        } else {
            plugins_loaded = TRUE;
        }
        free(plugindir);
    }

    if(!plugins_loaded) {
        if((!load_plugin_dir("/usr/lib/firefly/plugins")) &&
           (!load_plugin_dir("/usr/lib/mt-daapd/plugins")) &&
           (!load_plugin_dir("/lib/mt-daapd/plugins")) &&
           (!load_plugin_dir("/lib/mt-daapd/plugins")) &&
           (!load_plugin_dir("/usr/local/lib/mt-daapd/plugins")) &&
           (!load_plugin_dir("/usr/local/lib/mt-daapd/plugins")) &&
           (!load_plugin_dir("/opt/share/firefly/plugins")) &&
           (!load_plugin_dir("/opt/share/mt-daapd/plugins")) &&
           (!load_plugin_dir("/opt/lib/firefly/plugins")) &&
           (!load_plugin_dir("/opt/lib/mt-daapd/plugins")) &&
           (!load_plugin_dir("plugins/.libs"))) {
            DPRINTF(E_FATAL,L_MAIN,"plugins/plugin_dir not specified\n");
        }
    }

    phandle=NULL;
    while((phandle=plugin_enum(phandle))) {
        DPRINTF(E_LOG,L_MAIN,"Plugin loaded: %s\n",plugin_get_description(phandle));
    }

    runas = conf_alloc_string("general","runas","nobody");

#ifndef WITHOUT_MDNS
    if(config.use_mdns) {
        DPRINTF(E_LOG,L_MAIN,"Starting rendezvous daemon\n");
        if(rend_init(runas)) {
            DPRINTF(E_FATAL,L_MAIN|L_REND,"Error in rend_init: %s\n",
                    strerror(errno));
        }
    }
#endif

    if(!os_init(config.foreground,runas)) {
        DPRINTF(E_LOG,L_MAIN,"Could not initialize server\n");
        os_deinit();
        exit(EXIT_FAILURE);
    }

    free(runas);

#ifdef UPNP
    upnp_init();
#endif

    /* this will require that the db be readable by the runas user */
    db_type = conf_alloc_string("general","db_type","sqlite");
    db_parms = conf_alloc_string("general","db_parms","/var/cache/mt-daapd");
    err=db_open(&perr,db_type,db_parms);

    if(err) {
        DPRINTF(E_LOG,L_MAIN|L_DB,"Error opening db: %s\n",perr);
#ifndef WITHOUT_MDNS
        if(config.use_mdns) {
            rend_stop();
        }
#endif
        os_deinit();
        exit(EXIT_FAILURE);
    }

    free(db_type);
    free(db_parms);

    /* Initialize the database before starting */
    DPRINTF(E_LOG,L_MAIN|L_DB,"Initializing database\n");
    if(db_init(reload)) {
        DPRINTF(E_FATAL,L_MAIN|L_DB,"Error in db_init: %s\n",strerror(errno));
    }

    err=db_get_song_count(&perr,&song_count);
    if(err != DB_E_SUCCESS) {
        DPRINTF(E_FATAL,L_MISC,"Error getting song count: %s\n",perr);
    }
    /* do a full reload if the db is empty */
    if(!song_count)
        reload = 1;

    if(conf_get_array("general","mp3_dir",&mp3_dir_array)) {
        if((!skip_initial) || (reload)) {
            DPRINTF(E_LOG,L_MAIN|L_SCAN,"Starting mp3 scan\n");
	#ifdef ALPHA_CUSTOMIZE
	    share_path = conf_alloc_string("general", "mp3_dir", "AAA");
		printf("mp3_dir_array[0] = [%s]\n", mp3_dir_array[0]);
	    if (strlen(share_path) > 0)
	    {
		Cnt_total_file(mp3_dir_array[0]);
		pthread_create( &thread1, NULL, (void*)process_bar, NULL);
		free(share_path);
	    }
	#endif
            plugin_event_dispatch(PLUGIN_EVENT_FULLSCAN_START,0,NULL,0);
            start_time=(int) time(NULL);
            if(scan_init(mp3_dir_array)) {
                DPRINTF(E_LOG,L_MAIN|L_SCAN,"Error scanning MP3 files: %s\n",strerror(errno));
            }
            if(!config.stop) { /* don't send popup when shutting down */
                plugin_event_dispatch(PLUGIN_EVENT_FULLSCAN_END,0,NULL,0);
                err=db_get_song_count(&perr,&song_count);
                end_time=(int) time(NULL);
                DPRINTF(E_LOG,L_MAIN|L_SCAN,"Scanned %d songs in %d seconds\n",
                        song_count,end_time - start_time);
            }
        }
        conf_dispose_array(mp3_dir_array);
    }
    
#ifdef ALPHA_CUSTOMIZE
    thread_exit = 1;
#endif

    /* start up the web server */
    web_root = conf_alloc_string("general","web_root",NULL);
    ws_config.web_root=web_root;
    ws_config.port=conf_get_int("general","port",0);

    DPRINTF(E_LOG,L_MAIN|L_WS,"Starting web server from %s on port %d\n",
            ws_config.web_root, ws_config.port);

    config.server=ws_init(&ws_config);
    if(!config.server) {
        /* pthreads or malloc error */
        DPRINTF(E_FATAL,L_MAIN|L_WS,"Error initializing web server\n");
    }

    if(E_WS_SUCCESS != ws_start(config.server)) {
        /* listen or pthread error */
        DPRINTF(E_FATAL,L_MAIN|L_WS,"Error starting web server\n");
    }

    ws_registerhandler(config.server, "/",main_handler,main_auth,
                       0,1);

#ifndef WITHOUT_MDNS
    if(config.use_mdns) { /* register services */
        servername = conf_get_servername();

        memset(txtrecord,0,sizeof(txtrecord));
        txt_add(txtrecord,"txtvers=1");
        txt_add(txtrecord,"Database ID=%0X",util_djb_hash_str(servername));
        txt_add(txtrecord,"Machine ID=%0X",util_djb_hash_str(servername));
        txt_add(txtrecord,"Machine Name=%s",servername);
        txt_add(txtrecord,"mtd-version=" VERSION);
        txt_add(txtrecord,"iTSh Version=131073"); /* iTunes 6.0.4 */
        txt_add(txtrecord,"Version=196610");      /* iTunes 6.0.4 */
        tmp = conf_alloc_string("general","password",NULL);
        if(tmp && (strlen(tmp)==0)) tmp=NULL;

        txt_add(txtrecord,"Password=%s",tmp ? "true" : "false");
        if(tmp) free(tmp);

        srand((unsigned int)time(NULL));

        if(ffid) {
            txt_add(txtrecord,"ffid=%s",ffid);
        } else {
            txt_add(txtrecord,"ffid=%08x",rand());
        }

        DPRINTF(E_LOG,L_MAIN|L_REND,"Registering rendezvous names\n");
        iface = conf_alloc_string("general","interface","");

        rend_register(servername,"_http._tcp",ws_config.port,iface,txtrecord);

        plugin_rend_register(servername,ws_config.port,iface,txtrecord);

        free(servername);
        free(iface);
    }
#endif

    end_time=(int) time(NULL);

    err=db_get_song_count(&perr,&song_count);
    if(err != DB_E_SUCCESS) {
        DPRINTF(E_FATAL,L_MISC,"Error getting song count: %s\n",perr);
    }

    DPRINTF(E_LOG,L_MAIN,"Serving %d songs.  Startup complete in %d seconds\n",
            song_count,end_time-start_time);

    if(conf_get_int("general","rescan_interval",0) && (!reload) &&
       (!conf_get_int("scanning","skip_first",0)))
        config.reload = 1; /* force a reload on start */

    while(!config.stop) {
        if((conf_get_int("general","rescan_interval",0) &&
            (rescan_counter > conf_get_int("general","rescan_interval",0)))) {
            if((conf_get_int("general","always_scan",0)) ||
                (config_get_session_count())) {
                config.reload=1;
            } else {
                DPRINTF(E_DBG,L_MAIN|L_SCAN|L_DB,"Skipped bground scan... no users\n");
            }
            rescan_counter=0;
        }

        if(config.reload) {
            old_song_count = song_count;
            start_time=(int) time(NULL);

            DPRINTF(E_LOG,L_MAIN|L_DB|L_SCAN,"Rescanning database\n");

            if(conf_get_array("general","mp3_dir",&mp3_dir_array)) {
                if(config.full_reload) {
                    config.full_reload=0;
                    db_force_rescan(NULL);
                }

                if(scan_init(mp3_dir_array)) {
                    DPRINTF(E_LOG,L_MAIN|L_DB|L_SCAN,"Error rescanning... bad path?\n");
                }

                conf_dispose_array(mp3_dir_array);
            }
            config.reload=0;
            db_get_song_count(NULL,&song_count);
            DPRINTF(E_LOG,L_MAIN|L_DB|L_SCAN,"Scanned %d songs (was %d) in "
                    "%d seconds\n",song_count,old_song_count,
                    time(NULL)-start_time);
        }

        os_wait(MAIN_SLEEP_INTERVAL);
        rescan_counter += MAIN_SLEEP_INTERVAL;
    }

    DPRINTF(E_LOG,L_MAIN,"Stopping gracefully\n");

#ifndef WITHOUT_MDNS
    if(config.use_mdns) {
        DPRINTF(E_LOG,L_MAIN|L_REND,"Stopping rendezvous daemon\n");
        rend_stop();
    }
#endif

#ifdef UPNP
    upnp_deinit();
#endif


    /* Got to find a cleaner way to stop the web server.
     * Closing the fd of the socking accepting doesn't necessarily
     * cause the accept to fail on some libcs.
     *
    DPRINTF(E_LOG,L_MAIN|L_WS,"Stopping web server\n");
    ws_stop(config.server);
    */
    free(web_root);
    conf_close();

    DPRINTF(E_LOG,L_MAIN|L_DB,"Closing database\n");
    db_deinit();

    DPRINTF(E_LOG,L_MAIN,"Done!\n");

    os_deinit();
    io_deinit();
    mem_dump();
    return EXIT_SUCCESS;
}