⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lircd.c

📁 很少见的linux下的红外口的工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/*      $Id: lircd.c,v 5.46 2002/09/21 15:25:28 lirc Exp $      *//**************************************************************************** ** lircd.c ***************************************************************** **************************************************************************** * * lircd - LIRC Decoder Daemon *  * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de> * Copyright (C) 1998,99 Christoph Bartelmus <lirc@bartelmus.de> * *  ======= *  HISTORY *  ======= * * 0.1:  03/27/96  decode SONY infra-red signals *                 create mousesystems mouse signals on pipe /dev/lircm *       04/07/96  send ir-codes to clients via socket (see irpty) *       05/16/96  now using ir_remotes for decoding *                 much easier now to describe new remotes * * 0.5:  09/02/98 finished (nearly) complete rewrite (Christoph) * */#ifdef HAVE_CONFIG_H# include <config.h>#endif/* disable daemonise if maintainer mode SIM_REC / SIM_SEND defined */#if defined(SIM_REC) || defined (SIM_SEND)# undef DAEMONIZE#endif#define _GNU_SOURCE#define _BSD_SOURCE#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <signal.h>#include <unistd.h>#include <time.h>#include <getopt.h>#include <sys/time.h>#include <sys/socket.h>#include <sys/un.h>#include <netinet/in.h>#include <netdb.h>#include <arpa/inet.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <limits.h>#include <fcntl.h>#include <sys/file.h>#ifndef timersub#define timersub(a, b, result)                                                \  do {                                                                        \    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \    if ((result)->tv_usec < 0) {                                              \      --(result)->tv_sec;                                                     \      (result)->tv_usec += 1000000;                                           \    }                                                                         \  } while (0)#endif#include "lircd.h"#include "ir_remote.h"#include "config_file.h"#include "hardware.h"#include "hw-types.h"struct ir_remote *remotes;struct ir_remote *free_remotes=NULL;extern struct ir_remote *decoding;extern struct ir_remote *last_remote;extern struct ir_remote *repeat_remote;extern struct ir_ncode *repeat_code;static int repeat_fd=-1;static char *repeat_message=NULL;extern struct hardware hw;char *progname="lircd " VERSION;char *configfile=LIRCDCFGFILE;char *logfile=LOGFILE;FILE *pidfile;struct protocol_directive directives[] ={	{"LIST",list},	{"SEND_ONCE",send_once},	{"SEND_START",send_start},	{"SEND_STOP",send_stop},	{"VERSION",version},	{NULL,NULL}	/*	{"DEBUG",debug},	{"DEBUG_LEVEL",debug_level},	*/};enum protocol_string_num {	P_BEGIN=0,	P_DATA,	P_END,	P_ERROR,	P_SUCCESS,	P_SIGHUP};char *protocol_string[] = {	"BEGIN\n",	"DATA\n",	"END\n",	"ERROR\n",	"SUCCESS\n",	"SIGHUP\n"};#ifndef USE_SYSLOG#define HOSTNAME_LEN 128char hostname[HOSTNAME_LEN+1];FILE *lf=NULL;#endif/* fixme: */#define MAX_PEERS	100int sockfd, sockinet;int clis[FD_SETSIZE-5-MAX_PEERS]; /* substract one for lirc, sockfd, sockinet, logfile, pidfile */#define CT_LOCAL  1#define CT_REMOTE 2int cli_type[FD_SETSIZE-5-MAX_PEERS];int clin=0;int listen_tcpip=0;unsigned short int port=LIRC_INET_PORT;struct	peer_connection *peers[MAX_PEERS];int	peern = 0;int debug=0;int daemonized=0;static sig_atomic_t term=0,hup=0,alrm=0;static int termsig;inline int max(int a,int b){	return(a>b ? a:b);}/* cut'n'paste from fileutils-3.16: */#define isodigit(c) ((c) >= '0' && (c) <= '7')/* Return a positive integer containing the value of the ASCII   octal number S.  If S is not an octal number, return -1.  */static intoatoi (s)     char *s;{  register int i;  if (*s == 0)    return -1;  for (i = 0; isodigit (*s); ++s)    i = i * 8 + *s - '0';  if (*s)    return -1;  return i;}/* A safer write(), since sockets might not write all but only some of the   bytes requested */inline int write_socket(int fd, char *buf, int len){	int done,todo=len;	while(todo)	{		done=write(fd,buf,todo);		if(done<=0) return(done);		buf+=done;		todo-=done;	}	return(len);}inline int write_socket_len(int fd, char *buf){	int len;	len=strlen(buf);	if(write_socket(fd,buf,len)<len) return(0);	return(1);}inline int read_timeout(int fd,char *buf,int len,int timeout){	fd_set fds;	struct timeval tv;	int ret,n;		FD_ZERO(&fds);	FD_SET(fd,&fds);	tv.tv_sec=timeout;	tv.tv_usec=0;		/* CAVEAT: (from libc documentation)     Any signal will cause `select' to return immediately.  So if your     program uses signals, you can't rely on `select' to keep waiting     for the full time specified.  If you want to be sure of waiting     for a particular amount of time, you must check for `EINTR' and     repeat the `select' with a newly calculated timeout based on the     current time.  See the example below.     Obviously the timeout is not recalculated in the example because     this is done automatically on Linux systems...	*/     	do	{		ret=select(fd+1,&fds,NULL,NULL,&tv);	}	while(ret==-1 && errno==EINTR);	if(ret==-1)	{		logprintf(LOG_ERR,"select() failed");		logperror(LOG_ERR,NULL);		return(-1);	}	else if(ret==0) return(0); /* timeout */	n=read(fd,buf,len);	if(n==-1)	{		logprintf(LOG_ERR,"read() failed");		logperror(LOG_ERR,NULL);		return(-1);	}	return(n);}void sigterm(int sig){	/* all signals are blocked now */	if(term) return;	term=1;	termsig=sig;}void dosigterm(int sig){	int i;		signal(SIGALRM,SIG_IGN);		if(free_remotes!=NULL)	{		free_config(free_remotes);	}	free_config(remotes);	logprintf(LOG_NOTICE,"caught signal");	for (i=0; i<clin; i++)	{		shutdown(clis[i],2);		close(clis[i]);	};	shutdown(sockfd,2);	close(sockfd);	if(listen_tcpip)	{		shutdown(sockinet,2);		close(sockinet);	}	fclose(pidfile);	(void) unlink(PIDFILE);	if(clin>0 && hw.deinit_func) hw.deinit_func();#ifdef USE_SYSLOG	closelog();#else	if(lf) fclose(lf);#endif	signal(sig,SIG_DFL);	raise(sig);}void sighup(int sig){	hup=1;}void dosighup(int sig){#ifndef USE_SYSLOG	struct stat s;#endif	int i;	/* reopen logfile first */#ifdef USE_SYSLOG	/* we don't need to do anyting as this is syslogd's task */#else	logprintf(LOG_INFO,"closing logfile");	if(-1==fstat(fileno(lf),&s))			{		dosigterm(SIGTERM); /* shouldn't ever happen */	}	fclose(lf);	lf=fopen(logfile,"a");	if(lf==NULL)	{		/* can't print any error messagees */		dosigterm(SIGTERM);	}	logprintf(LOG_INFO,"reopened logfile");	if(-1==fchmod(fileno(lf),s.st_mode))	{		logprintf(LOG_WARNING,"could not set file permissions");		logperror(0,NULL);	}#endif	config();		for (i=0; i<clin; i++)	{		if(!(write_socket_len(clis[i],protocol_string[P_BEGIN]) &&		     write_socket_len(clis[i],protocol_string[P_SIGHUP]) &&		     write_socket_len(clis[i],protocol_string[P_END])))		{			remove_client(clis[i]);			i--;		}	}      /* restart all connection timers */      for (i=0; i<peern; i++)      {              if (peers[i]->socket == -1)              {                      gettimeofday(&peers[i]->reconnect, NULL);                      peers[i]->connection_failure = 0;              }      }}void config(void){	FILE *fd;	struct ir_remote *config_remotes;		if(free_remotes!=NULL)	{		logprintf(LOG_ERR,"cannot read config file");		logprintf(LOG_ERR,"old config is still in use");		return;	}	fd=fopen(configfile,"r");	if(fd==NULL)	{		logprintf(LOG_ERR,"could not open config file '%s'",			  configfile);		logperror(LOG_ERR,NULL);		return;	}	config_remotes=read_config(fd);	fclose(fd);	if(config_remotes==(void *) -1)	{		logprintf(LOG_ERR,"reading of config file failed");	}	else	{		LOGPRINTF(1,"config file read");		if(config_remotes==NULL)		{			logprintf(LOG_WARNING,"config file contains no "				  "valid remote control definition");		}		/* I cannot free the data structure		   as they could still be in use */		free_remotes=remotes;		remotes=config_remotes;		if(hw.config_func) (void) hw.config_func(remotes);	}}void nolinger(int sock){	static struct linger  linger = {0, 0};	int lsize  = sizeof(struct linger);	setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, lsize);}void remove_client(int fd){	int i;	for(i=0;i<clin;i++)	{		if(clis[i]==fd)		{			shutdown(clis[i],2);			close(clis[i]);			logprintf(LOG_INFO,"removed client");						clin--;			if(clin==0 &&			   repeat_remote==NULL &&			   hw.deinit_func)			{				hw.deinit_func();			}			for(;i<clin;i++)			{				clis[i]=clis[i+1];			}			return;		}	}	LOGPRINTF(1,"internal error in remove_client: no such fd");}void add_client(int sock){	int fd;	int clilen;	struct sockaddr client_addr;	int flags;	clilen=sizeof(client_addr);	fd=accept(sock,(struct sockaddr *)&client_addr,&clilen);	if(fd==-1) 	{		logprintf(LOG_ERR,"accept() failed for new client");		logperror(LOG_ERR,NULL);		dosigterm(SIGTERM);	};	if(fd>=FD_SETSIZE)	{		logprintf(LOG_ERR,"connection rejected");		shutdown(fd,2);		close(fd);		return;	}	nolinger(fd);	flags=fcntl(fd,F_GETFL,0);	if(flags!=-1)	{		fcntl(fd,F_SETFL,flags|O_NONBLOCK);	}	if(client_addr.sa_family==AF_UNIX)	{		cli_type[clin]=CT_LOCAL;		logprintf(LOG_NOTICE,"accepted new client on %s",LIRCD);	}	else if(client_addr.sa_family==AF_INET)	{		cli_type[clin]=CT_REMOTE;		logprintf(LOG_NOTICE,"accepted new client from %s",			  inet_ntoa(((struct sockaddr_in *)&client_addr)->sin_addr));	}	else	{		cli_type[clin]=0; /* what? */	}	clis[clin++]=fd;	if(clin==1 && repeat_remote==NULL)	{		if(hw.init_func)		{			if(!hw.init_func())			{				shutdown(clis[0],2);				close(clis[0]);				clin=0;				dosigterm(SIGTERM);			}		}	}}int add_peer_connection(char *server){	char *sep;	struct servent *service;		if(peern<MAX_PEERS)	{		peers[peern]=malloc(sizeof(struct peer_connection));		if(peers[peern]!=NULL)		{			gettimeofday(&peers[peern]->reconnect,NULL);			peers[peern]->connection_failure = 0;			sep=strchr(server,':');			if(sep!=NULL)			{				*sep=0;sep++;				peers[peern]->host=strdup(server);				service=getservbyname(sep,"tcp");				if(service)				{					peers[peern]->port=						ntohs(service->s_port);				}				else				{					long p;					char *endptr;									p=strtol(sep,&endptr,10);					if(!*sep || *endptr ||					   p<1 || p>USHRT_MAX)					{						fprintf(stderr,							"%s: bad port number \"%s\"\n",							progname,sep);						return(0);					}										peers[peern]->port=						(unsigned short int) p;				}			}			else			{				peers[peern]->host=strdup(server);				peers[peern]->port=LIRC_INET_PORT;			}			if(peers[peern]->host==NULL)			{				fprintf(stderr, "%s: out of memory\n",progname);			}		}		else		{			fprintf(stderr, "%s: out of memory\n",progname);			return(0);		}		peers[peern]->socket=-1;		peern++;		return(1);	}	else	{		fprintf(stderr,"%s: too many client connections\n",			progname);	}	return(0);}void connect_to_peers(){	int	i;	struct	hostent *host;	struct	sockaddr_in	addr;	struct timeval now;	int enable=1;		gettimeofday(&now,NULL);	for(i=0;i<peern;i++)	{		if(peers[i]->socket!=-1)			continue;		/* some timercmp() definitions don't work with <= */		if(timercmp(&peers[i]->reconnect,&now,<))		{			peers[i]->socket=socket(AF_INET, SOCK_STREAM,0);			host=gethostbyname(peers[i]->host);			if(host==NULL)			{				logprintf(LOG_ERR,"name lookup failure "					  "connecting to %s",peers[i]->host);				peers[i]->connection_failure++;				gettimeofday(&peers[i]->reconnect,NULL);				peers[i]->reconnect.tv_sec+=					5*peers[i]->connection_failure;				close(peers[i]->socket);				peers[i]->socket=-1;				continue;			}						(void) setsockopt(peers[i]->socket,SOL_SOCKET,					  SO_KEEPALIVE,&enable,sizeof(enable));						addr.sin_family=host->h_addrtype;;			addr.sin_addr=*((struct in_addr *)host->h_addr);			addr.sin_port=htons(peers[i]->port);			if(connect(peers[i]->socket,(struct sockaddr *) &addr,				   sizeof(addr))==-1)			{				logprintf(LOG_ERR, "failure connecting to %s",					  peers[i]->host);				logperror(LOG_ERR, NULL);				peers[i]->connection_failure++;				gettimeofday(&peers[i]->reconnect,NULL);				peers[i]->reconnect.tv_sec+=					5*peers[i]->connection_failure;				close(peers[i]->socket);				peers[i]->socket=-1;				continue;			}			logprintf(LOG_NOTICE, "connected to %s",				  peers[i]->host);			peers[i]->connection_failure=0;		}	}}int get_peer_message(struct peer_connection *peer){	int length;	char buffer[PACKET_SIZE+1];	char *end;	int	i;	length=read_timeout(peer->socket,buffer,PACKET_SIZE,0);	if(length)	{		buffer[length]=0;		end=strchr(buffer,'\n');		if(end==NULL)		{			logprintf(LOG_ERR,"bad send packet: \"%s\"",buffer);			/* remove clients that behave badly */			return(0);		}		end++;	/* include the \n */		end[0]=0;		LOGPRINTF(1,"received peer message: \"%s\"",buffer);		for(i=0;i<clin;i++)		{			/* don't relay messages to remote clients */			if(cli_type[i]==CT_REMOTE)				continue;			LOGPRINTF(1,"writing to client %d",i);			if(write_socket(clis[i],buffer,length)<length)			{				remove_client(clis[i]);				i--;			}			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -