int lirc_readconfig(const struct lirc_state *state, const char *file, struct lirc_config **config, int (check)(char *s)) { struct sockaddr_un addr; int sockfd = -1; char *sha_bang, *filename; const char *sha_bang2; char *command; unsigned int ret; filename = NULL; sha_bang = NULL; if(lirc_readconfig_only_internal(state,file,config,check,&filename,&sha_bang)==-1) { return -1; } if(sha_bang == NULL) { goto lirc_readconfig_compat; } /* connect to lircrcd */ addr.sun_family=AF_UNIX; if(lirc_getsocketname(filename, addr.sun_path, sizeof(addr.sun_path))>sizeof(addr.sun_path)) { lirc_printf(state, "%s: WARNING: file name too long\n", state->lirc_prog); goto lirc_readconfig_compat; } sockfd=socket(AF_UNIX,SOCK_STREAM,0); if(sockfd==-1) { lirc_printf(state, "%s: WARNING: could not open socket\n",state->lirc_prog); lirc_perror(state, state->lirc_prog); goto lirc_readconfig_compat; } if(connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))!=-1) { if(sha_bang!=NULL) free(sha_bang); (*config)->sockfd=sockfd; free(filename); /* tell daemon state->lirc_prog */ if(lirc_identify(state, sockfd) == LIRC_RET_SUCCESS) { /* we're connected */ return 0; } close(sockfd); lirc_freeconfig(*config); return -1; } close(sockfd); sockfd = -1; /* launch lircrcd */ sha_bang2=sha_bang!=NULL ? sha_bang:"lircrcd"; command=malloc(strlen(sha_bang2)+1+strlen(filename)+1); if(command==NULL) { goto lirc_readconfig_compat; } strcpy(command, sha_bang2); strcat(command, " "); strcat(command, filename); ret = myth_system_c(command, kMSNone, 0); free(command); if(ret!=EXIT_SUCCESS) { goto lirc_readconfig_compat; } if(sha_bang!=NULL) { free(sha_bang); sha_bang = NULL; } free(filename); filename = NULL; sockfd=socket(AF_UNIX,SOCK_STREAM,0); if(sockfd==-1) { lirc_printf(state, "%s: WARNING: could not open socket\n",state->lirc_prog); lirc_perror(state, state->lirc_prog); goto lirc_readconfig_compat; } if(connect(sockfd, (struct sockaddr *)&addr, sizeof(addr))!=-1) { if(lirc_identify(state, sockfd) == LIRC_RET_SUCCESS) { (*config)->sockfd=sockfd; return 0; } } close(sockfd); lirc_freeconfig(*config); return -1; lirc_readconfig_compat: /* compat fallback */ if(sockfd != -1) close(sockfd); if(sha_bang!=NULL) free(sha_bang); free(filename); return 0; }
static int opensocket(const char* socket_id, const char* socketname, mode_t permission, struct sockaddr_un* addr) { int sockfd; struct stat s; int new_socket = 1; int ret; /* get socket name */ if ((socketname == NULL && lirc_getsocketname(socket_id, addr->sun_path, sizeof(addr->sun_path)) > sizeof(addr->sun_path)) || (socketname != NULL && strlen(socketname) >= sizeof(addr->sun_path))) { fprintf(stderr, "%s: filename too long", progname); return -1; } if (socketname != NULL) strcpy(addr->sun_path, socketname); /* create socket */ sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd == -1) { perror("could not create socket"); return -1; } /* * get owner, permissions, etc. * so new socket can be the same since we * have to delete the old socket. */ ret = stat(addr->sun_path, &s); if (ret == -1 && errno != ENOENT) { perrorf("could not get file information for %s", addr->sun_path); goto opensocket_failed; } if (ret != -1) { new_socket = 0; ret = unlink(addr->sun_path); if (ret == -1) { perrorf("could not delete %s", addr->sun_path); goto opensocket_failed; } } addr->sun_family = AF_UNIX; if (bind(sockfd, (struct sockaddr*)addr, sizeof(*addr)) == -1) { perror("could not assign address to socket"); goto opensocket_failed; } if (new_socket ? chmod(addr->sun_path, permission) : (chmod(addr->sun_path, s.st_mode) == -1 || chown(addr->sun_path, s.st_uid, s.st_gid) == -1) ) { perrorf("could not set file permissions on %s", addr->sun_path); goto opensocket_failed; } listen(sockfd, 3); nolinger(sockfd); return sockfd; opensocket_failed: close(sockfd); return -1; }