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