/* * UNO Monitor Daemon v.0.1.0 * Kidacro * https://kidacro.archamedis.net/git/kidacro/Arduino/src/branch/main/uno-stats-monitor * * monitor_daemon.c - Sends and Receives commands to UNO Monitor over serial connection * * Input Schema: * Start char is: '#' * End char is: '@' * 2nd char denotes which line number/mode to use * * Setting Schema: * LCDLength:LCDRows:LCDDelay:LEDBrightness:LEDDelay * 16:2:5:0:3 * * Example: * Line 1: #1Archamedis Status@ * Line 2: #299% free / etc.@ * LAVG -: #324@ * LSET 0: #16:2:5:0:3@ * * Output Schema: * Multimedia Controls use single characters to denote which button was pressed * P power * M mute * m mode * p pause/play * b back * f forward * e eq * - vol down * + vol up * r return * u usb scan * 0 number 0 * 1 number 1 * 2 number 2 * 3 number 3 * 4 number 4 * 5 number 5 * 6 number 6 * 7 number 7 * 8 number 8 * 9 number 9 * R repeat * Z other button pressed */ // C library #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // external libs #include #define MAX_ENTRIES 10 // global variables int debug = 0; int running = 0; char *conf_file_name = "unomond.conf"; char *pid_file_name = "/tmp/unomond.pid"; int pid_fd = -1; const char *app_name = "UnomonD v.0.1.0"; FILE *log_stream; char *log_file_name = NULL; int serial_port; struct termios tty; struct timeval __millis_start; // config file settings int delay = 5000; int line_length = 16; int line_count = 2; int lcd_delay = 5; int led_brightness = 5; int led_delay = 3; const char *cpu_temp_file = ""; const char *cpu_fanspeed_file = ""; char *drive_free_space[MAX_ENTRIES]; int drive_free_space_count; const char *ttydevice = "/dev/ttyACM0"; const char *ircmd_P = ""; // power const char *ircmd_M = ""; // mute const char *ircmd_m = ""; // mode const char *ircmd_p = ""; // pause/play const char *ircmd_b = ""; // back const char *ircmd_f = ""; // forward const char *ircmd_e = ""; // eq const char *ircmd_minus = ""; // vol down const char *ircmd_plus = ""; // vol up const char *ircmd_r = ""; // return const char *ircmd_u = ""; // usb scan const char *ircmd_0 = ""; // number 0 const char *ircmd_1 = ""; // number 1 const char *ircmd_2 = ""; // number 2 const char *ircmd_3 = ""; // number 3 const char *ircmd_4 = ""; // number 4 const char *ircmd_5 = ""; // number 5 const char *ircmd_6 = ""; // number 6 const char *ircmd_7 = ""; // number 7 const char *ircmd_8 = ""; // number 8 const char *ircmd_9 = ""; // number 9 const char *ircmd_R = ""; // repeat const char *ircmd_Z = ""; // other button pressed // function prototypes void init_millis(); unsigned long int millis(); char* timestamp(); bool file_exists(const char *filename); int read_conf_file(int reload); void handle_signal(int sig); static void daemonize(); void print_help(void); int serial_open_port(); int listen_server(); void send_stats(); void send_settings(); void log_method(); // from gather_stats.c void get_stats(); // local functions void init_millis() { gettimeofday(&__millis_start, NULL); } unsigned long int millis() { long mtime, seconds, useconds; struct timeval end; gettimeofday(&end, NULL); seconds = end.tv_sec - __millis_start.tv_sec; useconds = end.tv_usec - __millis_start.tv_usec; mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5; return mtime; } char* timestamp() { unsigned size = 300; char* buffer = malloc(size); //char time_s; time_t ltime; /* calendar time */ ltime=time(NULL); /* get current cal time */ //time_s = sprintf("%s",asctime( localtime(<ime) ) ); snprintf(buffer, size, "%s", asctime( localtime(<ime) )); return buffer; } bool file_exists(const char *filename) { FILE *fp = fopen(filename, "r"); bool is_exist = false; if(fp != NULL) { is_exist = true; fclose(fp); // close the file } return is_exist; } // read from config file int read_conf_file(int reload) { int ret = -1, n = 0; config_t cfg; config_setting_t *drive_free_space_entries; char *mydrive; const char *myttydevice; const char *mylogfile; const char *mycpu_temp_file; const char *mycpu_fanspeed_file; const char *myircmd_P; const char *myircmd_M; const char *myircmd_m; const char *myircmd_p; const char *myircmd_b; const char *myircmd_f; const char *myircmd_e; const char *myircmd_minus; const char *myircmd_plus; const char *myircmd_r; const char *myircmd_u; const char *myircmd_0; const char *myircmd_1; const char *myircmd_2; const char *myircmd_3; const char *myircmd_4; const char *myircmd_5; const char *myircmd_6; const char *myircmd_7; const char *myircmd_8; const char *myircmd_9; const char *myircmd_R; const char *myircmd_Z; if(conf_file_name == NULL) { syslog(LOG_INFO, "Configuration file: %s is empty or not valid.\n",conf_file_name); return(EXIT_FAILURE); } // check if conf file exists if(!file_exists(conf_file_name)) { return(EXIT_FAILURE); } // read the file config_init(&cfg); if(!config_read_file(&cfg, conf_file_name)) { syslog(LOG_INFO, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); config_destroy(&cfg); syslog(LOG_INFO, "Can not open configuration file: %s.\n",conf_file_name); return(EXIT_FAILURE); } // logfile (lookup logfile first and if found do a log_method to reload it) if(config_lookup_string(&cfg, "logfile", &mylogfile)) { log_file_name = strdup(mylogfile); log_method(); fprintf(log_stream, "Config: Using 'logfile': %s\n", mylogfile); } else { syslog(LOG_INFO, "No 'logfile' setting in configuration file, using default stderr output.\n"); } // load the base config // delay if(config_lookup_int(&cfg, "delay", &delay)) { fprintf(log_stream, "Config: Using 'delay': %i\n",delay); } else { fprintf(log_stream, "No 'delay' setting in configuration file, using default delay of %i.\n",delay); } // ttydevice if(config_lookup_string(&cfg, "tty", &myttydevice)) { ttydevice = strdup(myttydevice); fprintf(log_stream, "Config: Using 'TTY': %s\n",ttydevice); } else { fprintf(log_stream, "No 'tty' setting in configuration file, using default tty of %s.\n",ttydevice); } // line_length if(config_lookup_int(&cfg, "line_length", &line_length)) { fprintf(log_stream, "Config: Using 'line_length': %i\n",line_length); } else { fprintf(log_stream, "No 'line_length' setting in configuration file, using default line_length of %i.\n",line_length); } // line_count if(config_lookup_int(&cfg, "line_count", &line_count)) { fprintf(log_stream, "Config: Using 'line_count': %i\n",line_count); } else { fprintf(log_stream, "No 'line_count' setting in configuration file, using default line_count of %i.\n",line_count); } // led_brightness if(config_lookup_int(&cfg, "led_brightness", &led_brightness)) { fprintf(log_stream, "Config: Using 'led_brightness': %i\n",led_brightness); } else { fprintf(log_stream, "No 'led_brightness' setting in configuration file, using default led_brightness of %i.\n",led_brightness); } // led_delay if(config_lookup_int(&cfg, "led_delay", &led_delay)) { fprintf(log_stream, "Config: Using 'led_delay': %i\n",led_delay); } else { fprintf(log_stream, "No 'led_delay' setting in configuration file, using default led_delay of %i.\n",led_delay); } // lcd_delay if(config_lookup_int(&cfg, "lcd_delay", &lcd_delay)) { fprintf(log_stream, "Config: Using 'lcd_delay': %i\n",lcd_delay); } else { fprintf(log_stream, "No 'lcd_delay' setting in configuration file, using default lcd_delay of %i.\n",lcd_delay); } // cpu stats settings if(config_lookup_string(&cfg, "cpu_temp_file", &mycpu_temp_file)) { cpu_temp_file = strdup(mycpu_temp_file); } if(config_lookup_string(&cfg, "cpu_fanspeed_file", &mycpu_fanspeed_file)) { cpu_fanspeed_file = strdup(mycpu_fanspeed_file); } // IR commands if(config_lookup_string(&cfg, "ircmd_P", &myircmd_P)) { ircmd_P = strdup(myircmd_P); } if(config_lookup_string(&cfg, "ircmd_M", &myircmd_M)) { ircmd_M = strdup(myircmd_M); } if(config_lookup_string(&cfg, "ircmd_m", &myircmd_m)) { ircmd_m = strdup(myircmd_m); } if(config_lookup_string(&cfg, "ircmd_p", &myircmd_p)) { ircmd_p = strdup(myircmd_p); } if(config_lookup_string(&cfg, "ircmd_b", &myircmd_b)) { ircmd_b = strdup(myircmd_b); } if(config_lookup_string(&cfg, "ircmd_f", &myircmd_f)) { ircmd_f = strdup(myircmd_f); } if(config_lookup_string(&cfg, "ircmd_e", &myircmd_e)) { ircmd_e = strdup(myircmd_e); } if(config_lookup_string(&cfg, "ircmd_minus", &myircmd_minus)) { ircmd_minus = strdup(myircmd_minus); } if(config_lookup_string(&cfg, "ircmd_plus", &myircmd_plus)) { ircmd_plus = strdup(myircmd_plus); } if(config_lookup_string(&cfg, "ircmd_r", &myircmd_r)) { ircmd_r = strdup(myircmd_r); } if(config_lookup_string(&cfg, "ircmd_u", &myircmd_u)) { ircmd_u = strdup(myircmd_u); } if(config_lookup_string(&cfg, "ircmd_0", &myircmd_0)) { ircmd_0 = strdup(myircmd_0); } if(config_lookup_string(&cfg, "ircmd_1", &myircmd_1)) { ircmd_1 = strdup(myircmd_1); } if(config_lookup_string(&cfg, "ircmd_2", &myircmd_2)) { ircmd_2 = strdup(myircmd_2); } if(config_lookup_string(&cfg, "ircmd_3", &myircmd_3)) { ircmd_3 = strdup(myircmd_3); } if(config_lookup_string(&cfg, "ircmd_4", &myircmd_4)) { ircmd_4 = strdup(myircmd_4); } if(config_lookup_string(&cfg, "ircmd_5", &myircmd_5)) { ircmd_5 = strdup(myircmd_5); } if(config_lookup_string(&cfg, "ircmd_6", &myircmd_6)) { ircmd_6 = strdup(myircmd_6); } if(config_lookup_string(&cfg, "ircmd_7", &myircmd_7)) { ircmd_7 = strdup(myircmd_7); } if(config_lookup_string(&cfg, "ircmd_8", &myircmd_8)) { ircmd_8 = strdup(myircmd_8); } if(config_lookup_string(&cfg, "ircmd_9", &myircmd_9)) { ircmd_9 = strdup(myircmd_9); } if(config_lookup_string(&cfg, "ircmd_0", &myircmd_0)) { ircmd_0 = strdup(myircmd_0); } if(config_lookup_string(&cfg, "ircmd_R", &myircmd_R)) { ircmd_R = strdup(myircmd_R); } if(config_lookup_string(&cfg, "ircmd_Z", &myircmd_Z)) { ircmd_Z = strdup(myircmd_Z); } // free drive space settings drive_free_space_entries = config_lookup(&cfg, "drive_free_space"); drive_free_space_count = config_setting_length(drive_free_space_entries); fprintf(log_stream,"Config: I have %d free drive space entries:\n", drive_free_space_count); for(n = 0; n < drive_free_space_count; n++) { mydrive = strdup(config_setting_get_string_elem(drive_free_space_entries, n)); drive_free_space[n] = strdup(mydrive); fprintf(log_stream,"\t#%d. %s\n", n + 1, config_setting_get_string_elem(drive_free_space_entries, n)); } // report to syslog if(reload == 1) { syslog(LOG_INFO, "Reloaded configuration file %s of %s", conf_file_name, app_name); } else { syslog(LOG_INFO, "Configuration of %s read from file %s", app_name, conf_file_name); } config_destroy(&cfg); return ret; } void handle_signal(int sig) { int lock_result = 0; if(sig == SIGINT) { syslog(LOG_INFO, "Received INT signal, Stopping daemon ..."); /* Unlock and close lockfile */ if(pid_fd != -1) { lock_result = lockf(pid_fd, F_ULOCK, 0); if(lock_result < 0) { syslog(LOG_INFO, "Lockfile could not be unlocked."); } close(pid_fd); } /* Try to delete lockfile */ if(pid_file_name != NULL) { unlink(pid_file_name); } running = 0; /* Reset signal handling to default behavior */ signal(SIGINT, SIG_DFL); running = 0; return; } else if (sig == SIGHUP) { syslog(LOG_INFO, "Received HUP signal, Reloading daemon config file ..."); read_conf_file(1); } else if (sig == SIGCHLD) { syslog(LOG_INFO, "Received SIGCHLD signal... but I have no kids!."); return; } } static void daemonize() { pid_t pid = 0; int myfd = -1; int chdir_result = 0; int write_result = 0; /* Fork off the parent process */ pid = fork(); /* An error occurred */ if(pid < 0) { exit(EXIT_FAILURE); } /* Success: Let the parent terminate */ if(pid > 0) { exit(EXIT_SUCCESS); } /* On success: The child process becomes session leader */ if(setsid() < 0) { exit(EXIT_FAILURE); } /* Ignore signal sent from child to parent process */ signal(SIGCHLD, SIG_IGN); /* Fork off for the second time*/ pid = fork(); /* An error occurred */ if(pid < 0) { exit(EXIT_FAILURE); } /* Success: Let the parent terminate */ if(pid > 0) { exit(EXIT_SUCCESS); } /* Set new file permissions */ umask(0); /* Change the working directory to the root directory */ /* or another appropriated directory */ chdir_result = chdir("/"); if(chdir_result <0) { syslog(LOG_INFO, "Could not change to our working directory."); } /* Close all open file descriptors */ for(myfd = sysconf(_SC_OPEN_MAX); myfd > 0; myfd--) { close(myfd); } /* Reopen stdin (myfd = 0), stdout (myfd = 1), stderr (myfd = 2) */ stdin = fopen("/dev/null", "r"); stdout = fopen("/dev/null", "w+"); stderr = fopen("/dev/null", "w+"); /* Try to write PID of daemon to lockfile */ if(pid_file_name != NULL) { char str[256]; pid_fd = open(pid_file_name, O_RDWR|O_CREAT, 0640); if(pid_fd < 0) { /* Can't open lockfile */ exit(EXIT_FAILURE); } if(lockf(pid_fd, F_TLOCK, 0) < 0) { /* Can't lock file */ exit(EXIT_FAILURE); } /* Get current PID */ sprintf(str, "%d\n", getpid()); /* Write PID to lockfile */ write_result = write(pid_fd, str, strlen(str)); if(write_result < 0) { syslog(LOG_INFO, "PID could not be written to lockfile."); } } } void print_help(void) { printf("\n Usage: %s [OPTIONS]\n\n", app_name); printf(" Options:\n"); printf(" -h --help Print this help\n"); printf(" -c --conf_file filename Read configuration from the file\n"); printf(" -l --log_file filename Write logs to the file\n"); printf(" -d --daemon Daemonize this application\n"); printf(" -D --debug Debug this application\n"); printf(" -n --tty /dev/tty* TTY device to connect to\n"); printf(" -p --pid_file filename PID file used by daemonized app\n"); printf("\n"); } /* Open Serial Port */ int serial_open_port() { serial_port = open(ttydevice, O_RDWR); // Read in existing settings, and handle any error if(tcgetattr(serial_port, &tty) != 0) { fprintf(log_stream, "Error %i from tcgetattr in open ttydevice: %s\n", errno, strerror(errno)); syslog(LOG_INFO, "Could not open serial port! Exiting."); exit(EXIT_FAILURE); } tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common) tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common) tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size tty.c_cflag |= CS8; // 8 bits per byte (most common) tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common) tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1) tty.c_lflag &= ~ICANON; tty.c_lflag &= ~ECHO; // Disable echo tty.c_lflag &= ~ECHOE; // Disable erasure tty.c_lflag &= ~ECHONL; // Disable new-line echo tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars) tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed // tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX) // tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX) tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received. tty.c_cc[VMIN] = 0; // Set in/out baud rate to 9600 cfsetispeed(&tty, B9600); cfsetospeed(&tty, B9600); // Save tty settings, also checking for error if(tcsetattr(serial_port, TCSANOW, &tty) != 0) { fprintf(log_stream, "Error %i from tcsetattr in save tty settings: %s\n", errno, strerror(errno)); syslog(LOG_INFO, "Could not save serial port settings! Exiting."); exit(EXIT_FAILURE); } return 1; } /* Server */ int listen_server() { char read_buf [2]; int exec_result = 0; memset(&read_buf, '\0', sizeof(read_buf)); int num_bytes = read(serial_port, &read_buf, sizeof(read_buf)); // may be 0 if no bytes were received, and can also be -1 to signal an error. if(num_bytes < 0) { fprintf(log_stream, "Error reading: %s\n", strerror(errno)); return 1; } // do stuff goes here // switch on read_buf // input proto: PMmpbfe-+ru0123456789RZ if(strcmp(read_buf,"P") == 0) { exec_result = system(ircmd_P); } if(strcmp(read_buf,"M") == 0) { exec_result = system(ircmd_M); } if(strcmp(read_buf,"m") == 0) { exec_result = system(ircmd_m); } if(strcmp(read_buf,"p") == 0) { exec_result = system(ircmd_p); } if(strcmp(read_buf,"b") == 0) { exec_result = system(ircmd_b); } if(strcmp(read_buf,"f") == 0) { exec_result = system(ircmd_f); } if(strcmp(read_buf,"e") == 0) { exec_result = system(ircmd_e); } if(strcmp(read_buf,"-") == 0) { exec_result = system(ircmd_minus); } if(strcmp(read_buf,"+") == 0) { exec_result = system(ircmd_plus); } if(strcmp(read_buf,"r") == 0) { exec_result = system(ircmd_r); } if(strcmp(read_buf,"u") == 0) { exec_result = system(ircmd_u); } if(strcmp(read_buf,"0") == 0) { exec_result = system(ircmd_0); } if(strcmp(read_buf,"1") == 0) { exec_result = system(ircmd_1); } if(strcmp(read_buf,"2") == 0) { exec_result = system(ircmd_2); } if(strcmp(read_buf,"3") == 0) { exec_result = system(ircmd_3); } if(strcmp(read_buf,"4") == 0) { exec_result = system(ircmd_4); } if(strcmp(read_buf,"5") == 0) { exec_result = system(ircmd_5); } if(strcmp(read_buf,"6") == 0) { exec_result = system(ircmd_6); } if(strcmp(read_buf,"7") == 0) { exec_result = system(ircmd_7); } if(strcmp(read_buf,"8") == 0) { exec_result = system(ircmd_8); } if(strcmp(read_buf,"9") == 0) { exec_result = system(ircmd_9); } if(strcmp(read_buf,"R") == 0) { exec_result = system(ircmd_R); } if(strcmp(read_buf,"Z") == 0) { exec_result = system(ircmd_Z); } if(exec_result != 0) { fprintf(log_stream, "Command for %s failed with %i bytes. Received message: %s\n", read_buf, num_bytes, read_buf); syslog(LOG_INFO, "Command for %s failed.",read_buf); } if(debug) { fprintf(log_stream, "Read %i bytes. Received message: %s\n", num_bytes, read_buf); } return 0; } // send stats void send_stats(char *line_1, char *line_2, char *line_3) { int write_result = 0; unsigned int mylen_1 = 0; unsigned int mylen_2 = 0; unsigned int mylen_3 = 0; // Line 1 mylen_1 = strlen(line_1); write_result = write(serial_port, line_1, mylen_1); if(write_result < 0) { fprintf(log_stream, "Writing stats to serial report resulted in %i error. Size of message: %i\n", write_result, mylen_1); syslog(LOG_INFO, "Writing stats to serial report resulted in %i error.",write_result); } // Line 2 mylen_2 = strlen(line_2); write_result = write(serial_port, line_2, mylen_2); if(write_result < 0) { fprintf(log_stream, "Writing stats to serial report resulted in %i error. Size of message: %i\n", write_result, mylen_2); syslog(LOG_INFO, "Writing stats to serial report resulted in %i error.",write_result); } // Line 3 mylen_3 = strlen(line_3); write_result = write(serial_port, line_3, mylen_3); if(write_result < 0) { fprintf(log_stream, "Writing stats to serial report resulted in %i error. Size of message: %i\n", write_result, mylen_3); syslog(LOG_INFO, "Writing stats to serial report resulted in %i error.",write_result); } return; } /* Send settings to receiver */ // Setting Schema: // LCDLength:LCDRows:LCDDelay:LEDBrightness:LEDDelay // 16:2:5:0:3 void send_settings() { char myline[16]; unsigned int mylen = 0; int write_result = 0; sprintf(myline,"#0%i:%i:%i:%i:%i@",line_length,line_count,lcd_delay,led_brightness,led_delay); mylen = strlen(myline); write_result = write(serial_port, myline, mylen); if(write_result < 0) { fprintf(log_stream, "Writing settings to serial report resulted in %i error. Size of message: %i\n", write_result, mylen); syslog(LOG_INFO, "Writing settings to serial report resulted in %i error.",write_result); } return; } /* Daemon log method */ void log_method() { // close log file, if its open if(log_stream != stderr && log_stream != NULL) { fclose(log_stream); } // command line logfile takes precedence if(log_file_name != NULL && file_exists(log_file_name)) { log_stream = fopen(log_file_name, "a+"); if(log_stream == NULL) { syslog(LOG_ERR, "Can not open log file: %s, error: %s", log_file_name, strerror(errno)); log_stream = stderr; // stdout; return; } syslog(LOG_INFO, "Using logfile: %s\n",log_file_name); } // use stderr as failback else { log_stream = stderr; // stdout; } return; } /* Main function */ int main(int argc, char *argv[]) { static struct option long_options[] = { {"conf_file", required_argument, 0, 'c'}, {"log_file", required_argument, 0, 'l'}, {"help", no_argument, 0, 'h'}, {"debug", no_argument, 0, 'D'}, {"daemon", no_argument, 0, 'd'}, {"pid_file", required_argument, 0, 'p'}, {"tty", required_argument, 0, 'n'}, {NULL, 0, 0, 0} }; int value, option_index = 0; char *mytty = NULL; int start_daemonized = 0; // TODO: fix timestamps for logfile //fprintf(log_stream,"Timestamp %s\n",timestamp()); /* Open system log and write startup message to it */ openlog(argv[0], LOG_PID|LOG_CONS, LOG_DAEMON); syslog(LOG_INFO, "Started %s", app_name); /* Daemon will handle two signals */ signal(SIGINT, handle_signal); signal(SIGHUP, handle_signal); /* Set default log method */ log_method(); /* Read configuration from config file * dev: keep this b4 command line arguments so below takes precedence */ read_conf_file(0); /* Try to process all command line arguments */ while((value = getopt_long(argc, argv, "c:l:p:n:dDh", long_options, &option_index)) != -1) { switch (value) { case 'c': conf_file_name = strdup(optarg); fprintf(log_stream, "Reloading configuation from command line...\n"); read_conf_file(0); fprintf(log_stream, "Command Line: Using 'conffile': %s\n",conf_file_name); break; case 'l': log_file_name = strdup(optarg); log_method(); fprintf(log_stream, "Command Line: Using 'logfile': %s\n",log_file_name); break; case 'p': pid_file_name = strdup(optarg); fprintf(log_stream, "Command Line: Using 'pidfile': %s\n",pid_file_name); break; case 'n': mytty = strdup(optarg); ttydevice = mytty; fprintf(log_stream, "Command Line: Using 'TTY': %s\n",ttydevice); break; case 'd': start_daemonized = 1; fprintf(log_stream, "Command Line: Daemonizing...\n"); break; case 'D': debug = 1; fprintf(log_stream, "Command Line: Using Debugging\n"); break; case 'h': print_help(); return EXIT_SUCCESS; default: break; } } /* When daemonizing is requested at command line. */ if(start_daemonized == 1) { daemonize(); } /* This global variable can be changed in function handling signal */ running = 1; /* Main loop */ serial_open_port(); send_settings(); send_settings(); // yes twice due to the arduino getting reset on 1st access on linux (if not modified) init_millis(); while(running == 1) { listen_server(); // listen for IR events (blocks for ~1 second at a time) if(debug) { fprintf(log_stream,"Elapsed time: %ld milliseconds\n", millis()); } if(millis() >= (unsigned long)delay) { get_stats(); // get and send stats if its time to do so (non blocking timer) init_millis(); // reset timer } } close(serial_port); /* Close log file, when it is used. */ if(log_stream != stderr && log_stream != NULL) { fclose(log_stream); } /* Write system log and close it. */ syslog(LOG_INFO, "Stopped %s.\n", app_name); closelog(); return EXIT_SUCCESS; }