int main(int argc, char *argv[]) { pid_t pid; const char *pcFD_GPIO = NULL; const char *pcI2Cbus = NULL; uint8_t u8I2CAddress = 0; const char *pcPWR_GPIO = NULL; { static struct option long_options[] = { /* Program options */ {"help", no_argument, NULL, 'h'}, {"foreground", no_argument, NULL, 'f'}, {"verbosity", required_argument, NULL, 'v'}, {"gpio-fd", required_argument, NULL, 0}, {"i2c-bus", required_argument, NULL, 1}, {"i2c-address", required_argument, NULL, 2}, {"gpio-pwr", required_argument, NULL, 3}, { NULL, 0, NULL, 0} }; signed char opt; int option_index; while ((opt = getopt_long(argc, argv, "hfv:", long_options, &option_index)) != -1) { switch (opt) { case 'h': print_usage_exit(argv); break; case 'f': daemonize = 0; break; case 'v': verbosity = atoi(optarg); break; case 0: pcFD_GPIO = optarg; break; case 1: pcI2Cbus = optarg; break; case 2: { char *pcEnd; errno = 0; uint32_t u32I2CAddress = strtoul(optarg, &pcEnd, 0); if (errno) { fprintf(stderr, "I2C Address '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { fprintf(stderr, "I2C Address '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32I2CAddress > 0x7F) { fprintf(stderr, "I2C Address '%s' outside allowable range (0x01 - 0x7F)\n", optarg); print_usage_exit(argv); } u8I2CAddress = u32I2CAddress; break; } case 3: pcPWR_GPIO = optarg; break; default: /* '?' */ print_usage_exit(argv); } } } if (!pcFD_GPIO) { fprintf(stderr, "GPIO for field detect pin must be specified\n"); print_usage_exit(argv); } if (!pcI2Cbus) { fprintf(stderr, "I2C bus must be specified\n"); print_usage_exit(argv); } if (!u8I2CAddress) { fprintf(stderr, "I2C address must be specified\n"); print_usage_exit(argv); } /* Log everything into syslog */ daemon_log_ident = daemon_ident_from_argv0(argv[0]); if (daemonize) { /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { daemon_log(LOG_ERR, "Failed to create pipe."); return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_log(LOG_ERR, "Failed to fork() daemon process."); daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); return 255; } if (ret == 0) { daemon_log(LOG_INFO, "Daemon process started."); } else { daemon_log(LOG_ERR, "Daemon returned %i.", ret); } return ret; } else { /* The daemon */ /* Close FDs */ if (daemon_close_all(-1) < 0) { daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); /* Send the error condition to the parent process */ daemon_retval_send(1); goto finish; } daemon_log_use = DAEMON_LOG_SYSLOG; /* Send OK to parent process */ daemon_retval_send(0); daemon_log(LOG_INFO, "Daemon started"); } } else { /* Running foreground - set verbosity */ if (verbosity > LOG_WARNING) { daemon_set_verbosity(verbosity); } } /* Install signal handlers */ signal(SIGTERM, vQuitSignalHandler); signal(SIGINT, vQuitSignalHandler); if (eNtagSetup(pcPWR_GPIO, pcFD_GPIO, pcI2Cbus, u8I2CAddress) == E_NFC_OK) { if (eNdefSetup() == E_NFC_OK) { while (bRunning != 0) { if (eNtagWait(30000) == E_NFC_READER_PRESENT) { /* Tag detected */ while ((eNtagPresent() == E_NFC_READER_PRESENT) && bRunning) { sleep(1); teNfcStatus eStatus = eNtagRfUnlocked(); switch (eStatus) { case (E_NFC_OK): vHandleTag(); break; case (E_NFC_RF_LOCKED): DEBUG_PRINTF("RF Locked\n"); break; default: break; } //usleep(100000); //sleep(1); } } else { /* Blank the tag */ tsNdefData sData; eNdefInitData(&sData, 0, 0); eNdefWriteData(&sData); } } } } else { DEBUG_PRINTF("Failed to init NTAG\n"); } finish: if (daemonize) { daemon_log(LOG_INFO, "Daemon process exiting"); } return 0; }
int main(int argc, char *argv[]) { fd_set rfds; struct timeval tv; int retval; pid_t pid; char *cpSerialDevice = NULL; { static struct option long_options[] = { /* Required arguments */ {"serial", required_argument, NULL, 's'}, /* Program options */ {"help", no_argument, NULL, 'h'}, {"foreground", no_argument, NULL, 'f'}, {"verbosity", required_argument, NULL, 'v'}, {"baud", required_argument, NULL, 'B'}, {"interface", required_argument, NULL, 'I'}, {"reset", no_argument, NULL, 'R'}, {"confignotify", required_argument, NULL, 'C'}, {"activityled", required_argument, NULL, 'A'}, /* Module options */ {"frontend", required_argument, NULL, 'F'}, {"diversity", no_argument, NULL, 'D'}, /* 6LoWPAN network options */ {"mode", required_argument, NULL, 'm'}, {"region", required_argument, NULL, 'r'}, {"channel", required_argument, NULL, 'c'}, {"pan", required_argument, NULL, 'p'}, {"network", required_argument, NULL, 'j'}, {"profile", required_argument, NULL, 'P'}, {"prefix", required_argument, NULL, '6'}, /* Security options */ {"key", required_argument, NULL, 'k'}, {"authscheme", required_argument, NULL, 'a'}, /* Radius with PAP options */ {"radiusip", required_argument, NULL, 'i'}, { NULL, 0, NULL, 0} }; signed char opt; int option_index; while ((opt = getopt_long(argc, argv, "s:hfv:B:I:RC:A:F:Dm:r:c:p:j:P:6:k:a:i:", long_options, &option_index)) != -1) { switch (opt) { case 'h': print_usage_exit(argv); break; case 'f': daemonize = 0; break; case 'v': verbosity = atoi(optarg); break; case 'B': { char *pcEnd; errno = 0; u32BaudRate = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Baud rate '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Baud rate '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } break; } case 's': cpSerialDevice = optarg; break; case 'C': { struct stat sStat; /* Check if the given program exists and is executable */ if (stat(optarg, &sStat) == 0) { /* File stat'd ok */ pcConfigProgram = optarg; vprConfigChanged = ConfigChangedCallback; } else { printf("Config stat notification program '%s' (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } break; } case 'A': { char *pcEnd; uint32_t u32ActivityLED; errno = 0; u32ActivityLED = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Activity LED '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Activity LED '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } eActivityLED = u32ActivityLED; break; } case 'F': if (strcmp(optarg, "SP") == 0) { eRadioFrontEnd = E_FRONTEND_STANDARD_POWER; } else if (strcmp(optarg, "HP") == 0) { eRadioFrontEnd = E_FRONTEND_HIGH_POWER; } else if (strcmp(optarg, "ETSI") == 0) { eRadioFrontEnd = E_FRONTEND_ETSI; } else { printf("Unknown mode '%s' specified. Supported modes are 'coordinator', 'router', 'commissioning'\n", optarg); print_usage_exit(argv); } break; case 'D': iAntennaDiversity = 1; break; case 'm': if (strcmp(optarg, "coordinator") == 0) { eModuleMode = E_MODE_COORDINATOR; } else if (strcmp(optarg, "router") == 0) { eModuleMode = E_MODE_ROUTER; } else if (strcmp(optarg, "commissioning") == 0) { eModuleMode = E_MODE_COMMISSIONING; } else { printf("Unknown mode '%s' specified. Supported modes are 'coordinator', 'router', 'commissioning'\n", optarg); print_usage_exit(argv); } break; case 'r': { char *pcEnd; uint32_t u32Region; errno = 0; u32Region = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Region '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Region '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32Region > E_REGION_MAX) { printf("Invalid region '%s' specified\n", optarg); print_usage_exit(argv); } eRegion = (uint8_t)u32Region; break; } case 'c': { char *pcEnd; uint32_t u32Channel; errno = 0; u32Channel = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Channel '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Channel '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if ( !((u32Channel == E_CHANNEL_AUTOMATIC) || ((u32Channel >= E_CHANNEL_MINIMUM) && (u32Channel <= E_CHANNEL_MAXIMUM)))) { printf("Invalid Channel '%s' specified\n", optarg); print_usage_exit(argv); } eChannel = (uint8_t)u32Channel; break; } case 'p': { char *pcEnd; uint32_t u32PanID; errno = 0; u32PanID = strtoul(optarg, &pcEnd, 0); if (errno) { printf("PAN ID '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("PAN ID '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32PanID > 0xFFFF) { printf("Invalid PAN ID '%s' specified\n", optarg); print_usage_exit(argv); } u16PanID = (uint16_t)u32PanID; break; } case 'j': { char *pcEnd; uint32_t u32JenNetID; errno = 0; u32JenNetID = strtoul(optarg, &pcEnd, 0); if (errno) { printf("JenNet ID '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("JenNet ID '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } u32UserData = u32JenNetID; break; } case 'P': { char *pcEnd; uint32_t u32JenNetProfile; errno = 0; u32JenNetProfile = strtoul(optarg, &pcEnd, 0); if (errno) { printf("JenNet Profile '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("JenNet Profile '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } if (u32JenNetProfile > 0xFF) { printf("Invalid JenNet Profile '%s' specified\n", optarg); print_usage_exit(argv); } u8JenNetProfile = (uint8_t)u32JenNetProfile; break; } case '6': { int result; struct in6_addr address; result = inet_pton(AF_INET6, optarg, &address); if (result <= 0) { if (result == 0) { printf("Unknown host: %s\n", optarg); } else if (result < 0) { perror("inet_pton failed"); } exit(EXIT_FAILURE); } else { u64NetworkPrefix = ((uint64_t)address.s6_addr[0] << 56) | ((uint64_t)address.s6_addr[1] << 48) | ((uint64_t)address.s6_addr[2] << 40) | ((uint64_t)address.s6_addr[3] << 32) | ((uint64_t)address.s6_addr[4] << 24) | ((uint64_t)address.s6_addr[5] << 16) | ((uint64_t)address.s6_addr[6] << 8) | ((uint64_t)address.s6_addr[7] << 0); } break; } case 'I': cpTunDevice = optarg; break; case 'R': iResetCoordinator = 1; break; case 'k': { int result; /* The network key is specified like an IPv6 address, in 8 groups of 16-bit hexadecimal values separated by colons (:) */ result = inet_pton(AF_INET6, optarg, &sSecurityKey); if (result <= 0) { if (result == 0) { printf("Could not parse network key: %s\n", optarg); } else if (result < 0) { perror("inet_pton failed"); } exit(EXIT_FAILURE); } iSecureNetwork = 1; break; } case 'a': { char *pcEnd; uint32_t u32AuthScheme; errno = 0; u32AuthScheme = strtoul(optarg, &pcEnd, 0); if (errno) { printf("Authorisation scheme '%s' cannot be converted to 32 bit integer (%s)\n", optarg, strerror(errno)); print_usage_exit(argv); } if (*pcEnd != '\0') { printf("Authorisation scheme '%s' contains invalid characters\n", optarg); print_usage_exit(argv); } switch(u32AuthScheme) { case 0: printf("Warning - no authorisation scheme selected\n"); eAuthScheme = u32AuthScheme; break; case (1): eAuthScheme = u32AuthScheme; break; default: printf("Unknown authorisation scheme selected (%d)\n", u32AuthScheme); print_usage_exit(argv); break; } break; } case 'i': { switch(eAuthScheme) { case (E_AUTH_SCHEME_RADIUS_PAP): { int result = inet_pton(AF_INET6, optarg, &uAuthSchemeData.sRadiusPAP.sAuthServerIP); if (result <= 0) { if (result == 0) { printf("Unknown host: %s\n", optarg); } else if (result < 0) { perror("inet_pton failed"); } exit(EXIT_FAILURE); } break; } default: printf("Option '-i' is not appropriate for authorisation scheme %d\n", eAuthScheme); break; } break; } default: /* '?' */ print_usage_exit(argv); } } } /* Log everything into syslog */ daemon_log_ident = daemon_ident_from_argv0(argv[0]); if (!cpSerialDevice) { print_usage_exit(argv); } if (daemonize) { /* Prepare for return value passing from the initialization procedure of the daemon process */ if (daemon_retval_init() < 0) { daemon_log(LOG_ERR, "Failed to create pipe."); return 1; } /* Do the fork */ if ((pid = daemon_fork()) < 0) { /* Exit on error */ daemon_log(LOG_ERR, "Failed to fork() daemon process."); daemon_retval_done(); return 1; } else if (pid) { /* The parent */ int ret; /* Wait for 20 seconds for the return value passed from the daemon process */ if ((ret = daemon_retval_wait(20)) < 0) { daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); return 255; } if (ret == 0) { daemon_log(LOG_INFO, "Daemon process started."); } else { daemon_log(LOG_ERR, "Daemon returned %i.", ret); } return ret; } else { /* The daemon */ /* Close FDs */ if (daemon_close_all(-1) < 0) { daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); /* Send the error condition to the parent process */ daemon_retval_send(1); goto finish; } daemon_log_use = DAEMON_LOG_SYSLOG; /* Send OK to parent process */ daemon_retval_send(0); daemon_log(LOG_INFO, "Daemon started"); } } else { /* Running foreground - set verbosity */ if (verbosity > LOG_WARNING) { daemon_set_verbosity(verbosity); } } FD_ZERO(&rfds); /* Wait up to five seconds. */ tv.tv_sec = 5; tv.tv_usec = 0; if ((serial_open(cpSerialDevice, u32BaudRate) < 0) || (eTunDeviceOpen(cpTunDevice) != E_TUN_OK)) { goto finish; } /* Install signal handlers */ signal(SIGTERM, vQuitSignalHandler); signal(SIGINT, vQuitSignalHandler); eJennicModuleStart(); while (bRunning) { int max_fd = 0; /* Wait up to one second each loop. */ tv.tv_sec = 1; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(serial_fd, &rfds); if (serial_fd > max_fd) { max_fd = serial_fd; } FD_SET(tun_fd, &rfds); if (tun_fd > max_fd) { max_fd = tun_fd; } /* Wait for data on one either the serial port or the TUN interface. */ retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); if (retval == -1) { daemon_log(LOG_ERR, "error in select(): %s", strerror(errno)); } else if (retval) { int i; /* Got data on one of the file descriptors */ for (i = 0; i < max_fd + 1; i++) { if (FD_ISSET(i, &rfds) && (i == serial_fd)) { if(bSL_ReadMessage(&sIncomingMsg.u8Type, &sIncomingMsg.u16Length, sizeof(sIncomingMsg.u8Message), sIncomingMsg.u8Message)) { if (eJennicModuleProcessMessage(sIncomingMsg.u8Type, sIncomingMsg.u16Length, sIncomingMsg.u8Message) != E_MODULE_OK) { daemon_log(LOG_ERR, "Error communicating with border router module"); bRunning = FALSE; } } } else if (FD_ISSET(i, &rfds) && (i == tun_fd)) { if (eTunDeviceReadPacket() != E_TUN_OK) { daemon_log(LOG_ERR, "Error handling tun packet"); } /* Kick the state machine to prompt the sending of a ping packet if necessary. */ if (eJennicModuleStateMachine(1) != E_MODULE_OK) { daemon_log(LOG_ERR, "Error communicating with border router module"); bRunning = FALSE; } } else if (FD_ISSET(i, &rfds)) { daemon_log(LOG_DEBUG, "Data on unknown file desciptor (%d)", i); } else { /* Should not get here */ } } } else { /* Select timeout */ if (eJennicModuleStateMachine(1) != E_MODULE_OK) { daemon_log(LOG_ERR, "Error communicating with border router module"); bRunning = FALSE; } } } if (iResetCoordinator) { daemon_log(LOG_INFO, "Resetting Coordinator Module"); eJennicModuleReset(); } finish: if (daemonize) { daemon_log(LOG_INFO, "Daemon process exiting"); } return 0; }
int main(int argc, char **argv) { int pid, ret; struct sigaction new_action, old_action; GOptionContext *ctx; GError *parse_err = NULL; daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); daemon_pid_file_proc = conf_pid_file_proc; if (conf_init() < 0) return EXIT_FAILURE; ctx = g_option_context_new(""); g_option_context_add_main_entries(ctx, options, PACKAGE); g_option_context_set_summary(ctx, PACKAGE"-"VERSION GITHEAD" - mpd cron daemon"); if (!g_option_context_parse(ctx, &argc, &argv, &parse_err)) { g_printerr("option parsing failed: %s\n", parse_err->message); g_option_context_free(ctx); g_error_free(parse_err); return EXIT_FAILURE; } g_option_context_free(ctx); if (optv) { about(); cleanup(); return EXIT_SUCCESS; } #ifdef DAEMON_SET_VERBOSITY_AVAILABLE if (conf.no_daemon) daemon_set_verbosity(LOG_DEBUG); #endif /* DAEMON_SET_VERBOSITY_AVAILABLE */ /* Version to environment variable */ g_setenv("MPDCRON_PACKAGE", PACKAGE, 1); g_setenv("MPDCRON_VERSION", VERSION, 1); g_setenv("MPDCRON_GITHEAD", GITHEAD, 1); /* Command line options to environment variables */ if (conf.no_daemon) g_unsetenv("MCOPT_DAEMONIZE"); else g_setenv("MCOPT_DAEMONIZE", "1", 1); /* Important! Parse configuration file before killing the daemon * because the configuration file has a pidfile and killwait option. */ cfd = g_key_file_new(); if (keyfile_load(&cfd) < 0) { cleanup(); return EXIT_FAILURE; } if (optk) { if (daemon_pid_file_kill_wait(SIGINT, conf.killwait) < 0) { g_warning("Failed to kill daemon: %s", strerror(errno)); cleanup(); return EXIT_FAILURE; } daemon_pid_file_remove(); cleanup(); return EXIT_SUCCESS; } /* Logging */ g_log_set_default_handler(log_handler, GINT_TO_POINTER(conf.no_daemon ? 5 : conf.loglevel)); /* Signal handling */ new_action.sa_handler = sig_cleanup; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; #define HANDLE_SIGNAL(sig) \ do { \ sigaction((sig), NULL, &old_action); \ if (old_action.sa_handler != SIG_IGN) \ sigaction((sig), &new_action, NULL); \ } while (0) HANDLE_SIGNAL(SIGABRT); HANDLE_SIGNAL(SIGSEGV); HANDLE_SIGNAL(SIGINT); HANDLE_SIGNAL(SIGTERM); #undef HANDLE_SIGNAL if (conf.no_daemon) { /* Create the main loop */ loop = g_main_loop_new(NULL, FALSE); #ifdef HAVE_GMODULE /* Load modules which may add initial events */ keyfile_load_modules(&cfd); #endif /* HAVE_GMODULE */ g_key_file_free(cfd); cfd = NULL; /* Add default initial events */ loop_connect(); /* Run the main loop */ g_main_loop_run(loop); cleanup(); return EXIT_SUCCESS; } /* Daemonize */ if ((pid = daemon_pid_file_is_running()) > 0) { g_critical("Daemon already running on PID %u", pid); return EXIT_FAILURE; } daemon_retval_init(); pid = daemon_fork(); if (pid < 0) { g_critical("Failed to fork: %s", strerror(errno)); daemon_retval_done(); return EXIT_FAILURE; } else if (pid != 0) { /* Parent */ cleanup(); if ((ret = daemon_retval_wait(2)) < 0) { g_critical("Could not receive return value from daemon process: %s", strerror(errno)); return 255; } if (ret != 0) g_critical("Daemon returned %i as return value", ret); else g_critical("Daemon returned %i as return value", ret); return ret; } else { /* Daemon */ if (daemon_close_all(-1) < 0) { g_critical("Failed to close all file descriptors: %s", strerror(errno)); daemon_retval_send(1); return EXIT_FAILURE; } if (daemon_pid_file_create() < 0) { g_critical("Failed to create PID file: %s", strerror(errno)); daemon_retval_send(2); return EXIT_FAILURE; } /* Send OK to parent process */ daemon_retval_send(0); /* Create the main loop */ loop = g_main_loop_new(NULL, FALSE); #ifdef HAVE_GMODULE /* Load modules which may add initial events */ keyfile_load_modules(&cfd); #endif /* HAVE_GMODULE */ g_key_file_free(cfd); cfd = NULL; /* Add default initial events */ loop_connect(); /* Run the main loop */ g_main_loop_run(loop); cleanup(); return EXIT_SUCCESS; } return EXIT_SUCCESS; }