minidlna: update to 1.1.5
[tomato.git] / release / src / router / minidlna / minidlna.c
blob20af1df500fc0880c3cef66932c2f89b9af1f8cd
1 /* MiniDLNA project
3 * http://sourceforge.net/projects/minidlna/
5 * MiniDLNA media server
6 * Copyright (C) 2008-2012 Justin Maggard
8 * This file is part of MiniDLNA.
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.
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.
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/>.
22 * Portions of the code from the MiniUPnP project:
24 * Copyright (c) 2006-2007, Thomas Bernard
25 * All rights reserved.
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.
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.
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>
72 #include "config.h"
74 #ifdef ENABLE_NLS
75 #include <locale.h>
76 #include <libintl.h>
77 #endif
79 #include "upnpglobalvars.h"
80 #include "sql.h"
81 #include "upnphttp.h"
82 #include "upnpdescgen.h"
83 #include "minidlnapath.h"
84 #include "getifaddr.h"
85 #include "upnpsoap.h"
86 #include "options.h"
87 #include "utils.h"
88 #include "minissdp.h"
89 #include "minidlnatypes.h"
90 #include "process.h"
91 #include "upnpevents.h"
92 #include "scanner.h"
93 #include "inotify.h"
94 #include "log.h"
95 #include "tivo_beacon.h"
96 #include "tivo_utils.h"
98 #if SQLITE_VERSION_NUMBER < 3005001
99 # warning "Your SQLite3 library appears to be too old! Please use 3.5.1 or newer."
100 # define sqlite3_threadsafe() 0
101 #endif
103 /* OpenAndConfHTTPSocket() :
104 * setup the socket used to handle incoming HTTP connections. */
105 static int
106 OpenAndConfHTTPSocket(unsigned short port)
108 int s;
109 int i = 1;
110 struct sockaddr_in listenname;
112 /* Initialize client type cache */
113 memset(&clients, 0, sizeof(struct client_cache_s));
115 s = socket(PF_INET, SOCK_STREAM, 0);
116 if (s < 0)
118 DPRINTF(E_ERROR, L_GENERAL, "socket(http): %s\n", strerror(errno));
119 return -1;
122 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
123 DPRINTF(E_WARN, L_GENERAL, "setsockopt(http, SO_REUSEADDR): %s\n", strerror(errno));
125 memset(&listenname, 0, sizeof(struct sockaddr_in));
126 listenname.sin_family = AF_INET;
127 listenname.sin_port = htons(port);
128 listenname.sin_addr.s_addr = htonl(INADDR_ANY);
130 if (bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)
132 DPRINTF(E_ERROR, L_GENERAL, "bind(http): %s\n", strerror(errno));
133 close(s);
134 return -1;
137 if (listen(s, 6) < 0)
139 DPRINTF(E_ERROR, L_GENERAL, "listen(http): %s\n", strerror(errno));
140 close(s);
141 return -1;
144 return s;
147 /* Handler for the SIGTERM signal (kill)
148 * SIGINT is also handled */
149 static void
150 sigterm(int sig)
152 signal(sig, SIG_IGN); /* Ignore this signal while we are quitting */
154 DPRINTF(E_WARN, L_GENERAL, "received signal %d, good-bye\n", sig);
156 quitting = 1;
159 static void
160 sigusr1(int sig)
162 signal(sig, sigusr1);
163 DPRINTF(E_WARN, L_GENERAL, "received signal %d, clear cache\n", sig);
165 memset(&clients, '\0', sizeof(clients));
168 static void
169 sighup(int sig)
171 signal(sig, sighup);
172 DPRINTF(E_WARN, L_GENERAL, "received signal %d, re-read\n", sig);
174 reload_ifaces(1);
177 /* record the startup time */
178 static void
179 set_startup_time(void)
181 startup_time = time(NULL);
184 static void
185 getfriendlyname(char *buf, int len)
187 char *p = NULL;
188 char hn[256];
189 int off;
191 if (gethostname(hn, sizeof(hn)) == 0)
193 strncpyt(buf, hn, len);
194 p = strchr(buf, '.');
195 if (p)
196 *p = '\0';
198 else
199 strcpy(buf, "Unknown");
201 off = strlen(buf);
202 off += snprintf(buf+off, len-off, ": ");
203 #ifdef READYNAS
204 FILE *info;
205 char ibuf[64], *key, *val;
206 snprintf(buf+off, len-off, "ReadyNAS");
207 info = fopen("/proc/sys/dev/boot/info", "r");
208 if (!info)
209 return;
210 while ((val = fgets(ibuf, 64, info)) != NULL)
212 key = strsep(&val, ": \t");
213 val = trim(val);
214 if (strcmp(key, "model") == 0)
216 snprintf(buf+off, len-off, "%s", val);
217 key = strchr(val, ' ');
218 if (key)
220 strncpyt(modelnumber, key+1, MODELNUMBER_MAX_LEN);
221 *key = '\0';
223 snprintf(modelname, MODELNAME_MAX_LEN,
224 "Windows Media Connect compatible (%s)", val);
226 else if (strcmp(key, "serial") == 0)
228 strncpyt(serialnumber, val, SERIALNUMBER_MAX_LEN);
229 if (serialnumber[0] == '\0')
231 char mac_str[13];
232 if (getsyshwaddr(mac_str, sizeof(mac_str)) == 0)
233 strcpy(serialnumber, mac_str);
234 else
235 strcpy(serialnumber, "0");
237 break;
240 fclose(info);
241 #if PNPX
242 memcpy(pnpx_hwid+4, "01F2", 4);
243 if (strcmp(modelnumber, "NVX") == 0)
244 memcpy(pnpx_hwid+17, "0101", 4);
245 else if (strcmp(modelnumber, "Pro") == 0 ||
246 strcmp(modelnumber, "Pro 6") == 0 ||
247 strncmp(modelnumber, "Ultra 6", 7) == 0)
248 memcpy(pnpx_hwid+17, "0102", 4);
249 else if (strcmp(modelnumber, "Pro 2") == 0 ||
250 strncmp(modelnumber, "Ultra 2", 7) == 0)
251 memcpy(pnpx_hwid+17, "0103", 4);
252 else if (strcmp(modelnumber, "Pro 4") == 0 ||
253 strncmp(modelnumber, "Ultra 4", 7) == 0)
254 memcpy(pnpx_hwid+17, "0104", 4);
255 else if (strcmp(modelnumber+1, "100") == 0)
256 memcpy(pnpx_hwid+17, "0105", 4);
257 else if (strcmp(modelnumber+1, "200") == 0)
258 memcpy(pnpx_hwid+17, "0106", 4);
259 /* 0107 = Stora */
260 else if (strcmp(modelnumber, "Duo v2") == 0)
261 memcpy(pnpx_hwid+17, "0108", 4);
262 else if (strcmp(modelnumber, "NV+ v2") == 0)
263 memcpy(pnpx_hwid+17, "0109", 4);
264 #endif
265 #else
266 char * logname;
267 logname = getenv("LOGNAME");
268 #ifndef STATIC // Disable for static linking
269 if (!logname)
271 struct passwd * pwent;
272 pwent = getpwuid(getuid());
273 if (pwent)
274 logname = pwent->pw_name;
276 #endif
277 snprintf(buf+off, len-off, "%s", logname?logname:"Unknown");
278 #endif
281 static int
282 open_db(sqlite3 **sq3)
284 char path[PATH_MAX];
285 int new_db = 0;
287 snprintf(path, sizeof(path), "%s/files.db", db_path);
288 if (access(path, F_OK) != 0)
290 new_db = 1;
291 make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
293 if (sqlite3_open(path, &db) != SQLITE_OK)
294 DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to open sqlite database! Exiting...\n");
295 if (sq3)
296 *sq3 = db;
297 sqlite3_busy_timeout(db, 5000);
298 sql_exec(db, "pragma page_size = 4096");
299 sql_exec(db, "pragma journal_mode = OFF");
300 sql_exec(db, "pragma synchronous = OFF;");
301 // this sets the sqlite database cache size
302 // original code had 8192 = 32MB - reduce it to 4MB
303 sql_exec(db, "pragma default_cache_size = 1024;");
305 return new_db;
308 static void
309 check_db(sqlite3 *db, int new_db, pid_t *scanner_pid)
311 struct media_dir_s *media_path = NULL;
312 char cmd[PATH_MAX*2];
313 char **result;
314 int i, rows = 0;
315 int ret;
317 if (!new_db)
319 /* Check if any new media dirs appeared */
320 media_path = media_dirs;
321 while (media_path)
323 ret = sql_get_int_field(db, "SELECT TIMESTAMP from DETAILS where PATH = %Q", media_path->path);
324 if (ret != media_path->types)
326 ret = 1;
327 goto rescan;
329 media_path = media_path->next;
331 /* Check if any media dirs disappeared */
332 sql_get_table(db, "SELECT VALUE from SETTINGS where KEY = 'media_dir'", &result, &rows, NULL);
333 for (i=1; i <= rows; i++)
335 media_path = media_dirs;
336 while (media_path)
338 if (strcmp(result[i], media_path->path) == 0)
339 break;
340 media_path = media_path->next;
342 if (!media_path)
344 ret = 2;
345 sqlite3_free_table(result);
346 goto rescan;
349 sqlite3_free_table(result);
352 ret = db_upgrade(db);
353 if (ret != 0)
355 rescan:
356 if (ret < 0)
357 DPRINTF(E_WARN, L_GENERAL, "Creating new database at %s/files.db\n", db_path);
358 else if (ret == 1)
359 DPRINTF(E_WARN, L_GENERAL, "New media_dir detected; rescanning...\n");
360 else if (ret == 2)
361 DPRINTF(E_WARN, L_GENERAL, "Removed media_dir detected; rescanning...\n");
362 else
363 DPRINTF(E_WARN, L_GENERAL, "Database version mismatch (%d=>%d); need to recreate...\n",
364 ret, DB_VERSION);
365 sqlite3_close(db);
367 snprintf(cmd, sizeof(cmd), "rm -rf %s/files.db %s/art_cache", db_path, db_path);
368 if (system(cmd) != 0)
369 DPRINTF(E_FATAL, L_GENERAL, "Failed to clean old file cache! Exiting...\n");
371 open_db(&db);
372 if (CreateDatabase() != 0)
373 DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to create sqlite database! Exiting...\n");
374 #if USE_FORK
375 scanning = 1;
376 sqlite3_close(db);
377 *scanner_pid = fork();
378 open_db(&db);
379 if (*scanner_pid == 0) /* child (scanner) process */
381 start_scanner();
382 sqlite3_close(db);
383 log_close();
384 freeoptions();
385 free(children);
386 exit(EXIT_SUCCESS);
388 else if (*scanner_pid < 0)
390 start_scanner();
392 #else
393 start_scanner();
394 #endif
398 static int
399 writepidfile(const char *fname, int pid, uid_t uid)
401 FILE *pidfile;
402 struct stat st;
403 char path[PATH_MAX], *dir;
404 int ret = 0;
406 if(!fname || *fname == '\0')
407 return -1;
409 /* Create parent directory if it doesn't already exist */
410 strncpyt(path, fname, sizeof(path));
411 dir = dirname(path);
412 if (stat(dir, &st) == 0)
414 if (!S_ISDIR(st.st_mode))
416 DPRINTF(E_ERROR, L_GENERAL, "Pidfile path is not a directory: %s\n",
417 fname);
418 return -1;
421 else
423 if (make_dir(dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0)
425 DPRINTF(E_ERROR, L_GENERAL, "Unable to create pidfile directory: %s\n",
426 fname);
427 return -1;
429 if (uid > 0)
431 if (chown(dir, uid, -1) != 0)
432 DPRINTF(E_WARN, L_GENERAL, "Unable to change pidfile %s ownership: %s\n",
433 dir, strerror(errno));
437 pidfile = fopen(fname, "w");
438 if (!pidfile)
440 DPRINTF(E_ERROR, L_GENERAL, "Unable to open pidfile for writing %s: %s\n",
441 fname, strerror(errno));
442 return -1;
445 if (fprintf(pidfile, "%d\n", pid) <= 0)
447 DPRINTF(E_ERROR, L_GENERAL,
448 "Unable to write to pidfile %s: %s\n", fname, strerror(errno));
449 ret = -1;
451 if (uid > 0)
453 if (fchown(fileno(pidfile), uid, -1) != 0)
454 DPRINTF(E_WARN, L_GENERAL, "Unable to change pidfile %s ownership: %s\n",
455 fname, strerror(errno));
458 fclose(pidfile);
460 return ret;
463 static int strtobool(const char *str)
465 return ((strcasecmp(str, "yes") == 0) ||
466 (strcasecmp(str, "true") == 0) ||
467 (atoi(str) == 1));
470 static void init_nls(void)
472 #ifdef ENABLE_NLS
473 setlocale(LC_MESSAGES, "");
474 setlocale(LC_CTYPE, "en_US.utf8");
475 DPRINTF(E_DEBUG, L_GENERAL, "Using locale dir %s\n", bindtextdomain("minidlna", getenv("TEXTDOMAINDIR")));
476 textdomain("minidlna");
477 #endif
480 /* init phase :
481 * 1) read configuration file
482 * 2) read command line arguments
483 * 3) daemonize
484 * 4) check and write pid file
485 * 5) set startup time stamp
486 * 6) compute presentation URL
487 * 7) set signal handlers */
488 static int
489 init(int argc, char **argv)
491 int i;
492 int pid;
493 int debug_flag = 0;
494 int verbose_flag = 0;
495 int options_flag = 0;
496 struct sigaction sa;
497 const char * presurl = NULL;
498 const char * optionsfile = "/etc/minidlna.conf";
499 char mac_str[13];
500 char *string, *word;
501 char *path;
502 char buf[PATH_MAX];
503 char log_str[75] = "general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn";
504 char *log_level = NULL;
505 struct media_dir_s *media_dir;
506 int ifaces = 0;
507 media_types types;
508 uid_t uid = 0;
510 /* first check if "-f" option is used */
511 for (i=2; i<argc; i++)
513 if (strcmp(argv[i-1], "-f") == 0)
515 optionsfile = argv[i];
516 options_flag = 1;
517 break;
521 /* set up uuid based on mac address */
522 if (getsyshwaddr(mac_str, sizeof(mac_str)) < 0)
524 DPRINTF(E_OFF, L_GENERAL, "No MAC address found. Falling back to generic UUID.\n");
525 strcpy(mac_str, "554e4b4e4f57");
527 strcpy(uuidvalue+5, "4d696e69-444c-164e-9d41-");
528 strncat(uuidvalue, mac_str, 12);
530 getfriendlyname(friendly_name, FRIENDLYNAME_MAX_LEN);
532 runtime_vars.port = 8200;
533 runtime_vars.notify_interval = 895; /* seconds between SSDP announces */
534 runtime_vars.max_connections = 50;
535 runtime_vars.root_container = NULL;
536 runtime_vars.ifaces[0] = NULL;
538 /* read options file first since
539 * command line arguments have final say */
540 if (readoptionsfile(optionsfile) < 0)
542 /* only error if file exists or using -f */
543 if(access(optionsfile, F_OK) == 0 || options_flag)
544 DPRINTF(E_FATAL, L_GENERAL, "Error reading configuration file %s\n", optionsfile);
547 for (i=0; i<num_options; i++)
549 switch (ary_options[i].id)
551 case UPNPIFNAME:
552 for (string = ary_options[i].value; (word = strtok(string, ",")); string = NULL)
554 if (ifaces >= MAX_LAN_ADDR)
556 DPRINTF(E_ERROR, L_GENERAL, "Too many interfaces (max: %d), ignoring %s\n",
557 MAX_LAN_ADDR, word);
558 break;
560 while (isspace(*word))
561 word++;
562 runtime_vars.ifaces[ifaces++] = word;
564 break;
565 case UPNPPORT:
566 runtime_vars.port = atoi(ary_options[i].value);
567 break;
568 case UPNPPRESENTATIONURL:
569 presurl = ary_options[i].value;
570 break;
571 case UPNPNOTIFY_INTERVAL:
572 runtime_vars.notify_interval = atoi(ary_options[i].value);
573 break;
574 case UPNPSERIAL:
575 strncpyt(serialnumber, ary_options[i].value, SERIALNUMBER_MAX_LEN);
576 break;
577 case UPNPMODEL_NAME:
578 strncpyt(modelname, ary_options[i].value, MODELNAME_MAX_LEN);
579 break;
580 case UPNPMODEL_NUMBER:
581 strncpyt(modelnumber, ary_options[i].value, MODELNUMBER_MAX_LEN);
582 break;
583 case UPNPFRIENDLYNAME:
584 strncpyt(friendly_name, ary_options[i].value, FRIENDLYNAME_MAX_LEN);
585 break;
586 case UPNPMEDIADIR:
587 types = ALL_MEDIA;
588 path = ary_options[i].value;
589 word = strchr(path, ',');
590 if (word && (access(path, F_OK) != 0))
592 types = 0;
593 while (*path)
595 if (*path == ',')
597 path++;
598 break;
600 else if (*path == 'A' || *path == 'a')
601 types |= TYPE_AUDIO;
602 else if (*path == 'V' || *path == 'v')
603 types |= TYPE_VIDEO;
604 else if (*path == 'P' || *path == 'p')
605 types |= TYPE_IMAGES;
606 else
607 DPRINTF(E_FATAL, L_GENERAL, "Media directory entry not understood [%s]\n",
608 ary_options[i].value);
609 path++;
612 path = realpath(path, buf);
613 if (!path || access(path, F_OK) != 0)
615 DPRINTF(E_ERROR, L_GENERAL, "Media directory \"%s\" not accessible [%s]\n",
616 ary_options[i].value, strerror(errno));
617 break;
619 media_dir = calloc(1, sizeof(struct media_dir_s));
620 media_dir->path = strdup(path);
621 media_dir->types = types;
622 if (media_dirs)
624 struct media_dir_s *all_dirs = media_dirs;
625 while( all_dirs->next )
626 all_dirs = all_dirs->next;
627 all_dirs->next = media_dir;
629 else
630 media_dirs = media_dir;
631 break;
632 case UPNPALBUMART_NAMES:
633 for (string = ary_options[i].value; (word = strtok(string, "/")); string = NULL)
635 struct album_art_name_s * this_name = calloc(1, sizeof(struct album_art_name_s));
636 int len = strlen(word);
637 if (word[len-1] == '*')
639 word[len-1] = '\0';
640 this_name->wildcard = 1;
642 this_name->name = strdup(word);
643 if (album_art_names)
645 struct album_art_name_s * all_names = album_art_names;
646 while( all_names->next )
647 all_names = all_names->next;
648 all_names->next = this_name;
650 else
651 album_art_names = this_name;
653 break;
654 case UPNPDBDIR:
655 path = realpath(ary_options[i].value, buf);
656 if (!path)
657 path = (ary_options[i].value);
658 make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
659 if (access(path, F_OK) != 0)
660 DPRINTF(E_FATAL, L_GENERAL, "Database path not accessible! [%s]\n", path);
661 strncpyt(db_path, path, PATH_MAX);
662 break;
663 case UPNPLOGDIR:
664 path = realpath(ary_options[i].value, buf);
665 if (!path)
666 path = (ary_options[i].value);
667 make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
668 if (access(path, F_OK) != 0)
669 DPRINTF(E_FATAL, L_GENERAL, "Log path not accessible! [%s]\n", path);
670 strncpyt(log_path, path, PATH_MAX);
671 break;
672 case UPNPLOGLEVEL:
673 log_level = ary_options[i].value;
674 break;
675 case UPNPINOTIFY:
676 if (!strtobool(ary_options[i].value))
677 CLEARFLAG(INOTIFY_MASK);
678 break;
679 case ENABLE_TIVO:
680 if (strtobool(ary_options[i].value))
681 SETFLAG(TIVO_MASK);
682 break;
683 case ENABLE_DLNA_STRICT:
684 if (strtobool(ary_options[i].value))
685 SETFLAG(DLNA_STRICT_MASK);
686 break;
687 case ROOT_CONTAINER:
688 switch (ary_options[i].value[0]) {
689 case '.':
690 runtime_vars.root_container = NULL;
691 break;
692 case 'B':
693 case 'b':
694 runtime_vars.root_container = BROWSEDIR_ID;
695 break;
696 case 'M':
697 case 'm':
698 runtime_vars.root_container = MUSIC_ID;
699 break;
700 case 'V':
701 case 'v':
702 runtime_vars.root_container = VIDEO_ID;
703 break;
704 case 'P':
705 case 'p':
706 runtime_vars.root_container = IMAGE_ID;
707 break;
708 default:
709 runtime_vars.root_container = ary_options[i].value;
710 DPRINTF(E_WARN, L_GENERAL, "Using arbitrary root container [%s]\n",
711 ary_options[i].value);
712 break;
714 break;
715 case UPNPMINISSDPDSOCKET:
716 minissdpdsocketpath = ary_options[i].value;
717 break;
718 case UPNPUUID:
719 strcpy(uuidvalue+5, ary_options[i].value);
720 break;
721 case USER_ACCOUNT:
722 uid = strtoul(ary_options[i].value, &string, 0);
723 if (*string)
725 /* Symbolic username given, not UID. */
726 struct passwd *entry = getpwnam(ary_options[i].value);
727 if (!entry)
728 DPRINTF(E_FATAL, L_GENERAL, "Bad user '%s'.\n",
729 ary_options[i].value);
730 uid = entry->pw_uid;
732 break;
733 case FORCE_SORT_CRITERIA:
734 force_sort_criteria = ary_options[i].value;
735 break;
736 case MAX_CONNECTIONS:
737 runtime_vars.max_connections = atoi(ary_options[i].value);
738 break;
739 case MERGE_MEDIA_DIRS:
740 if (strtobool(ary_options[i].value))
741 SETFLAG(MERGE_MEDIA_DIRS_MASK);
742 break;
743 default:
744 DPRINTF(E_ERROR, L_GENERAL, "Unknown option in file %s\n",
745 optionsfile);
748 if (log_path[0] == '\0')
750 if (db_path[0] == '\0')
751 strncpyt(log_path, DEFAULT_LOG_PATH, PATH_MAX);
752 else
753 strncpyt(log_path, db_path, PATH_MAX);
755 if (db_path[0] == '\0')
756 strncpyt(db_path, DEFAULT_DB_PATH, PATH_MAX);
758 /* command line arguments processing */
759 for (i=1; i<argc; i++)
761 if (argv[i][0] != '-')
763 DPRINTF(E_FATAL, L_GENERAL, "Unknown option: %s\n", argv[i]);
765 else if (strcmp(argv[i], "--help") == 0)
767 runtime_vars.port = -1;
768 break;
770 else switch(argv[i][1])
772 case 't':
773 if (i+1 < argc)
774 runtime_vars.notify_interval = atoi(argv[++i]);
775 else
776 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
777 break;
778 case 's':
779 if (i+1 < argc)
780 strncpyt(serialnumber, argv[++i], SERIALNUMBER_MAX_LEN);
781 else
782 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
783 break;
784 case 'm':
785 if (i+1 < argc)
786 strncpyt(modelnumber, argv[++i], MODELNUMBER_MAX_LEN);
787 else
788 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
789 break;
790 case 'p':
791 if (i+1 < argc)
792 runtime_vars.port = atoi(argv[++i]);
793 else
794 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
795 break;
796 case 'P':
797 if (i+1 < argc)
799 if (argv[++i][0] != '/')
800 DPRINTF(E_FATAL, L_GENERAL, "Option -%c requires an absolute filename.\n", argv[i-1][1]);
801 else
802 pidfilename = argv[i];
804 else
805 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
806 break;
807 case 'd':
808 debug_flag = 1;
809 case 'v':
810 verbose_flag = 1;
811 break;
812 case 'L':
813 SETFLAG(NO_PLAYLIST_MASK);
814 break;
815 case 'w':
816 if (i+1 < argc)
817 presurl = argv[++i];
818 else
819 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
820 break;
821 case 'i':
822 if (i+1 < argc)
824 i++;
825 if (ifaces >= MAX_LAN_ADDR)
827 DPRINTF(E_ERROR, L_GENERAL, "Too many interfaces (max: %d), ignoring %s\n",
828 MAX_LAN_ADDR, argv[i]);
829 break;
831 runtime_vars.ifaces[ifaces++] = argv[i];
833 else
834 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
835 break;
836 case 'f':
837 i++; /* discarding, the config file is already read */
838 break;
839 case 'h':
840 runtime_vars.port = -1; // triggers help display
841 break;
842 case 'R':
843 snprintf(buf, sizeof(buf), "rm -rf %s/files.db %s/art_cache", db_path, db_path);
844 if (system(buf) != 0)
845 DPRINTF(E_FATAL, L_GENERAL, "Failed to clean old file cache. EXITING\n");
846 break;
847 case 'u':
848 if (i+1 != argc)
850 i++;
851 uid = strtoul(argv[i], &string, 0);
852 if (*string)
854 /* Symbolic username given, not UID. */
855 struct passwd *entry = getpwnam(argv[i]);
856 if (!entry)
857 DPRINTF(E_FATAL, L_GENERAL, "Bad user '%s'.\n", argv[i]);
858 uid = entry->pw_uid;
861 else
862 DPRINTF(E_FATAL, L_GENERAL, "Option -%c takes one argument.\n", argv[i][1]);
863 break;
864 break;
865 #ifdef __linux__
866 case 'S':
867 SETFLAG(SYSTEMD_MASK);
868 break;
869 #endif
870 case 'V':
871 printf("Version " MINIDLNA_VERSION "\n");
872 exit(0);
873 break;
874 default:
875 DPRINTF(E_ERROR, L_GENERAL, "Unknown option: %s\n", argv[i]);
876 runtime_vars.port = -1; // triggers help display
880 if (runtime_vars.port < 0)
882 printf("Usage:\n\t"
883 "%s [-d] [-v] [-f config_file] [-p port]\n"
884 "\t\t[-i network_interface] [-u uid_to_run_as]\n"
885 "\t\t[-t notify_interval] [-P pid_filename]\n"
886 "\t\t[-s serial] [-m model_number]\n"
887 #ifdef __linux__
888 "\t\t[-w url] [-R] [-L] [-S] [-V] [-h]\n"
889 #else
890 "\t\t[-w url] [-R] [-L] [-V] [-h]\n"
891 #endif
892 "\nNotes:\n\tNotify interval is in seconds. Default is 895 seconds.\n"
893 "\tDefault pid file is %s.\n"
894 "\tWith -d minidlna will run in debug mode (not daemonize).\n"
895 "\t-w sets the presentation url. Default is http address on port 80\n"
896 "\t-v enables verbose output\n"
897 "\t-h displays this text\n"
898 "\t-R forces a full rescan\n"
899 "\t-L do not create playlists\n"
900 #ifdef __linux__
901 "\t-S changes behaviour for systemd\n"
902 #endif
903 "\t-V print the version number\n",
904 argv[0], pidfilename);
905 return 1;
908 if (verbose_flag)
910 strcpy(log_str+65, "debug");
911 log_level = log_str;
913 else if (!log_level)
914 log_level = log_str;
916 /* Set the default log file path to NULL (stdout) */
917 path = NULL;
918 if (debug_flag)
920 pid = getpid();
921 strcpy(log_str+65, "maxdebug");
922 log_level = log_str;
924 else if (GETFLAG(SYSTEMD_MASK))
926 pid = getpid();
928 else
930 pid = process_daemonize();
931 #ifdef READYNAS
932 unlink("/ramfs/.upnp-av_scan");
933 path = "/var/log/upnp-av.log";
934 #else
935 if (access(db_path, F_OK) != 0)
936 make_dir(db_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
937 snprintf(buf, sizeof(buf), "%s/minidlna.log", log_path);
938 unlink("/var/notice/dlna");
939 path = buf;
940 #endif
942 log_init(path, log_level);
944 if (process_check_if_running(pidfilename) < 0)
946 DPRINTF(E_ERROR, L_GENERAL, SERVER_NAME " is already running. EXITING.\n");
947 return 1;
950 set_startup_time();
952 /* presentation url */
953 if (presurl)
954 strncpyt(presentationurl, presurl, PRESENTATIONURL_MAX_LEN);
955 else
956 strcpy(presentationurl, "/");
958 /* set signal handlers */
959 memset(&sa, 0, sizeof(struct sigaction));
960 sa.sa_handler = sigterm;
961 if (sigaction(SIGTERM, &sa, NULL))
962 DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGTERM");
963 if (sigaction(SIGINT, &sa, NULL))
964 DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGINT");
965 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
966 DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGPIPE");
967 if (signal(SIGHUP, &sighup) == SIG_ERR)
968 DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGHUP");
969 signal(SIGUSR1, &sigusr1);
970 sa.sa_handler = process_handle_child_termination;
971 if (sigaction(SIGCHLD, &sa, NULL))
972 DPRINTF(E_FATAL, L_GENERAL, "Failed to set %s handler. EXITING.\n", "SIGCHLD");
974 if (writepidfile(pidfilename, pid, uid) != 0)
975 pidfilename = NULL;
977 if (uid > 0)
979 struct stat st;
980 if (stat(db_path, &st) == 0 && st.st_uid != uid && chown(db_path, uid, -1) != 0)
981 DPRINTF(E_ERROR, L_GENERAL, "Unable to set db_path [%s] ownership to %d: %s\n",
982 db_path, uid, strerror(errno));
985 if (uid > 0 && setuid(uid) == -1)
986 DPRINTF(E_FATAL, L_GENERAL, "Failed to switch to uid '%d'. [%s] EXITING.\n",
987 uid, strerror(errno));
989 children = calloc(runtime_vars.max_connections, sizeof(struct child));
990 if (!children)
992 DPRINTF(E_ERROR, L_GENERAL, "Allocation failed\n");
993 return 1;
996 return 0;
999 /* === main === */
1000 /* process HTTP or SSDP requests */
1002 main(int argc, char **argv)
1004 int ret, i;
1005 int shttpl = -1;
1006 int smonitor = -1;
1007 LIST_HEAD(httplisthead, upnphttp) upnphttphead;
1008 struct upnphttp * e = 0;
1009 struct upnphttp * next;
1010 fd_set readset; /* for select() */
1011 fd_set writeset;
1012 struct timeval timeout, timeofday, lastnotifytime = {0, 0};
1013 time_t lastupdatetime = 0;
1014 int max_fd = -1;
1015 int last_changecnt = 0;
1016 pid_t scanner_pid = 0;
1017 pthread_t inotify_thread = 0;
1018 #ifdef TIVO_SUPPORT
1019 uint8_t beacon_interval = 5;
1020 int sbeacon = -1;
1021 struct sockaddr_in tivo_bcast;
1022 struct timeval lastbeacontime = {0, 0};
1023 #endif
1025 for (i = 0; i < L_MAX; i++)
1026 log_level[i] = E_WARN;
1027 init_nls();
1029 ret = init(argc, argv);
1030 if (ret != 0)
1031 return 1;
1033 DPRINTF(E_WARN, L_GENERAL, "Starting " SERVER_NAME " version " MINIDLNA_VERSION ".\n");
1034 if (sqlite3_libversion_number() < 3005001)
1036 DPRINTF(E_WARN, L_GENERAL, "SQLite library is old. Please use version 3.5.1 or newer.\n");
1039 LIST_INIT(&upnphttphead);
1041 ret = open_db(NULL);
1042 if (ret == 0)
1044 updateID = sql_get_int_field(db, "SELECT VALUE from SETTINGS where KEY = 'UPDATE_ID'");
1045 if (updateID == -1)
1046 ret = -1;
1048 check_db(db, ret, &scanner_pid);
1049 #ifdef HAVE_INOTIFY
1050 if( GETFLAG(INOTIFY_MASK) )
1052 if (!sqlite3_threadsafe() || sqlite3_libversion_number() < 3005001)
1053 DPRINTF(E_ERROR, L_GENERAL, "SQLite library is not threadsafe! "
1054 "Inotify will be disabled.\n");
1055 else if (pthread_create(&inotify_thread, NULL, start_inotify, NULL) != 0)
1056 DPRINTF(E_FATAL, L_GENERAL, "ERROR: pthread_create() failed for start_inotify. EXITING\n");
1058 #endif
1059 smonitor = OpenAndConfMonitorSocket();
1061 sssdp = OpenAndConfSSDPReceiveSocket();
1062 if (sssdp < 0)
1064 DPRINTF(E_INFO, L_GENERAL, "Failed to open socket for receiving SSDP. Trying to use MiniSSDPd\n");
1065 reload_ifaces(0); /* populate lan_addr[0].str */
1066 if (SubmitServicesToMiniSSDPD(lan_addr[0].str, runtime_vars.port) < 0)
1067 DPRINTF(E_FATAL, L_GENERAL, "Failed to connect to MiniSSDPd. EXITING");
1069 /* open socket for HTTP connections. */
1070 shttpl = OpenAndConfHTTPSocket((runtime_vars.port > 0) ? runtime_vars.port : 0);
1071 if (shttpl < 0)
1072 DPRINTF(E_FATAL, L_GENERAL, "Failed to open socket for HTTP. EXITING\n");
1074 if(runtime_vars.port <= 0)
1076 struct sockaddr_in sockinfo;
1077 socklen_t len = sizeof(struct sockaddr_in);
1078 if (getsockname(shttpl, (struct sockaddr *)&sockinfo, &len) < 0)
1080 DPRINTF(E_FATAL, L_GENERAL, "getsockname(): %s. EXITING\n", strerror(errno));
1082 runtime_vars.port = ntohs(sockinfo.sin_port);
1085 DPRINTF(E_WARN, L_GENERAL, "HTTP listening on port %d\n", runtime_vars.port);
1087 #ifdef TIVO_SUPPORT
1088 if (GETFLAG(TIVO_MASK))
1090 DPRINTF(E_WARN, L_GENERAL, "TiVo support is enabled.\n");
1091 /* Add TiVo-specific randomize function to sqlite */
1092 ret = sqlite3_create_function(db, "tivorandom", 1, SQLITE_UTF8, NULL, &TiVoRandomSeedFunc, NULL, NULL);
1093 if (ret != SQLITE_OK)
1094 DPRINTF(E_ERROR, L_TIVO, "ERROR: Failed to add sqlite randomize function for TiVo!\n");
1095 /* open socket for sending Tivo notifications */
1096 sbeacon = OpenAndConfTivoBeaconSocket();
1097 if(sbeacon < 0)
1098 DPRINTF(E_FATAL, L_GENERAL, "Failed to open sockets for sending Tivo beacon notify "
1099 "messages. EXITING\n");
1100 tivo_bcast.sin_family = AF_INET;
1101 tivo_bcast.sin_addr.s_addr = htonl(getBcastAddress());
1102 tivo_bcast.sin_port = htons(2190);
1104 #endif
1106 reload_ifaces(0);
1107 lastnotifytime.tv_sec = time(NULL) + runtime_vars.notify_interval;
1109 /* main loop */
1110 while (!quitting)
1112 /* Check if we need to send SSDP NOTIFY messages and do it if
1113 * needed */
1114 if (gettimeofday(&timeofday, 0) < 0)
1116 DPRINTF(E_ERROR, L_GENERAL, "gettimeofday(): %s\n", strerror(errno));
1117 timeout.tv_sec = runtime_vars.notify_interval;
1118 timeout.tv_usec = 0;
1120 else
1122 /* the comparison is not very precise but who cares ? */
1123 if (timeofday.tv_sec >= (lastnotifytime.tv_sec + runtime_vars.notify_interval))
1125 DPRINTF(E_DEBUG, L_SSDP, "Sending SSDP notifies\n");
1126 for (i = 0; i < n_lan_addr; i++)
1128 SendSSDPNotifies(lan_addr[i].snotify, lan_addr[i].str,
1129 runtime_vars.port, runtime_vars.notify_interval);
1131 memcpy(&lastnotifytime, &timeofday, sizeof(struct timeval));
1132 timeout.tv_sec = runtime_vars.notify_interval;
1133 timeout.tv_usec = 0;
1135 else
1137 timeout.tv_sec = lastnotifytime.tv_sec + runtime_vars.notify_interval
1138 - timeofday.tv_sec;
1139 if (timeofday.tv_usec > lastnotifytime.tv_usec)
1141 timeout.tv_usec = 1000000 + lastnotifytime.tv_usec
1142 - timeofday.tv_usec;
1143 timeout.tv_sec--;
1145 else
1146 timeout.tv_usec = lastnotifytime.tv_usec - timeofday.tv_usec;
1148 #ifdef TIVO_SUPPORT
1149 if (sbeacon >= 0)
1151 if (timeofday.tv_sec >= (lastbeacontime.tv_sec + beacon_interval))
1153 sendBeaconMessage(sbeacon, &tivo_bcast, sizeof(struct sockaddr_in), 1);
1154 memcpy(&lastbeacontime, &timeofday, sizeof(struct timeval));
1155 if (timeout.tv_sec > beacon_interval)
1157 timeout.tv_sec = beacon_interval;
1158 timeout.tv_usec = 0;
1160 /* Beacons should be sent every 5 seconds or so for the first minute,
1161 * then every minute or so thereafter. */
1162 if (beacon_interval == 5 && (timeofday.tv_sec - startup_time) > 60)
1163 beacon_interval = 60;
1165 else if (timeout.tv_sec > (lastbeacontime.tv_sec + beacon_interval + 1 - timeofday.tv_sec))
1166 timeout.tv_sec = lastbeacontime.tv_sec + beacon_interval - timeofday.tv_sec;
1168 #endif
1171 if (scanning)
1173 if (!scanner_pid || kill(scanner_pid, 0) != 0)
1175 scanning = 0;
1176 updateID++;
1180 /* select open sockets (SSDP, HTTP listen, and all HTTP soap sockets) */
1181 FD_ZERO(&readset);
1183 if (sssdp >= 0)
1185 FD_SET(sssdp, &readset);
1186 max_fd = MAX(max_fd, sssdp);
1189 if (shttpl >= 0)
1191 FD_SET(shttpl, &readset);
1192 max_fd = MAX(max_fd, shttpl);
1194 #ifdef TIVO_SUPPORT
1195 if (sbeacon >= 0)
1197 FD_SET(sbeacon, &readset);
1198 max_fd = MAX(max_fd, sbeacon);
1200 #endif
1201 if (smonitor >= 0)
1203 FD_SET(smonitor, &readset);
1204 max_fd = MAX(max_fd, smonitor);
1207 i = 0; /* active HTTP connections count */
1208 for (e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1210 if ((e->socket >= 0) && (e->state <= 2))
1212 FD_SET(e->socket, &readset);
1213 max_fd = MAX(max_fd, e->socket);
1214 i++;
1217 FD_ZERO(&writeset);
1218 upnpevents_selectfds(&readset, &writeset, &max_fd);
1220 ret = select(max_fd+1, &readset, &writeset, 0, &timeout);
1221 if (ret < 0)
1223 if(quitting) goto shutdown;
1224 if(errno == EINTR) continue;
1225 DPRINTF(E_ERROR, L_GENERAL, "select(all): %s\n", strerror(errno));
1226 DPRINTF(E_FATAL, L_GENERAL, "Failed to select open sockets. EXITING\n");
1228 upnpevents_processfds(&readset, &writeset);
1229 /* process SSDP packets */
1230 if (sssdp >= 0 && FD_ISSET(sssdp, &readset))
1232 /*DPRINTF(E_DEBUG, L_GENERAL, "Received SSDP Packet\n");*/
1233 ProcessSSDPRequest(sssdp, (unsigned short)runtime_vars.port);
1235 #ifdef TIVO_SUPPORT
1236 if (sbeacon >= 0 && FD_ISSET(sbeacon, &readset))
1238 /*DPRINTF(E_DEBUG, L_GENERAL, "Received UDP Packet\n");*/
1239 ProcessTiVoBeacon(sbeacon);
1241 #endif
1242 if (smonitor >= 0 && FD_ISSET(smonitor, &readset))
1244 ProcessMonitorEvent(smonitor);
1246 /* increment SystemUpdateID if the content database has changed,
1247 * and if there is an active HTTP connection, at most once every 2 seconds */
1248 if (i && (timeofday.tv_sec >= (lastupdatetime + 2)))
1250 if (scanning || sqlite3_total_changes(db) != last_changecnt)
1252 updateID++;
1253 last_changecnt = sqlite3_total_changes(db);
1254 upnp_event_var_change_notify(EContentDirectory);
1255 lastupdatetime = timeofday.tv_sec;
1258 /* process active HTTP connections */
1259 for (e = upnphttphead.lh_first; e != NULL; e = e->entries.le_next)
1261 if ((e->socket >= 0) && (e->state <= 2) && (FD_ISSET(e->socket, &readset)))
1262 Process_upnphttp(e);
1264 /* process incoming HTTP connections */
1265 if (shttpl >= 0 && FD_ISSET(shttpl, &readset))
1267 int shttp;
1268 socklen_t clientnamelen;
1269 struct sockaddr_in clientname;
1270 clientnamelen = sizeof(struct sockaddr_in);
1271 shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen);
1272 if (shttp<0)
1274 DPRINTF(E_ERROR, L_GENERAL, "accept(http): %s\n", strerror(errno));
1276 else
1278 struct upnphttp * tmp = 0;
1279 DPRINTF(E_DEBUG, L_GENERAL, "HTTP connection from %s:%d\n",
1280 inet_ntoa(clientname.sin_addr),
1281 ntohs(clientname.sin_port) );
1282 /*if (fcntl(shttp, F_SETFL, O_NONBLOCK) < 0) {
1283 DPRINTF(E_ERROR, L_GENERAL, "fcntl F_SETFL, O_NONBLOCK\n");
1285 /* Create a new upnphttp object and add it to
1286 * the active upnphttp object list */
1287 tmp = New_upnphttp(shttp);
1288 if (tmp)
1290 tmp->clientaddr = clientname.sin_addr;
1291 LIST_INSERT_HEAD(&upnphttphead, tmp, entries);
1293 else
1295 DPRINTF(E_ERROR, L_GENERAL, "New_upnphttp() failed\n");
1296 close(shttp);
1300 /* delete finished HTTP connections */
1301 for (e = upnphttphead.lh_first; e != NULL; e = next)
1303 next = e->entries.le_next;
1304 if(e->state >= 100)
1306 LIST_REMOVE(e, entries);
1307 Delete_upnphttp(e);
1312 shutdown:
1313 /* kill the scanner */
1314 if (scanning && scanner_pid)
1315 kill(scanner_pid, SIGKILL);
1317 /* kill other child processes */
1318 process_reap_children();
1319 free(children);
1321 /* close out open sockets */
1322 while (upnphttphead.lh_first != NULL)
1324 e = upnphttphead.lh_first;
1325 LIST_REMOVE(e, entries);
1326 Delete_upnphttp(e);
1328 if (sssdp >= 0)
1329 close(sssdp);
1330 if (shttpl >= 0)
1331 close(shttpl);
1332 #ifdef TIVO_SUPPORT
1333 if (sbeacon >= 0)
1334 close(sbeacon);
1335 #endif
1336 if (smonitor >= 0)
1337 close(smonitor);
1339 for (i = 0; i < n_lan_addr; i++)
1341 SendSSDPGoodbyes(lan_addr[i].snotify);
1342 close(lan_addr[i].snotify);
1345 if (inotify_thread)
1346 pthread_join(inotify_thread, NULL);
1348 sql_exec(db, "UPDATE SETTINGS set VALUE = '%u' where KEY = 'UPDATE_ID'", updateID);
1349 sqlite3_close(db);
1351 upnpevents_removeSubscribers();
1353 if (pidfilename && unlink(pidfilename) < 0)
1354 DPRINTF(E_ERROR, L_GENERAL, "Failed to remove pidfile %s: %s\n", pidfilename, strerror(errno));
1356 log_close();
1357 freeoptions();
1359 exit(EXIT_SUCCESS);