📄 lircd.c
字号:
} } if(length==0) /* EOF: connection closed by client */ { return(0); } return(1);}void start_server(mode_t permission,int nodaemon){ struct sockaddr_un serv_addr; struct sockaddr_in serv_addr_in; struct stat s; int ret; int new=1; int fd; /* create pid lockfile in /var/run */ if((fd=open(PIDFILE,O_RDWR|O_CREAT,0644))==-1 || (pidfile=fdopen(fd,"r+"))==NULL) { fprintf(stderr,"%s: can't open or create %s\n", progname,PIDFILE); perror(progname); exit(EXIT_FAILURE); } if(flock(fd,LOCK_EX|LOCK_NB)==-1) { pid_t otherpid; if(fscanf(pidfile,"%d\n",&otherpid)>0) { fprintf(stderr,"%s: there seems to already be " "a lircd process with pid %d\n", progname,otherpid); fprintf(stderr,"%s: otherwise delete stale " "lockfile %s\n",progname,PIDFILE); } else { fprintf(stderr,"%s: invalid %s encountered\n", progname,PIDFILE); } exit(EXIT_FAILURE); } (void) fcntl(fd,F_SETFD,FD_CLOEXEC); rewind(pidfile); (void) fprintf(pidfile,"%d\n",getpid()); (void) fflush(pidfile); (void) ftruncate(fileno(pidfile),ftell(pidfile)); /* create socket*/ sockfd=socket(AF_UNIX,SOCK_STREAM,0); if(sockfd==-1) { fprintf(stderr,"%s: could not create socket\n",progname); perror(progname); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); }; /* get owner, permissions, etc. so new socket can be the same since we have to delete the old socket. */ ret=stat(LIRCD,&s); if(ret==-1 && errno!=ENOENT) { fprintf(stderr,"%s: could not get file information for %s\n", progname,LIRCD); perror(progname); close(sockfd); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); } if(ret!=-1) { new=0; ret=unlink(LIRCD); if(ret==-1) { fprintf(stderr,"%s: could not delete %s\n", progname,LIRCD); perror(NULL); close(sockfd); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); } } serv_addr.sun_family=AF_UNIX; strcpy(serv_addr.sun_path,LIRCD); if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==-1) { fprintf(stderr,"%s: could not assign address to socket\n", progname); perror(progname); close(sockfd); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); } if(new ? chmod(LIRCD,permission): (chmod(LIRCD,s.st_mode)==-1 || chown(LIRCD,s.st_uid,s.st_gid)==-1) ) { fprintf(stderr,"%s: could not set file permissions\n", progname); perror(progname); close(sockfd); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); } listen(sockfd,3); nolinger(sockfd); if(listen_tcpip) { int enable=1; /* create socket*/ sockinet=socket(PF_INET,SOCK_STREAM,IPPROTO_IP); if(sockinet==-1) { fprintf(stderr,"%s: could not create TCP/IP socket\n", progname); perror(progname); close(sockfd); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); }; (void) setsockopt(sockinet,SOL_SOCKET,SO_REUSEADDR, &enable,sizeof(enable)); serv_addr_in.sin_family=AF_INET; serv_addr_in.sin_addr.s_addr=htonl(INADDR_ANY); serv_addr_in.sin_port=htons(port); if(bind(sockinet,(struct sockaddr *) &serv_addr_in, sizeof(serv_addr_in))==-1) { fprintf(stderr,"%s: could not assign address to socket\n", progname); perror(progname); close(sockinet); close(sockfd); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); } listen(sockinet,3); nolinger(sockinet); } #ifdef USE_SYSLOG#ifdef DAEMONIZE if(nodaemon) { openlog(progname,LOG_CONS|LOG_PID|LOG_PERROR,LIRC_SYSLOG); } else { openlog(progname,LOG_CONS|LOG_PID,LIRC_SYSLOG); }#else openlog(progname,LOG_CONS|LOG_PID|LOG_PERROR,LIRC_SYSLOG);#endif#else lf=fopen(logfile,"a"); if(lf==NULL) { fprintf(stderr,"%s: could not open logfile\n",progname); perror(progname); if(listen_tcpip) { close(sockinet); } close(sockfd); fclose(pidfile); (void) unlink(PIDFILE); exit(EXIT_FAILURE); } gethostname(hostname,HOSTNAME_LEN);#endif LOGPRINTF(1,"started server socket");}#ifndef USE_SYSLOGvoid logprintf(int prio,char *format_str, ...){ time_t current; char *currents; va_list ap; current=time(¤t); currents=ctime(¤t); if(lf) fprintf(lf,"%15.15s %s %s: ",currents+4,hostname,progname); if(!daemonized) fprintf(stderr,"%s: ",progname); va_start(ap,format_str); if(lf) { if(prio==LOG_WARNING) fprintf(lf,"WARNING: "); vfprintf(lf,format_str,ap); fputc('\n',lf);fflush(lf); } if(!daemonized) { if(prio==LOG_WARNING) fprintf(stderr,"WARNING: "); vfprintf(stderr,format_str,ap); fputc('\n',stderr);fflush(stderr); } va_end(ap);}void logperror(int prio,const char *s){ if(s!=NULL) { logprintf(prio,"%s: %s",s,strerror(errno)); } else { logprintf(prio,"%s",strerror(errno)); }}#endif#ifdef DAEMONIZEvoid daemonize(void){ if(daemon(0,0)==-1) { logprintf(LOG_ERR,"daemon() failed"); logperror(LOG_ERR,NULL); dosigterm(SIGTERM); } umask(0); rewind(pidfile); (void) fprintf(pidfile,"%d\n",getpid()); (void) fflush(pidfile); (void) ftruncate(fileno(pidfile),ftell(pidfile)); daemonized=1;}#endif /* DAEMONIZE */void sigalrm(int sig){ alrm=1;}void dosigalrm(int sig){ struct itimerval repeat_timer; if(repeat_remote->last_code!=repeat_code) { /* we received a different code from the original remote control we could repeat the wrong code so better stop repeating */ repeat_remote=NULL; repeat_code=NULL; repeat_fd=-1; if(repeat_message!=NULL) { free(repeat_message); repeat_message=NULL; } if(clin==0 && repeat_remote==NULL && hw.deinit_func) { hw.deinit_func(); } return; } repeat_remote->repeat_countdown--; if(hw.send_func(repeat_remote,repeat_code) && repeat_remote->repeat_countdown>0) { repeat_timer.it_value.tv_sec=0; repeat_timer.it_value.tv_usec=repeat_remote->remaining_gap; repeat_timer.it_interval.tv_sec=0; repeat_timer.it_interval.tv_usec=0; setitimer(ITIMER_REAL,&repeat_timer,NULL); return; } repeat_remote=NULL; repeat_code=NULL; if(repeat_fd!=-1) { send_success(repeat_fd,repeat_message); free(repeat_message); repeat_message=NULL; repeat_fd=-1; } if(clin==0 && repeat_remote==NULL && hw.deinit_func) { hw.deinit_func(); }}int parse_rc(int fd,char *message,char *arguments,struct ir_remote **remote, struct ir_ncode **code,int *reps,int n){ char *name=NULL,*command=NULL,*repeats,*end_ptr=NULL; *remote=NULL; *code=NULL; if(arguments==NULL) return(1); name=strtok(arguments,WHITE_SPACE); if(name==NULL) return(1); *remote=get_ir_remote(remotes,name); if(*remote==NULL) { return(send_error(fd,message,"unknown remote: \"%s\"\n", name)); } command=strtok(NULL,WHITE_SPACE); if(command==NULL) return(1); *code=get_ir_code(*remote,command); if(*code==NULL) { return(send_error(fd,message,"unknown command: \"%s\"\n", command)); } if(reps!=NULL) { repeats=strtok(NULL,WHITE_SPACE); if (repeats!=NULL) { *reps=strtol(repeats,&end_ptr,10); if (*end_ptr || *reps<0 ) { return(send_error(fd,message, "bad send packet\n")); } if (*reps>REPEAT_MAX) { return(send_error (fd,message, "too many repeats: \"%d\"\n",*reps)); } } else { *reps=-1; } } if(strtok(NULL,WHITE_SPACE)!=NULL) { return(send_error(fd,message,"bad send packet\n")); } if(n>0 && *remote==NULL) { return(send_error(fd,message,"remote missing\n")); } if(n>1 && *code==NULL) { return(send_error(fd,message,"code missing\n")); } return(1);}int send_success(int fd,char *message){ 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_END]))) return(0); return(1);}int send_error(int fd,char *message,char *format_str, ...){ char lines[4],buffer[PACKET_SIZE+1]; int i,n,len; va_list ap; char *s1,*s2; va_start(ap,format_str); vsprintf(buffer,format_str,ap); va_end(ap); s1=strrchr(message,'\n'); s2=strrchr(buffer,'\n'); if(s1!=NULL) s1[0]=0; if(s2!=NULL) s2[0]=0; logprintf(LOG_ERR,"error processing command: %s",message); logprintf(LOG_ERR,"%s",buffer); if(s1!=NULL) s1[0]='\n'; if(s2!=NULL) s2[0]='\n'; n=0; len=strlen(buffer); for(i=0;i<len;i++) if(buffer[i]=='\n') n++; sprintf(lines,"%d\n",n); if(!(write_socket_len(fd,protocol_string[P_BEGIN]) && write_socket_len(fd,message) && write_socket_len(fd,protocol_string[P_ERROR]) && write_socket_len(fd,protocol_string[P_DATA]) && write_socket_len(fd,lines) && write_socket_len(fd,buffer) && write_socket_len(fd,protocol_string[P_END]))) return(0); return(1);}int send_remote_list(int fd,char *message){ char buffer[PACKET_SIZE+1]; struct ir_remote *all; int n,len; n=0; all=remotes; while(all) { n++; all=all->next; } if(!(write_socket_len(fd,protocol_string[P_BEGIN]) && write_socket_len(fd,message) && write_socket_len(fd,protocol_string[P_SUCCESS]))) return(0); if(n==0) { return(write_socket_len(fd,protocol_string[P_END])); } sprintf(buffer,"%d\n",n); len=strlen(buffer); if(!(write_socket_len(fd,protocol_string[P_DATA]) && write_socket_len(fd,buffer))) return(0); all=remotes; while(all) { len=snprintf(buffer,PACKET_SIZE+1,"%s\n",all->name); if(len==PACKET_SIZE+1) { len=sprintf(buffer,"name_too_long\n"); } if(write_socket(fd,buffer,len)<len) return(0); all=all->next; } return(write_socket_len(fd,protocol_string[P_END]));}int send_remote(int fd,char *message,struct ir_remote *remote){ struct ir_ncode *codes; char buffer[PACKET_SIZE+1]; int n,len; n=0; codes=remote->codes; if(codes!=NULL) { while(codes->name!=NULL) { n++; codes++; } } if(!(write_socket_len(fd,protocol_string[P_BEGIN]) && write_socket_len(fd,message) && write_socket_len(fd,protocol_string[P_SUCCESS]))) return(0); if(n==0) { return(write_socket_len(fd,protocol_string[P_END])); } sprintf(buffer,"%d\n",n); if(!(write_socket_len(fd,protocol_string[P_DATA]) && write_socket_len(fd,buffer))) return(0); codes=remote->codes; while(codes->name!=NULL) {#ifdef __GLIBC__ /* It seems you can't print 64-bit longs on glibc */ len=snprintf(buffer,PACKET_SIZE+1,"%08lx%08lx %s\n", (unsigned long) (codes->code>>32), (unsigned long) (codes->code&0xFFFFFFFF), codes->name);#else len=snprintf(buffer,PACKET_SIZE,"%016llx %s\n", codes->code, codes->name);#endif if(len==PACKET_SIZE+1) { len=sprintf(buffer,"code_too_long\n"); } if(write_socket(fd,buffer,len)<len) return(0); codes++; } return(write_socket_len(fd,protocol_string[P_END]));}int send_name(int fd,char *message,struct ir_ncode *code){ char buffer[PACKET_SIZE+1]; int len; 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]))) return(0);#ifdef __GLIBC__ /* It seems you can't print 64-bit longs on glibc */ len=snprintf(buffer,PACKET_SIZE+1,"1\n%08lx%08lx %s\n", (unsigned long) (code->code>>32), (unsigned long) (code->code&0xFFFFFFFF), code->name);#else len=snprintf(buffer,PACKET_SIZE,"1\n%016llx %s\n", code->code, code->name);#endif if(len==PACKET_SIZE+1) { len=sprintf(buffer,"1\ncode_too_long\n"); } if(write_socket(fd,buffer,len)<len) return(0); return(write_socket_len(fd,protocol_string[P_END]));}int list(int fd,char *message,char *arguments){ struct ir_remote *remote; struct ir_ncode *code; if(parse_rc(fd,message,arguments,&remote,&code,NULL,0)==0) return(0); if(remote==NULL) { return(send_remote_list(fd,message)); } if(code==NULL) { return(send_remote(fd,message,remote)); } return(send_name(fd,message,code));}int send_once(int fd,char *message,char *arguments){ return(send_core(fd,message,arguments,1));}int send_start(int fd,char *message,char *arguments){ return(send_core(fd,message,arguments,0));}int send_core(int fd,char *message,char *arguments,int once){ struct ir_remote *remote; struct ir_ncode *code; struct itimerval repeat_timer; int reps; if(hw.send_mode==0) return(send_error(fd,message,"hardware does not " "support sending\n")); if(parse_rc(fd,message,arguments,&remote,&code, once ? &reps:NULL,2)==0) return(0); if(remote==NULL || code==NULL) return(1); if(once) { if(repeat_remote!=NULL) { return(send_error(fd,message,"busy: repeating\n")); } } else { if(repeat_remote!=NULL) { return(send_error(fd,message,"already repeating\n")); } } if(has_toggle_mask(remote)) { remote->toggle_mask_state=0; } if(remote->toggle_bit>0) remote->repeat_state= !remote->repeat_state; if(!hw.send_func(remote,code)) { return(send_error(fd,message,"transmission failed\n")); } if(once) { remote->repeat_countdown=max(remote->min_repeat,reps); } else { /* you've been warned, now we have a limit */ remote->repeat_countdown=REPEAT_MAX; } if(remote->repeat_countdown>0) { repeat_remote=remote; repeat_code=code; repeat_timer.it_value.tv_sec=0; repeat_timer.it_value.tv_usec= remote->remaining_gap; repeat_timer.it_interval.tv_sec=0; repeat_timer.it_interval.tv_usec=0; if(once) { repeat_message=strdup(message); if(repeat_message==NULL) { repeat_remote=NULL; repeat_code=NULL; return(send_error(fd,message, "out of memory\n")); } repeat_fd=fd; } else if(!send_success(fd,message)) { repeat_remote=NULL; repeat_code=NULL; return(0); } setitimer(ITIMER_REAL,&repeat_timer,NULL); return(1); } else { return(send_success(fd,message)); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -