long redrobd_voltage_monitor_thread::setup(void) { try { redrobd_log_writeln(get_name() + " : setup started"); init_members(); // Start timer controlling when to log voltages if (m_voltage_log_timer.reset() != TIMER_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR, "Error resetting voltage log timer for thread %s", get_name().c_str()); } redrobd_log_writeln(get_name() + " : setup done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_voltage_monitor_thread::setup->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long redrobd_rc_net_server_thread::execute(void *arg) { // Make GCC happy (-Wextra) if (arg) { return THREAD_INTERNAL_ERROR; } try { redrobd_log_writeln(get_name() + " : execute started"); handle_clients(); redrobd_log_writeln(get_name() + " : execute done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_rc_net_server_thread::execute->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
static void client_srv_passive(char *arg) { int h1, h2, h3, h4, p1, p2; u_int32_t addr, ladr; u_int16_t port; int incr; if (arg == NULL) /* Basic sanity check */ return; /* ** Read the port. According to RFC 1123, 4.1.2.6, ** we have to scan the string for the first digit. */ while (*arg < '0' || *arg > '9') arg++; if (sscanf(arg, "%d,%d,%d,%d,%d,%d", &h1, &h2, &h3, &h4, &p1, &p2) != 6) { syslog_error("bad PASV 277 response from server for %s", ctx.cli_ctrl->peer); client_respond(425, NULL, "Can't open data connection"); client_data_reset(MOD_RESET); ctx.expect = EXP_IDLE; return; } addr = (u_int32_t) ((h1 << 24) + (h2 << 16) + (h3 << 8) + h4); port = (u_int16_t) ((p1 << 8) + p2); syslog_write(T_DBG, "got SRV-PASV %s:%d for %s:%d", socket_addr2str(addr), port, ctx.cli_ctrl->peer, ctx.cli_ctrl->port); /* ** should we bind a rand(port-range) or increment? */ incr = !config_bool(NULL,"SockBindRand", 0); /* ** Open a connection to the server at the given port */ ladr = socket_sck2addr(ctx.srv_ctrl->sock, LOC_END, NULL); if (socket_d_connect(addr, port, ladr, ctx.srv_lrng, ctx.srv_urng, &(ctx.srv_data), "Srv-Data", incr) == 0) { syslog_error("can't connect Srv-Data for %s", ctx.cli_ctrl->peer); client_respond(425, NULL, "Can't open data connection"); client_data_reset(MOD_RESET); ctx.expect = EXP_IDLE; return; } /* ** Finally send the original command from the client */ client_xfer_fireup(); }
long redrobd_voltage_monitor_thread::cyclic_execute(void) { try { uint16_t adc_value; float v_mon; float v_in; // Get voltage from analog input m_mcp3008_io_ptr->read_single(m_mcp3008_io_chn, adc_value); v_mon = m_mcp3008_io_ptr->to_voltage(adc_value); // Scale back to input voltage v_in = v_mon / m_voltage_sf; // Lockdown read operation pthread_mutex_lock(&m_voltage_mutex); m_voltage.v_mon = v_mon; m_voltage.v_in = v_in; // Lockup read operation pthread_mutex_unlock(&m_voltage_mutex); // Check if time to log voltages if ( m_voltage_log_timer.get_elapsed_time() > LOG_VOLTAGES_INTERVAL ) { // Log voltages ostringstream oss_msg; oss_msg.precision(3); oss_msg << fixed; oss_msg << get_name() << " : Vmon=" << v_mon << ", Vin=" << v_in; redrobd_log_writeln(oss_msg.str()); oss_msg.str(""); // Reset timer if (m_voltage_log_timer.reset() != TIMER_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR, "Error resetting voltage log timer for thread %s", get_name().c_str()); } } return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_voltage_monitor_thread::cyclic_execute->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long redrobd_rc_net_server_thread::setup(void) { try { redrobd_log_writeln(get_name() + " : setup started"); // Create server socket if (create_tcp_socket(&m_server_sd) != SOCKET_SUPPORT_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED, "Create server socket failed in thread %s", get_name().c_str()); } // Create socket address socket_address server_sa; if (to_net_address(m_server_ip_address.c_str(), &server_sa.net_addr) != SOCKET_SUPPORT_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED, "Create server socket address failed in thread %s", get_name().c_str()); } server_sa.port = m_server_port; // Bind socket to local address and port if (bind_socket(m_server_sd, server_sa) != SOCKET_SUPPORT_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED, "Bind server socket failed in thread %s", get_name().c_str()); } // Mark socket as accepting connections if (listen_socket(m_server_sd, 0) != SOCKET_SUPPORT_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED, "Listen server socket failed in thread %s", get_name().c_str()); } redrobd_log_writeln(get_name() + " : setup done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_rc_net_server_thread::setup->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long redrobd_alive_thread::cyclic_execute(void) { try { redrobd_led_alive(m_led_alive_activate); // Toggle status LED on/off m_led_alive_activate = !m_led_alive_activate; return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_alive_thread::cyclic_execute->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long redrobd_voltage_monitor_thread::cleanup(void) { try { redrobd_log_writeln(get_name() + " : cleanup started"); redrobd_log_writeln(get_name() + " : cleanup done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_voltage_monitor_thread::cleanup->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long redrobd_rc_net_server_thread::cleanup(void) { try { redrobd_log_writeln(get_name() + " : cleanup started"); /////////////////////////////////////////////// // If no controlled shutdown was requested, // proceed with cleanup /////////////////////////////////////////////// if (!m_shutdown_requested) { // Shutdown server socket if (shutdown_socket(m_server_sd, true, true) != SOCKET_SUPPORT_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED, "Shutdown server socket failed in thread %s", get_name().c_str()); } // Close server socket if (close_socket(m_server_sd) != SOCKET_SUPPORT_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_SOCKET_OPERATION_FAILED, "Close server socket failed in thread %s", get_name().c_str()); } m_server_closed = true; } redrobd_log_writeln(get_name() + " : cleanup done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_rc_net_server_thread::cleanup->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long send_signal_self(int sig) { // Send signal to calling process if (kill(getpid(), sig) == -1) { syslog_error("kill failed for signal(%d), code=%d (%s)", sig, errno, strerror(errno)); return DAEMON_FAILURE; } return DAEMON_SUCCESS; }
long redrobd_alive_thread::cleanup(void) { try { redrobd_log_writeln(get_name() + " : cleanup started"); redrobd_led_alive(false); // Turn status LED off redrobd_log_writeln(get_name() + " : cleanup done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_alive_thread::cleanup->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long define_signal_handler(int sig, void (*handler)(int)) { struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = handler; if (sigaction(sig, &sa, NULL) == -1) { syslog_error("sigaction failed for signal(%d), code=%d (%s)", sig, errno, strerror(errno)); return DAEMON_FAILURE; } return DAEMON_SUCCESS; }
static long acquire_lock_file(const char *lock_file, int *fd_lock_file) { long rc = DAEMON_FAILURE; int fd; *fd_lock_file = DAEMON_BAD_FD_LOCK_FILE; // No file descriptor yet fd = open(lock_file, O_RDWR | O_CLOEXEC | O_CREAT, S_IRUSR | S_IWUSR); if (fd != -1) { struct flock fl; fl.l_type = F_WRLCK; // Place a write lock fl.l_whence = SEEK_SET; // on the entire file fl.l_start = 0; fl.l_len = 0; fl.l_pid = getpid(); if (fcntl(fd, F_SETLK, &fl) != -1) { // We have locked file, truncate to zero bytes if (ftruncate(fd, 0) != -1) { // Write PID to file char pid_text[20]; snprintf(pid_text, sizeof(pid_text), "%ld\n", (long)getpid()); if (write(fd, pid_text, strlen(pid_text)) == (int)strlen(pid_text)) { rc = DAEMON_SUCCESS; // We created the PID lock file, // truncated, and write the PID to it. *fd_lock_file = fd; // Return descriptor to caller } } } } if ( (rc != DAEMON_SUCCESS) && (fd != -1) ) { close(fd); syslog_error("Unable to acquire lock file '%s', code=%d (%s)", lock_file, errno, strerror(errno)); } return rc; }
void client_srv_open(void) { struct sockaddr_in saddr; u_int16_t lprt, lowrng, res; int sock, incr, retry; /* ** should we bind a rand(port-range) or increment? */ incr = !config_bool(NULL,"SockBindRand", 0); /* ** mark socket invalid */ sock = -1; /* ** Forward connection to destination */ retry = MAX_RETRIES; lprt = ctx.srv_lrng; while(0 <= retry--) { /* ** First of all, get a socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog_error("Srv-Ctrl: can't create socket for %s", ctx.cli_ctrl->peer); exit(EXIT_FAILURE); } socket_opts(sock, SK_CONTROL); /* ** check if we have to take care to a port range */ if( !(INPORT_ANY == ctx.srv_lrng && INPORT_ANY == ctx.srv_urng)) { u_int32_t ladr = INADDR_ANY; /* ** bind the socket, taking care of a given port range */ if(incr) { lowrng = lprt; #if defined(COMPILE_DEBUG) debug(2, "Srv-Ctrl: " "about to bind to %s:range(%d-%d)", socket_addr2str(ladr), lowrng, ctx.srv_urng); #endif res = socket_d_bind(sock, ladr, lowrng, ctx.srv_urng, incr); } else { lowrng = ctx.srv_lrng; #if defined(COMPILE_DEBUG) debug(2, "Srv-Ctrl: " "about to bind to %s:range(%d-%d)", socket_addr2str(ladr), lowrng, ctx.srv_urng); #endif res = socket_d_bind(sock, ladr, lowrng, ctx.srv_urng, incr); } if (INPORT_ANY == res) { /* nothing found? */ close(sock); syslog_error("Srv-Ctrl: can't bind to" " %s:%d for %s", socket_addr2str(ladr), (int)lprt, ctx.cli_ctrl->peer); exit(EXIT_FAILURE); } else { lprt = res; } } else lprt = INPORT_ANY; /* ** Okay, now try the actual connect to the server */ memset(&saddr, 0, sizeof(saddr)); saddr.sin_addr.s_addr = htonl(ctx.srv_addr); saddr.sin_family = AF_INET; saddr.sin_port = htons(ctx.srv_port); if (connect(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { #if defined(COMPILE_DEBUG) debug(2, "Srv-Ctrl: connect failed with '%s'", strerror(errno)); #endif close(sock); sock = -1; /* check if is makes sense to retry? ** perhaps we only need an other ** local port (EADDRNOTAVAIL) for ** this destination? */ if( !(EINTR == errno || EAGAIN == errno || EADDRINUSE == errno || EADDRNOTAVAIL == errno)) { /* ** an other (real) error ocurred */ syslog_error("Srv-Ctrl: " "can't connect %s:%d for %s", socket_addr2str(ctx.srv_addr), (int) ctx.srv_port, ctx.cli_ctrl->peer); exit(EXIT_FAILURE); } if(incr && INPORT_ANY != lprt) { /* increment lower range if we use ** increment mode and have a range */ if(lprt < ctx.srv_urng) { lprt++; } else { /* ** no more ports in range we can try */ syslog_error("Srv-Ctrl: " "can't connect %s:%d for %s", socket_addr2str(ctx.srv_addr), (int) ctx.srv_port, ctx.cli_ctrl->peer); exit(EXIT_FAILURE); } } } else break; } /* ** check if we have a valid, connected socket */ if(-1 == sock) { syslog_error("Srv-Ctrl: can't connect %s:%d for %s", socket_addr2str(ctx.srv_addr), (int) ctx.srv_port, ctx.cli_ctrl->peer); exit(EXIT_FAILURE); } if ((ctx.srv_ctrl = socket_init(sock)) == NULL) misc_die(FL, "cmds_user: ?srv_ctrl?"); ctx.srv_ctrl->ctyp = "Srv-Ctrl"; #if defined(COMPILE_DEBUG) debug(2, "Srv-Ctrl is %s:%d", ctx.srv_ctrl->peer, (int) ctx.srv_port); #endif ctx.expect = EXP_CONN; /* Expect Welcome */ }
long redrobd_ctrl_thread::cleanup(void) { try { redrobd_log_writeln(get_name() + " : cleanup started"); //////////////////////////////////////// // FINALIZE battery monitor //////////////////////////////////////// redrobd_log_writeln("About to finalize battery monitor thread"); // Take back ownership from auto_ptr redrobd_voltage_monitor_thread *thread_ptr2 = m_bat_mon_thread_auto.release(); try { // Finalize the cyclic battery monitor thread object redrobd_thread_finalize((thread *)thread_ptr2, BAT_MON_THREAD_STOP_TIMEOUT); } catch (...) { m_bat_mon_thread_auto = auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2); throw; } // Give back ownership to auto_ptr m_bat_mon_thread_auto = auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2); // Delete the cyclic battery monitor thread object m_bat_mon_thread_auto.reset(); //////////////////////////////////////// // FINALIZE motor control //////////////////////////////////////// // Finalize and delete the motor control object if (m_cont_steering) { m_mc_cont_steer_auto->finalize(); m_mc_cont_steer_auto.reset(); } else { m_mc_non_cont_steer_auto->finalize(); m_mc_non_cont_steer_auto.reset(); } //////////////////////////////////////// // FINALIZE camera control //////////////////////////////////////// // Finalize and delete the camera control object m_cc_auto->finalize(); m_cc_auto.reset(); //////////////////////////////////////// // FINALIZE remote control //////////////////////////////////////// // Finalize and delete the remote control objects m_rc_net_auto->finalize(); m_rc_net_auto.reset(); m_rc_rf_auto->finalize(); m_rc_rf_auto.reset(); //////////////////////////////////////// // FINALIZE HW configuration //////////////////////////////////////// // Finalize and delete the hardware configuration object m_hw_cfg_auto->finalize(); m_hw_cfg_auto.reset(); //////////////////////////////////////// // FINALIZE A/D Converter //////////////////////////////////////// // Finalize and delete A/D Converter m_mcp3008_io_ptr->finalize(); delete m_mcp3008_io_ptr; m_mcp3008_io_ptr = NULL; ///////////////////////////////// // FINALIZE ALIVE THREAD ///////////////////////////////// redrobd_log_writeln("About to finalize alive thread"); // Take back ownership from auto_ptr redrobd_alive_thread *thread_ptr1 = m_alive_thread_auto.release(); try { // Finalize the cyclic alive thread object redrobd_thread_finalize((thread *)thread_ptr1, ALIVE_THREAD_STOP_TIMEOUT); } catch (...) { m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1); throw; } // Give back ownership to auto_ptr m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1); // Delete the cyclic alive thread object m_alive_thread_auto.reset(); redrobd_log_writeln(get_name() + " : cleanup done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_ctrl_thread::cleanup->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
long redrobd_ctrl_thread::cyclic_execute(void) { try { // Check if shutdown was selected (DIP-switch) if ( (!m_shutdown_select) && (m_hw_cfg_auto->select_shutdown()) ) { redrobd_log_writeln(get_name() + " : Shutdown selected"); // Send signal to main process if (send_signal_self(SIG_TERMINATE_DAEMON) != DAEMON_SUCCESS) { THROW_EXP(REDROBD_LINUX_ERROR, REDROBD_SIGNAL_OPERATION_FAILED, "Error sending shutdown signal for thread %s", get_name().c_str()); } m_shutdown_select = true; // Only signal once } // Check battery voltage if ( !battery_voltage_ok() ) { redrobd_led_bat_low(true); // Turn status LED on } else { redrobd_led_bat_low(false); // Turn status LED off } // Check system stats check_system_stats(); // Check state and status of created threads check_thread_run_status(); // Check remote control steering uint16_t steering = get_remote_steering(); // Do motor control switch (steering) { case REDROBD_RC_STEER_NONE: motor_control(REDROBD_MC_NONE); break; case REDROBD_RC_STEER_FORWARD: if (m_verbose) { redrobd_log_writeln(get_name() + " : steer forward"); } motor_control(REDROBD_MC_FORWARD); break; case REDROBD_RC_STEER_REVERSE: if (m_verbose) { redrobd_log_writeln(get_name() + " : steer reverse"); } motor_control(REDROBD_MC_REVERSE); break; case REDROBD_RC_STEER_RIGHT: if (m_verbose) { redrobd_log_writeln(get_name() + " : steer right"); } motor_control(REDROBD_MC_RIGHT); break; case REDROBD_RC_STEER_LEFT: if (m_verbose) { redrobd_log_writeln(get_name() + " : steer left"); } motor_control(REDROBD_MC_LEFT); break; default: // All other steerings are ignored for now ostringstream oss_msg; oss_msg << get_name() << " : Got undefined steering = 0x" << hex << setw(4) << setfill('0') << (unsigned)steering; redrobd_log_writeln(oss_msg.str()); oss_msg.str(""); motor_control(REDROBD_MC_STOP); } // Check remote control camera code uint16_t camera_code = m_rc_net_auto->get_camera_code(); // Do camera control switch (camera_code) { case REDROBD_RC_CAMERA_NONE: camera_control(REDROBD_CC_NONE); break; case REDROBD_RC_CAMERA_STOP_STREAM: camera_control(REDROBD_CC_STOP_STREAM); break; case REDROBD_RC_CAMERA_START_STREAM: camera_control(REDROBD_CC_START_STREAM); break; default: // All other camera codes are ignored for now ostringstream oss_msg; oss_msg << get_name() << " : Got undefined camera code = 0x" << hex << setw(4) << setfill('0') << (unsigned)steering; redrobd_log_writeln(oss_msg.str()); oss_msg.str(""); } return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_ctrl_thread::cyclic_execute->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
static void client_xfer_fireup(void) { u_int32_t ladr = INADDR_ANY; int incr; /* ** should we bind a rand(port-range) or increment? */ incr = !config_bool(NULL,"SockBindRand", 0); /* ** If appropriate, connect to the client's data port */ if (ctx.cli_mode == MOD_ACT_FTP) { /* ** TransProxy mode: check if we can use our real ** ip instead of the server's one as our local ip, ** we pre-bind the socket/ports to before connect. */ if(config_bool(NULL, "AllowTransProxy", 0)) { ladr = config_addr(NULL, "Listen", (u_int32_t)INADDR_ANY); } if(INADDR_ANY == ladr) { ladr = socket_sck2addr(ctx.cli_ctrl->sock, LOC_END, NULL); } if (socket_d_connect(ctx.cli_addr, ctx.cli_port, ladr, ctx.act_lrng, ctx.act_urng, &(ctx.cli_data), "Cli-Data", incr) == 0) { syslog_error("can't connect Cli-Data for %s", ctx.cli_ctrl->peer); client_respond(425, NULL, "Can't open data connection"); client_data_reset(MOD_RESET); ctx.expect = EXP_IDLE; return; } } /* ** Send the original command from the client */ if (ctx.xfer_arg[0] != '\0') { socket_printf(ctx.srv_ctrl, "%s %s\r\n", ctx.xfer_cmd, ctx.xfer_arg); syslog_write(T_INF, "'%s %s' sent for %s", ctx.xfer_cmd, ctx.xfer_arg, ctx.cli_ctrl->peer); } else { socket_printf(ctx.srv_ctrl, "%s\r\n", ctx.xfer_cmd); syslog_write(T_INF, "'%s' sent for %s", ctx.xfer_cmd, ctx.cli_ctrl->peer); } /* ** Prepare the handling and statistics buffers */ memset(ctx.xfer_rep, 0, sizeof(ctx.xfer_rep)); ctx.xfer_beg = time(NULL); ctx.expect = EXP_XFER; /* Expect 226 complete */ }
long redrobd_ctrl_thread::setup(void) { try { redrobd_log_writeln(get_name() + " : setup started"); init_members(); ///////////////////////////////// // INITIALIZE ALIVE THREAD ///////////////////////////////// // Create the cyclic alive thread object with garbage collector redrobd_alive_thread *thread_ptr1 = new redrobd_alive_thread(ALIVE_THREAD_NAME, ALIVE_THREAD_FREQUENCY); m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1); redrobd_log_writeln("About to initialize alive thread"); // Take back ownership from auto_ptr thread_ptr1 = m_alive_thread_auto.release(); try { // Initialize cyclic alive thread object redrobd_thread_initialize((thread *)thread_ptr1, ALIVE_THREAD_START_TIMEOUT, ALIVE_THREAD_EXECUTE_TIMEOUT); } catch (...) { m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1); throw; } // Give back ownership to auto_ptr m_alive_thread_auto = auto_ptr<redrobd_alive_thread>(thread_ptr1); ///////////////////////////////// // INITIALIZE A/D Converter ///////////////////////////////// // Create the A/D Converter object m_mcp3008_io_ptr = new mcp3008_io(MCP3008_SPI_DEV, MCP3008_REF_VOLTAGE); // Initialize A/D Converter m_mcp3008_io_ptr->initialize(MCP3008_SPI_SPEED); ///////////////////////////////// // INITIALIZE HW configuration ///////////////////////////////// // Create the hardware configuration object object with garbage collector redrobd_hw_cfg *redrobd_hw_cfg_ptr = new redrobd_hw_cfg(m_mcp3008_io_ptr, (MCP3008_IO_CHANNEL)MCP3008_CHN_SHUTDOWN, (MCP3008_IO_CHANNEL)MCP3008_CHN_CONT_STEER); m_hw_cfg_auto = auto_ptr<redrobd_hw_cfg>(redrobd_hw_cfg_ptr); // Initialize hardware configuration m_hw_cfg_auto->initialize(); ///////////////////////////////// // INITIALIZE remote control ///////////////////////////////// // Create the remote control object with garbage collector (RF, Radio) redrobd_rc_rf *rc_rf_ptr = new redrobd_rc_rf(PIN_RF_IN_3, // Forward PIN_RF_IN_2, // Reverse PIN_RF_IN_0, // Right PIN_RF_IN_1); // Left m_rc_rf_auto = auto_ptr<redrobd_rc_rf>(rc_rf_ptr); // Initialize remote control (RF, Radio) m_rc_rf_auto->initialize(); // Create the remote control object with garbage collector (NET, Sockets) redrobd_rc_net *rc_net_ptr = new redrobd_rc_net(RC_NET_SERVER_IP, // Server local IP address RC_NET_SERVER_PORT); // Server local port m_rc_net_auto = auto_ptr<redrobd_rc_net>(rc_net_ptr); // Initialize remote control (NET, Sockets) m_rc_net_auto->initialize(); m_rc_net_auto->set_voltage(0.0); ///////////////////////////////// // INITIALIZE camera control ///////////////////////////////// // Create the camera control object with garbage collector redrobd_camera_ctrl *cc_ptr = new redrobd_camera_ctrl(); m_cc_auto = auto_ptr<redrobd_camera_ctrl>(cc_ptr); // Initialize camera control m_cc_auto->initialize(); ///////////////////////////////// // INITIALIZE motor control ///////////////////////////////// // Check if continuous steering was selected (DIP-switch) m_cont_steering = m_hw_cfg_auto->select_continuous_steering(); if (m_cont_steering) { redrobd_log_writeln(get_name() + " : Continuous steering selected"); } else { redrobd_log_writeln(get_name() + " : Non-continuous steering selected"); } // Create the motor control object with garbage collector if (m_cont_steering) { redrobd_mc_cont_steer *mc_ptr = new redrobd_mc_cont_steer(PIN_L293D_1A, // Right motor PIN_L293D_2A, PIN_L293D_3A, // Left motor PIN_L293D_4A); m_mc_cont_steer_auto = auto_ptr<redrobd_mc_cont_steer>(mc_ptr); } else { redrobd_mc_non_cont_steer *mc_ptr = new redrobd_mc_non_cont_steer(PIN_L293D_1A, // Right motor PIN_L293D_2A, PIN_L293D_3A, // Left motor PIN_L293D_4A); m_mc_non_cont_steer_auto = auto_ptr<redrobd_mc_non_cont_steer>(mc_ptr); } // Initialize motor control if (m_cont_steering) { m_mc_cont_steer_auto->initialize(); } else { m_mc_non_cont_steer_auto->initialize(); } ///////////////////////////////// // INITIALIZE battery monitor ///////////////////////////////// // Create the cyclic battery monitor thread object with garbage collector redrobd_voltage_monitor_thread *thread_ptr2 = new redrobd_voltage_monitor_thread(BAT_MON_THREAD_NAME, BAT_MON_THREAD_FREQUENCY, m_mcp3008_io_ptr, (MCP3008_IO_CHANNEL)MCP3008_CHN_VBAT, MCP3008_CHN_VBAT_SF); m_bat_mon_thread_auto = auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2); redrobd_log_writeln("About to initialize battery monitor thread"); // Take back ownership from auto_ptr thread_ptr2 = m_bat_mon_thread_auto.release(); try { // Initialize cyclic battery monitor thread object redrobd_thread_initialize((thread *)thread_ptr2, BAT_MON_THREAD_START_TIMEOUT, BAT_MON_THREAD_EXECUTE_TIMEOUT); } catch (...) { m_bat_mon_thread_auto = auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2); throw; } // Give back ownership to auto_ptr m_bat_mon_thread_auto = auto_ptr<redrobd_voltage_monitor_thread>(thread_ptr2); // Start timer controlling when to check battery if (m_battery_check_timer.reset() != TIMER_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR, "Error resetting battery check timer for thread %s", get_name().c_str()); } // Start timer controlling when to check system stats if (m_sys_stat_check_timer.reset() != TIMER_SUCCESS) { THROW_EXP(REDROBD_INTERNAL_ERROR, REDROBD_TIME_ERROR, "Error resetting system stats check timer for thread %s", get_name().c_str()); } redrobd_log_writeln(get_name() + " : setup done"); return THREAD_SUCCESS; } catch (excep &exp) { syslog_error(redrobd_error_syslog_string(exp).c_str()); return THREAD_INTERNAL_ERROR; } catch (...) { syslog_error("redrobd_ctrl_thread::setup->Unexpected exception"); return THREAD_INTERNAL_ERROR; } }
static void client_srv_ctrl_read(char *str) { int code, c1, c2, c3; char *arg; if (str == NULL) /* Basic sanity check */ return; syslog_write(T_DBG, "from Server-PI (%d): '%.512s'", ctx.srv_ctrl->sock, str); #if defined(COMPILE_DEBUG) debug(1, "from Server-PI (%d): '%.512s'", ctx.srv_ctrl->sock, str); #endif /* ** Intermediate responses can usually be forwarded */ if (*str < '2' || *str > '5' || str[3] != ' ') { /* ** If this is the destination host's ** welcome message let's discard it. */ if (ctx.expect == EXP_CONN) return; if (ctx.expect == EXP_USER && UAUTH_NONE != ctx.auth_mode) return; #if defined(COMPILE_DEBUG) debug(2, "'%.4s'... forwarded to %s %d=%s", str, ctx.cli_ctrl->ctyp, ctx.cli_ctrl->sock, ctx.cli_ctrl->peer); #endif socket_printf(ctx.cli_ctrl, "%s\r\n", str); return; } /* ** Consider only valid final response codes */ if ((code = atoi(str)) < 200 || code > 599) { syslog_error("bad response %d from server for %s", code, ctx.srv_ctrl->peer); return; } c1 = code / 100; c2 = (code % 100) / 10; c3 = code % 10; for (arg = str + 3; *arg == ' '; arg++) ; /* ** We have a response code, go see what we expected */ switch (ctx.expect) { case EXP_CONN: /* ** Waiting for a 220 Welcome */ if (c1 == 2) { socket_printf(ctx.srv_ctrl, "USER %s\r\n", ctx.username); ctx.expect = EXP_USER; } else { if(UAUTH_NONE != ctx.auth_mode) { client_respond(530, NULL, "Login incorrect"); } else { socket_printf(ctx.cli_ctrl, "%s\r\n", str); } ctx.expect = EXP_IDLE; ctx.cli_ctrl->kill = 1; } break; case EXP_USER: /* ** Only the following codes are useful: ** 230=logged in, ** 331=need password, ** 332=need password+account */ if(UAUTH_NONE != ctx.auth_mode) { /* ** logged in, NO password needed */ if(c1 == 2 && c2 == 3) { client_respond(230, NULL, "User logged in, proceed."); ctx.expect = EXP_IDLE; break; } else /* ** OK, password (+account) needed */ if(c1 == 3 && c2 == 3) { if(ctx.userpass) { socket_printf(ctx.srv_ctrl, "PASS %s\r\n", ctx.userpass); misc_free(FL, ctx.userpass); ctx.userpass = NULL; } else { socket_printf(ctx.srv_ctrl, "PASS \r\n"); } ctx.expect = EXP_PTHR; break; } } /* ** pass server response through to client */ socket_printf(ctx.cli_ctrl, "%s\r\n", str); if (c1 != 2 && c1 != 3) { ctx.cli_ctrl->kill = 1; } ctx.expect = EXP_IDLE; break; case EXP_ABOR: if (c1 == 2) { client_data_reset(MOD_RESET); ctx.expect = EXP_IDLE; } break; case EXP_PASV: if (code == 227 && *arg != '\0') { client_srv_passive(arg); } else { socket_printf(ctx.cli_ctrl, "%s\r\n", str); client_data_reset(MOD_RESET); ctx.expect = EXP_IDLE; } break; case EXP_PORT: if (code == 200) { client_xfer_fireup(); } else { socket_printf(ctx.cli_ctrl, "%s\r\n", str); client_data_reset(MOD_RESET); ctx.expect = EXP_IDLE; } break; case EXP_XFER: /* ** Distinguish between success and failure */ if (c1 == 2) { misc_strncpy(ctx.xfer_rep, str, sizeof(ctx.xfer_rep)); } else { socket_printf(ctx.cli_ctrl, "%s\r\n", str); if(config_bool(NULL,"FailResetsPasv", 0)) { client_data_reset(MOD_RESET); } else { client_data_reset(ctx.cli_mode); } } ctx.expect = EXP_IDLE; break; case EXP_PTHR: socket_printf(ctx.cli_ctrl, "%s\r\n", str); ctx.expect = EXP_IDLE; break; case EXP_IDLE: socket_printf(ctx.cli_ctrl, "%s\r\n", str); if (code == 421) { syslog_write(T_WRN, "server closed connection " "for %s", ctx.cli_ctrl->peer); ctx.cli_ctrl->kill = 1; } else { syslog_write(T_WRN, "bogus '%.512s' from " "Server-PI for %s", ctx.cli_ctrl->peer, str); } break; } }
static int client_setup_file(CONTEXT *ctx, char *who) { char *p; u_int16_t l, u; /* ** little bit sanity check */ if( !(ctx && who && *who)) { return -1; } /* ** Inform the auditor that we are using the config file */ syslog_write(U_INF, "reading data for '%s' from cfg-file", who); /* ** Evaluate DestinationAddress, except we have magic_addr */ if (INADDR_ANY != ctx->magic_addr) { ctx->srv_addr = ctx->magic_addr; } else { ctx->srv_addr = config_addr(who, "DestinationAddress", INADDR_ANY); #if defined(COMPILE_DEBUG) debug(2, "file DestAddr for %s: '%s'", ctx->cli_ctrl->peer, socket_addr2str(ctx->srv_addr)); #endif } /* ** Evaluate DestinationPort, except we have magic_port */ if (INPORT_ANY != ctx->magic_port) { ctx->srv_port = ctx->magic_port; } else { ctx->srv_port = config_port(who, "DestinationPort", IPPORT_FTP); #if defined(COMPILE_DEBUG) debug(2, "file DestPort for %s: %d", ctx->cli_ctrl->peer, (int) ctx->srv_port); #endif } /* ** Evaluate the destination transfer mode */ p = config_str(who, "DestinationTransferMode", "client"); if(0 == strcasecmp(p, "active")) { ctx->srv_mode = MOD_ACT_FTP; } else if(0 == strcasecmp(p, "passive")) { ctx->srv_mode = MOD_PAS_FTP; } else if(0 == strcasecmp(p, "client")) { ctx->srv_mode = MOD_CLI_FTP; } else { syslog_error("can't eval DestMode for %s", ctx->cli_ctrl->peer); return -1; } #if defined(COMPILE_DEBUG) debug(2, "file DestMode for %s: %s", ctx->cli_ctrl->peer, p); #endif /* ** Evaluate min/max destination port range */ l = config_port(who, "DestinationMinPort", INPORT_ANY); u = config_port(who, "DestinationMaxPort", INPORT_ANY); if (l > 0 && u > 0 && u >= l) { ctx->srv_lrng = l; ctx->srv_urng = u; } else { ctx->srv_lrng = INPORT_ANY; ctx->srv_urng = INPORT_ANY; } #if defined(COMPILE_DEBUG) debug(2, "file DestRange for %s: %u-%u", ctx->cli_ctrl->peer, ctx->srv_lrng, ctx->srv_urng); #endif /* ** Evaluate min/max active port range */ l = config_port(who, "ActiveMinDataPort", INPORT_ANY); u = config_port(who, "ActiveMaxDataPort", INPORT_ANY); if (l > 0 && u > 0 && u >= l) { ctx->act_lrng = l; ctx->act_urng = u; } else { /* do not try to bind a port < 1024 if running as UID != 0 */ if(0 == getuid()) { ctx->act_lrng = (IPPORT_FTP - 1); ctx->act_urng = (IPPORT_FTP - 1); } else { ctx->act_lrng = INPORT_ANY; ctx->act_urng = INPORT_ANY; } } #if defined(COMPILE_DEBUG) debug(2, "file ActiveRange for %s: %u-%u", ctx->cli_ctrl->peer, ctx->act_lrng, ctx->act_urng); #endif /* ** Evaluate min/max passive port range */ l = config_port(who, "PassiveMinDataPort", INPORT_ANY); u = config_port(who, "PassiveMaxDataPort", INPORT_ANY); if (l > 0 && u > 0 && u >= l) { ctx->pas_lrng = l; ctx->pas_urng = u; } else { ctx->pas_lrng = INPORT_ANY; ctx->pas_urng = INPORT_ANY; } #if defined(COMPILE_DEBUG) debug(2, "file PassiveRange for %s: %u-%u", ctx->cli_ctrl->peer, ctx->pas_lrng, ctx->pas_urng); #endif /* ** Setup other configuration options */ ctx->same_adr = config_bool(who, "SameAddress", 1); ctx->timeout = config_int (who, "TimeOut", 900); #if defined(COMPILE_DEBUG) debug(2, "file SameAddress for %s: %s", ctx->cli_ctrl->peer, ctx->same_adr ? "yes" : "no"); debug(2, "file TimeOut for %s: %d", ctx->cli_ctrl->peer, ctx->timeout); #endif /* ** Adjust the allow/deny flags for the commands */ p = config_str(who, "ValidCommands", NULL); cmds_set_allow(p); return 0; }
int client_setup(char *pwd) { char *type; char *who; /* ** Setup defaults for the client's DTP process */ ctx.cli_mode = MOD_ACT_FTP; ctx.cli_addr = ctx.cli_ctrl->addr; ctx.cli_port = ctx.cli_ctrl->port; ctx.srv_addr = INADDR_ANY; ctx.srv_port = INPORT_ANY; /* ** select the proper name for user specific setup... */ if(NULL != ctx.userauth) { who = ctx.userauth; } else { who = ctx.username; } /* ** don't allow empty or invalid names... */ if(NULL != who && '\0' != who[0]) { char *ptr; #if defined(HAVE_REGEX) char *rule; void *preg = NULL; rule = config_str(NULL, "UserNameRule", "^[[:alnum:]]+([%20@/\\._-][[:alnum:]]+)*$"); syslog_write(T_DBG, "compiling UserNameRule: '%.1024s'", rule); if(NULL == (ptr = cmds_reg_comp(&preg, rule))) { return -1; } syslog_write(T_DBG, "DeHTMLized UserNameRule: '%.1024s'", ptr); ptr = cmds_reg_exec(preg, who); if(NULL != ptr) { syslog_write(U_WRN, "invalid user name '%.128s'%s: %s", who, (strlen(who)>128 ? "..." : ""), ptr); cmds_reg_comp(&preg, NULL); /* free regex ptr */ return -1; } else { cmds_reg_comp(&preg, NULL); /* free regex ptr */ } #else /* ** Simplified "emulation" of the above regex: */ if( !(isalnum(who[0]) && isalnum(who[strlen(who)-1]))) { syslog_write(U_ERR, "invalid user name '%.128s'%s", who, (strlen(who)>128 ? "..." : "")); return 1; } for(ptr=who+1; *ptr; ptr++) { if( !(isalnum(*ptr) || ' ' == *ptr || '@' == *ptr || '/' == *ptr || '.' == *ptr || '_' == *ptr || '-' == *ptr)) { syslog_write(U_ERR, "invalid user name '%.128s'%s", who, (strlen(who)>128 ? "..." : "")); return -1; } } #endif } else { /* HUH ?! */ syslog_write(U_ERR, "empty user name"); return -1; } /* ** user specific setup from config file ** with fallback to default values */ if(0 != client_setup_file(&ctx, who)) { return -1; } /* ** check if we have to authenticate the user ** ** authenticate user and setup user specific ** from ldap server if configured */ type = config_str(NULL, "UserAuthType", NULL); if(NULL != type) { if(0 == strcasecmp(type, "ldap")) { /* ** ldap server is mandatory */ if(NULL == config_str(NULL, "LDAPServer", NULL)) { misc_die(FL, "client_setup: ?LDAPServer?"); } /* ** ldap auth + setup */ if(0 != ldap_setup_user(&ctx, who, pwd ? pwd : "")) return -1; } else { misc_die(FL, "client_setup: unknown ?UserAuthType?"); } } else { /* ** try ldap setup only */ ldap_setup_user(&ctx, who, NULL); } /* ** Evaluate mandatory settings or refuse to run. */ errno = 0; if(INADDR_ANY == ctx.srv_addr || INADDR_BROADCAST == ctx.srv_addr) { syslog_error("can't eval DestAddr for %s", ctx.cli_ctrl->peer); return -1; } if(INPORT_ANY == ctx.srv_port) { syslog_error("can't eval DestPort for %s", ctx.cli_ctrl->peer); return -1; } return 0; /* all right */ }
static int client_setup_file(CONTEXT *ctx, char *who) { char *p; u_int16_t l, u; /* ** little bit sanity check */ if( !(ctx && who && *who)) { return -1; } /* ** Inform the auditor that we are using the config file */ syslog_write(U_INF, "[ %s ] reading data for '%s' from cfg-file", ctx->cli_ctrl->peer, who); /* ** Evaluate DestinationAddress, except we have magic_addr */ if (INADDR_ANY != ctx->magic_addr) { ctx->srv_addr = ctx->magic_addr; } else { ctx->srv_addr = config_addr(who, "DestinationAddress", INADDR_ANY); #if defined(COMPILE_DEBUG) debug(2, "[ %s ] file DestAddr for %s: '%s'", ctx->cli_ctrl->peer, ctx->cli_ctrl->peer, socket_addr2str(ctx->srv_addr)); #endif } /* ** Evaluate DestinationPort, except we have magic_port */ if (INPORT_ANY != ctx->magic_port) { ctx->srv_port = ctx->magic_port; } else { ctx->srv_port = config_port(who, "DestinationPort", IPPORT_FTP); #if defined(COMPILE_DEBUG) debug(2, "[ %s ] file DestPort for %s: %d", ctx->cli_ctrl->peer, ctx->cli_ctrl->peer, (int) ctx->srv_port); #endif } /* ** Evaluate the destination transfer mode */ p = config_str(who, "DestinationTransferMode", "client"); if(0 == strcasecmp(p, "active")) { ctx->srv_mode = MOD_ACT_FTP; } else if(0 == strcasecmp(p, "passive")) { ctx->srv_mode = MOD_PAS_FTP; } else if(0 == strcasecmp(p, "client")) { ctx->srv_mode = MOD_CLI_FTP; } else { syslog_error("can't eval DestMode for %s", ctx->cli_ctrl->peer); return -1; } #if defined(COMPILE_DEBUG) debug(2, "file DestMode for %s: %s", ctx->cli_ctrl->peer, p); #endif /* ** Evaluate min/max destination port range */ l = config_port(who, "DestinationMinPort", INPORT_ANY); u = config_port(who, "DestinationMaxPort", INPORT_ANY); if (l > 0 && u > 0 && u >= l) { ctx->srv_lrng = l; ctx->srv_urng = u; } else { ctx->srv_lrng = INPORT_ANY; ctx->srv_urng = INPORT_ANY; } #if defined(COMPILE_DEBUG) debug(2, "file DestRange for %s: %u-%u", ctx->cli_ctrl->peer, ctx->srv_lrng, ctx->srv_urng); #endif /* ** Evaluate min/max active port range */ l = config_port(who, "ActiveMinDataPort", INPORT_ANY); u = config_port(who, "ActiveMaxDataPort", INPORT_ANY); if (l > 0 && u > 0 && u >= l) { ctx->act_lrng = l; ctx->act_urng = u; } else { /* do not try to bind a port < 1024 if running as UID != 0 */ if(0 == getuid()) { ctx->act_lrng = (IPPORT_FTP - 1); ctx->act_urng = (IPPORT_FTP - 1); } else { ctx->act_lrng = INPORT_ANY; ctx->act_urng = INPORT_ANY; } } #if defined(COMPILE_DEBUG) debug(2, "file ActiveRange for %s: %u-%u", ctx->cli_ctrl->peer, ctx->act_lrng, ctx->act_urng); #endif /* ** Evaluate min/max passive port range */ l = config_port(who, "PassiveMinDataPort", INPORT_ANY); u = config_port(who, "PassiveMaxDataPort", INPORT_ANY); if (l > 0 && u > 0 && u >= l) { ctx->pas_lrng = l; ctx->pas_urng = u; } else { ctx->pas_lrng = INPORT_ANY; ctx->pas_urng = INPORT_ANY; } #if defined(COMPILE_DEBUG) debug(2, "file PassiveRange for %s: %u-%u", ctx->cli_ctrl->peer, ctx->pas_lrng, ctx->pas_urng); #endif /* ** Setup other configuration options */ ctx->same_adr = config_bool(who, "SameAddress", 1); ctx->timeout = config_int (who, "TimeOut", 900); #if defined(COMPILE_DEBUG) debug(2, "file SameAddress for %s: %s", ctx->cli_ctrl->peer, ctx->same_adr ? "yes" : "no"); debug(2, "file TimeOut for %s: %d", ctx->cli_ctrl->peer, ctx->timeout); #endif /*** Adjust the allow/deny flags for the commands ** Fred patch */ char dest[17]; char ipdest[17]; char ipsrc[17]; strcpy (ipsrc,ctx->cli_ctrl->peer); strcpy (ipdest, socket_addr2str(ctx->srv_addr)); syslog_write(U_INF, "\n"); syslog_write(U_INF, "[ %s ] Fred Patch rules dest: %s src: %s", ipsrc, ipdest, ipsrc); char groupname[]="group"; char commandename[]="ValidCommands"; char *group; FILE *fp; group = "group1"; int ix; int ix2; u_int32_t dnsaddr; for(ix=1; group != NULL; ix++) { sprintf (&groupname[5],"%d",ix); group = config_str(who, groupname, NULL); } syslog_write(U_INF, "[ %s ] Number of groups: %d", ipsrc, ix-2); for (ix2=1; ix2 <= ix-2; ix2++) { sprintf (&groupname[5],"%d",ix2); group = config_str(who, groupname, NULL); syslog_write(U_INF, "[ %s ] Reading: %s",ipsrc, group ); if ((fp = fopen(group, "r")) == NULL) { syslog_write(U_INF, "File not found"); return 0; } else { fseek(fp, 0, SEEK_SET); while (fgets(dest, 17 , fp) != NULL) { // Pour une IP // Correction Bug Ligne sans \n dest[16] = '\n'; char *c = strchr (dest, '\n'); *c = 0; /* Dns resolution */ if (ipdest != dest) { dnsaddr = socket_str2addr(dest, INADDR_ANY); if (dnsaddr != 0) strcpy (dest, socket_addr2str(dnsaddr)); } if (strcmp(dest,ipdest) == 0 || strcmp(dest,ipsrc) == 0) { sprintf (&commandename[13],"%d",ix); p = config_str(who,commandename, NULL); cmds_set_allow(p); syslog_write(U_INF, "[ %s ] Apply rules for: %s dst: %s",ipsrc, ipsrc, ipdest); syslog_write(U_INF, "[ %s ] Server match %s ",ipsrc, group ); syslog_write(U_INF, "\n"); fclose(fp); return 0; } // Network if (strchr(dest, 'x') != NULL) { char *c = strchr(dest, 'x'); *c = 0; int longueur; longueur = strlen(dest); if (strncmp(dest,ipdest,longueur) == 0 || strncmp(dest,ipsrc,longueur) == 0) { sprintf (&commandename[13],"%d",ix); p = config_str(who,commandename, NULL); cmds_set_allow(p); syslog_write(U_INF, "[ %s ] Apply rules for Network: %s src: %s",ipsrc, ipdest, ipsrc); syslog_write(U_INF, "[ %s ] Server match %s ",ipsrc, group ); syslog_write(U_INF, "\n"); fclose(fp); return 0; } } } fclose(fp); } } syslog_write(U_INF, "[ %s ] Oh, Oh, no rule found -> defaultrules", ipsrc) ; p = config_str(who, "defaultrules", NULL); cmds_set_allow(p); return 0; }
long become_daemon(const char *run_as_user, const char *work_dir, const char *lock_file, int *fd_lock_file) { pid_t pid; int fd; *fd_lock_file = DAEMON_BAD_FD_LOCK_FILE; // Switch to specified user if (run_as_user) { struct passwd *pw_info = getpwnam(run_as_user); if (pw_info) { if (setuid(pw_info->pw_uid) == -1) { syslog_error("setuid failed for %s, code=%d (%s)", run_as_user, errno, strerror(errno)); return DAEMON_FAILURE; } } else { syslog_error("getpwnam failed for %s", run_as_user); return DAEMON_FAILURE; } } // Step 1 : Create a child process pid = fork(); switch (pid) { case -1 : syslog_error("fork(1) failed, code=%d (%s)", errno, strerror(errno)); return DAEMON_FAILURE; case 0 : break; // Child falls through default : exit(EXIT_SUCCESS); // Parent terminates OK } // Step 2 : Become leader of new session if (setsid() == -1) { syslog_error("setsid failed, code=%d (%s)", errno, strerror(errno)); return DAEMON_FAILURE; } // Step 3 : Ensure no controlling terminal pid = fork(); switch (pid) { case -1 : syslog_error("fork(2) failed, code=%d (%s)", errno, strerror(errno)); return DAEMON_FAILURE; case 0 : break; // Grand-child falls through default : exit(EXIT_SUCCESS); // Child terminates OK } // This process (grand-child) will be the actual daemon // Step 4 : Clear file mode creation mask umask(0); // Step 5 : Change current working directory if (chdir(work_dir) == -1) { syslog_error("chdir to '%s' failed, code=%d (%s)", work_dir, errno, strerror(errno)); return DAEMON_FAILURE; } // Step 6: Close standard file descriptors close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); // Step 7 : Redirect standard file descriptors to /dev/null fd = open("/dev/null", O_RDWR); if (fd != STDIN_FILENO) { syslog_error("Redirect STDIN failed, code=%d (%s)", errno, strerror(errno)); return DAEMON_FAILURE; } if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO) { syslog_error("Redirect STDOUT failed, code=%d (%s)", errno, strerror(errno)); return DAEMON_FAILURE; } if (dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO) { syslog_error("Redirect STDERR failed, code=%d (%s)", errno, strerror(errno)); return DAEMON_FAILURE; } // Create lock file to prevent more than one instance // of the daemon is being executed if (lock_file) { if (acquire_lock_file(lock_file, fd_lock_file) != DAEMON_SUCCESS) { return DAEMON_FAILURE; } } return DAEMON_SUCCESS; }