/** Connects to the fish socket and starts listening for connections */ static int get_socket(void) { // Cygwin has random problems involving sockets. When using Cygwin, // allow 20 attempts at making socket correctly. #ifdef __CYGWIN__ int attempts = 0; repeat: attempts += 1; #endif int s, len, doexit = 0; int exitcode = EXIT_FAILURE; struct sockaddr_un local; const std::string sock_name = get_socket_filename(); /* Start critical section protected by lock */ std::string lockfile; if (! acquire_socket_lock(sock_name, &lockfile)) { debug(0, L"Unable to obtain lock on socket, exiting"); exit(EXIT_FAILURE); } debug(4, L"Acquired lockfile: %s", lockfile.c_str()); local.sun_family = AF_UNIX; strcpy(local.sun_path, sock_name.c_str()); len = sizeof(local); debug(1, L"Connect to socket at %s", sock_name.c_str()); if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { wperror(L"socket"); doexit = 1; goto unlock; } /* First check whether the socket has been opened by another fishd; if so, exit with success status */ if (connect(s, (struct sockaddr *)&local, len) == 0) { debug(1, L"Socket already exists, exiting"); doexit = 1; exitcode = 0; goto unlock; } unlink(local.sun_path); if (bind(s, (struct sockaddr *)&local, len) == -1) { wperror(L"bind"); doexit = 1; goto unlock; } if (make_fd_nonblocking(s) != 0) { wperror(L"fcntl"); close(s); doexit = 1; } else if (listen(s, 64) == -1) { wperror(L"listen"); doexit = 1; } unlock: (void)unlink(lockfile.c_str()); debug(4, L"Released lockfile: %s", lockfile.c_str()); /* End critical section protected by lock */ if (doexit) { // If Cygwin, only allow normal quit when made lots of attempts. #ifdef __CYGWIN__ if (exitcode && attempts < 20) goto repeat; #endif exit_without_destructors(exitcode); } return s; }
/** Connects to the fish socket and starts listening for connections */ static int get_socket() { int s, len, doexit = 0; int exitcode = EXIT_FAILURE; struct sockaddr_un local; char *sock_name = get_socket_filename(); /* Start critical section protected by lock */ char *lockfile = acquire_socket_lock( sock_name ); if( lockfile == NULL ) { debug( 0, L"Unable to obtain lock on socket, exiting" ); exit( EXIT_FAILURE ); } debug( 4, L"Acquired lockfile: %s", lockfile ); local.sun_family = AF_UNIX; strcpy( local.sun_path, sock_name ); len = sizeof(local); debug(1, L"Connect to socket at %s", sock_name); if( ( s = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) { wperror( L"socket" ); doexit = 1; goto unlock; } /* First check whether the socket has been opened by another fishd; if so, exit with success status */ if( connect( s, (struct sockaddr *)&local, len ) == 0 ) { debug( 1, L"Socket already exists, exiting" ); doexit = 1; exitcode = 0; goto unlock; } unlink( local.sun_path ); if( bind( s, (struct sockaddr *)&local, len ) == -1 ) { wperror( L"bind" ); doexit = 1; goto unlock; } if( fcntl( s, F_SETFL, O_NONBLOCK ) != 0 ) { wperror( L"fcntl" ); close( s ); doexit = 1; } else if( listen( s, 64 ) == -1 ) { wperror( L"listen" ); doexit = 1; } unlock: (void)unlink( lockfile ); debug( 4, L"Released lockfile: %s", lockfile ); /* End critical section protected by lock */ free( lockfile ); free( sock_name ); if( doexit ) { exit( exitcode ); } return s; }
void load_params(int argc, char **argv) { config_t cfg; config_setting_t *setting, *interrupt_setting; char const *config_socket, *inter_name, *inter_type_string, *inter_pud; char *config_file_name; int ch, inter_pin, inter_type, inter_wait, r, pud; int lcd_di, lcd_led, lcd_spics, read_config = 0; InterruptInfo *interrupt_info; while ((ch = getopt(argc, argv, "dhvs:a:l:c:i:")) != -1) { switch (ch) { case 'd': set_flag_dont_detach(1); break; case 'h': usage(); exit(EXIT_SUCCESS); break; case 'v': set_flag_verbose(1); break; case 's': set_socket_filename(optarg); break; case 'a': if (is_valid_pin_num(atoi(optarg))) { set_lcd_di(atoi(optarg)); } else { printf("Only valid Pinnumber between 1 and 16 allowed!\n"); usage(); exit(EXIT_FAILURE); } break; case 'l': if (is_valid_pin_num(atoi(optarg))) { set_lcd_led(atoi(optarg)); } else { printf("Only valid Pinnumber between 1 and 16 allowed!\n"); usage(); exit(EXIT_FAILURE); } break; case 'c': if (is_valid_pin_num(atoi(optarg))) { set_lcd_spics(atoi(optarg)); } else { printf("Only 0 or 1 allowed!\n"); usage(); exit(EXIT_FAILURE); } break; case 'i': read_config = 1; config_file_name = optarg; break; default: usage(); exit(1); } } if (read_config) { config_init(&cfg); /* Read the config file and about on error */ if (!config_read_file(&cfg, config_file_name)) { printf("\n%s:%d - %s\n", config_file_name, config_error_line(&cfg), config_error_text(&cfg)); config_destroy(&cfg); exit(1); } if (config_lookup_string(&cfg, "socket", &config_socket)) { set_socket_filename(strndup(config_socket, strlen(config_socket))); printf("Socket file configured from config file as: %s\n", get_socket_filename()); } setting = config_lookup(&cfg, "lcd"); if (setting != NULL) { if (!config_setting_lookup_int(setting, "di_pin", &lcd_di)) { set_lcd_di(lcd_di); if (get_flag_verbose()) { printf("Set DI Pin of the LCD Display to %i with config file\n", lcd_di); } } if (!config_setting_lookup_int(setting, "led_pin", &lcd_led)) { set_lcd_led(lcd_led); if (get_flag_verbose()) { printf("Set PWM LED Pin of the LCD Display to %i with config file\n", lcd_led); } } if (!config_setting_lookup_int(setting, "spi_cs", &lcd_spics)) { set_lcd_spics(lcd_spics); if (get_flag_verbose()) { printf("Set SPI CS Pin of the LCD Display to %i with config file\n", lcd_spics); } } } setting = config_lookup(&cfg, "interrupt"); if (setting != NULL) { if (config_setting_type(setting) == CONFIG_TYPE_LIST) { set_interrupts_count(config_setting_length(setting)); // Max interrupts are 10 if more configured only the first 10 are used! if (get_interrupts_count() > 10) { set_interrupts_count(10); } for (r=0; r < get_interrupts_count(); r++) { interrupt_setting = config_setting_get_elem(setting, r); if (!(config_setting_lookup_int(interrupt_setting, "pin", &inter_pin) && config_setting_lookup_string(interrupt_setting, "type", &inter_type_string) && config_setting_lookup_string(interrupt_setting, "name", &inter_name) && config_setting_lookup_int(interrupt_setting, "wait", &inter_wait) && config_setting_lookup_string(interrupt_setting, "pud", &inter_pud))) { // TODO: Error message if configuration is not valid continue; } if(strncmp(inter_pud, "none", strlen("none")) == 0) { pud = PUD_OFF; } else if (strncmp(inter_pud, "up", strlen("up")) == 0) { pud = PUD_UP; } else if (strncmp(inter_pud, "down", strlen("down")) == 0) { pud = PUD_DOWN; } else { // TODO: Error message if configuration is not valid continue; } if(strncmp(inter_type_string, "falling", strlen("falling")) == 0) { inter_type = INT_EDGE_FALLING; } else if (strncmp(inter_type_string, "rising", strlen("rising")) == 0) { inter_type = INT_EDGE_RISING; } else if (strncmp(inter_type_string, "both", strlen("both")) == 0) { inter_type = INT_EDGE_BOTH; } else { // TODO: Error message if configuration is not valid continue; } interrupt_info = malloc(sizeof(InterruptInfo)); if (r <= 10) { interrupt_info->pin = inter_pin; interrupt_info->wait = inter_wait; interrupt_info->type = inter_type; interrupt_info->name = strndup(inter_name, strlen(inter_name)); interrupt_info->occure = 0; interrupt_info->pud = pud; set_interrupt_info(r, *interrupt_info); } } } } config_destroy(&cfg); } }