1 /*
2  * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation version 2
7  * of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18  *
19  */
20 
21 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
22 #define _XOPEN_SOURCE 600
23 #else
24 #define	tdestroy(...) do {} while (0)
25 #endif
26 
27 #define _FILE_OFFSET_BITS 64
28 #define _LARGEFILE_SOURCE 1
29 #define _LARGEFILE64_SOURCE 1
30 
31 #include <config.h>
32 
33 #ifdef HAVE_BACKTRACE
34 #include <execinfo.h>
35 #endif
36 
37 #include <argp.h>
38 #include <config.h>
39 #include <sys/endian.h>
40 #include <netinet/in.h>
41 #include <poll.h>
42 #include <pthread.h>
43 #include <search.h>
44 #include <signal.h>
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <signal.h>
49 #include <syslog.h>
50 #include <sys/socket.h>
51 #include <unistd.h>
52 
53 #include <netdb.h>
54 #include <netinet/in.h>
55 #include <netinet/tcp.h>
56 
57 #include "../../lib/libdvbv5/dvb-fe-priv.h"
58 #include "../../lib/libdvbv5/dvb-dev-priv.h"
59 #include "libdvbv5/dvb-file.h"
60 #include "libdvbv5/dvb-dev.h"
61 
62 #ifdef ENABLE_NLS
63 # define _(string) gettext(string)
64 # include <stdio.h>
65 # include <locale.h>
66 # include <langinfo.h>
67 # include <iconv.h>
68 #else
69 # define _(string) string
70 #endif
71 
72 # define N_(string) string
73 
74 /* Max number of open files */
75 #define NUM_FOPEN	1024
76 
77 /*
78  * Argument processing data and logic
79  */
80 
81 #define PROGRAM_NAME	"dvbv5-daemon"
82 
83 const char *argp_program_version = PROGRAM_NAME " version " V4L_UTILS_VERSION;
84 const char *argp_program_bug_address = "Mauro Carvalho Chehab <mchehab@kernel.org>";
85 
86 static const char doc[] = N_(
87 	"\nA DVB remote daemon using API version 5\n");
88 
89 static const struct argp_option options[] = {
90 	{"verbose",	'v',	0,		0,	N_("enables debug messages"), 0},
91 	{"port",	'p',	"5555",		0,	N_("port to listen"), 0},
92 	{"help",        '?',	0,		0,	N_("Give this help list"), -1},
93 	{"usage",	-3,	0,		0,	N_("Give a short usage message")},
94 	{"version",	'V',	0,		0,	N_("Print program version"), -1},
95 	{ 0, 0, 0, 0, 0, 0 }
96 };
97 
98 static int port = 0;
99 static int verbose = 0;
100 
parse_opt(int k,char * arg,struct argp_state * state)101 static int parse_opt(int k, char *arg, struct argp_state *state)
102 {
103 	switch (k) {
104 	case 'p':
105 		port = atoi(arg);
106 		break;
107 	case 'v':
108 		verbose	++;
109 		break;
110 	case '?':
111 		argp_state_help(state, state->out_stream,
112 				ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG
113 				| ARGP_HELP_DOC);
114 		fprintf(state->out_stream, _("\nReport bugs to %s.\n"), argp_program_bug_address);
115 		exit(0);
116 	case 'V':
117 		fprintf (state->out_stream, "%s\n", argp_program_version);
118 		exit(0);
119 	case -3:
120 		argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
121 		exit(0);
122 	default:
123 		return ARGP_ERR_UNKNOWN;
124 	}
125 	return 0;
126 }
127 
128 static struct argp argp = {
129 	.options = options,
130 	.parser = parse_opt,
131 	.doc = doc,
132 };
133 
134 /*
135  * Local log
136  *
137  * Error messages should ideally be sent to the remote end, but, if
138  * an error happens during the processing of a packet, we need to
139  * report locally, as reporting remotely may not work.
140  */
141 static const struct loglevel {
142 	const char *name;
143 	const char *color;
144 	int fd;
145 } loglevels[9] = {
146 	{N_("EMERG    "), "\033[31m", STDERR_FILENO },
147 	{N_("ALERT    "), "\033[31m", STDERR_FILENO },
148 	{N_("CRITICAL "), "\033[31m", STDERR_FILENO },
149 	{N_("ERROR    "), "\033[31m", STDERR_FILENO },
150 	{N_("WARNING  "), "\033[33m", STDOUT_FILENO },
151 	{NULL,            "\033[36m", STDOUT_FILENO }, /* NOTICE */
152 	{NULL,            NULL,       STDOUT_FILENO }, /* INFO */
153 	{N_("DEBUG    "), "\033[32m", STDOUT_FILENO },
154 	{NULL,            "\033[0m",  STDOUT_FILENO }, /* reset*/
155 };
156 #define LOG_COLOROFF 8
157 
local_log(int level,const char * fmt,...)158 void local_log(int level, const char *fmt, ...)
159 {
160 	if(level > sizeof(loglevels) / sizeof(struct loglevel) - 2) // ignore LOG_COLOROFF as well
161 		level = LOG_INFO;
162 	va_list ap;
163 	va_start(ap, fmt);
164 	FILE *out = stdout;
165 	if (STDERR_FILENO == loglevels[level].fd)
166 		out = stderr;
167 	if (loglevels[level].color && isatty(loglevels[level].fd))
168 		fputs(loglevels[level].color, out);
169 	if (loglevels[level].name)
170 		fprintf(out, "%s", _(loglevels[level].name));
171 	vfprintf(out, fmt, ap);
172 	fprintf(out, "\n");
173 	if(loglevels[level].color && isatty(loglevels[level].fd))
174 		fputs(loglevels[LOG_COLOROFF].color, out);
175 	va_end(ap);
176 }
177 
178 #define info(fmt, arg...) do {\
179 	local_log(LOG_INFO, fmt, ##arg); \
180 } while (0)
181 
182 #define warn(fmt, arg...) do {\
183 	local_log(LOG_WARNING, fmt, ##arg); \
184 } while (0)
185 
186 #define err(fmt, arg...) do {\
187 	local_log(LOG_ERR, "%s: " fmt, __FUNCTION__, ##arg); \
188 } while (0)
189 
190 #define dbg(fmt, arg...) do {\
191 	local_log(LOG_DEBUG, "%s: " fmt, __FUNCTION__, ##arg); \
192 } while (0)
193 
194 #define local_perror(msg) do {\
195 	local_log(LOG_ERR, "%s: %s: %m (%d)",  __FUNCTION__, msg, errno); \
196 } while (0)
197 
198 /*
199  * Static data used by the code
200  */
201 
202 static pthread_mutex_t msg_mutex;
203 static pthread_mutex_t dvb_read_mutex;
204 static pthread_t read_id = 0;
205 
206 struct dvb_descriptors {
207 	int uid;
208 	struct dvb_open_descriptor *open_dev;
209 };
210 
211 static struct dvb_device *dvb = NULL;
212 static void *desc_root = NULL;
213 static int dvb_fd = -1;
214 
215 static struct pollfd fds[NUM_FOPEN];
216 static nfds_t numfds = 0;
217 
218 static char output_charset[256] = "utf-8";
219 static char default_charset[256] = "iso-8859-1";
220 
stack_dump()221 void stack_dump()
222 {
223 #ifdef HAVE_BACKTRACE
224 	int i, nptrs = 0;
225 	void *buffer[10];
226 	char **strings = NULL;
227 
228 	nptrs = backtrace(buffer, sizeof(buffer));
229 
230 	if (nptrs) {
231 		strings = backtrace_symbols(buffer, nptrs);
232 		dbg("Stack:");
233 	}
234 
235 	for (i = 0; i < nptrs; i++)
236 		dbg("   %s", strings[i]);
237 
238 	free(strings);
239 #endif
240 }
241 
242 /*
243  * Open dev descriptor handling
244  */
245 
dvb_desc_compare(const void * __a,const void * __b)246 static int dvb_desc_compare(const void *__a, const void *__b)
247 {
248 	const struct dvb_descriptors *a = __a, *b = __b;
249 
250 	return (b->uid - a->uid);
251 }
252 
get_open_dev(int uid)253 static struct dvb_open_descriptor *get_open_dev(int uid)
254 {
255 	struct dvb_descriptors desc, **p;
256 
257 	if (!desc_root)
258 		return NULL;
259 
260 	desc.uid = uid;
261 	p = tfind(&desc, &desc_root, dvb_desc_compare);
262 
263 	if (!p) {
264 		err("open element not retrieved!");
265 		return NULL;
266 	}
267 
268 	return (*p)->open_dev;
269 }
270 
destroy_open_dev(int uid)271 static void destroy_open_dev(int uid)
272 {
273 	struct dvb_descriptors desc, **p;
274 
275 	desc.uid = uid;
276 	p = tdelete(&desc, &desc_root, dvb_desc_compare);
277 	if (!p)
278 		err("can't destroy opened element");
279 }
280 
free_opendevs(void * node)281 static void free_opendevs(void *node)
282 {
283 	struct dvb_descriptors *desc = node;
284 
285 	if (verbose)
286 		dbg("closing dev %p", desc, desc->open_dev);
287 
288 	dvb_dev_close(desc->open_dev);
289 	free (desc);
290 }
291 
close_all_devs(void)292 static void close_all_devs(void)
293 {
294 	dvb_fd = -1;
295 	numfds = 0;
296 	tdestroy(desc_root, free_opendevs);
297 
298 	desc_root = NULL;
299 }
300 
301 /*
302  * Signal handling logic
303  */
304 
sigterm_handler(int const sig_class)305 static void sigterm_handler(int const sig_class)
306 {
307 	info(PROGRAM_NAME" interrupted.");
308 
309 	pthread_exit(NULL);
310 
311 	close_all_devs();
312 	dvb_dev_free(dvb);
313 }
314 
start_signal_handler(void)315 static void start_signal_handler(void)
316 {
317 	struct sigaction action;
318 
319 	sigemptyset(&action.sa_mask);
320 	action.sa_flags = 0;
321 	action.sa_handler = sigterm_handler;
322 	sigaction(SIGTERM, &action, NULL);
323 }
324 
stop_signal_handler(void)325 static void stop_signal_handler(void)
326 {
327 	struct sigaction action;
328 
329 	sigemptyset(&action.sa_mask);
330 	action.sa_flags = 0;
331 	action.sa_handler = SIG_DFL;
332 	sigaction(SIGTERM, &action, NULL);
333 }
334 
335 /*
336  * Functions to send/receive messages to the client
337  */
338 
__prepare_data(char * buf,const size_t size,const char * fmt,va_list ap)339 static ssize_t __prepare_data(char *buf, const size_t size,
340 			      const char *fmt, va_list ap)
341 {
342 	char *p = buf, *endp = &buf[size], *s;
343 	int len;
344 	int32_t i32;
345 	uint64_t u64;
346 
347 	while (*fmt && *fmt != '%') fmt++;
348 	if (*fmt == '%') fmt++;
349 	while (*fmt) {
350 		switch (*fmt++) {
351 		case 's':              /* string */
352 			s = va_arg(ap, char *);
353 			if (s)
354 				len = strlen(s);
355 			else
356 				len = 0;
357 			if (p + len + 4 > endp) {
358 				dbg("buffer to short for string");
359 				stack_dump();
360 				return -1;
361 			}
362 			i32 = htobe32(len);
363 			memcpy(p, &i32, 4);
364 			p += 4;
365 			if (s)
366 				memcpy(p, s, len);
367 			p += len;
368 			break;
369 		case 'p':              /* binary data with specified length */
370 			s = va_arg(ap, char *);
371 			len = va_arg(ap, ssize_t);
372 			if (p + len + 4 > endp) {
373 				dbg("buffer to short for string");
374 				stack_dump();
375 				return -1;
376 			}
377 			i32 = htobe32(len);
378 			memcpy(p, &i32, 4);
379 			p += 4;
380 			memcpy(p, s, len);
381 			p += len;
382 			break;
383 		case 'i':              /* 32-bit int */
384 			if (p + 4 > endp) {
385 				dbg("buffer to short for int32_t");
386 				stack_dump();
387 				return -1;
388 			}
389 
390 			i32 = htobe32(va_arg(ap, int32_t));
391 			memcpy(p, &i32, 4);
392 			p += 4;
393 			break;
394 		case 'l':              /* 64-bit unsigned int */
395 			if (*fmt++ != 'u') {
396 				dbg("invalid long format character: '%c'", *fmt);
397 				stack_dump();
398 				break;
399 			}
400 			if (p + 8 > endp) {
401 				dbg("buffer to short for uint64_t");
402 				stack_dump();
403 				return -1;
404 			}
405 			u64 = htobe64(va_arg(ap, uint64_t));
406 			memcpy(p, &u64, 8);
407 			p += 8;
408 			break;
409 		default:
410 			dbg("invalid format character: '%c'", *fmt);
411 			stack_dump();
412 		}
413 		while (*fmt && *fmt != '%') fmt++;
414 		if (*fmt == '%') fmt++;
415 	}
416 	return p - buf;
417 }
418 
419 
420 static ssize_t prepare_data(char *buf, const size_t size,
421 			      const char *fmt, ...)
422 	__attribute__ (( format( printf, 3, 4 )));
423 
prepare_data(char * buf,const size_t size,const char * fmt,...)424 static ssize_t prepare_data(char *buf, const size_t size,
425 			      const char *fmt, ...)
426 {
427 	va_list ap;
428 	int ret;
429 
430 	va_start(ap, fmt);
431 	ret = __prepare_data(buf, size, fmt, ap);
432 	va_end(ap);
433 
434 	return ret;
435 }
436 
send_buf(int fd,const char * buf,size_t size)437 static int send_buf(int fd, const char *buf, size_t size)
438 {
439 	int ret;
440 	int32_t i32;
441 
442 	if (fd < 0)
443 		return ECONNRESET;
444 
445 	pthread_mutex_lock(&msg_mutex);
446 	i32 = htobe32(size);
447 	ret = send(fd, (void *)&i32, 4, 0);
448 	if (ret >= 0)
449 		ret = send(fd, buf, size, 0);
450 	pthread_mutex_unlock(&msg_mutex);
451 	if (ret < 0) {
452 		local_perror("write");
453 		if (ret == ECONNRESET)
454 			close_all_devs();
455 
456 		return errno;
457 	}
458 
459 	return ret;
460 }
461 
462 static ssize_t send_data(int fd, const char *fmt, ...)
463 	__attribute__ (( format( printf, 2, 3 )));
464 
send_data(int fd,const char * fmt,...)465 static ssize_t send_data(int fd, const char *fmt, ...)
466 {
467 	char buf[REMOTE_BUF_SIZE];
468 	va_list ap;
469 	int ret;
470 
471 	if (verbose)
472 		dbg("called %s(fd, \"%s\", ...)", __FUNCTION__, fmt);
473 
474 	va_start(ap, fmt);
475 	ret = __prepare_data(buf, sizeof(buf), fmt, ap);
476 	va_end(ap);
477 	if (ret < 0)
478 		return ret;
479 
480 	return send_buf(fd, buf, ret);
481 }
482 
483 static ssize_t scan_data(char *buf, int buf_size, const char *fmt, ...)
484 	__attribute__ (( format( scanf, 3, 4 )));
485 
scan_data(char * buf,int buf_size,const char * fmt,...)486 static ssize_t scan_data(char *buf, int buf_size, const char *fmt, ...)
487 {
488 	char *p = buf, *endp = &buf[buf_size], *s;
489 	int len;
490 	int32_t *i32;
491 	uint64_t *u64;
492 	va_list ap;
493 
494 	va_start(ap, fmt);
495 	while (*fmt && *fmt != '%') fmt++;
496 	if (*fmt == '%') fmt++;
497 	while (*fmt) {
498 		switch (*fmt++) {
499 		case 's':              /* string */
500 			s = va_arg(ap, char *);
501 			if (p + 4 > endp) {
502 				dbg("buffer to short for string length");
503 				stack_dump();
504 				return -1;
505 			}
506 			len = be32toh(*(int32_t *)p);
507 			p += 4;
508 			if (p + len > endp) {
509 				dbg("buffer to short for string");
510 				stack_dump();
511 				return -1;
512 			}
513 
514 			memcpy(s, p, len);
515 			s[len] = '\0';
516 			p += len;
517 			break;
518 		case 'i':              /* 32-bit int */
519 			if (p + 4 > endp) {
520 				dbg("buffer to short for int32_t");
521 				stack_dump();
522 				return -1;
523 			}
524 			i32 = va_arg(ap, int32_t *);
525 
526 			*i32 = be32toh(*(int32_t *)p);
527 			p += 4;
528 			break;
529 		case 'l':              /* 64-bit unsigned int */
530 			if (*fmt++ != 'u') {
531 				dbg("invalid long format character: '%c'", *fmt);
532 				stack_dump();
533 				break;
534 			}
535 			if (p + 8 > endp) {
536 				dbg("buffer to short for uint64_t");
537 				stack_dump();
538 				return -1;
539 			}
540 			u64 = va_arg(ap, uint64_t *);
541 
542 			*u64 = be32toh(*(uint64_t *)p);
543 			p += 8;
544 			break;
545 		default:
546 			dbg("invalid format character: '%c'", *fmt);
547 			stack_dump();
548 		}
549 		while (*fmt && *fmt != '%') fmt++;
550 		if (*fmt == '%') fmt++;
551 	}
552 	va_end(ap);
553 
554 	return p - buf;
555 }
556 
557 /*
558  * Remote log
559  */
dvb_remote_log(void * priv,int level,const char * fmt,...)560 void dvb_remote_log(void *priv, int level, const char *fmt, ...)
561 {
562 	int ret;
563 	char *buf;
564 
565 	va_list ap;
566 	int fd = *(int*)priv;
567 
568 	va_start(ap, fmt);
569 	ret = vasprintf(&buf, fmt, ap);
570 	if (ret <= 0) {
571 		local_perror("vasprintf");
572 		return;
573 	}
574 
575 	va_end(ap);
576 
577 	if (fd >= 0)
578 		send_data(fd, "%i%s%i%s", 0, "log", level, buf);
579 	else
580 		local_log(level, buf);
581 
582 	free(buf);
583 }
584 
dev_change_monitor(char * sysname,enum dvb_dev_change_type type,void * user_priv)585 static int dev_change_monitor(char *sysname,
586 			      enum dvb_dev_change_type type, void *user_priv)
587 {
588 	send_data(dvb_fd, "%i%s%i%s", 0, "dev_change", type, sysname);
589 
590 	return 0;
591 }
592 
593 
594 /*
595  * command handler methods
596  */
daemon_get_version(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)597 static int daemon_get_version(uint32_t seq, char *cmd, int fd,
598 			      char *buf, ssize_t size)
599 {
600 	int ret = 0;
601 
602 	return send_data(fd, "%i%s%i%s", seq, cmd, ret, argp_program_version);
603 }
604 
dev_find(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)605 static int dev_find(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
606 {
607 	int enable_monitor = 0, ret;
608 	dvb_dev_change_t handler = NULL;
609 
610 	ret = scan_data(buf, size, "%i", &enable_monitor);
611 	if (ret < 0)
612 		goto error;
613 
614 	if (enable_monitor)
615 		handler = &dev_change_monitor;
616 
617 	ret = dvb_dev_find(dvb, handler, NULL);
618 
619 error:
620 	return send_data(fd, "%i%s%i", seq, cmd, ret);
621 }
622 
dev_stop_monitor(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)623 static int dev_stop_monitor(uint32_t seq, char *cmd, int fd,
624 			    char *buf, ssize_t size)
625 {
626 	dvb_dev_stop_monitor(dvb);
627 
628 	return send_data(fd, "%i%s%i", seq, cmd, 0);
629 }
630 
dev_seek_by_adapter(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)631 static int dev_seek_by_adapter(uint32_t seq, char *cmd, int fd,
632 			       char *buf, ssize_t size)
633 {
634 	struct dvb_dev_list *dev;
635 	int adapter, num, type, ret;
636 
637 	ret = scan_data(buf, size, "%i%i%i", &adapter, &num, &type);
638 	if (ret < 0)
639 		goto error;
640 
641 	dev = dvb_dev_seek_by_adapter(dvb, adapter, num, type);
642 	if (!dev)
643 		goto error;
644 
645 	return send_data(fd, "%i%s%i%s%s%s%i%s%s%s%s%s", seq, cmd, ret,
646 			 dev->syspath, dev->path, dev->sysname, dev->dvb_type,
647 			 dev->bus_addr, dev->bus_id, dev->manufacturer,
648 			 dev->product, dev->serial);
649 error:
650 	return send_data(fd, "%i%s%i", seq, cmd, ret);
651 }
652 
dev_get_dev_info(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)653 static int dev_get_dev_info(uint32_t seq, char *cmd, int fd,
654 			       char *buf, ssize_t size)
655 {
656 	struct dvb_dev_list *dev;
657 	char sysname[REMOTE_BUF_SIZE];
658 	int ret;
659 
660 	ret = scan_data(buf, size, "%s", sysname);
661 	if (ret < 0)
662 		goto error;
663 
664 	dev = dvb_get_dev_info(dvb, sysname);
665 	if (!dev)
666 		goto error;
667 
668 	return send_data(fd, "%i%s%i%s%s%s%i%s%s%s%s%s", seq, cmd, ret,
669 			 dev->syspath, dev->path, dev->sysname, dev->dvb_type,
670 			 dev->bus_addr, dev->bus_id, dev->manufacturer,
671 			 dev->product, dev->serial);
672 error:
673 	return send_data(fd, "%i%s%i", seq, cmd, ret);
674 }
675 
read_data(void * privdata)676 static void *read_data(void *privdata)
677 {
678 	struct dvb_open_descriptor *open_dev;
679 	int timeout;
680 	int ret, read_ret = -1, fd, i;
681 	char databuf[REMOTE_BUF_SIZE];
682 	char buf[REMOTE_BUF_SIZE + 32], *p;
683 	size_t size;
684 	size_t count;
685 	struct pollfd __fds[NUM_FOPEN];
686 	nfds_t __numfds;
687 
688 	timeout = 10; /* ms */
689 	while (1) {
690 		pthread_mutex_lock(&dvb_read_mutex);
691 		if (!numfds) {
692 			pthread_mutex_unlock(&dvb_read_mutex);
693 			break;
694 		}
695 		__numfds = numfds;
696 		memcpy(__fds, fds, sizeof(fds));
697 		pthread_mutex_unlock(&dvb_read_mutex);
698 
699 		ret = poll(__fds, __numfds, timeout);
700 		if (!ret)
701 			continue;
702 		if (ret < 0) {
703 			err("poll");
704 			continue;
705 		}
706 
707 		for (i = 0; i < __numfds; i++) {
708 			if (__fds[i].revents & (POLLERR | POLLHUP | POLLNVAL))
709 				continue;
710 			if (__fds[i].revents)
711 				break;
712 		}
713 
714 		/*
715 		 * it means that one error condition happened.
716 		 * Likely the file was closed.
717 		 */
718 		if (i == __numfds)
719 			continue;
720 
721 		fd = __fds[i].fd;
722 
723 		if (!desc_root)
724 			break;
725 
726 		open_dev = get_open_dev(fd);
727 		if (!open_dev) {
728 			err("Couldn't find opened file %d", fd);
729 			continue;
730 		}
731 
732 		count = REMOTE_BUF_SIZE;
733 		read_ret = dvb_dev_read(open_dev, databuf, count);
734 		if (verbose) {
735 			if (read_ret < 0)
736 				dbg("#%d: read error: %d on %p", fd, read_ret, open_dev);
737 			else
738 				dbg("#%d: read %d bytes (count %d)", fd, read_ret, count);
739 		}
740 
741 		/* Initialize to the start of the buffer */
742 		p = buf;
743 		size = sizeof(buf);
744 
745 		ret = prepare_data(p, size, "%i%s%i%i", 0, "data_read",
746 				   read_ret, fd);
747 		if (ret < 0) {
748 			err("Failed to prepare answer to dvb_read()");
749 			break;
750 		}
751 
752 		p += ret;
753 		size -= ret;
754 
755 		if (read_ret > 0) {
756 			if (read_ret > size) {
757 				dbg("buffer to short to store read data!");
758 				read_ret = -EOVERFLOW;
759 			} else {
760 				memcpy(p, databuf, read_ret);
761 				p += read_ret;
762 			}
763 		}
764 
765 		ret = send_buf(dvb_fd, buf, p - buf);
766 		if (ret < 0) {
767 			err("Error %d sending buffer\n", ret);
768 			if (ret == ECONNRESET) {
769 				close_all_devs();
770 				break;
771 			}
772 			continue;
773 		}
774 	}
775 
776 	dbg("Finishing kthread");
777 	read_id = 0;
778 	return NULL;
779 }
780 
dev_open(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)781 static int dev_open(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
782 {
783 	struct dvb_open_descriptor *open_dev;
784 	struct dvb_dev_list *dev;
785 	struct dvb_descriptors *desc, **p;
786 	int ret, flags, uid;
787 	char sysname[REMOTE_BUF_SIZE];
788 
789 	desc = calloc(1, sizeof(*desc));
790 	if (!desc) {
791 		local_perror("calloc");
792 		ret = -ENOMEM;
793 		goto error;
794 	}
795 
796 	ret = scan_data(buf, size, "%s%i", sysname, &flags);
797 	if (ret < 0) {
798 		free(desc);
799 		goto error;
800 	}
801 
802 	/*
803 	 * Discard requests for O_NONBLOCK, as the daemon will use threads
804 	 * to handle unblocked reads.
805 	 */
806 	flags &= ~O_NONBLOCK;
807 
808 	open_dev = dvb_dev_open(dvb, sysname, flags);
809 	if (!open_dev) {
810 		ret = -errno;
811 		free(desc);
812 		goto error;
813 	}
814 
815 
816 	if (verbose)
817 		dbg("open dev handler for %s: %p with uid#%d", sysname, open_dev, open_dev->fd);
818 
819 	dev = open_dev->dev;
820 	if (dev->dvb_type == DVB_DEVICE_DEMUX ||
821 	    dev->dvb_type == DVB_DEVICE_DVR) {
822 		pthread_mutex_lock(&dvb_read_mutex);
823 		fds[numfds].fd = open_dev->fd;
824 		fds[numfds].events = POLLIN | POLLPRI;
825 		numfds++;
826 		pthread_mutex_unlock(&dvb_read_mutex);
827 	}
828 
829 	if (!read_id) {
830 		ret = pthread_create(&read_id, NULL, read_data, NULL);
831 		if (ret < 0) {
832 			local_perror("pthread_create");
833 			pthread_mutex_unlock(&msg_mutex);
834 			free(desc);
835 			return -1;
836 		}
837 	}
838 
839 	pthread_mutex_unlock(&msg_mutex);
840 	uid = open_dev->fd;
841 
842 	desc->uid = uid;
843 	desc->open_dev = open_dev;
844 
845 	/* Add element to the desc_root tree */
846 	p = tsearch(desc, &desc_root, dvb_desc_compare);
847 	if (!p) {
848 		local_perror("tsearch");
849 		uid = 0;
850 	}
851 	if (*p != desc) {
852 		err("uid %d was already opened!");
853 	}
854 
855 	pthread_mutex_unlock(&msg_mutex);
856 
857 	ret = uid;
858 error:
859 	return send_data(fd, "%i%s%i", seq, cmd, ret);
860 }
861 
dev_close(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)862 static int dev_close(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
863 {
864 	struct dvb_open_descriptor *open_dev;
865 	int uid, ret, i;
866 
867 	ret = scan_data(buf, size, "%i",  &uid);
868 	if (ret < 0)
869 		goto error;
870 
871 	open_dev = get_open_dev(uid);
872 	if (!open_dev) {
873 		err("Can't find uid to close");
874 		ret = -1;
875 		goto error;
876 	}
877 
878 	/* Delete fd from the opened array */
879 	pthread_mutex_lock(&dvb_read_mutex);
880 	for (i = 0; i < numfds; i++) {
881 		if (fds[i].fd != open_dev->fd)
882 		    continue;
883 		if (i < numfds - 1)
884 			memmove(&fds[i], &fds[i + 1],
885 				sizeof(*fds)*(numfds - i - 1));
886 		numfds--;
887 		break;
888 	}
889 	pthread_mutex_unlock(&dvb_read_mutex);
890 	if (read_id && !numfds) {
891 		pthread_cancel(read_id);
892 		read_id = 0;
893 	}
894 
895 	dvb_dev_close(open_dev);
896 	destroy_open_dev(uid);
897 
898 error:
899 	return send_data(fd, "%i%s%i", seq, cmd, ret);
900 }
901 
dev_dmx_stop(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)902 static int dev_dmx_stop(uint32_t seq, char *cmd, int fd,
903 			char *buf, ssize_t size)
904 {
905 	struct dvb_open_descriptor *open_dev;
906 	int uid, ret;
907 
908 	ret = scan_data(buf, size, "%i",  &uid);
909 	if (ret < 0)
910 		goto error;
911 
912 	open_dev = get_open_dev(uid);
913 	if (!open_dev) {
914 		ret = -1;
915 		err("Can't find uid to stop");
916 		goto error;
917 	}
918 
919 	dvb_dev_dmx_stop(open_dev);
920 
921 error:
922 	return send_data(fd, "%i%s%i", seq, cmd, ret);
923 }
924 
dev_set_bufsize(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)925 static int dev_set_bufsize(uint32_t seq, char *cmd, int fd,
926 			   char *buf, ssize_t size)
927 {
928 	struct dvb_open_descriptor *open_dev;
929 	int uid, ret, bufsize;
930 
931 	ret = scan_data(buf, size, "%i%i",  &uid, &bufsize);
932 	if (ret < 0)
933 		goto error;
934 
935 	open_dev = get_open_dev(uid);
936 	if (!open_dev) {
937 		ret = -1;
938 		err("Can't find uid to stop");
939 		goto error;
940 	}
941 
942 	dvb_dev_set_bufsize(open_dev, bufsize);
943 
944 error:
945 	return send_data(fd, "%i%s%i", seq, cmd, ret);
946 }
947 
dev_dmx_set_pesfilter(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)948 static int dev_dmx_set_pesfilter(uint32_t seq, char *cmd, int fd,
949 				 char *buf, ssize_t size)
950 {
951 	struct dvb_open_descriptor *open_dev;
952 	int uid, ret, pid, type, output, bufsize;
953 
954 	ret = scan_data(buf, size, "%i%i%i%i%i",
955 			&uid, &pid, &type, &output, &bufsize);
956 	if (ret < 0)
957 		goto error;
958 
959 	open_dev = get_open_dev(uid);
960 	if (!open_dev) {
961 		ret = -1;
962 		err("Can't find uid to set pesfilter");
963 		goto error;
964 	}
965 
966 	ret = dvb_dev_dmx_set_pesfilter(open_dev, pid, type, output, bufsize);
967 
968 error:
969 	return send_data(fd, "%i%s%i", seq, cmd, ret);
970 }
971 
dev_dmx_set_section_filter(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)972 static int dev_dmx_set_section_filter(uint32_t seq, char *cmd, int fd,
973 				      char *buf, ssize_t size)
974 {
975 	struct dvb_open_descriptor *open_dev;
976 	int uid, ret, pid, filtsize, flags;
977 	unsigned char filter[17], mask[17], mode[17];
978 
979 	ret = scan_data(buf, size, "%i%i%i%s%s%s%i",
980 			&uid, &pid, &filtsize, filter, mask, mode, &flags);
981 	if (ret < 0)
982 		goto error;
983 
984 	open_dev = get_open_dev(uid);
985 	if (!open_dev) {
986 		ret = -1;
987 		err("Can't find uid to set section filter");
988 		goto error;
989 	}
990 
991 	ret = dvb_dev_dmx_set_section_filter(open_dev, pid, filtsize, filter,
992 					     mask, mode, flags);
993 
994 error:
995 	return send_data(fd, "%i%s%i", seq, cmd, ret);
996 }
997 
dev_dmx_get_pmt_pid(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)998 static int dev_dmx_get_pmt_pid(uint32_t seq, char *cmd, int fd,
999 			       char *buf, ssize_t size)
1000 {
1001 	struct dvb_open_descriptor *open_dev;
1002 	int uid, ret, sid;
1003 
1004 	ret = scan_data(buf, size, "%i%i",  &uid, &sid);
1005 	if (ret < 0)
1006 		goto error;
1007 
1008 	open_dev = get_open_dev(uid);
1009 	if (!open_dev) {
1010 		ret = -1;
1011 		err("Can't find uid to get PMT PID");
1012 		goto error;
1013 	}
1014 
1015 	ret = dvb_dev_dmx_get_pmt_pid(open_dev, sid);
1016 
1017 error:
1018 	return send_data(fd, "%i%s%i", seq, cmd, ret);
1019 }
1020 
dev_scan(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)1021 static int dev_scan(uint32_t seq, char *cmd, int fd, char *buf, ssize_t size)
1022 {
1023 	int ret = -1;
1024 
1025 	/*
1026 	 * FIXME: There are too many stuff here! Maybe we should
1027 	 * split this into smaller per-table calls.
1028 	 */
1029 
1030 #if 0
1031 	struct dvb_open_descriptor *open_dev;
1032 	int uid;
1033 
1034 	ret = scan_data(buf, size, "%i%i",  &uid);
1035 	if (ret < 0)
1036 		goto error;
1037 
1038 	open_dev = get_open_dev(uid);
1039 	if (!open_dev) {
1040 		ret = -1;
1041 		err("Can't find uid to scan");
1042 		goto error;
1043 	}
1044 
1045 	ret = dvb_scan(foo);
1046 
1047 error:
1048 	return send_data(fd, "%i%s%i", seq, cmd, ret);
1049 #else
1050 	return send_data(fd, "%i%s%i", seq, cmd, ret);
1051 #endif
1052 }
1053 
dev_set_sys(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)1054 static int dev_set_sys(uint32_t seq, char *cmd, int fd,
1055 		       char *buf, ssize_t size)
1056 {
1057 	struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1058 	struct dvb_v5_fe_parms *p = (void *)parms;
1059 	int sys = 0, ret;
1060 
1061 	ret = scan_data(buf, size, "%i", &sys);
1062 	if (ret < 0)
1063 		goto error;
1064 
1065 	ret = __dvb_set_sys(p, sys);
1066 error:
1067 	return send_data(fd, "%i%s%i", seq, cmd, ret);
1068 }
1069 
dev_get_parms(uint32_t seq,char * cmd,int fd,char * inbuf,ssize_t insize)1070 static int dev_get_parms(uint32_t seq, char *cmd, int fd,
1071 			 char *inbuf, ssize_t insize)
1072 {
1073 	struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1074 	struct dvb_v5_fe_parms *par = (void *)parms;
1075 	struct dvb_frontend_info *info = &par->info;
1076 	int ret, i;
1077 	char buf[REMOTE_BUF_SIZE], lnb_name[80] = "", *p = buf;
1078 	size_t size = sizeof(buf);
1079 
1080 	if (verbose)
1081 		dbg("dev_get_parms called");
1082 
1083 	ret = __dvb_fe_get_parms(par);
1084 	if (ret < 0)
1085 		goto error;
1086 
1087 	/* Send first the public params */
1088 
1089 	ret = prepare_data(p, size, "%i%s%i%s%i%i%i%i%i%i%i", seq, cmd, ret,
1090 			   info->name, info->frequency_min,
1091 			   info->frequency_max, info->frequency_stepsize,
1092 			   info->frequency_tolerance, info->symbol_rate_min,
1093 			   info->symbol_rate_max, info->symbol_rate_tolerance);
1094 	if (ret < 0)
1095 		goto error;
1096 
1097 	p += ret;
1098 	size -= ret;
1099 
1100 	if (par->lnb)
1101 		strcpy(lnb_name, par->lnb->name);
1102 
1103 	ret = prepare_data(p, size, "%i%i%i%i%i%i%i%s%i%i%i%i%s%s",
1104 			   par->version, par->has_v5_stats, par->current_sys,
1105 			   par->num_systems, par->legacy_fe, par->abort,
1106 		           par->lna, lnb_name,
1107 			   par->sat_number, par->freq_bpf, par->diseqc_wait,
1108 			   par->verbose, par->default_charset,
1109 			   par->output_charset);
1110 	if (ret < 0)
1111 		goto error;
1112 
1113 	p += ret;
1114 	size -= ret;
1115 
1116 	for (i = 0; i < MAX_DELIVERY_SYSTEMS; i++) {
1117 		ret = prepare_data(p, size, "%i", par->systems[i]);
1118 		if (ret < 0)
1119 			goto error;
1120 
1121 		p += ret;
1122 		size -= ret;
1123 	}
1124 
1125 	/* Now, send the private ones - except for stats */
1126 
1127 	ret = prepare_data(p, size, "%i%i%i%i",
1128 			   parms->n_props,
1129 			   parms->country,
1130 			   parms->high_band,
1131 			   parms->freq_offset);
1132 	if (ret < 0)
1133 		goto error;
1134 
1135 	p += ret;
1136 	size -= ret;
1137 
1138 	for (i = 0; i < parms->n_props; i++) {
1139 		ret = prepare_data(p, size, "%i%i",
1140 				   parms->dvb_prop[i].cmd,
1141 				   parms->dvb_prop[i].u.data);
1142 		if (ret < 0)
1143 			goto error;
1144 
1145 		p += ret;
1146 		size -= ret;
1147 	}
1148 
1149 	strcpy(output_charset, par->output_charset);
1150 	strcpy(default_charset, par->default_charset);
1151 
1152 	return send_buf(fd, buf, p - buf);
1153 error:
1154 	return send_data(fd, "%i%s%i", seq, cmd, ret);
1155 }
1156 
dev_set_parms(uint32_t seq,char * cmd,int fd,char * buf,ssize_t size)1157 static int dev_set_parms(uint32_t seq, char *cmd, int fd,
1158 			 char *buf, ssize_t size)
1159 {
1160 	struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1161 	struct dvb_v5_fe_parms *par = (void *)parms;
1162 	int ret, i;
1163 	char *p = buf;
1164 	const char *old_lnb = "";
1165 	char new_lnb[256];
1166 
1167 	if (verbose)
1168 		dbg("dev_set_parms called");
1169 
1170 	/* first the public params that aren't read only */
1171 
1172 	/* Get current LNB name */
1173 	if (par->lnb)
1174 		old_lnb = par->lnb->name;
1175 
1176 	ret = scan_data(p, size, "%i%i%s%i%i%i%i%s%s",
1177 			&par->abort, &par->lna, new_lnb,
1178 			&par->sat_number, &par->freq_bpf, &par->diseqc_wait,
1179 			&par->verbose, default_charset, output_charset);
1180 
1181 	if (ret < 0)
1182 		goto error;
1183 
1184 	p += ret;
1185 	size -= ret;
1186 
1187 	/* Now, the private ones */
1188 
1189 	ret = scan_data(p, size, "%i", &i);
1190 	if (ret < 0)
1191 		goto error;
1192 	parms->country = i;
1193 
1194 	p += ret;
1195 	size -= ret;
1196 
1197 	for (i = 0; i < parms->n_props; i++) {
1198 		ret = scan_data(p, size, "%i%i",
1199 				&parms->dvb_prop[i].cmd,
1200 				&parms->dvb_prop[i].u.data);
1201 		if (ret < 0)
1202 			goto error;
1203 
1204 		p += ret;
1205 		size -= ret;
1206 	}
1207 
1208 	if (!*new_lnb) {
1209 		par->lnb = NULL;
1210 	} else if (strcmp(old_lnb, new_lnb)) {
1211 		int lnb = dvb_sat_search_lnb(new_lnb);
1212 
1213 		if (lnb < 0) {
1214 			dvb_logerr("Invalid lnb: %s", new_lnb);
1215 			ret = -1;
1216 			goto error;
1217 		}
1218 
1219 		par->lnb = dvb_sat_get_lnb(lnb);
1220 	}
1221 
1222 	par->output_charset = output_charset;
1223 	par->default_charset = default_charset;
1224 
1225 	ret = __dvb_fe_set_parms(par);
1226 
1227 error:
1228 	return send_data(fd, "%i%s%i", seq, cmd, ret);
1229 }
1230 
dev_get_stats(uint32_t seq,char * cmd,int fd,char * inbuf,ssize_t insize)1231 static int dev_get_stats(uint32_t seq, char *cmd, int fd,
1232 			 char *inbuf, ssize_t insize)
1233 {
1234 	struct dvb_v5_fe_parms_priv *parms = (void *)dvb->fe_parms;
1235 	struct dvb_v5_stats *st = &parms->stats;
1236 	struct dvb_v5_fe_parms *par = (void *)parms;
1237 	int ret, i;
1238 	char buf[REMOTE_BUF_SIZE], *p = buf;
1239 	size_t size = sizeof(buf);
1240 
1241 	if (verbose)
1242 		dbg("dev_get_stats called");
1243 
1244 	ret = __dvb_fe_get_stats(par);
1245 	if (ret < 0)
1246 		goto error;
1247 
1248 	ret = prepare_data(p, size, "%i%s%i%i", seq, cmd, ret, st->prev_status);
1249 	if (ret < 0)
1250 		goto error;
1251 
1252 	p += ret;
1253 	size -= ret;
1254 
1255 	for (i = 0; i < DTV_NUM_STATS_PROPS; i++) {
1256 		ret = prepare_data(p, size, "%i%i",
1257 				   st->prop[i].cmd,
1258 				   st->prop[i].u.data);
1259 		if (ret < 0)
1260 			goto error;
1261 
1262 		p += ret;
1263 		size -= ret;
1264 	}
1265 	for (i = 0; i < MAX_DTV_STATS; i++) {
1266 		struct dvb_v5_counters *prev = st->prev;
1267 		struct dvb_v5_counters *cur = st->cur;
1268 
1269 		ret = prepare_data(p, size, "%i%i%i",
1270 				   st->has_post_ber[i],
1271 				   st->has_pre_ber[i],
1272 				   st->has_per[i]);
1273 		if (ret < 0)
1274 			goto error;
1275 
1276 		p += ret;
1277 		size -= ret;
1278 
1279 #pragma GCC diagnostic ignored "-Wformat"
1280 		ret = prepare_data(p, size,
1281 				   "%lu%lu%lu%lu%lu%lu%lu%lu%lu%lu%lu%lu",
1282 				   prev->pre_bit_count,
1283 				   prev->pre_bit_error,
1284 				   prev->post_bit_count,
1285 				   prev->post_bit_error,
1286 				   prev->block_count,
1287 				   prev->block_error,
1288 				   cur->pre_bit_count,
1289 				   cur->pre_bit_error,
1290 				   cur->post_bit_count,
1291 				   cur->post_bit_error,
1292 				   cur->block_count,
1293 				   cur->block_error);
1294 #pragma GCC diagnostic pop
1295 		if (ret < 0)
1296 			goto error;
1297 
1298 		p += ret;
1299 		size -= ret;
1300 	}
1301 
1302 	return send_buf(fd, buf, p - buf);
1303 error:
1304 	return send_data(fd, "%i%s%i", seq, cmd, ret);
1305 }
1306 
1307 /*
1308  * Structure with all methods with RPC calls
1309  */
1310 
1311 typedef int (*method_handler) (uint32_t seq, char *cmd, int fd,
1312 			       char *buf, ssize_t size);
1313 
1314 struct method_types {
1315 	char *name;
1316 	method_handler handler;
1317 	int locks_dvb;
1318 };
1319 
1320 static const struct method_types methods[] = {
1321 	{"daemon_get_version", &daemon_get_version, 1},
1322 	{"dev_find", &dev_find, 0},
1323 	{"dev_stop_monitor", &dev_stop_monitor, 0},
1324 	{"dev_seek_by_adapter", &dev_seek_by_adapter, 0},
1325 	{"dev_get_dev_info", &dev_get_dev_info, 0},
1326 	{"dev_open", &dev_open, 0},
1327 	{"dev_close", &dev_close, 0},
1328 	{"dev_dmx_stop", &dev_dmx_stop, 0},
1329 	{"dev_set_bufsize", &dev_set_bufsize, 0},
1330 	{"dev_dmx_set_pesfilter", &dev_dmx_set_pesfilter, 0},
1331 	{"dev_dmx_set_section_filter", &dev_dmx_set_section_filter, 0},
1332 	{"dev_dmx_get_pmt_pid", &dev_dmx_get_pmt_pid, 0},
1333 
1334 	{"dev_scan", &dev_scan, 0},
1335 
1336 	{"dev_set_sys", &dev_set_sys, 0},
1337 	{"fe_get_parms", &dev_get_parms, 0},
1338 	{"fe_set_parms", &dev_set_parms, 0},
1339 	{"fe_get_stats", &dev_get_stats, 0},
1340 
1341 	{}
1342 };
1343 
start_server(void * fd_pointer)1344 static void *start_server(void *fd_pointer)
1345 {
1346 	const struct method_types *method;
1347 	int fd = *(int *)fd_pointer, ret, flag = 1;
1348 	char buf[REMOTE_BUF_SIZE + 8], cmd[80], *p;
1349 	ssize_t size;
1350 	uint32_t seq;
1351 	int bufsize;
1352 
1353 	if (verbose)
1354 		dbg("Opening socket %d", fd);
1355 
1356 	/* Set a large buffer for read() to work better */
1357 	bufsize = REMOTE_BUF_SIZE;
1358 	setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
1359 		   (void *)&bufsize, (int)sizeof(bufsize));
1360 
1361 	/* Disable Naggle algorithm, as we want errors to be sent ASAP */
1362 	setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
1363 
1364 	/* Command dispatcher */
1365 	do {
1366 		size = recv(fd, buf, 4, MSG_WAITALL);
1367 		if (size <= 0)
1368 			break;
1369 		size = (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16 |
1370 		       (uint32_t)buf[2] << 8 | (uint32_t)buf[3];
1371 		size = recv(fd, buf, size, MSG_WAITALL);
1372 		if (size <= 0)
1373 			break;
1374 
1375 		ret = scan_data(buf, size, "%i%s",  &seq, cmd);
1376 		if (ret < 0) {
1377 			if (verbose)
1378 				dbg("message too short: %d", size);
1379 			send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1380 				  "msg too short");
1381 			continue;
1382 		}
1383 
1384 		p = buf + ret;
1385 		size -= ret;
1386 
1387 		if (verbose)
1388 			dbg("received command: %i '%s'", seq, cmd);
1389 
1390 		if (size > buf + sizeof(buf) - p) {
1391 			if (verbose)
1392 				dbg("data length too big: %d", size);
1393 			send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1394 				  "data length too big");
1395 			continue;
1396 		}
1397 
1398 		method = methods;
1399 		while (method->name) {
1400 			if (!strcmp(cmd, method->name)) {
1401 				if (dvb_fd > 0 || method->locks_dvb) {
1402 					ret = method->handler(seq, cmd,
1403 							      fd, p, size);
1404 					if (ret < 0)
1405 						break;
1406 					if (method->locks_dvb)
1407 						dvb_fd = fd;
1408 					break;
1409 				}
1410 				send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1411 					  "daemon busy");
1412 				break;
1413 			}
1414 			method++;
1415 		}
1416 		if (!method->name) {
1417 			if (verbose)
1418 				dbg("invalid command: %s", cmd);
1419 			send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
1420 				  "invalid command");
1421 		}
1422 	} while (1);
1423 
1424 	if (verbose)
1425 		dbg("Closing socket %d", fd);
1426 
1427 	close(fd);
1428 	if (read_id) {
1429 		pthread_cancel(read_id);
1430 		read_id = 0;
1431 	}
1432 	if (dvb_fd > 0)
1433 		close_all_devs();
1434 
1435 	return NULL;
1436 }
1437 
1438 /*
1439  * main program
1440  */
1441 
main(int argc,char * argv[])1442 int main(int argc, char *argv[])
1443 {
1444 	int ret;
1445 	int sockfd;
1446 	socklen_t addrlen;
1447 	struct sockaddr_in serv_addr, cli_addr;
1448 
1449 #ifdef ENABLE_NLS
1450 	setlocale (LC_ALL, "");
1451 	bindtextdomain (PACKAGE, LOCALEDIR);
1452 	textdomain (PACKAGE);
1453 #endif
1454 
1455 	if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, 0, 0)) {
1456 		argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
1457 		return -1;
1458 	}
1459 
1460 	if (!port) {
1461 		argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
1462 		return -1;
1463 	}
1464 
1465 	/* Allocate DVB structure and start seek for devices */
1466 	dvb = dvb_dev_alloc();
1467 	if (!dvb) {
1468 		err("Can't allocate DVB data\n");
1469 		return -1;
1470 	}
1471 
1472 	dvb_dev_find(dvb, 0, NULL);
1473 
1474 	/* Create a socket */
1475 	sockfd = socket(AF_INET, SOCK_STREAM, 0);
1476 	if (sockfd < 0) {
1477 		local_perror("socket");
1478 		goto error;
1479 	}
1480 
1481 	/* Initialize listen address struct */
1482 	memset((char *) &serv_addr, 0, sizeof(serv_addr));
1483 	serv_addr.sin_family = AF_INET;
1484 	serv_addr.sin_addr.s_addr = INADDR_ANY;
1485 	serv_addr.sin_port = htons(port);
1486 
1487 	/* Bind to the address */
1488 	ret = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
1489 	if (ret < 0) {
1490 		local_perror("bind");
1491 		goto error;
1492 	}
1493 
1494 	/* FIXME: should allow the caller to set the verbosity */
1495 	dvb_dev_set_logpriv(dvb, 1, dvb_remote_log, &dvb_fd);
1496 
1497 	/* Listen up to 5 connections */
1498 	listen(sockfd, 5);
1499 	addrlen = sizeof(cli_addr);
1500 
1501 	start_signal_handler();
1502 	pthread_mutex_init(&msg_mutex, NULL);
1503 	pthread_mutex_init(&dvb_read_mutex, NULL);
1504 
1505 	/* Accept actual connection from the client */
1506 
1507 	warn("Support for Digital TV remote access is still highly experimental.\n"
1508 	     "\nKnown issues:\n"
1509 	     "  - Abort needed to be implemented in a proper way;\n"
1510 	     "  - Need to make more stuff opaque, as touching on fields at the local\n"
1511 	     "    end is not automatically reflected remotely;\n"
1512 	     "  - The libdvbv5 API support is incomplete: it misses satellite, scan\n"
1513 	     "    and other functions;\n\n");
1514 
1515 	info(PROGRAM_NAME" started.");
1516 
1517 	while (1) {
1518 		int fd;
1519 		pthread_t id;
1520 
1521 		if (verbose)
1522 			dbg("waiting for connections");
1523 		fd = accept(sockfd, (struct sockaddr *)&cli_addr, &addrlen);
1524 		if (fd < 0) {
1525 			local_perror("accept");
1526 			break;
1527 		}
1528 
1529 		if (verbose)
1530 			dbg("accepted connection %d", fd);
1531 		ret = pthread_create(&id, NULL, start_server, (void *)&fd);
1532 		if (ret < 0) {
1533 			local_perror("pthread_create");
1534 			break;
1535 		}
1536 	}
1537 
1538 	/* Just in case we add some way for the remote part to stop the daemon */
1539 	stop_signal_handler();
1540 
1541 error:
1542 	info(PROGRAM_NAME" stopped.");
1543 
1544 	pthread_exit(NULL);
1545 
1546 	if (dvb)
1547 		dvb_dev_free(dvb);
1548 
1549 	return -1;
1550 }
1551