📄 lircd.c
字号:
int send_stop(int fd,char *message,char *arguments){ struct ir_remote *remote; struct ir_ncode *code; struct itimerval repeat_timer; if(parse_rc(fd,message,arguments,&remote,&code,NULL,2)==0) return(0); if(remote==NULL || code==NULL) return(1); if(repeat_remote && repeat_code && strcasecmp(remote->name,repeat_remote->name)==0 && strcasecmp(code->name,repeat_code->name)==0) { int done; done=REPEAT_MAX-remote->repeat_countdown; if(done<remote->min_repeat) { /* we still have some repeats to do */ remote->repeat_countdown=remote->min_repeat-done; return(send_success(fd,message)); } repeat_timer.it_value.tv_sec=0; repeat_timer.it_value.tv_usec=0; repeat_timer.it_interval.tv_sec=0; repeat_timer.it_interval.tv_usec=0; setitimer(ITIMER_REAL,&repeat_timer,NULL); repeat_remote->toggle_mask_state=0; repeat_remote=NULL; repeat_code=NULL; /* clin!=0, so we don't have to deinit hardware */ alrm=0; return(send_success(fd,message)); } else { return(send_error(fd,message,"not repeating\n")); }}int version(int fd,char *message,char *arguments){ char buffer[PACKET_SIZE+1]; if(arguments!=NULL) { return(send_error(fd,message,"bad send packet\n")); } sprintf(buffer,"1\n%s\n",VERSION); if(!(write_socket_len(fd,protocol_string[P_BEGIN]) && write_socket_len(fd,message) && write_socket_len(fd,protocol_string[P_SUCCESS]) && write_socket_len(fd,protocol_string[P_DATA]) && write_socket_len(fd,buffer) && write_socket_len(fd,protocol_string[P_END]))) return(0); return(1);}int get_command(int fd){ int length; char buffer[PACKET_SIZE+1],backup[PACKET_SIZE+1]; char *end; int packet_length,i; char *directive; length=read_timeout(fd,buffer,PACKET_SIZE,0); packet_length=0; while(length>packet_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[0]=0; LOGPRINTF(1,"received command: \"%s\"",buffer); packet_length=strlen(buffer)+1; strcpy(backup,buffer);strcat(backup,"\n"); directive=strtok(buffer,WHITE_SPACE); if(directive==NULL) { if(!send_error(fd,backup,"bad send packet\n")) return(0); goto skip; } for(i=0;directives[i].name!=NULL;i++) { if(strcasecmp(directive,directives[i].name)==0) { if(!directives[i]. function(fd,backup,strtok(NULL,""))) return(0); goto skip; } } if(!send_error(fd,backup,"unknown directive: \"%s\"\n", directive)) return(0); skip: if(length>packet_length) { int new_length; memmove(buffer,buffer+packet_length, length-packet_length+1); if(strchr(buffer,'\n')==NULL) { new_length=read_timeout(fd,buffer+length- packet_length, PACKET_SIZE- (length- packet_length),5); if(new_length>0) { length=length-packet_length+new_length; } else { length=new_length; } } else { length-=packet_length; } packet_length=0; } } if(length==0) /* EOF: connection closed by client */ { return(0); } return(1);}void free_old_remotes(){ struct ir_remote *scan_remotes,*found; struct ir_ncode *code; if(last_remote!=NULL) { scan_remotes=free_remotes; while(scan_remotes!=NULL) { if(last_remote==scan_remotes) { found=get_ir_remote(remotes,last_remote->name); if(found!=NULL) { code=get_ir_code(found,last_remote->last_code->name); if(code!=NULL) { found->reps=last_remote->reps; found->repeat_state=last_remote->repeat_state; found->remaining_gap=last_remote->remaining_gap; last_remote=found; last_remote->last_code=code; } } break; } scan_remotes=scan_remotes->next; } if(scan_remotes==NULL) last_remote=NULL; } /* check if last config is still needed */ found=NULL; if(repeat_remote!=NULL) { scan_remotes=free_remotes; while(scan_remotes!=NULL) { if(repeat_remote==scan_remotes) { found=repeat_remote; break; } scan_remotes=scan_remotes->next; } if(found!=NULL) { found=get_ir_remote(remotes,repeat_remote->name); if(found!=NULL) { code=get_ir_code(found,repeat_code->name); if(code!=NULL) { struct itimerval repeat_timer; repeat_timer.it_value.tv_sec=0; repeat_timer.it_value.tv_usec=0; repeat_timer.it_interval.tv_sec=0; repeat_timer.it_interval.tv_usec=0; found->last_code=code; found->last_send=repeat_remote->last_send; found->repeat_state=repeat_remote->repeat_state; found->remaining_gap=repeat_remote->remaining_gap; setitimer(ITIMER_REAL,&repeat_timer,&repeat_timer); /* "atomic" (shouldn't be necessary any more) */ repeat_remote=found; repeat_code=code; /* end "atomic" */ setitimer(ITIMER_REAL,&repeat_timer,NULL); found=NULL; } } else { found=repeat_remote; } } } if(found==NULL && decoding!=free_remotes) { free_config(free_remotes); free_remotes=NULL; } else { LOGPRINTF(1,"free_remotes still in use"); }}int waitfordata(long maxusec){ fd_set fds; int maxfd,i,ret,reconnect; struct timeval tv,start,now; while(1) { do{ /* handle signals */ if(term) { dosigterm(termsig); /* never reached */ } if(hup) { dosighup(SIGHUP); hup=0; } if(alrm) { dosigalrm(SIGALRM); alrm=0; } FD_ZERO(&fds); FD_SET(sockfd,&fds); maxfd=sockfd; if(listen_tcpip) { FD_SET(sockinet,&fds); maxfd=max(maxfd,sockinet); } if(clin>0 && hw.rec_mode!=0) { FD_SET(hw.fd,&fds); maxfd=max(maxfd,hw.fd); } for(i=0;i<clin;i++) { /* Ignore this client until codes have been sent and it will get an answer. Otherwise we could mix up answer packets and send them back in the wrong order.*/ if(clis[i]!=repeat_fd) { FD_SET(clis[i],&fds); maxfd=max(maxfd,clis[i]); } } timerclear(&tv); reconnect=0; for(i=0;i<peern;i++) { if(peers[i]->socket!=-1) { FD_SET(peers[i]->socket,&fds); maxfd=max(maxfd,peers[i]->socket); } else if(timerisset(&tv)) { if(timercmp (&tv,&peers[i]->reconnect,>)) { tv=peers[i]->reconnect; } } else { tv=peers[i]->reconnect; } } if(timerisset(&tv)) { gettimeofday(&now,NULL); if(timercmp(&now,&tv,>)) { timerclear(&tv); } else { timersub(&tv,&now,&start); tv=start; } reconnect=1; } gettimeofday(&start,NULL); if(maxusec>0) { tv.tv_sec=0; tv.tv_usec=maxusec; }#ifdef SIM_REC ret=select(maxfd+1,&fds,NULL,NULL,NULL);#else if(timerisset(&tv) || reconnect) { ret=select(maxfd+1,&fds,NULL,NULL,&tv); } else { ret=select(maxfd+1,&fds,NULL,NULL,NULL); }#endif if(ret==-1 && errno!=EINTR) { logprintf(LOG_ERR,"select() failed"); logperror(LOG_ERR,NULL); raise(SIGTERM); continue; } gettimeofday(&now,NULL); if(free_remotes!=NULL) { free_old_remotes(); } if(maxusec>0) { if(ret==0) { return(0); } if(time_elapsed(&start,&now)>=maxusec) { return(0); } else { maxusec-=time_elapsed(&start,&now); } } if(reconnect) { connect_to_peers(); } } while(ret==-1 && errno==EINTR); for(i=0;i<clin;i++) { if(FD_ISSET(clis[i],&fds)) { FD_CLR(clis[i],&fds); if(get_command(clis[i])==0) { remove_client(clis[i]); i--; } } } for(i=0;i<peern;i++) { if(peers[i]->socket!=-1 && FD_ISSET(peers[i]->socket,&fds)) { if(get_peer_message(peers[i])==0) { shutdown(peers[i]->socket,2); close(peers[i]->socket); peers[i]->socket=-1; peers[i]->connection_failure = 1; gettimeofday(&peers[i]->reconnect,NULL); peers[i]->reconnect.tv_sec+=5; } } } if(FD_ISSET(sockfd,&fds)) { LOGPRINTF(1,"registering local client"); add_client(sockfd); } if(listen_tcpip && FD_ISSET(sockinet,&fds)) { LOGPRINTF(1,"registering inet client"); add_client(sockinet); } if(clin>0 && hw.rec_mode!=0 && FD_ISSET(hw.fd,&fds)) { /* we will read later */ return(1); } }}void loop(){ char *message; int len,i; logprintf(LOG_NOTICE,"lircd(%s) ready",LIRC_DRIVER); while(1) { (void) waitfordata(0); if(!hw.rec_func) continue; message=hw.rec_func(remotes); if(message!=NULL) { len=strlen(message); for (i=0; i<clin; i++) { LOGPRINTF(1,"writing to client %d",i); if(write_socket(clis[i],message,len)<len) { remove_client(clis[i]); i--; } } } }}int main(int argc,char **argv){ struct sigaction act; int nodaemon=0; mode_t permission=S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; hw_choose_driver(NULL); while(1) { int c; static struct option long_options[] = { {"help",no_argument,NULL,'h'}, {"version",no_argument,NULL,'v'}, {"nodaemon",no_argument,NULL,'n'}, {"permission",required_argument,NULL,'p'}, {"driver",required_argument,NULL,'H'}, {"device",required_argument,NULL,'d'}, {"listen",optional_argument,NULL,'l'}, {"connect",required_argument,NULL,'c'},# ifdef DEBUG {"debug",optional_argument,NULL,'D'},# endif {0, 0, 0, 0} };# ifdef DEBUG c = getopt_long(argc,argv,"hvnp:H:d:l::c:D::",long_options,NULL);# else c = getopt_long(argc,argv,"hvnp:H:d:l::c:",long_options,NULL);# endif if(c==-1) break; switch (c) { case 'h': printf("Usage: %s [options] [config-file]\n",progname); printf("\t -h --help\t\t\tdisplay this message\n"); printf("\t -v --version\t\t\tdisplay version\n"); printf("\t -n --nodaemon\t\t\tdon't fork to background\n"); printf("\t -p --permission=mode\t\tfile permissions for " LIRCD "\n"); printf("\t -H --driver=driver\t\tuse given driver\n"); printf("\t -d --device=device\t\tread from given device\n"); printf("\t -l --listen[=port]\t\tlisten for network connections on port\n"); printf("\t -c --connect=host[:port]\t\tconnect to remote lircd server\n");# ifdef DEBUG printf("\t -D[debug_level] --debug[=debug_level]\n");# endif return(EXIT_SUCCESS); case 'v': printf("%s\n",progname); return(EXIT_SUCCESS); case 'n': nodaemon=1; break; case 'p': if(oatoi(optarg)==-1) { fprintf(stderr,"%s: invalid mode\n",progname); return(EXIT_FAILURE); } permission=oatoi(optarg); break; case 'H': if(hw_choose_driver(optarg) != 0){ fprintf(stderr, "Driver `%s' not supported.\n", optarg); hw_print_drivers(stderr); exit (EXIT_FAILURE); } break; case 'd': hw.device=optarg; break; case 'l': listen_tcpip=1; if(optarg) { long p; char *endptr; p=strtol(optarg,&endptr,10); if(!*optarg || *endptr || p<1 || p>USHRT_MAX) { fprintf(stderr, "%s: bad port number \"%s\"\n", progname,optarg); return(EXIT_FAILURE); } port=(unsigned short int) p; } else { port=LIRC_INET_PORT; } break; case 'c': if(!add_peer_connection(optarg)) return(EXIT_FAILURE); break;# ifdef DEBUG case 'D': if(optarg==NULL) debug=1; else { /* don't check for errors */ debug=atoi(optarg); } break;# endif default: printf("Usage: %s [options] [config-file]\n",progname); return(EXIT_FAILURE); } } if(optind==argc-1) { configfile=argv[optind]; } else if(optind!=argc) { fprintf(stderr,"%s: invalid argument count\n",progname); return(EXIT_FAILURE); } if(strcmp(hw.name, "null")==0 && peern==0) { fprintf(stderr,"%s: there's no hardware I can use and " "no peers are specified\n",progname); return(EXIT_FAILURE); } signal(SIGPIPE,SIG_IGN); start_server(permission,nodaemon); act.sa_handler=sigterm; sigfillset(&act.sa_mask); act.sa_flags=SA_RESTART; /* don't fiddle with EINTR */ sigaction(SIGTERM,&act,NULL); sigaction(SIGINT,&act,NULL); act.sa_handler=sigalrm; sigemptyset(&act.sa_mask); act.sa_flags=SA_RESTART; /* don't fiddle with EINTR */ sigaction(SIGALRM,&act,NULL); remotes=NULL; config(); /* read config file */ act.sa_handler=sighup; sigemptyset(&act.sa_mask); act.sa_flags=SA_RESTART; /* don't fiddle with EINTR */ sigaction(SIGHUP,&act,NULL); #ifdef DAEMONIZE /* ready to accept connections */ if(!nodaemon) daemonize();#endif #if defined(SIM_SEND) && !defined(DAEMONIZE) { struct ir_remote *r; struct ir_ncode *c; if(hw.init_func) { if(!hw.init_func()) dosigterm(SIGTERM); } printf("space 1000000\n"); r=remotes; while(r!=NULL) { c=r->codes; while(c->name!=NULL) { repeat_remote=NULL; repeat_code=NULL; hw.send_func(r,c); repeat_remote=r; repeat_code=c; hw.send_func(r,c); hw.send_func(r,c); hw.send_func(r,c); hw.send_func(r,c); c++; } r=r->next; } fflush(stdout); if(hw.deinit_func) hw.deinit_func(); } fprintf(stderr,"Ready.\n"); dosigterm(SIGTERM);#endif loop(); /* never reached */ return(EXIT_SUCCESS); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -