1/* MiniDLNA project
2 *
3 * http://sourceforge.net/projects/minidlna/
4 *
5 * MiniDLNA media server
6 * Copyright (C) 2008-2012  Justin Maggard
7 *
8 * This file is part of MiniDLNA.
9 *
10 * MiniDLNA is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * MiniDLNA is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * Portions of the code from the MiniUPnP project:
23 *
24 * Copyright (c) 2006-2007, Thomas Bernard
25 * All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions are met:
29 *     * Redistributions of source code must retain the above copyright
30 *       notice, this list of conditions and the following disclaimer.
31 *     * Redistributions in binary form must reproduce the above copyright
32 *       notice, this list of conditions and the following disclaimer in the
33 *       documentation and/or other materials provided with the distribution.
34 *     * The name of the author may not be used to endorse or promote products
35 *       derived from this software without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
41 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 * POSSIBILITY OF SUCH DAMAGE.
48 */
49#include <stdlib.h>
50#include <unistd.h>
51#include <string.h>
52#include <stdio.h>
53#include <ctype.h>
54#include <sys/types.h>
55#include <sys/socket.h>
56#include <sys/wait.h>
57#include <sys/file.h>
58#include <sys/time.h>
59#include <sys/param.h>
60#include <sys/stat.h>
61#include <netinet/in.h>
62#include <arpa/inet.h>
63#include <fcntl.h>
64#include <time.h>
65#include <signal.h>
66#include <errno.h>
67#include <pthread.h>
68#include <limits.h>
69#include <libgen.h>
70#include <pwd.h>
71
72#include <sys/stat.h>
73
74#include "config.h"
75
76#ifdef ENABLE_NLS
77#include <locale.h>
78#include <libintl.h>
79#endif
80
81#include "upnpglobalvars.h"
82#include "sql.h"
83#include "upnphttp.h"
84#include "upnpdescgen.h"
85#include "minidlnapath.h"
86#include "getifaddr.h"
87#include "upnpsoap.h"
88#include "options.h"
89#include "utils.h"
90#include "minissdp.h"
91#include "minidlnatypes.h"
92#include "process.h"
93#include "upnpevents.h"
94#include "scanner.h"
95#include "inotify.h"
96#include "log.h"
97#include "tivo_beacon.h"
98#include "tivo_utils.h"
99
100#if SQLITE_VERSION_NUMBER < 3005001
101# warning "Your SQLite3 library appears to be too old!  Please use 3.5.1 or newer."
102# define sqlite3_threadsafe() 0
103#endif
104
105/* OpenAndConfHTTPSocket() :
106 * setup the socket used to handle incoming HTTP connections. */
107static int
108OpenAndConfHTTPSocket(unsigned short port)
109{
110	int s;
111	int i = 1;
112	struct sockaddr_in listenname;
113
114	/* Initialize client type cache */
115	memset(&clients, 0, sizeof(struct client_cache_s));
116
117	s = socket(PF_INET, SOCK_STREAM, 0);
118	if (s < 0)
119	{
120		DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
121		return -1;
122	}
123
124	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
125		DPRINTF(E_WARN, L_GENERAL, "setsockopt(http, SO_REUSEADDR): %s\n", strerror(errno));
126
127	memset(&listenname, 0, sizeof(struct sockaddr_in));
128	listenname.sin_family = AF_INET;
129	listenname.sin_port = htons(port);
130	listenname.sin_addr.s_addr = htonl(INADDR_ANY);
131
132	if (bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)
133	{
134		DPRINTF(E_ERROR, L_GENERAL, "bind(http): %s\n", strerror(errno));
135		close(s);
136		return -1;
137	}
138
139	if (listen(s, 6) < 0)
140	{
141		DPRINTF(E_ERROR, L_GENERAL, "listen(http): %s\n", strerror(errno));
142		close(s);
143		return -1;
144	}
145
146	return s;
147}
148
149/* Handler for the SIGTERM signal (kill)
150 * SIGINT is also handled */
151static void
152sigterm(int sig)
153{
154	signal(sig, SIG_IGN);	/* Ignore this signal while we are quitting */
155
156	DPRINTF(E_WARN, L_GENERAL, "received signal %d, good-bye\n", sig);
157
158	quitting = 1;
159}
160
161static void
162sigusr1(int sig)
163{
164	signal(sig, sigusr1);
165	DPRINTF(E_WARN, L_GENERAL, "received signal %d, clear cache\n", sig);
166
167	memset(&clients, '\0', sizeof(clients));
168}
169
170static void
171sighup(int sig)
172{
173	signal(sig, sighup);
174	DPRINTF(E_WARN, L_GENERAL, "received signal %d, re-read\n", sig);
175
176	reload_ifaces(1);
177}
178
179/* record the startup time */
180static void
181set_startup_time(void)
182{
183#if 0
184	startup_time = time(NULL);
185#else
186	startup_time = uptime();
187#endif
188}
189
190static void
191getfriendlyname(char *buf, int len)
192{
193	char *p = NULL;
194	char hn[256];
195	int off;
196
197	if (gethostname(hn, sizeof(hn)) == 0)
198	{
199		strncpyt(buf, hn, len);
200		p = strchr(buf, '.');
201		if (p)
202			*p = '\0';
203	}
204	else
205		strcpy(buf, "Unknown");
206
207	off = strlen(buf);
208	off += snprintf(buf+off, len-off, ": ");
209#ifdef READYNAS
210	FILE *info;
211	char ibuf[64], *key, *val;
212	snprintf(buf+off, len-off, "ReadyNAS");
213	info = fopen("/proc/sys/dev/boot/info", "r");
214	if (!info)
215		return;
216	while ((val = fgets(ibuf, 64, info)) != NULL)
217	{
218		key = strsep(&val, ": \t");
219		val = trim(val);
220		if (strcmp(key, "model") == 0)
221		{
222			snprintf(buf+off, len-off, "%s", val);
223			key = strchr(val, ' ');
224			if (key)
225			{
226				strncpyt(modelnumber, key+1, MODELNUMBER_MAX_LEN);
227				*key = '\0';
228			}
229			snprintf(modelname, MODELNAME_MAX_LEN,
230				"Windows Media Connect compatible (%s)", val);
231		}
232		else if (strcmp(key, "serial") == 0)
233		{
234			strncpyt(serialnumber, val, SERIALNUMBER_MAX_LEN);
235			if (serialnumber[0] == '\0')
236			{
237				char mac_str[13];
238				if (getsyshwaddr(mac_str, sizeof(mac_str)) == 0)
239					strcpy(serialnumber, mac_str);
240				else
241					strcpy(serialnumber, "0");
242			}
243			break;
244		}
245	}
246	fclose(info);
247#if PNPX
248	memcpy(pnpx_hwid+4, "01F2", 4);
249	if (strcmp(modelnumber, "NVX") == 0)
250		memcpy(pnpx_hwid+17, "0101", 4);
251	else if (strcmp(modelnumber, "Pro") == 0 ||
252	         strcmp(modelnumber, "Pro 6") == 0 ||
253	         strncmp(modelnumber, "Ultra 6", 7) == 0)
254		memcpy(pnpx_hwid+17, "0102", 4);
255	else if (strcmp(modelnumber, "Pro 2") == 0 ||
256	         strncmp(modelnumber, "Ultra 2", 7) == 0)
257		memcpy(pnpx_hwid+17, "0103", 4);
258	else if (strcmp(modelnumber, "Pro 4") == 0 ||
259	         strncmp(modelnumber, "Ultra 4", 7) == 0)
260		memcpy(pnpx_hwid+17, "0104", 4);
261	else if (strcmp(modelnumber+1, "100") == 0)
262		memcpy(pnpx_hwid+17, "0105", 4);
263	else if (strcmp(modelnumber+1, "200") == 0)
264		memcpy(pnpx_hwid+17, "0106", 4);
265	/* 0107 = Stora */
266	else if (strcmp(modelnumber, "Duo v2") == 0)
267		memcpy(pnpx_hwid+17, "0108", 4);
268	else if (strcmp(modelnumber, "NV+ v2") == 0)
269		memcpy(pnpx_hwid+17, "0109", 4);
270#endif
271#else
272	char * logname;
273	logname = getenv("LOGNAME");
274#ifndef STATIC // Disable for static linking
275	if (!logname)
276	{
277		struct passwd * pwent;
278		pwent = getpwuid(getuid());
279		if (pwent)
280			logname = pwent->pw_name;
281	}
282#endif
283	snprintf(buf+off, len-off, "%s", logname?logname:"Unknown");
284#endif
285}
286
287static int
288open_db(sqlite3 **sq3)
289{
290	char path[PATH_MAX];
291	int new_db = 0;
292
293	snprintf(path, sizeof(path), "%s/files.db", db_path);
294	if (access(path, F_OK) != 0)
295	{
296		new_db = 1;
297		make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
298	}
299	if (sqlite3_open(path, &db) != SQLITE_OK)
300		DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to open sqlite database!  Exiting...\n");
301	if (sq3)
302		*sq3 = db;
303	sqlite3_busy_timeout(db, 5000);
304	sql_exec(db, "pragma page_size = 4096");
305	sql_exec(db, "pragma journal_mode = OFF");
306	sql_exec(db, "pragma synchronous = OFF;");
307	sql_exec(db, "pragma default_cache_size = 8192;");
308
309	return new_db;
310}
311
312static void
313check_db(sqlite3 *db, int new_db, pid_t *scanner_pid)
314{
315	struct media_dir_s *media_path = NULL;
316	char cmd[PATH_MAX*2];
317	char **result;
318	int i, rows = 0;
319	int ret;
320	int retry_times;
321
322	if (!new_db)
323	{
324		/* Check if any new media dirs appeared */
325		media_path = media_dirs;
326		while (media_path)
327		{
328			ret = sql_get_int_field(db, "SELECT TIMESTAMP from DETAILS where PATH = %Q", media_path->path);
329			if (ret != media_path->types)
330			{
331				ret = 1;
332				goto rescan;
333			}
334			media_path = media_path->next;
335		}
336		/* Check if any media dirs disappeared */
337		sql_get_table(db, "SELECT VALUE from SETTINGS where KEY = 'media_dir'", &result, &rows, NULL);
338		for (i=1; i <= rows; i++)
339		{
340			media_path = media_dirs;
341			while (media_path)
342			{
343				if (strcmp(result[i], media_path->path) == 0)
344					break;
345				media_path = media_path->next;
346			}
347			if (!media_path)
348			{
349				ret = 2;
350				sqlite3_free_table(result);
351				goto rescan;
352			}
353		}
354		sqlite3_free_table(result);
355	}
356
357	ret = db_upgrade(db);
358	if (ret != 0)
359	{
360rescan:
361		rescan_db = 0;
362		if (ret < 0)
363			DPRINTF(E_WARN, L_GENERAL, "Creating new database at %s/files.db\n", db_path);
364		else if (ret == 1)
365			DPRINTF(E_WARN, L_GENERAL, "New media_dir detected; rebuilding...\n");
366		else if (ret == 2)
367			DPRINTF(E_WARN, L_GENERAL, "Removed media_dir detected; rebuilding...\n");
368		else
369			DPRINTF(E_WARN, L_GENERAL, "Database version mismatch (%d=>%d); need to recreate...\n",
370				ret, DB_VERSION);
371		sqlite3_close(db);
372
373		retry_times = 0;
374retry:
375		snprintf(cmd, sizeof(cmd), "rm -rf %s/files.db %s/art_cache", db_path_spec, db_path_spec);
376		if (system(cmd) != 0) {
377			if (retry_times++ < 2)
378				goto retry;
379
380			DPRINTF(E_FATAL, L_GENERAL, "Failed to clean old file cache!  Exiting...\n");
381		}
382
383		open_db(&db);
384		if (CreateDatabase() != 0)
385			DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to create sqlite database!  Exiting...\n");
386	}
387	if (ret != 0 || rescan_db == 1)
388	{
389#if USE_FORK
390		scanning = 1;
391		sqlite3_close(db);
392		*scanner_pid = fork();
393		open_db(&db);
394		if (*scanner_pid == 0) /* child (scanner) process */
395		{
396			start_scanner();
397			sqlite3_close(db);
398			log_close();
399			freeoptions();
400			free(children);
401			exit(EXIT_SUCCESS);
402		}
403		else if (*scanner_pid < 0)
404		{
405			start_scanner();
406		}
407#else
408		start_scanner();
409#endif
410	}
411}
412
413static int
414writepidfile(const char *fname, int pid, uid_t uid)
415{
416	FILE *pidfile;
417	struct stat st;
418	char path[PATH_MAX], *dir;
419	int ret = 0;
420
421	if(!fname || *fname == '\0')
422		return -1;
423
424	/* Create parent directory if it doesn't already exist */
425	strncpyt(path, fname, sizeof(path));
426	dir = dirname(path);
427	if (stat(dir, &st) == 0)
428	{
429		if (!S_ISDIR(st.st_mode))
430		{
431			DPRINTF(E_ERROR, L_GENERAL, "Pidfile path is not a directory: %s\n",
432				fname);
433			return -1;
434		}
435	}
436	else
437	{
438		if (make_dir(dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0)
439		{
440			DPRINTF(E_ERROR, L_GENERAL, "Unable to create pidfile directory: %s\n",
441				fname);
442			return -1;
443		}
444		if (uid > 0)
445		{
446			if (chown(dir, uid, -1) != 0)
447				DPRINTF(E_WARN, L_GENERAL, "Unable to change pidfile %s ownership: %s\n",
448					dir, strerror(errno));
449		}
450	}
451
452	pidfile = fopen(fname, "w");
453	if (!pidfile)
454	{
455		DPRINTF(E_ERROR, L_GENERAL, "Unable to open pidfile for writing %s: %s\n",
456			fname, strerror(errno));
457		return -1;
458	}
459
460	if (fprintf(pidfile, "%d\n", pid) <= 0)
461	{
462		DPRINTF(E_ERROR, L_GENERAL,
463			"Unable to write to pidfile %s: %s\n", fname, strerror(errno));
464		ret = -1;
465	}
466	if (uid > 0)
467	{
468		if (fchown(fileno(pidfile), uid, -1) != 0)
469			DPRINTF(E_WARN, L_GENERAL, "Unable to change pidfile %s ownership: %s\n",
470				fname, strerror(errno));
471	}
472
473	fclose(pidfile);
474
475	return ret;
476}
477
478static int strtobool(const char *str)
479{
480	return ((strcasecmp(str, "yes") == 0) ||
481		(strcasecmp(str, "true") == 0) ||
482		(atoi(str) == 1));
483}
484
485static void init_nls(void)
486{
487#ifdef ENABLE_NLS
488	setlocale(LC_MESSAGES, "");
489	setlocale(LC_CTYPE, "en_US.utf8");
490	DPRINTF(E_DEBUG, L_GENERAL, "Using locale dir %s\n", bindtextdomain("minidlna", getenv("TEXTDOMAINDIR")));
491	textdomain("minidlna");
492#endif
493}
494
495// add for getting scanning status
496
497void create_scantag(void)
498{
499	char path[PATH_MAX];
500	FILE *fp;
501
502	snprintf(path, sizeof(path), "%s/scantag", db_path);
503
504	fp=fopen(path, "w");
505
506	if(fp) fclose(fp);
507}
508
509void remove_scantag(void)
510{
511	char path[PATH_MAX];
512
513	snprintf(path, sizeof(path), "%s/scantag", db_path);
514
515	unlink(path);
516}
517
518/* init phase :
519 * 1) read configuration file
520 * 2) read command line arguments
521 * 3) daemonize
522 * 4) check and write pid file
523 * 5) set startup time stamp
524 * 6) compute presentation URL
525 * 7) set signal handlers */
526static int
527init(int argc, char **argv)
528{
529	int i;
530	int pid;
531	int debug_flag = 0;
532	int verbose_flag = 0;
533	int options_flag = 0;
534	struct sigaction sa;
535	const char * presurl = NULL;
536	const char * optionsfile = "/etc/minidlna.conf";
537	char mac_str[13];
538	char *string, *word;
539	char *path;
540	char buf[PATH_MAX];
541	char log_str[75] = "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn";
542	char *log_level = NULL;
543	struct media_dir_s *media_dir;
544	int ifaces = 0;
545	media_types types;
546	uid_t uid = 0;
547	char *ptr, *shift;
548	int retry_times;
549
550	/* first check if "-f" option is used */
551	for (i=2; i<argc; i++)
552	{
553		if (strcmp(argv[i-1], "-f") == 0)
554		{
555			optionsfile = argv[i];
556			options_flag = 1;
557			break;
558		}
559	}
560
561	/* set up uuid based on mac address */
562	if (getsyshwaddr(mac_str, sizeof(mac_str)) < 0)
563	{
564		DPRINTF(E_OFF, L_GENERAL, "No MAC address found.  Falling back to generic UUID.\n");
565		strcpy(mac_str, "554e4b4e4f57");
566	}
567	strcpy(uuidvalue+5, "4d696e69-444c-164e-9d41-");
568	strncat(uuidvalue, mac_str, 12);
569
570	getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
571
572	runtime_vars.port = 8200;
573	runtime_vars.notify_interval = 895;	/* seconds between SSDP announces */
574	runtime_vars.max_connections = 50;
575	runtime_vars.root_container = NULL;
576	runtime_vars.ifaces[0] = NULL;
577
578	/* read options file first since
579	 * command line arguments have final say */
580	if (readoptionsfile(optionsfile) < 0)
581	{
582		/* only error if file exists or using -f */
583		if(access(optionsfile, F_OK) == 0 || options_flag)
584			DPRINTF(E_FATAL, L_GENERAL, "Error reading configuration file %s\n", optionsfile);
585	}
586
587	for (i=0; i<num_options; i++)
588	{
589		switch (ary_options[i].id)
590		{
591		case UPNPIFNAME:
592			for (string = ary_options[i].value; (word = strtok(string, ",")); string = NULL)
593			{
594				if (ifaces >= MAX_LAN_ADDR)
595				{
596					DPRINTF(E_ERROR, L_GENERAL, "Too many interfaces (max: %d), ignoring %s\n",
597						MAX_LAN_ADDR, word);
598					break;
599				}
600				while (isspace(*word))
601					word++;
602				runtime_vars.ifaces[ifaces++] = word;
603			}
604			break;
605		case UPNPPORT:
606			runtime_vars.port = atoi(ary_options[i].value);
607			break;
608		case UPNPPRESENTATIONURL:
609			presurl = ary_options[i].value;
610			break;
611		case UPNPNOTIFY_INTERVAL:
612			runtime_vars.notify_interval = atoi(ary_options[i].value);
613			break;
614		case UPNPSERIAL:
615			strncpyt(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
616			break;
617		case UPNPMODEL_NAME:
618			strncpyt(modelname, ary_options[i].value, MODELNAME_MAX_LEN);
619			break;
620		case UPNPMODEL_NUMBER:
621			strncpyt(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
622			break;
623		case UPNPFRIENDLYNAME:
624			strncpyt(friendly_name, ary_options[i].value, FRIENDLYNAME_MAX_LEN);
625			break;
626		case UPNPMEDIADIR:
627			types = ALL_MEDIA;
628			path = ary_options[i].value;
629			word = strchr(path, ',');
630			if (word && (access(path, F_OK) != 0))
631			{
632				types = 0;
633				while (*path)
634				{
635					if (*path == ',')
636					{
637						path++;
638						break;
639					}
640					else if (*path == 'A' || *path == 'a')
641						types |= TYPE_AUDIO;
642					else if (*path == 'V' || *path == 'v')
643						types |= TYPE_VIDEO;
644					else if (*path == 'P' || *path == 'p')
645						types |= TYPE_IMAGES;
646					else
647						DPRINTF(E_FATAL, L_GENERAL, "Media directory entry not understood [%s]\n",
648							ary_options[i].value);
649					path++;
650				}
651			}
652			path = realpath(path, buf);
653			if (!path || access(path, F_OK) != 0)
654			{
655				DPRINTF(E_ERROR, L_GENERAL, "Media directory \"%s\" not accessible [%s]\n",
656					ary_options[i].value, strerror(errno));
657				break;
658			}
659			media_dir = calloc(1, sizeof(struct media_dir_s));
660			media_dir->path = strdup(path);
661			media_dir->types = types;
662			if (media_dirs)
663			{
664				struct media_dir_s *all_dirs = media_dirs;
665				while( all_dirs->next )
666					all_dirs = all_dirs->next;
667				all_dirs->next = media_dir;
668			}
669			else
670				media_dirs = media_dir;
671			break;
672		case UPNPALBUMART_NAMES:
673			for (string = ary_options[i].value; (word = strtok(string, "/")); string = NULL)
674			{
675				struct album_art_name_s * this_name = calloc(1, sizeof(struct album_art_name_s));
676				int len = strlen(word);
677				if (word[len-1] == '*')
678				{
679					word[len-1] = '\0';
680					this_name->wildcard = 1;
681				}
682				this_name->name = strdup(word);
683				if (album_art_names)
684				{
685					struct album_art_name_s * all_names = album_art_names;
686					while( all_names->next )
687						all_names = all_names->next;
688					all_names->next = this_name;
689				}
690				else
691					album_art_names = this_name;
692			}
693			break;
694		case UPNPDBDIR:
695			path = realpath(ary_options[i].value, buf);
696			if (!path)
697				path = (ary_options[i].value);
698			make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
699			if (access(path, F_OK) != 0)
700				DPRINTF(E_FATAL, L_GENERAL, "Database path not accessible! [%s]\n", path);
701			strncpyt(db_path, path, PATH_MAX);
702			break;
703		case UPNPLOGDIR:
704			path = realpath(ary_options[i].value, buf);
705			if (!path)
706				path = (ary_options[i].value);
707			make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
708			if (access(path, F_OK) != 0)
709				DPRINTF(E_FATAL, L_GENERAL, "Log path not accessible! [%s]\n", path);
710			strncpyt(log_path, path, PATH_MAX);
711			break;
712		case UPNPLOGLEVEL:
713			log_level = ary_options[i].value;
714			break;
715		case UPNPINOTIFY:
716			if (!strtobool(ary_options[i].value))
717				CLEARFLAG(INOTIFY_MASK);
718			break;
719		case ENABLE_TIVO:
720			if (strtobool(ary_options[i].value))
721				SETFLAG(TIVO_MASK);
722			break;
723		case ENABLE_DLNA_STRICT:
724			if (strtobool(ary_options[i].value))
725				SETFLAG(DLNA_STRICT_MASK);
726			break;
727		case ROOT_CONTAINER:
728			switch (ary_options[i].value[0]) {
729			case '.':
730				runtime_vars.root_container = NULL;
731				break;
732			case 'B':
733			case 'b':
734				runtime_vars.root_container = BROWSEDIR_ID;
735				break;
736			case 'M':
737			case 'm':
738				runtime_vars.root_container = MUSIC_ID;
739				break;
740			case 'V':
741			case 'v':
742				runtime_vars.root_container = VIDEO_ID;
743				break;
744			case 'P':
745			case 'p':
746				runtime_vars.root_container = IMAGE_ID;
747				break;
748			default:
749				runtime_vars.root_container = ary_options[i].value;
750				DPRINTF(E_WARN, L_GENERAL, "Using arbitrary root container [%s]\n",
751					ary_options[i].value);
752				break;
753			}
754			break;
755		case UPNPMINISSDPDSOCKET:
756			minissdpdsocketpath = ary_options[i].value;
757			break;
758		case UPNPUUID:
759			strcpy(uuidvalue+5, ary_options[i].value);
760			break;
761		case USER_ACCOUNT:
762			uid = strtoul(ary_options[i].value, &string, 0);
763			if (*string)
764			{
765				/* Symbolic username given, not UID. */
766				struct passwd *entry = getpwnam(ary_options[i].value);
767				if (!entry)
768					DPRINTF(E_FATAL, L_GENERAL, "Bad user '%s'.\n",
769						ary_options[i].value);
770				uid = entry->pw_uid;
771			}
772			break;
773		case FORCE_SORT_CRITERIA:
774			force_sort_criteria = ary_options[i].value;
775			break;
776		case MAX_CONNECTIONS:
777			runtime_vars.max_connections = atoi(ary_options[i].value);
778			break;
779		case MERGE_MEDIA_DIRS:
780			if (strtobool(ary_options[i].value))
781				SETFLAG(MERGE_MEDIA_DIRS_MASK);
782			break;
783		default:
784			DPRINTF(E_ERROR, L_GENERAL, "Unknown option in file %s\n",
785				optionsfile);
786		}
787	}
788	if (log_path[0] == '\0')
789	{
790		if (db_path[0] == '\0')
791			strncpyt(log_path, DEFAULT_LOG_PATH, PATH_MAX);
792		else
793			strncpyt(log_path, db_path, PATH_MAX);
794	}
795	if (db_path[0] == '\0')
796		strncpyt(db_path, DEFAULT_DB_PATH, PATH_MAX);
797
798	/* command line arguments processing */
799	for (i=1; i<argc; i++)
800	{
801		if (argv[i][0] != '-')
802		{
803			DPRINTF(E_FATAL, L_GENERAL, "Unknown option: %s\n", argv[i]);
804		}
805		else if (strcmp(argv[i], "--help") == 0)
806		{
807			runtime_vars.port = -1;
808			break;
809		}
810		else switch(argv[i][1])
811		{
812		case 't':
813			if (i+1 < argc)
814				runtime_vars.notify_interval = atoi(argv[++i]);
815			else
816				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
817			break;
818		case 's':
819			if (i+1 < argc)
820				strncpyt(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
821			else
822				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
823			break;
824		case 'm':
825			if (i+1 < argc)
826				strncpyt(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
827			else
828				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
829			break;
830		case 'p':
831			if (i+1 < argc)
832				runtime_vars.port = atoi(argv[++i]);
833			else
834				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
835			break;
836		case 'P':
837			if (i+1 < argc)
838			{
839				if (argv[++i][0] != '/')
840					DPRINTF(E_FATAL, L_GENERAL, "Option -%c requires an absolute filename.\n", argv[i-1][1]);
841				else
842					pidfilename = argv[i];
843			}
844			else
845				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
846			break;
847		case 'd':
848			debug_flag = 1;
849		case 'v':
850			verbose_flag = 1;
851			break;
852		case 'L':
853			SETFLAG(NO_PLAYLIST_MASK);
854			break;
855		case 'w':
856			if (i+1 < argc)
857				presurl = argv[++i];
858			else
859				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
860			break;
861		case 'i':
862			if (i+1 < argc)
863			{
864				i++;
865				if (ifaces >= MAX_LAN_ADDR)
866				{
867					DPRINTF(E_ERROR, L_GENERAL, "Too many interfaces (max: %d), ignoring %s\n",
868						MAX_LAN_ADDR, argv[i]);
869					break;
870				}
871				runtime_vars.ifaces[ifaces++] = argv[i];
872			}
873			else
874				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
875			break;
876		case 'f':
877			i++;	/* discarding, the config file is already read */
878			break;
879		case 'h':
880			runtime_vars.port = -1; // triggers help display
881			break;
882		case 'r':
883			rescan_db = 1;
884			break;
885		case 'R':
886			memset(db_path_spec, 0, 256);
887			for(ptr = db_path, shift = db_path_spec; *ptr; ++ptr, ++shift){
888				if(strchr("()", *ptr))
889					*shift++ = '\\';
890				*shift = *ptr;
891			}
892
893			snprintf(buf, sizeof(buf), "rm -rf %s/files.db %s/art_cache", db_path_spec, db_path_spec);
894			retry_times = 0;
895retry:
896			if (system(buf) != 0) {
897				if (retry_times++ < 2)
898					goto retry;
899
900				DPRINTF(E_FATAL, L_GENERAL, "Failed to clean old file cache. EXITING\n");
901			}
902			break;
903		case 'u':
904			if (i+1 != argc)
905			{
906				i++;
907				uid = strtoul(argv[i], &string, 0);
908				if (*string)
909				{
910					/* Symbolic username given, not UID. */
911					struct passwd *entry = getpwnam(argv[i]);
912					if (!entry)
913						DPRINTF(E_FATAL, L_GENERAL, "Bad user '%s'.\n", argv[i]);
914					uid = entry->pw_uid;
915				}
916			}
917			else
918				DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
919			break;
920			break;
921#ifdef __linux__
922		case 'S':
923			SETFLAG(SYSTEMD_MASK);
924			break;
925#endif
926		case 'V':
927			printf("Version " MINIDLNA_VERSION "\n");
928			exit(0);
929			break;
930		default:
931			DPRINTF(E_ERROR, L_GENERAL, "Unknown option: %s\n", argv[i]);
932			runtime_vars.port = -1; // triggers help display
933		}
934	}
935
936	if (runtime_vars.port <= 0)
937	{
938		printf("Usage:\n\t"
939			"%s [-d] [-v] [-f config_file] [-p port]\n"
940			"\t\t[-i network_interface] [-u uid_to_run_as]\n"
941			"\t\t[-t notify_interval] [-P pid_filename]\n"
942			"\t\t[-s serial] [-m model_number]\n"
943#ifdef __linux__
944			"\t\t[-w url] [-r] [-R] [-L] [-S] [-V] [-h]\n"
945#else
946			"\t\t[-w url] [-r] [-R] [-L] [-V] [-h]\n"
947#endif
948			"\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
949			"\tDefault pid file is %s.\n"
950			"\tWith -d minidlna will run in debug mode (not daemonize).\n"
951			"\t-w sets the presentation url. Default is http address on port 80\n"
952			"\t-v enables verbose output\n"
953			"\t-h displays this text\n"
954			"\t-r forces a rescan\n"
955			"\t-R forces a rebuild\n"
956			"\t-L do not create playlists\n"
957#ifdef __linux__
958			"\t-S changes behaviour for systemd\n"
959#endif
960			"\t-V print the version number\n",
961			argv[0], pidfilename);
962		return 1;
963	}
964
965	if (verbose_flag)
966	{
967		strcpy(log_str+65, "debug");
968		log_level = log_str;
969	}
970	else if (!log_level)
971		log_level = log_str;
972
973	/* Set the default log file path to NULL (stdout) */
974	path = NULL;
975	if (debug_flag)
976	{
977		pid = getpid();
978		strcpy(log_str+65, "maxdebug");
979		log_level = log_str;
980	}
981	else if (GETFLAG(SYSTEMD_MASK))
982	{
983		pid = getpid();
984	}
985	else
986	{
987		pid = process_daemonize();
988		#ifdef READYNAS
989		unlink("/ramfs/.upnp-av_scan");
990		path = "/var/log/upnp-av.log";
991		#else
992		if (access(db_path, F_OK) != 0)
993			make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
994		snprintf(buf, sizeof(buf), "%s/minidlna.log", log_path);
995		path = buf;
996		#endif
997	}
998	log_init(path, log_level);
999
1000	if (process_check_if_running(pidfilename) < 0)
1001	{
1002		DPRINTF(E_ERROR, L_GENERAL, SERVER_NAME " is already running. EXITING.\n");
1003		return 1;
1004	}
1005
1006	set_startup_time();
1007
1008	/* presentation url */
1009	if (presurl)
1010		strncpyt(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
1011	else
1012		strcpy(presentationurl, "/");
1013
1014	/* set signal handlers */
1015	memset(&sa, 0, sizeof(struct sigaction));
1016	sa.sa_handler = sigterm;
1017	if (sigaction(SIGTERM, &sa, NULL))
1018		DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGTERM");
1019	if (sigaction(SIGINT, &sa, NULL))
1020		DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGINT");
1021	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1022		DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGPIPE");
1023	if (signal(SIGHUP, &sighup) == SIG_ERR)
1024		DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGHUP");
1025	signal(SIGUSR1, &sigusr1);
1026	sa.sa_handler = process_handle_child_termination;
1027	if (sigaction(SIGCHLD, &sa, NULL))
1028		DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGCHLD");
1029
1030	if (writepidfile(pidfilename, pid, uid) != 0)
1031		pidfilename = NULL;
1032
1033	if (uid > 0)
1034	{
1035		struct stat st;
1036		if (stat(db_path, &st) == 0 && st.st_uid != uid && chown(db_path, uid, -1) != 0)
1037			DPRINTF(E_ERROR, L_GENERAL, "Unable to set db_path [%s] ownership to %d: %s\n",
1038				db_path, uid, strerror(errno));
1039	}
1040
1041	if (uid > 0 && setuid(uid) == -1)
1042		DPRINTF(E_FATAL, L_GENERAL, "Failed to switch to uid '%d'. [%s] EXITING.\n",
1043			uid, strerror(errno));
1044
1045	children = calloc(runtime_vars.max_connections, sizeof(struct child));
1046	if (!children)
1047	{
1048		DPRINTF(E_ERROR, L_GENERAL, "Allocation failed\n");
1049		return 1;
1050	}
1051
1052	// remove working flag
1053	remove_scantag();
1054
1055	return 0;
1056}
1057
1058#if (!defined(RTN66U) && !defined(RTN56U))
1059#define PATH_ICON_PNG_SM	"/rom/dlna/icon_sm.png"
1060#define PATH_ICON_PNG_LRG	"/rom/dlna/icon_lrg.png"
1061#define PATH_ICON_JPEG_SM	"/rom/dlna/icon_sm.jpg"
1062#define PATH_ICON_JPEG_LRG	"/rom/dlna/icon_lrg.jpg"
1063unsigned char buf_png_sm[65536];
1064unsigned char buf_png_lrg[65536];
1065unsigned char buf_jpeg_sm[65536];
1066unsigned char buf_jpeg_lrg[65536];
1067int size_png_sm = 0;
1068int size_png_lrg = 0;
1069int size_jpeg_sm = 0;
1070int size_jpeg_lrg = 0;
1071
1072int
1073init_icon(const char *iconfile)
1074{
1075	int fd = 0;
1076	int *size = NULL;
1077	unsigned char *buf = NULL;
1078	FILE *in = NULL;
1079	size_t i, offset;
1080	int ret = 0;
1081
1082	if( strcmp(iconfile, PATH_ICON_PNG_SM) == 0 )
1083	{
1084		buf = buf_png_sm;
1085		size = &size_png_sm;
1086	}
1087	else if( strcmp(iconfile, PATH_ICON_PNG_LRG) == 0 )
1088	{
1089		buf = buf_png_lrg;
1090		size = &size_png_lrg;
1091	}
1092	else if( strcmp(iconfile, PATH_ICON_JPEG_SM) == 0 )
1093	{
1094		buf = buf_jpeg_sm;
1095		size = &size_jpeg_sm;
1096	}
1097	else if( strcmp(iconfile, PATH_ICON_JPEG_LRG) == 0 )
1098	{
1099		buf = buf_jpeg_lrg;
1100		size = &size_jpeg_lrg;
1101	}
1102	else
1103	{
1104		ret = -1;
1105		goto RETURN;
1106	}
1107
1108	fd = open(iconfile, O_RDONLY);
1109	if (fd < 0)
1110	{
1111		fprintf(stderr, "reading icon file %s FAILED : %s\n",
1112			iconfile, strerror(errno));
1113		ret = -1;
1114		goto RETURN;
1115	} else {
1116		struct stat filestats;
1117		int statstat;
1118
1119		statstat = fstat(fd, &filestats);
1120		if (statstat < 0)
1121		{
1122			fprintf(stderr, "stat-ing iconfile %s FAILED : %s\n",
1123				iconfile, strerror(errno));
1124			ret = -1;
1125			goto RETURN;
1126		} else {
1127			if (filestats.st_size > 65536)
1128			{
1129				ret = -1;
1130				goto RETURN;
1131			}
1132			else
1133				*size = filestats.st_size;
1134		}
1135
1136		close(fd);
1137
1138		if ((in = fopen(iconfile, "rb")) == NULL)
1139		{
1140			fprintf(stderr, "fopen icon file %s FAILED : %s\n",
1141				iconfile, strerror(errno));
1142			*size = 0;
1143			ret =  -1;
1144			goto RETURN;
1145		}
1146
1147		/* loop through the file */
1148		offset = 0;
1149		memset(buf, 0, *size);
1150		while ( (i = fread(buf + offset, 1, BUFSIZ, in)) != 0 ) {
1151			offset += i;
1152		}
1153	}
1154RETURN:
1155	if (fd > 0) close(fd);
1156	if (in) fclose(in);
1157	return ret;
1158}
1159#endif
1160
1161#define NOTIFY_INTERVAL	3
1162
1163/* === main === */
1164/* process HTTP or SSDP requests */
1165int
1166main(int argc, char **argv)
1167{
1168	int ret, i;
1169	int shttpl = -1;
1170	int smonitor = -1;
1171	LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1172	struct upnphttp * e = 0;
1173	struct upnphttp * next;
1174	fd_set readset;	/* for select() */
1175	fd_set writeset;
1176	struct timeval timeout, timeofday, lastnotifytime = {0, 0};
1177	time_t lastupdatetime = 0;
1178	int max_fd = -1;
1179	int last_changecnt = 0;
1180	pid_t scanner_pid = 0;
1181	pthread_t inotify_thread = 0;
1182#ifdef TIVO_SUPPORT
1183	uint8_t beacon_interval = 5;
1184	int sbeacon = -1;
1185	struct sockaddr_in tivo_bcast;
1186	struct timeval lastbeacontime = {0, 0};
1187#endif
1188
1189	for (i = 0; i < L_MAX; i++)
1190		log_level[i] = E_WARN;
1191	init_nls();
1192
1193	ret = init(argc, argv);
1194	if (ret != 0)
1195		return 1;
1196
1197#if (!defined(RTN66U) && !defined(RTN56U))
1198	init_icon(PATH_ICON_PNG_SM);
1199	init_icon(PATH_ICON_PNG_LRG);
1200	init_icon(PATH_ICON_JPEG_SM);
1201	init_icon(PATH_ICON_JPEG_LRG);
1202#endif
1203
1204	DPRINTF(E_WARN, L_GENERAL, "Starting " SERVER_NAME " version " MINIDLNA_VERSION ".\n");
1205	if (sqlite3_libversion_number() < 3005001)
1206	{
1207		DPRINTF(E_WARN, L_GENERAL, "SQLite library is old.  Please use version 3.5.1 or newer.\n");
1208	}
1209
1210	LIST_INIT(&upnphttphead);
1211
1212	ret = open_db(NULL);
1213	if (ret == 0)
1214	{
1215		updateID = sql_get_int_field(db, "SELECT VALUE from SETTINGS where KEY = 'UPDATE_ID'");
1216		if (updateID == -1)
1217			ret = -1;
1218	}
1219	check_db(db, ret, &scanner_pid);
1220#ifdef HAVE_INOTIFY
1221	if( GETFLAG(INOTIFY_MASK) )
1222	{
1223		if (!sqlite3_threadsafe() || sqlite3_libversion_number() < 3005001)
1224			DPRINTF(E_ERROR, L_GENERAL, "SQLite library is not threadsafe!  "
1225			                            "Inotify will be disabled.\n");
1226		else if (pthread_create(&inotify_thread, NULL, start_inotify, NULL) != 0)
1227			DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() failed for start_inotify. EXITING\n");
1228	}
1229#endif
1230	smonitor = OpenAndConfMonitorSocket();
1231
1232	sssdp = OpenAndConfSSDPReceiveSocket();
1233	if (sssdp < 0)
1234	{
1235		DPRINTF(E_INFO, L_GENERAL, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd\n");
1236		reload_ifaces(0);	/* populate lan_addr[0].str */
1237		if (SubmitServicesToMiniSSDPD(lan_addr[0].str, runtime_vars.port) < 0)
1238			DPRINTF(E_FATAL, L_GENERAL, "Failed to connect to MiniSSDPd. EXITING");
1239	}
1240	/* open socket for HTTP connections. */
1241	shttpl = OpenAndConfHTTPSocket(runtime_vars.port);
1242	if (shttpl < 0)
1243		DPRINTF(E_FATAL, L_GENERAL, "Failed to open socket for HTTP. EXITING\n");
1244	DPRINTF(E_WARN, L_GENERAL, "HTTP listening on port %d\n", runtime_vars.port);
1245
1246#ifdef TIVO_SUPPORT
1247	if (GETFLAG(TIVO_MASK))
1248	{
1249		DPRINTF(E_WARN, L_GENERAL, "TiVo support is enabled.\n");
1250		/* Add TiVo-specific randomize function to sqlite */
1251		ret = sqlite3_create_function(db, "tivorandom", 1, SQLITE_UTF8, NULL, &TiVoRandomSeedFunc, NULL, NULL);
1252		if (ret != SQLITE_OK)
1253			DPRINTF(E_ERROR, L_TIVO, "ERROR: Failed to add sqlite randomize function for TiVo!\n");
1254		/* open socket for sending Tivo notifications */
1255		sbeacon = OpenAndConfTivoBeaconSocket();
1256		if(sbeacon < 0)
1257			DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending Tivo beacon notify "
1258				"messages. EXITING\n");
1259		tivo_bcast.sin_family = AF_INET;
1260		tivo_bcast.sin_addr.s_addr = htonl(getBcastAddress());
1261		tivo_bcast.sin_port = htons(2190);
1262	}
1263#endif
1264
1265	reload_ifaces(0);
1266#if 0
1267	lastnotifytime.tv_sec = time(NULL) + runtime_vars.notify_interval;
1268#else
1269	lastnotifytime.tv_sec = uptime();
1270#endif
1271
1272	/* main loop */
1273	while (!quitting)
1274	{
1275		/* Check if we need to send SSDP NOTIFY messages and do it if
1276		 * needed */
1277#if 0
1278		if (gettimeofday(&timeofday, 0) < 0)
1279		{
1280			DPRINTF(E_ERROR, L_GENERAL, "gettimeofday(): %s\n", strerror(errno));
1281			timeout.tv_sec = runtime_vars.notify_interval;
1282			timeout.tv_usec = 0;
1283		}
1284		else
1285#else
1286		timeofday.tv_sec = uptime();
1287		timeofday.tv_usec = 0;
1288#endif
1289		{
1290			/* the comparison is not very precise but who cares ? */
1291#if 0
1292			if (timeofday.tv_sec >= (lastnotifytime.tv_sec + runtime_vars.notify_interval))
1293#else
1294			if (timeofday.tv_sec >= (lastnotifytime.tv_sec + NOTIFY_INTERVAL))
1295#endif
1296			{
1297				DPRINTF(E_DEBUG, L_SSDP, "Sending SSDP notifies\n");
1298				for (i = 0; i < n_lan_addr; i++)
1299				{
1300#if 0
1301					SendSSDPNotifies(lan_addr[i].snotify, lan_addr[i].str,
1302						runtime_vars.port, runtime_vars.notify_interval);
1303#else
1304					SendSSDPNotifies(lan_addr[i].snotify, lan_addr[i].str,
1305						runtime_vars.port, NOTIFY_INTERVAL);
1306#endif
1307				}
1308				memcpy(&lastnotifytime, &timeofday, sizeof(struct timeval));
1309#if 0
1310				timeout.tv_sec = runtime_vars.notify_interval;
1311#else
1312				timeout.tv_sec = NOTIFY_INTERVAL;
1313#endif
1314				timeout.tv_usec = 0;
1315			}
1316			else
1317			{
1318#if 0
1319				timeout.tv_sec = lastnotifytime.tv_sec + runtime_vars.notify_interval
1320				                 - timeofday.tv_sec;
1321#else
1322				timeout.tv_sec = lastnotifytime.tv_sec + NOTIFY_INTERVAL
1323						 - timeofday.tv_sec;
1324#endif
1325				if (timeofday.tv_usec > lastnotifytime.tv_usec)
1326				{
1327					timeout.tv_usec = 1000000 + lastnotifytime.tv_usec
1328					                  - timeofday.tv_usec;
1329					timeout.tv_sec--;
1330				}
1331				else
1332					timeout.tv_usec = lastnotifytime.tv_usec - timeofday.tv_usec;
1333			}
1334#ifdef TIVO_SUPPORT
1335			if (sbeacon >= 0)
1336			{
1337				if (timeofday.tv_sec >= (lastbeacontime.tv_sec + beacon_interval))
1338				{
1339					sendBeaconMessage(sbeacon, &tivo_bcast, sizeof(struct sockaddr_in), 1);
1340					memcpy(&lastbeacontime, &timeofday, sizeof(struct timeval));
1341					if (timeout.tv_sec > beacon_interval)
1342					{
1343						timeout.tv_sec = beacon_interval;
1344						timeout.tv_usec = 0;
1345					}
1346					/* Beacons should be sent every 5 seconds or so for the first minute,
1347					 * then every minute or so thereafter. */
1348					if (beacon_interval == 5 && (timeofday.tv_sec - startup_time) > 60)
1349						beacon_interval = 60;
1350				}
1351				else if (timeout.tv_sec > (lastbeacontime.tv_sec + beacon_interval + 1 - timeofday.tv_sec))
1352					timeout.tv_sec = lastbeacontime.tv_sec + beacon_interval - timeofday.tv_sec;
1353			}
1354#endif
1355		}
1356
1357		if (scanning)
1358		{
1359			if (!scanner_pid || kill(scanner_pid, 0) != 0)
1360			{
1361				scanning = 0;
1362				updateID++;
1363			}
1364		}
1365
1366		/* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1367		FD_ZERO(&readset);
1368
1369		if (sssdp >= 0)
1370		{
1371			FD_SET(sssdp, &readset);
1372			max_fd = MAX(max_fd, sssdp);
1373		}
1374
1375		if (shttpl >= 0)
1376		{
1377			FD_SET(shttpl, &readset);
1378			max_fd = MAX(max_fd, shttpl);
1379		}
1380#ifdef TIVO_SUPPORT
1381		if (sbeacon >= 0)
1382		{
1383			FD_SET(sbeacon, &readset);
1384			max_fd = MAX(max_fd, sbeacon);
1385		}
1386#endif
1387		if (smonitor >= 0)
1388		{
1389			FD_SET(smonitor, &readset);
1390			max_fd = MAX(max_fd, smonitor);
1391		}
1392
1393		i = 0;	/* active HTTP connections count */
1394		for (e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1395		{
1396			if ((e->socket >= 0) && (e->state <= 2))
1397			{
1398				FD_SET(e->socket, &readset);
1399				max_fd = MAX(max_fd, e->socket);
1400				i++;
1401			}
1402		}
1403		FD_ZERO(&writeset);
1404		upnpevents_selectfds(&readset, &writeset, &max_fd);
1405
1406		ret = select(max_fd+1, &readset, &writeset, 0, &timeout);
1407		if (ret < 0)
1408		{
1409			if(quitting) goto shutdown;
1410			if(errno == EINTR) continue;
1411			DPRINTF(E_ERROR, L_GENERAL, "select(all): %s\n", strerror(errno));
1412			DPRINTF(E_FATAL, L_GENERAL, "Failed to select open sockets. EXITING\n");
1413		}
1414		upnpevents_processfds(&readset, &writeset);
1415		/* process SSDP packets */
1416		if (sssdp >= 0 && FD_ISSET(sssdp, &readset))
1417		{
1418			/*DPRINTF(E_DEBUG, L_GENERAL, "Received SSDP Packet\n");*/
1419			ProcessSSDPRequest(sssdp, (unsigned short)runtime_vars.port);
1420		}
1421#ifdef TIVO_SUPPORT
1422		if (sbeacon >= 0 && FD_ISSET(sbeacon, &readset))
1423		{
1424			/*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/
1425			ProcessTiVoBeacon(sbeacon);
1426		}
1427#endif
1428		if (smonitor >= 0 && FD_ISSET(smonitor, &readset))
1429		{
1430			ProcessMonitorEvent(smonitor);
1431		}
1432		/* increment SystemUpdateID if the content database has changed,
1433		 * and if there is an active HTTP connection, at most once every 2 seconds */
1434		if (i && (timeofday.tv_sec >= (lastupdatetime + 2)))
1435		{
1436			if (scanning || sqlite3_total_changes(db) != last_changecnt)
1437			{
1438				updateID++;
1439				last_changecnt = sqlite3_total_changes(db);
1440				upnp_event_var_change_notify(EContentDirectory);
1441				lastupdatetime = timeofday.tv_sec;
1442			}
1443		}
1444		/* process active HTTP connections */
1445		for (e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1446		{
1447			if ((e->socket >= 0) && (e->state <= 2) && (FD_ISSET(e->socket, &readset)))
1448				Process_upnphttp(e);
1449		}
1450		/* process incoming HTTP connections */
1451		if (shttpl >= 0 && FD_ISSET(shttpl, &readset))
1452		{
1453			int shttp;
1454			socklen_t clientnamelen;
1455			struct sockaddr_in clientname;
1456			clientnamelen = sizeof(struct sockaddr_in);
1457			shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
1458			if (shttp<0)
1459			{
1460				DPRINTF(E_ERROR, L_GENERAL, "accept(http): %s\n", strerror(errno));
1461			}
1462			else
1463			{
1464				struct upnphttp * tmp = 0;
1465				DPRINTF(E_DEBUG, L_GENERAL, "HTTP connection from %s:%d\n",
1466					inet_ntoa(clientname.sin_addr),
1467					ntohs(clientname.sin_port) );
1468				/*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {
1469					DPRINTF(E_ERROR, L_GENERAL, "fcntl F_SETFL, O_NONBLOCK\n");
1470				}*/
1471				/* Create a new upnphttp object and add it to
1472				 * the active upnphttp object list */
1473				tmp = New_upnphttp(shttp);
1474				if (tmp)
1475				{
1476					tmp->clientaddr = clientname.sin_addr;
1477					LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
1478				}
1479				else
1480				{
1481					DPRINTF(E_ERROR, L_GENERAL, "New_upnphttp() failed\n");
1482					close(shttp);
1483				}
1484			}
1485		}
1486		/* delete finished HTTP connections */
1487		for (e = upnphttphead.lh_first; e != NULL; e = next)
1488		{
1489			next = e->entries.le_next;
1490			if(e->state >= 100)
1491			{
1492				LIST_REMOVE(e, entries);
1493				Delete_upnphttp(e);
1494			}
1495		}
1496	}
1497
1498shutdown:
1499	/* kill the scanner */
1500	if (scanning && scanner_pid)
1501		kill(scanner_pid, SIGKILL);
1502
1503	/* kill other child processes */
1504	process_reap_children();
1505	free(children);
1506
1507	/* close out open sockets */
1508	while (upnphttphead.lh_first != NULL)
1509	{
1510		e = upnphttphead.lh_first;
1511		LIST_REMOVE(e, entries);
1512		Delete_upnphttp(e);
1513	}
1514	if (sssdp >= 0)
1515		close(sssdp);
1516	if (shttpl >= 0)
1517		close(shttpl);
1518#ifdef TIVO_SUPPORT
1519	if (sbeacon >= 0)
1520		close(sbeacon);
1521#endif
1522	if (smonitor >= 0)
1523		close(smonitor);
1524
1525	for (i = 0; i < n_lan_addr; i++)
1526	{
1527		SendSSDPGoodbyes(lan_addr[i].snotify);
1528		close(lan_addr[i].snotify);
1529	}
1530
1531	if (inotify_thread)
1532		pthread_join(inotify_thread, NULL);
1533
1534	sql_exec(db, "UPDATE SETTINGS set VALUE = '%u' where KEY = 'UPDATE_ID'", updateID);
1535	sqlite3_close(db);
1536
1537	upnpevents_removeSubscribers();
1538
1539	if (pidfilename && unlink(pidfilename) < 0)
1540		DPRINTF(E_ERROR, L_GENERAL, "Failed to remove pidfile %s: %s\n", pidfilename, strerror(errno));
1541
1542	log_close();
1543	freeoptions();
1544
1545	exit(EXIT_SUCCESS);
1546}
1547
1548