--- audio-entropyd.c 2010-02-28 06:21:33.000000000 -0700 +++ audio-entropyd.c 2014-03-05 10:45:29.688013075 -0700 @@ -17,10 +17,11 @@ #include <getopt.h> #include <unistd.h> #include <string.h> #include <syslog.h> #include <signal.h> +#include <time.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> #include <sys/wait.h> @@ -36,511 +37,1444 @@ #include "proc.h" #include "val.h" #include "RNGTEST.h" #include "error.h" -#define RANDOM_DEVICE "/dev/random" -#define DEFAULT_SAMPLE_RATE 11025 -#define PID_FILE "/var/run/audio-entropyd.pid" -#define DEFAULT_CLICK_READ (1 * DEFAULT_SAMPLE_RATE) -#define DEFAULT_POOLSIZE_FN "/proc/sys/kernel/random/poolsize" -#define RNGTEST_PENALTY (20000 / 8) /* how many bytes to skip when the rng-test fails */ +#define RANDOM_DEVICE "/dev/random" +#define DEFAULT_FRAME_RATE 22050 +#define DEFAULT_SAMPLE_SIZE 11072 +#define DEFAULT_SKIP_SIZE 11025 +#define DEFAULT_CONFIGURATION_FILE "/etc/sysconfig/audio-entropyd" +#define PID_FILE "/var/run/audio-entropyd.pid" +#define DEFAULT_POOLSIZE_FN "/proc/sys/kernel/random/poolsize" +#define RNGTEST_PENALTY (20000 / 8) /* how many bytes to skip when the rng-test fails */ void dolog(int level, char *format, ...); +/* Global Variables - they all have a leading capital case, and + * they are used throughout the program without passing. That's why + * the case is different, so they can be recognized. + * Not optimal as it can obscure the logic flow, but simple. */ extern int loggingstate; -int treshold = 0; -char skip_test = 0; -int error_state = 0; -char dofork = 1; -char *file = NULL; - -static char *cdevice = "hw:0"; /* capture device */ -const char *id = "capture"; -int err; -int verbose=0; -int format = -1; +int Always_Close = 0; +unsigned Frame_Rate = (unsigned) DEFAULT_FRAME_RATE; +unsigned Process_Frames = (unsigned) DEFAULT_SAMPLE_SIZE; +unsigned Skip_Frames = (unsigned) DEFAULT_SAMPLE_SIZE; +char Internal_Test = 0; +int Error_State = 0; +int Entropy_Filter = 30; +float Lower_Threshold = .0; +float Upper_Threshold = .5; +char Do_Fork = 1; +char *Capture_File = NULL; +static char *Capture_Device = "plughw:0"; /* capture device */ +const char *Stream_Mode = "capture"; +int Snd_Pcm_Err; +int Verbose=0; +int Snd_Pcm_Format = -1; -#define max(x, y) ((x)>(y)?(x):(y)) +#define max(x, y) ((x)>(y)?(x):(y)) /* Prototypes */ -void main_loop(const char *cdevice, int sample_rate); -int setparams(snd_pcm_t *chandle, int sample_rate); +void main_loop(void); +int parse_options (int option_count, char **options); +int read_config_file (FILE * infile, char ***config_options); +void * Alloc (size_t len); +char * StrnDup (char *str); +char * StrMem (size_t slen); +int setparams(snd_pcm_t *chandle); void usage(void); void credit_krng(int random_fd, struct rand_pool_info *entropy); void daemonise(void); void gracefully_exit(int signum); void logging_handler(int signum); -void get_random_data(int sample_rate, int skip_samples, int process_samples, int *n_output_bytes, char **output_buffer); -int add_to_kernel_entropyspool(int handle, char *buffer, int nbytes); +void get_random_data (snd_pcm_t *chandle, unsigned char *input_buffer, unsigned char *output_buffer, int *n_output_bytes); +void add_entropy_bit (char bit, unsigned char *output_buffer, int *n_output_bytes); +int add_to_kernel_entropyspool(int handle, unsigned char *buffer, int nbytes); /* Functions */ int main(int argc, char **argv) { - int sample_rate = DEFAULT_SAMPLE_RATE; - int c; - static struct option long_options[] = - { - {"device", 1, NULL, 'd' }, - {"do-not-fork", 1, NULL, 'n' }, - {"sample-rate", 1, NULL, 'N' }, - {"skip-test", 0, NULL, 's' }, - {"file", 1, NULL, 'f' }, - {"verbose", 0, NULL, 'v' }, - {"help", 0, NULL, 'h' }, - {NULL, 0, NULL, 0 } - }; - - /* Process commandline options */ - while(1) - { - c = getopt_long (argc, argv, "f:nsr:d:N:vh", long_options, NULL); - if (c == -1) - break; - - switch(c) - { - case 'f': - file = optarg; - break; - - case 'n': - dofork = 0; - break; - - case 'N': - sample_rate = atoi(optarg); - break; - - case 'v': - loggingstate = 1; - verbose++; - break; - - case 's': - skip_test = 1; - break; - - case 'd': - cdevice = strdup(optarg); - break; - - case 'h': - usage(); - exit(0); - - case '?': - default: - fprintf(stderr, "Invalid commandline options.\n\n"); - usage(); - exit(1); - } - } - - RNGTEST_init(); - - signal(SIGPIPE, SIG_IGN); - signal(SIGHUP, gracefully_exit); - signal(SIGINT, gracefully_exit); - signal(SIGTERM, gracefully_exit); - signal(SIGUSR1, logging_handler); - signal(SIGUSR2, logging_handler); - - openlog("audio-entropyd", LOG_CONS, LOG_DAEMON); - - dolog(LOG_NOTICE, "audio-entropyd starting up"); - - if (mlockall(MCL_FUTURE | MCL_CURRENT) == -1) - error_exit("mlockall failed"); - - if (dofork) - daemonise(); - - main_loop(cdevice, sample_rate); + int option_count = 0, iii; + FILE *config_file; + char **config_file_options; + + config_file = fopen(DEFAULT_CONFIGURATION_FILE, "rt"); + if (!config_file) + error_exit("Couldn't open configuration file: %s", DEFAULT_CONFIGURATION_FILE); + option_count = read_config_file (config_file, &config_file_options); + fclose(config_file); + parse_options ( option_count, config_file_options); // Process configuration file + for (iii=0; iii < option_count; iii++) + { free (config_file_options [iii]); + } + free (config_file_options); + if (argc > 1) + { optind = 0; // start at first option + opterr = 0; // reset any error + optopt = 0; // reset any error + optarg = NULL; // reset any error + parse_options (argc, argv); // Process command line + } + RNGTEST_init(); + signal(SIGPIPE, SIG_IGN); + signal(SIGHUP, gracefully_exit); + signal(SIGINT, gracefully_exit); + signal(SIGTERM, gracefully_exit); + signal(SIGUSR1, logging_handler); + signal(SIGUSR2, logging_handler); + openlog("audio-entropyd", LOG_CONS, LOG_DAEMON); + dolog(LOG_NOTICE, "audio-entropyd starting up with entropy filter %d", Entropy_Filter); + if (mlockall(MCL_FUTURE | MCL_CURRENT) == -1) + error_exit("mlockall failed"); + if (Do_Fork) + daemonise(); + main_loop(); + exit(0); +} - exit(0); +/* + Parse the options passed in the char** array. + lines and comments. Rets: 0 on success. +*/ +int +parse_options (int option_count, char **options) +{ int c; + static struct option long_options[] = + { + {"always_close", 0, NULL, 'a' }, + {"device", 1, NULL, 'd' }, + {"do-not-fork", 0, NULL, 'n' }, + {"entropy-filter", 1, NULL, 'e' }, + {"sample-rate", 1, NULL, 'r' }, + {"sample-size", 1, NULL, 'z' }, + {"skip-size", 1, NULL, 's' }, + {"internal-test", 0, NULL, 'i' }, + {"store-in-file", 1, NULL, 'f' }, + {"lower-threshold", 1, NULL, 'l' }, + {"upper-threshold", 1, NULL, 'u' }, + {"verbose", 0, NULL, 'v' }, + {"help", 0, NULL, 'h' }, + {NULL, 0, NULL, 0 } + }; + + while(1) + { c = getopt_long (option_count, options, "ad:e:f:hil:nr:s:u:vz:", long_options, NULL); + if (c == -1) + break; + switch(c) + { case 'f': + Capture_File = StrnDup (optarg); + break; + case 'a': + Always_Close = 1; + break; + case 'n': + Do_Fork = 0; + break; + case 'r': + Frame_Rate = (unsigned) atoi(optarg); + break; + case 'z': + Process_Frames = (unsigned) atoi(optarg); + break; + case 's': + Skip_Frames = (unsigned) atoi(optarg); + break; + case 'v': + loggingstate = 1; + Verbose++; + break; + case 'i': + Internal_Test = 1; + break; + case 'e': + Entropy_Filter = atoi(optarg); + break; + case 'l': + Lower_Threshold = (float) atof(optarg); + break; + case 'u': + Upper_Threshold = (float) atof(optarg); + break; + case 'd': + Capture_Device = StrnDup(optarg); + break; + case 'h': + usage(); + exit(0); + case '?': + default: + fprintf(stderr, "Invalid commandline options.\n\n"); + usage(); + exit(1); + break; + } + } + return 0; } -int setparams(snd_pcm_t *chandle, int sample_rate) +/* + Read a configuration file, discarding blank + lines and comments. Rets: option count on success. + Everything from the file is put into an argv like array. +*/ + +int +read_config_file (FILE * infile, char ***config_options) { - snd_pcm_hw_params_t *ct_params; /* templates with rate, format and channels */ - snd_pcm_hw_params_alloca(&ct_params); + char *curr_option, *retptr, *workline, *cmnt, *token; + char **all_options; + int iii, line_count = 0, configuration_count = 0; + + workline= StrMem (256); + curr_option = StrnDup ("audio_entropyd"); // save the program name to simulate argv + all_options = (char **) StrMem ((sizeof (char *)) * (configuration_count+1)); // allocate an array for option char pointers, including the new option + configuration_count++; // update the option count + *(all_options + configuration_count - 1) = curr_option; // append the new option pointer + *config_options = all_options; // point to the new option pointer array + retptr = fgets (workline, 256, infile); + if (retptr == NULL) + error_exit ("Unable to read line from configuration file"); + while (*workline != '\0') + { line_count++; + token = strtok (workline, " \t\n"); // get first token separated by spaces, tabs, or newline + if (token) // not an empty line + { cmnt = strchr (workline, '#'); + if (token[0] == '-') // options line + { if (cmnt) + strncpy (cmnt, "\0", 1); // truncate at comment + curr_option = StrnDup (workline); // duplicate the option + all_options = (char **) StrMem ((sizeof (char *)) * (configuration_count+1)); // allocate an array for option char pointers, including the new option + for (iii = 0; iii < configuration_count; iii++) // transfer existing pointers to the new array of option pointers + { *(all_options + iii) = *((*config_options) + iii); + } + configuration_count++; // update the option count + *(all_options + configuration_count - 1) = curr_option; // append the new option pointer + free (*config_options); // free the existing option pointer array + *config_options = all_options; // point to the new option pointer array + } + else if (token[0] == '#') // line is a comment + ; // do nothing + else + { if (Verbose > 1) + dolog(LOG_DEBUG, "Skipped line %d in configuration file with invalid %s at start of line", line_count, token); + } + } + memset (workline, 0x00, 256); + retptr = fgets (workline, 256, infile); + } + curr_option = NULL; // terminate like argv is terminated, with a null char*. + all_options = (char **) StrMem ((sizeof (char *)) * (configuration_count+1)); // allocate an array for option char pointers, including the new option + for (iii = 0; iii < configuration_count; iii++) // transfer existing pointers to the new array of option pointers + { *(all_options + iii) = *((*config_options) + iii); + } + *(all_options + configuration_count) = curr_option; + free (*config_options); // free the existing option pointer array + //config_options = &all_options; // point to the new option pointer array + *config_options = all_options; // point to the new option pointer array + if (*workline == '\0') + { if (feof (infile)) + { free (workline); + return configuration_count; + } + free (workline); + error_exit ("Read error on configuration file"); + } + free (workline); + return configuration_count; +} - err = snd_pcm_hw_params_any(chandle, ct_params); - if (err < 0) - error_exit("Broken configuration for %s PCM: no configurations available: %s", id, snd_strerror(err)); - - /* Disable rate resampling */ - err = snd_pcm_hw_params_set_rate_resample(chandle, ct_params, 0); - if (err < 0) - error_exit("Could not disable rate resampling: %s", snd_strerror(err)); - - /* Set access to SND_PCM_ACCESS_RW_INTERLEAVED */ - err = snd_pcm_hw_params_set_access(chandle, ct_params, SND_PCM_ACCESS_RW_INTERLEAVED); - if (err < 0) - error_exit("Could not set access to SND_PCM_ACCESS_RW_INTERLEAVED: %s", snd_strerror(err)); - - /* Restrict a configuration space to have rate nearest to our target rate */ - err = snd_pcm_hw_params_set_rate_near(chandle, ct_params, &sample_rate, 0); - if (err < 0) - error_exit("Rate %iHz not available for %s: %s", sample_rate, id, snd_strerror(err)); - - /* Set sample format */ - format = SND_PCM_FORMAT_S16_BE; - err = snd_pcm_hw_params_set_format(chandle, ct_params, format); - if (err < 0) - { - format = SND_PCM_FORMAT_S16_LE; - err = snd_pcm_hw_params_set_format(chandle, ct_params, format); - } - if (err < 0) - error_exit("Sample format (SND_PCM_FORMAT_S16_BE and _LE) not available for %s: %s", id, snd_strerror(err)); - - /* Set stereo */ - err = snd_pcm_hw_params_set_channels(chandle, ct_params, 2); - if (err < 0) - error_exit("Channels count (%i) not available for %s: %s", 2, id, snd_strerror(err)); - - /* Apply settings to sound device */ - err = snd_pcm_hw_params(chandle, ct_params); - if (err < 0) - error_exit("Could not apply settings to sound device!"); +void * +Alloc (size_t len) +{ void *p = calloc (1, len); + if (!p) + error_exit ("Out of memory in request for %u", len); + return p; +} - return 0; +char * +StrnDup (char *str) +{ size_t len = strlen (str); + char *rv = strndup (str, len); + if (!rv) + error_exit ("Out of memory in StrnDup"); + return rv; } -void main_loop(const char *cdevice, int sample_rate) -{ - unsigned char *output_buffer = NULL; - int n_output_bytes = -1; - int random_fd = -1, max_bits; - FILE *poolsize_fh; - - /* Open kernel random device */ - random_fd = open(RANDOM_DEVICE, O_RDWR); - if (random_fd == -1) - error_exit("Couldn't open random device: %m"); - - /* find out poolsize */ - poolsize_fh = fopen(DEFAULT_POOLSIZE_FN, "rb"); - if (!poolsize_fh) - error_exit("Couldn't open poolsize file: %m"); - fscanf(poolsize_fh, "%d", &max_bits); - fclose(poolsize_fh); - - /* first get some data so that we can immediately submit something when the - * kernel entropy-buffer gets below some limit - */ - get_random_data(sample_rate, DEFAULT_CLICK_READ, DEFAULT_SAMPLE_RATE, &n_output_bytes, &output_buffer); - - /* Main read loop */ - for(;;) - { - int added = 0, before, loop, after; - fd_set write_fd; - FD_ZERO(&write_fd); - FD_SET(random_fd, &write_fd); - - if (!file) - { - for(;;) - { - int rc = select(random_fd+1, NULL, &write_fd, NULL, NULL); /* wait for krng */ - if (rc >= 0) break; - if (errno != EINTR) - error_exit("Select error: %m"); - } - } - - /* find out how many bits to add */ - if (ioctl(random_fd, RNDGETENTCNT, &before) == -1) - error_exit("Couldn't query entropy-level from kernel"); - - dolog(LOG_DEBUG, "woke up due to low entropy state (%d bits left)", before); - - /* loop until the buffer is (supposed to be) full: we do NOT check the number of bits - * currently in the buffer each iteration, since (on a heavily used random-driver) - * audio-entropyd might run constantly, using a lot of cpu-usage - */ - if (verbose > 1) - printf("max_bits: %d\n", max_bits); - for(loop=0; loop < max_bits;) - { - if (verbose > 1) - dolog(LOG_DEBUG, "n_output_bytes: %d", n_output_bytes); - - if (n_output_bytes > 0) - { - int cur_added; - - if (file) - { - FILE *fh = fopen(file, "a+"); - if (!fh) - error_exit("error accessing file %s", file); - - if (fwrite(output_buffer, 1, n_output_bytes, fh) != n_output_bytes) - error_exit("error writeing to file"); - - fclose(fh); - - cur_added = n_output_bytes * 8; - } - else - { - cur_added = add_to_kernel_entropyspool(random_fd, output_buffer, n_output_bytes); - } - - added += cur_added; - loop += cur_added; - - if (verbose > 1) - dolog(LOG_DEBUG, "%d bits of data, %d bits usable were added, total %d added", n_output_bytes * 8, cur_added, added); - } - - /* Get number of bits in KRNG after credit */ - if (ioctl(random_fd, RNDGETENTCNT, &after) == -1) - error_exit("Coundn't query entropy-level from kernel: %m"); - - if (verbose > 1 && after < max_bits) - dolog(LOG_DEBUG, "minimum level not reached: %d", after); - - free(output_buffer); - output_buffer = NULL; - get_random_data(sample_rate, DEFAULT_CLICK_READ, DEFAULT_SAMPLE_RATE, &n_output_bytes, &output_buffer); - } +/* Allocate a string of the passed in size from memory. + * Strings allocated with this routine can use the StrCat + * routine below safely. Does *not* allocate an extra + * position for the NULL terminator. Callers responsibility. */ +char * +StrMem (size_t slen) +{ char *nstr = NULL; + nstr = (char *) Alloc (slen); + if (!nstr) + error_exit ("Out of memory in StrMem"); + return nstr; +} + +int setparams(snd_pcm_t *chandle) +{ + snd_pcm_hw_params_t *ct_params; /* templates with rate, format and channels */ + snd_pcm_hw_params_alloca(&ct_params); + + Snd_Pcm_Err = snd_pcm_hw_params_any(chandle, ct_params); + if (Snd_Pcm_Err < 0) + error_exit("Broken configuration for %s PCM: no configurations available: %s", Stream_Mode, snd_strerror(Snd_Pcm_Err)); + + /* Disable rate resampling */ + // redundant with set_rate_near, as set_rate_near always picks a native rate of the device that would not be resampled. + //Snd_Pcm_Err = snd_pcm_hw_params_set_rate_resample(chandle, ct_params, 0); + //if (Snd_Pcm_Err < 0) + // error_exit("Could not disable rate resampling: %s", snd_strerror(Snd_Pcm_Err)); + + /* Set access to SND_PCM_ACCESS_RW_INTERLEAVED */ + Snd_Pcm_Err = snd_pcm_hw_params_set_access(chandle, ct_params, SND_PCM_ACCESS_RW_INTERLEAVED); + if (Snd_Pcm_Err < 0) + error_exit("Could not set access to SND_PCM_ACCESS_RW_INTERLEAVED: %s", snd_strerror(Snd_Pcm_Err)); + + /* Restrict a configuration space to have rate nearest to our target rate */ + Snd_Pcm_Err = snd_pcm_hw_params_set_rate_near(chandle, ct_params, &Frame_Rate, 0); + if (Snd_Pcm_Err < 0) + error_exit("Rate %iHz not available for %s: %s", Frame_Rate, Stream_Mode, snd_strerror(Snd_Pcm_Err)); + + /* Set sample format appropriate for architecture */ + int test_int = 1; + if ((* (char *) &test_int) == 1) + { Snd_Pcm_Format = SND_PCM_FORMAT_S32_LE; + Snd_Pcm_Err = snd_pcm_hw_params_set_format(chandle, ct_params, Snd_Pcm_Format); + if (Snd_Pcm_Err < 0) + { error_exit("Sample format SND_PCM_FORMAT_S32_LE not available for %s: %s", Stream_Mode, snd_strerror(Snd_Pcm_Err)); + } + } + else + { Snd_Pcm_Format = SND_PCM_FORMAT_S32_BE; + Snd_Pcm_Err = snd_pcm_hw_params_set_format(chandle, ct_params, Snd_Pcm_Format); + if (Snd_Pcm_Err < 0) + { error_exit("Sample format SND_PCM_FORMAT_S32_BE not available for %s: %s", Stream_Mode, snd_strerror(Snd_Pcm_Err)); + } + } + + /* Set stereo */ + Snd_Pcm_Err = snd_pcm_hw_params_set_channels(chandle, ct_params, 2); + if (Snd_Pcm_Err < 0) + error_exit("Channels count (%i) not available for %s: %s", 2, Stream_Mode, snd_strerror(Snd_Pcm_Err)); + + /* Apply settings to sound device */ + Snd_Pcm_Err = snd_pcm_hw_params(chandle, ct_params); + if (Snd_Pcm_Err < 0) + error_exit("Could not apply settings to sound device!"); + + int can_pause = snd_pcm_hw_params_can_pause (ct_params); + int can_resume = snd_pcm_hw_params_can_resume (ct_params); + if (can_pause == 1 && can_resume == 1) + return 1; + else + return 0; +} - dolog(LOG_INFO, "Entropy credit of %i bits made (%i bits before, %i bits after)", added, before, after); - } +void main_loop(void) +{ unsigned input_buffer_size, output_buffer_size; + unsigned char *input_buffer = NULL; + unsigned char *output_buffer = NULL; + int can_pause_resume = 0, pause = 1, resume = 0; + int n_output_bytes = -1; + int random_fd = -1, max_bits; + FILE *poolsize_fh; + snd_pcm_t *chandle = NULL; + + if ((Snd_Pcm_Err = snd_pcm_open(&chandle, Capture_Device, SND_PCM_STREAM_CAPTURE, 0)) < 0) + error_exit("Record open error: %s", snd_strerror(Snd_Pcm_Err)); + + if (Verbose > 1) + dolog(LOG_DEBUG, "main loop chandle %p", chandle); + + /* Open and set up ALSA device for reading */ + can_pause_resume = setparams(chandle); + + input_buffer_size = snd_pcm_frames_to_bytes(chandle, Process_Frames); + input_buffer = (unsigned char *)malloc(input_buffer_size); + output_buffer_size = (Process_Frames / 8) + (8 - ((Process_Frames / 8) % 8)); // max of 1 bit of entropy per frame + output_buffer = (unsigned char *)malloc(output_buffer_size); + if (!input_buffer || !output_buffer) + error_exit("problem allocating %d bytes of memory", input_buffer_size); + if (Verbose > 1) + dolog(LOG_DEBUG, "Input buffer size: %d bytes", input_buffer_size); + + /* Discard the first data read */ + /* it often contains weird looking data - probably a click from */ + /* driver loading / card initialisation */ + /* Read a buffer of audio */ + int total = Skip_Frames; + int n_to_do = Process_Frames; + if (Skip_Frames < Process_Frames) + n_to_do = Skip_Frames; + unsigned char *dummy = input_buffer; + while (total > 0) + { while (n_to_do > 0) + { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, Process_Frames); + /* Make sure we aren't hitting a disconnect/suspend case */ + if (frames_read < 0) + snd_pcm_recover(chandle, frames_read, 0); + /* Nope, something else is wrong. Bail. */ + if (frames_read < 0) + { snd_pcm_close(chandle); + free(input_buffer); + free(output_buffer); + error_exit("Read initial throw away data error: %m"); + } + else + { n_to_do -= frames_read; + total -= frames_read; + dummy += frames_read; + } + } + n_to_do = Process_Frames; + dummy = input_buffer; + } + /* Open kernel random device */ + random_fd = open(RANDOM_DEVICE, O_RDWR); + if (random_fd == -1) + error_exit("Couldn't open random device: %m"); + + /* find out poolsize */ + poolsize_fh = fopen(DEFAULT_POOLSIZE_FN, "rb"); + if (!poolsize_fh) + error_exit("Couldn't open poolsize file: %m"); + fscanf(poolsize_fh, "%d", &max_bits); + fclose(poolsize_fh); + /* first get some data so that we can immediately submit something when the + * kernel entropy-buffer gets below some limit + */ + get_random_data(chandle, input_buffer, output_buffer, &n_output_bytes); + if (can_pause_resume && Always_Close == 0) + snd_pcm_pause (chandle, pause); + else + snd_pcm_close(chandle); + /* Main read loop */ + for(;;) + { int added = 0, before, loop, after; + fd_set write_fd; + FD_ZERO(&write_fd); + FD_SET(random_fd, &write_fd); + if (!Capture_File) + { for(;;) + { int rc = select(random_fd+1, NULL, &write_fd, NULL, NULL); /* wait for krng */ + if (Verbose > 1) + dolog(LOG_DEBUG, "select return code rc %d", rc); + if (rc >= 0) + break; + else if (errno != EINTR) + error_exit("Select error: %m"); + } + } + /* find out how many bits to add */ + if (ioctl(random_fd, RNDGETENTCNT, &before) == -1) + error_exit("Couldn't query entropy-level from kernel"); + dolog(LOG_DEBUG, "woke up due to low entropy state (%d bits left)", before); + /* loop until the buffer is (supposed to be) full: we do NOT check the number of bits + * currently in the buffer each iteration, since (on a heavily used random-driver) + * audio-entropyd might run constantly, using a lot of cpu-usage + */ + if (Verbose > 1) + printf("max_bits: %d\n", max_bits); + if (can_pause_resume && Always_Close == 0) + snd_pcm_pause (chandle, resume); + else // no pause resume on this device, have to re initialize each time to avoid overrun errors + { if ((Snd_Pcm_Err = snd_pcm_open(&chandle, Capture_Device, SND_PCM_STREAM_CAPTURE, 0)) < 0) + error_exit("Record open error: %s", snd_strerror(Snd_Pcm_Err)); + if (Verbose > 1) + dolog(LOG_DEBUG, "main loop chandle %p", chandle); + /* Open and set up ALSA device for reading */ + setparams(chandle); + /* Discard the first data read */ + /* it often contains weird looking data - probably a click from */ + /* driver loading / card initialisation */ + /* Read a buffer of audio */ + int total = Skip_Frames; + int n_to_do = Process_Frames; + if (Skip_Frames < Process_Frames) + n_to_do = Skip_Frames; + unsigned char *dummy = input_buffer; + while (total > 0) + { while (n_to_do > 0) + { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, Process_Frames); + /* Make sure we aren't hitting a disconnect/suspend case */ + if (frames_read < 0) + snd_pcm_recover(chandle, frames_read, 0); + /* Nope, something else is wrong. Bail. */ + if (frames_read < 0) + { snd_pcm_close(chandle); + free(input_buffer); + free(output_buffer); + error_exit("Read initial throw away data error: %m"); + } + else + { n_to_do -= frames_read; + total -= frames_read; + dummy += frames_read; + } + } + n_to_do = Process_Frames; + dummy = input_buffer; + } + } + for(loop=0; loop < max_bits;) + { if (Verbose > 1) + dolog(LOG_DEBUG, "n_output_bytes: %d", n_output_bytes); + if (n_output_bytes > 0) + { int cur_added; + if (Capture_File) + { FILE *fh = fopen(Capture_File, "a+"); + if (!fh) + error_exit("error accessing Capture_File %s", Capture_File); + if (fwrite(output_buffer, 1, n_output_bytes, fh) != n_output_bytes) + error_exit("error writeing to Capture_File"); + fclose(fh); + cur_added = n_output_bytes * 8; + } + else + cur_added = add_to_kernel_entropyspool(random_fd, output_buffer, n_output_bytes); + added += cur_added; + loop += cur_added; + if (Verbose > 1) + dolog(LOG_DEBUG, "%d bits of data, %d bits usable were added, total %d added", n_output_bytes * 8, cur_added, added); + } + /* Get number of bits in KRNG after credit */ + if (ioctl(random_fd, RNDGETENTCNT, &after) == -1) + error_exit("Coundn't query entropy-level from kernel: %m"); + if (Verbose > 1 && after < max_bits) + dolog(LOG_DEBUG, "minimum level not reached: %d", after); + memset (output_buffer, 0x00, output_buffer_size); + get_random_data(chandle, input_buffer, output_buffer, &n_output_bytes); + } + dolog(LOG_INFO, "Entropy credit of %i bits made (%i bits before, %i bits after)", added, before, after); + if (can_pause_resume && Always_Close == 0) + snd_pcm_pause (chandle, pause); + else + snd_pcm_close(chandle); + } + if (can_pause_resume && Always_Close == 0) + snd_pcm_close(chandle); + free(input_buffer); + free(output_buffer); } -int add_to_kernel_entropyspool(int handle, char *buffer, int nbytes) +int add_to_kernel_entropyspool(int handle, unsigned char *buffer, int nbytes) { - double nbits; - struct rand_pool_info *output; + double nbits; + struct rand_pool_info *output; - output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + nbytes); - if (!output) - error_exit("malloc failure in add_to_kernel_entropyspool"); - - // calculate number of bits in the block of - // data. put in structure - nbits = calc_nbits_in_data((unsigned char *)buffer, nbytes); - if (nbits >= 1.0) - { - output -> entropy_count = (int)nbits; - output -> buf_size = nbytes; - memcpy(output -> buf, buffer, nbytes); - - if (ioctl(handle, RNDADDENTROPY, output) == -1) - error_exit("RNDADDENTROPY failed!"); - } + output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + nbytes); + if (!output) + error_exit("malloc failure in add_to_kernel_entropyspool"); + + // calculate number of bits in the block of + // data. put in structure + nbits = calc_nbits_in_data((unsigned char *)buffer, nbytes); + if (nbits >= 1.0) + { + output -> entropy_count = (int)nbits; + output -> buf_size = nbytes; + memcpy(output -> buf, buffer, nbytes); + + if (ioctl(handle, RNDADDENTROPY, output) == -1) + error_exit("RNDADDENTROPY failed!"); + } - free(output); + free(output); - return (int)nbits; + return (int)nbits; } #define order(a, b) (((a) == (b)) ? -1 : (((a) > (b)) ? 1 : 0)) -void get_random_data(int sample_rate, int skip_samples, int process_samples, int *n_output_bytes, char **output_buffer) +void get_random_data (snd_pcm_t *chandle, unsigned char *input_buffer, unsigned char *output_buffer, int *n_output_bytes) { - int n_to_do, bits_out=0, loop; - char *dummy; - static short psl=0, psr=0; /* previous samples */ + int n_to_do, loop; + unsigned char *dummy; + static int psl=0, psr=0; /* previous samples */ static char a=1; /* alternater */ - unsigned char byte_out=0; - int input_buffer_size; - char *input_buffer; - snd_pcm_t *chandle; - - if (verbose > 1) - dolog(LOG_DEBUG, "get_random_data(%p, %d, %d, %p, %p)", chandle, skip_samples, process_samples, n_output_bytes, output_buffer); - - if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE, 0)) < 0) - error_exit("Record open error: %s", snd_strerror(err)); - - /* Open and set up ALSA device for reading */ - setparams(chandle, sample_rate); - - *n_output_bytes=0; - - input_buffer_size = snd_pcm_frames_to_bytes(chandle, max(skip_samples, process_samples)) * 2; /* *2: stereo! */ - input_buffer = (char *)malloc(input_buffer_size); - *output_buffer = (char *)malloc(input_buffer_size); - if (!input_buffer || !output_buffer) - error_exit("problem allocating %d bytes of memory", input_buffer_size); - if (verbose > 1) - dolog(LOG_DEBUG, "Input buffer size: %d bytes", input_buffer_size); - - /* Discard the first data read */ - /* it often contains weird looking data - probably a click from */ - /* driver loading / card initialisation */ - snd_pcm_sframes_t garbage_frames_read = snd_pcm_readi(chandle, input_buffer, skip_samples); - /* Make sure we aren't hitting a disconnect/suspend case */ - if (garbage_frames_read < 0) - snd_pcm_recover(chandle, garbage_frames_read, 0); - /* Nope, something else is wrong. Bail. */ - if (garbage_frames_read < 0) - error_exit("Get random data: read error: %m"); - - /* Read a buffer of audio */ - n_to_do = process_samples * 2; - dummy = input_buffer; - while (n_to_do > 0) - { - snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, n_to_do); - /* Make sure we aren't hitting a disconnect/suspend case */ - if (frames_read < 0) - frames_read = snd_pcm_recover(chandle, frames_read, 0); - /* Nope, something else is wrong. Bail. */ - if (frames_read < 0) - error_exit("Read error: %m"); - if (frames_read == -1) - { - if (errno != EINTR) - error_exit("Read error: %m"); - } - else - { - n_to_do -= frames_read; - dummy += frames_read; - } - } - snd_pcm_close(chandle); - - /* de-biase the data */ - for(loop=0; loop<(process_samples * 2/*16bits*/ * 2/*stereo*/ * 2); loop+=8) - { - int w1, w2, w3, w4, o1, o2; - - if (format == SND_PCM_FORMAT_S16_BE) - { - w1 = (input_buffer[loop+0]<<8) + input_buffer[loop+1]; - w2 = (input_buffer[loop+2]<<8) + input_buffer[loop+3]; - w3 = (input_buffer[loop+4]<<8) + input_buffer[loop+5]; - w4 = (input_buffer[loop+6]<<8) + input_buffer[loop+7]; - } - else - { - w1 = (input_buffer[loop+1]<<8) + input_buffer[loop+0]; - w2 = (input_buffer[loop+3]<<8) + input_buffer[loop+2]; - w3 = (input_buffer[loop+5]<<8) + input_buffer[loop+4]; - w4 = (input_buffer[loop+7]<<8) + input_buffer[loop+6]; - } - - /* Determine order of channels for each sample, subtract previous sample - * to compensate for unbalanced audio devices */ - o1 = order(w1-psl, w2-psr); - o2 = order(w3-psl, w4-psr); - if (a > 0) - { - psl = w3; - psr = w4; - } - else - { - psl = w1; - psr = w2; - } - - /* If both samples have the same order, there is bias in the samples, so we - * discard them; if both channels are equal on either sample, we discard - * them too; additionally, alternate the sample we'll use next (even more - * bias removal) */ - if (o1 == o2 || o1 < 0 || o2 < 0) - { - a = -a; - } - else - { - /* We've got a random bit; the bit is either the order from the first or - * the second sample, determined by the alternator 'a' */ - char bit = (a > 0) ? o1 : o2; - - byte_out <<= 1; - byte_out += bit; - - bits_out++; - - if (bits_out>=8) - { - if (error_state == 0 || skip_test == 0) - { - (*output_buffer)[*n_output_bytes]=byte_out; - (*n_output_bytes)++; - } - bits_out=0; - - RNGTEST_add(byte_out); - if (skip_test == 0 && RNGTEST() == -1) - { - if (error_state == 0) - dolog(LOG_CRIT, "test of random data failed, skipping %d bytes before re-using data-stream (%d bytes in flush)", RNGTEST_PENALTY, error_state); - error_state = RNGTEST_PENALTY; - *n_output_bytes = 0; - } - else - { - if (error_state > 0) - { - error_state--; - - if (error_state == 0) - dolog(LOG_INFO, "Restarting fetching of entropy data"); - } - } - } - } - } + int min_left_val = 0x0fffffff, max_left_val = 0, min_right_val = 0x0fffffff, max_right_val = 0; + long left_input_total = 0, right_input_total = 0; + float dc_offset_left = 0.0, dc_offset_right = 0.0; + + if (Verbose > 1) + dolog(LOG_DEBUG, "get_random_data(%p, %u, %d, %d, %p, %p)", chandle, Frame_Rate, Process_Frames, input_buffer, output_buffer, n_output_bytes); + *n_output_bytes=0; + /* Read a buffer of audio */ + n_to_do = Process_Frames; + dummy = input_buffer; + while (n_to_do > 0) + { snd_pcm_sframes_t frames_read = snd_pcm_readi(chandle, dummy, n_to_do); + /* Make sure we aren't hitting a disconnect/suspend case */ + if (frames_read < 0) + frames_read = snd_pcm_recover(chandle, frames_read, 0); + /* Nope, something else is wrong. Bail. */ + if (frames_read < 0) + error_exit("Read error: %m"); + if (frames_read == -1) + { if (errno != EINTR) + error_exit("Read error: %m"); + } else + { n_to_do -= frames_read; + dummy += frames_read; + if (n_to_do > 0) + { double time_for_frames = (double) n_to_do / (double) Frame_Rate; // how long to create that many frames? + long nanoseconds = floor ((time_for_frames * 1000000.)); // how many nanoseconds is that? + struct timespec time_to_wait, time_left; + time_to_wait.tv_sec = (long) floor (time_for_frames); + time_to_wait.tv_nsec = (nanoseconds % 1000000); + int wait_retval = nanosleep (&time_to_wait, &time_left); // wait for that many nanoseconds + } + } + } + /* de-bias the data */ + for (loop = 0; loop < (Process_Frames*2); loop += 2) + { int32_t w1, w2; + /* because we are using plughw, alsa (or pulse) will have formatted the data + * to be signed 32 as requested by shifting, regardless of device internal format. + * 32 bits should take care of + * sound cards for now as there is really no discernable difference above that + * for human ears, while it allows for extracting maximum entropy from cards + * with larger internal formats. I think the new hda-intel standard defaults to + * 32 bit. Most systems will have this onboard now. + * Note that big endian or little endian doesn't matter as we are reading in native + * format we requested, whatever it is for int32_t. + */ + w1 = ((int32_t *) input_buffer) [loop + 0]; + left_input_total += w1; + if (w1 < min_left_val) + { min_left_val = w1; + } else if (w1 > max_left_val) + max_left_val = w1; + w2 = ((int32_t *) input_buffer) [loop + 1]; + right_input_total += w2; + if (w2 < min_right_val) + { min_right_val = w2; + } else if (w2 > max_right_val) + max_right_val = w2; + if (Verbose > 2) + dolog(LOG_DEBUG, "w1 %d w2 %d", w1, w2); + else if (Verbose > 1 && loop % 1024 == 0) + dolog(LOG_DEBUG, "w1 %d w2 %d", w1, w2); + } + if (Verbose > 1) + dolog(LOG_DEBUG, "left_input_total %ld right_input_total %ld", left_input_total, right_input_total); + if (Verbose > 1) + dolog(LOG_DEBUG, "min_left_val %d max_left_val %d", min_left_val, max_left_val); + if (Verbose > 1) + dolog(LOG_DEBUG, "min_right_val %d max_right_val %d", min_right_val, max_right_val); + dc_offset_left = (float) ((double) left_input_total / (double) (Process_Frames)); + dc_offset_right = (float) ((double) right_input_total / (double) (Process_Frames)); + if (Verbose > 1) + dolog(LOG_DEBUG, "dc_offset_left %8.3f dc_offset_right %8.3f", dc_offset_left, dc_offset_right); + char bit = 0; + int iii = 0; + if (Entropy_Filter == 0) // absolute normalized distance change between channels, more less or less more + { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [3]; + int jjj; + for (jjj = 0; jjj < 3; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] < Lower_Threshold && delta [2] - delta [1] > Upper_Threshold) // change less, change more + { bit = 0; + } else if (delta [1] - delta [0] > Upper_Threshold && delta [2] - delta [1] < Lower_Threshold) // change more, change less + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 1) // absolute normalized distance change between channels with second difference == 0 + { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [3]; + int jjj; + for (jjj = 0; jjj < 3; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] < Lower_Threshold + && delta [2] - delta [1] > Upper_Threshold + && delta [2] - delta [0] == 0.) // change less, change more, back at beginning value + { bit = 0; + } else if (delta [1] - delta [0] > Upper_Threshold + && delta [2] - delta [1] < Lower_Threshold + && delta [2] - delta [0] == 0.) // change more, change less, back at beginning value + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 2) // absolute normalized distance change between channels with second difference != 0 + { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [3]; + int jjj; + for (jjj = 0; jjj < 3; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] < Lower_Threshold + && delta [2] - delta [1] > Upper_Threshold + && delta [2] - delta [0] != 0.) // change less, change more, not at beginning value + { bit = 0; + } else if (delta [1] - delta [0] > Upper_Threshold + && delta [2] - delta [1] < Lower_Threshold + && delta [2] - delta [0] != 0.) // change more, change less, not at beginning value + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 3) // absolute normalized distance change between channels using 5 samples, less more less more or more less more less + { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [5]; + int jjj; + for (jjj = 0; jjj < 5; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] < Lower_Threshold + && delta [2] - delta [1] > Upper_Threshold + && delta [3] - delta [2] < Lower_Threshold + && delta [4] - delta [3] > Upper_Threshold) // change less, change more, change less, change more + { bit = 0; + } else if (delta [1] - delta [0] > Upper_Threshold + && delta [2] - delta [1] < Lower_Threshold + && delta [3] - delta [2] > Upper_Threshold + && delta [4] - delta [3] < Lower_Threshold) // change more, change less, change more, change less + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 4) // absolute normalized distance change between channels using 5 samples, less more more less or more less less more + { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [5]; + int jjj; + for (jjj = 0; jjj < 5; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] < Lower_Threshold + && delta [2] - delta [1] > Upper_Threshold + && delta [3] - delta [2] > Upper_Threshold + && delta [4] - delta [3] < Lower_Threshold) // change less, change more, change more, change less + { bit = 0; + } else if (delta [1] - delta [0] > Upper_Threshold + && delta [2] - delta [1] < Lower_Threshold + && delta [3] - delta [2] < Lower_Threshold + && delta [4] - delta [3] > Upper_Threshold) // change more, change less, change less, change more + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 5) // absolute normalized distance change between channels using 5 samples, less more same less or more less same more + { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [5]; + int jjj; + for (jjj = 0; jjj < 5; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] < Lower_Threshold + && delta [2] - delta [1] > Upper_Threshold + && delta [3] - delta [2] == 0. + && delta [4] - delta [3] < Lower_Threshold) // change less, change more, stay, change less + { bit = 0; + } else if (delta [1] - delta [0] > Upper_Threshold + && delta [2] - delta [1] < Lower_Threshold + && delta [3] - delta [2] == 0. + && delta [4] - delta [3] > Upper_Threshold) // change more, change less, stay, change more + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 6) // absolute normalized distance change between channels using 5 samples, same same more same or same same less same + { for (iii = 0; iii < (Process_Frames*2) - 8; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [5]; + int jjj; + for (jjj = 0; jjj < 5; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] == 0. + && delta [2] - delta [1] == 0. + && delta [3] - delta [2] < Lower_Threshold + && delta [4] - delta [3] == 0.) // step down + { bit = 0; + } else if (delta [1] - delta [0] == 0. + && delta [2] - delta [1] == 0. + && delta [3] - delta [2] > Upper_Threshold + && delta [4] - delta [3] == 0.) // step up + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 7) // absolute normalized distance change between channels with pattern same same more or same same less + { for (iii = 0; iii < (Process_Frames*2) - 6; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [4]; + int jjj; + for (jjj = 0; jjj < 4; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if (delta [1] - delta [0] == 0. + && delta [2] - delta [1] == 0. + && delta [3] - delta [2] < 0.) // same, change less + { bit = 0; + } else if (delta [1] - delta [0] == 0. + && delta [2] - delta [1] == 0. + && delta [3] - delta [2] > 0.) // same, change more + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 8) // absolute normalized distance change between channels, less more or more less, uses time mod 2 to set entropy bit + { for (iii = 0; iii < (Process_Frames*2) - 4; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta [3]; + int jjj; + for (jjj = 0; jjj < 3; jjj++) + { w1 = ((int32_t *) input_buffer) [iii + (2*jjj) + 0]; + w2 = ((int32_t *) input_buffer) [iii + (2*jjj) + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta [jjj] = fabs (leftval - rightval); + } + if ((delta [1] - delta [0] < Lower_Threshold && delta [2] - delta [1] > Upper_Threshold) + || (delta [1] - delta [0] > Upper_Threshold && delta [2] - delta [1] < Lower_Threshold)) // change less, change more or change more, change less + { clock_t used_time = clock (); + if (used_time != (clock_t) -1) + bit = (char) (used_time % 2); + else + { struct timespec current_time; + clock_gettime(CLOCK_REALTIME, ¤t_time); + bit = (char) current_time.tv_nsec % 2; + } + } + else + bit = -1; + if (bit != -1) + { if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 10) // original style Entropy_Filter for entropy + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 4) + { int32_t w1, w2, w3, w4; + char o1, o2; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w2 = ((int32_t *) input_buffer) [iii + 1]; + w3 = ((int32_t *) input_buffer) [iii + 2]; + w4 = ((int32_t *) input_buffer) [iii + 3]; + /* Determine order of channels for each sample, subtract previous sample + * to compensate for unbalanced audio devices */ + if ((w1-psl) > (w2-psr)) + o1 = 1; + else if ((w1-psl) < (w2-psr)) + o1 = 0; + else + o1 = -1; + if ((w3-psl) > (w4-psr)) + o2 = 1; + else if ((w3-psl) < (w4-psr)) + o2 = 0; + else + o2 = -1; + if (Verbose > 1) + dolog(LOG_DEBUG, "w1-psl %d w2-psr %d", w1-psl, w2-psr); + if (Verbose > 1) + dolog(LOG_DEBUG, "w3-psl %d w4-psr %d", w3-psl, w4-psr); + if (Verbose > 1) + dolog(LOG_DEBUG, "o1 %d o2 %d", (int) o1, (int) o2); + if (a > 0) + { psl = w3; + psr = w4; + } + else + { psl = w1; + psr = w2; + } + /* If both samples have the same order, there is bias in the samples, so we + * discard them; if both channels are equal on either sample, we discard + * them too; additionally, alternate the sample we'll use next (even more + * bias removal) */ + if (o1 == o2 || o1 < 0 || o2 < 0) + { a = -a; + } + else + { /* We've got a random bit; the bit is either the order from the first or + * the second sample, determined by the alternator 'a' */ + bit = (a > 0) ? o1 : o2; + if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 11) // original style Entropy_Filter for entropy but using dc_offset values for bias elimination + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 4) + { int32_t w1, w2, w3, w4; + char o1, o2; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w2 = ((int32_t *) input_buffer) [iii + 1]; + w3 = ((int32_t *) input_buffer) [iii + 2]; + w4 = ((int32_t *) input_buffer) [iii + 3]; + /* Determine order of channels for each sample, subtract previous sample + * to compensate for unbalanced audio devices */ + if ((w1-dc_offset_left) > (w2-dc_offset_right)) + o1 = 1; + else if ((w1-dc_offset_left) < (w2-dc_offset_right)) + o1 = 0; + else + o1 = -1; + if ((w3-dc_offset_left) > (w4-dc_offset_right)) + o2 = 1; + else if ((w3-dc_offset_left) < (w4-dc_offset_right)) + o2 = 0; + else + o2 = -1; + if (Verbose > 1) + dolog(LOG_DEBUG, "w1-dc_offset_left %d w2-dc_offset_right %d", w1-dc_offset_left, w2-dc_offset_right); + if (Verbose > 1) + dolog(LOG_DEBUG, "w3-dc_offset_left %d w4-dc_offset_right %d", w3-dc_offset_left, w4-dc_offset_right); + if (Verbose > 1) + dolog(LOG_DEBUG, "o1 %d o2 %d", (int) o1, (int) o2); + /* If both samples have the same order, there is bias in the samples, so we + * discard them; if both channels are equal on either sample, we discard + * them too; additionally, alternate the sample we'll use next (even more + * bias removal) */ + if (o1 == o2 || o1 < 0 || o2 < 0) + { a = -a; + } + else + { /* We've got a random bit; the bit is either the order from the first or + * the second sample, determined by the alternator 'a' */ + bit = (a > 0) ? o1 : o2; + if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 12) // original style Entropy_Filter for entropy, use system time mod 2 for bit + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 4) + { int32_t w1, w2, w3, w4; + char o1, o2; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w2 = ((int32_t *) input_buffer) [iii + 1]; + w3 = ((int32_t *) input_buffer) [iii + 2]; + w4 = ((int32_t *) input_buffer) [iii + 3]; + /* Determine order of channels for each sample, subtract previous sample + * to compensate for unbalanced audio devices */ + if ((w1-psl) > (w2-psr)) + o1 = 1; + else if ((w1-psl) < (w2-psr)) + o1 = 0; + else + o1 = -1; + if ((w3-psl) > (w4-psr)) + o2 = 1; + else if ((w3-psl) < (w4-psr)) + o2 = 0; + else + o2 = -1; + if (Verbose > 1) + dolog(LOG_DEBUG, "w1-psl %d w2-psr %d", w1-psl, w2-psr); + if (Verbose > 1) + dolog(LOG_DEBUG, "w3-psl %d w4-psr %d", w3-psl, w4-psr); + if (Verbose > 1) + dolog(LOG_DEBUG, "o1 %d o2 %d", (int) o1, (int) o2); + if (a > 0) + { psl = w3; + psr = w4; + } + else + { psl = w1; + psr = w2; + } + /* If both samples have the same order, there is bias in the samples, so we + * discard them; if both channels are equal on either sample, we discard + * them too; additionally, alternate the sample we'll use next (even more + * bias removal) */ + if (o1 == o2 || o1 < 0 || o2 < 0) + { a = -a; + } + else + { // We've matched our pattern, the orders are 0 and 1, and are different, make a bit + clock_t used_time = clock (); + if (used_time != (clock_t) -1) + bit = (char) (used_time % 2); + else + { struct timespec current_time; + clock_gettime(CLOCK_REALTIME, ¤t_time); + bit = (char) current_time.tv_nsec % 2; + } + if (Verbose > 1) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 20) // pattern in individual channels, both normalized get less or both get more + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2) + { int32_t w1, w2, w3, w4; + float leftval0, leftval1, rightval0, rightval1; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w3 = ((int32_t *) input_buffer) [iii + 2]; + leftval0 = ((float) w1 - dc_offset_left); + if (leftval0 < 0.) + leftval0 = leftval0 / (dc_offset_left - (float) min_left_val); + else + leftval0 = leftval0 / ((float) max_left_val - dc_offset_left); + leftval1 = ((float) w3 - dc_offset_left); + if (leftval1 < 0.) + leftval1 = leftval1 / (dc_offset_left - (float) min_left_val); + else + leftval1 = leftval1 / ((float) max_left_val - dc_offset_left); + if ((leftval1 - leftval0) < Lower_Threshold || (leftval1 - leftval0) > Upper_Threshold) // finding a bit is feasible + { w2 = ((int32_t *) input_buffer) [iii + 1]; + w4 = ((int32_t *) input_buffer) [iii + 3]; + rightval0 = ((float) w2 - dc_offset_right); + if (rightval0 < 0.) + rightval0 = rightval0 / (dc_offset_right - (float) min_right_val); + else + rightval0 = rightval0 / ((float) max_right_val - dc_offset_right); + rightval1 = ((float) w4 - dc_offset_right); + if (rightval1 < 0.) + rightval1 = rightval1 / (dc_offset_right - (float) min_right_val); + else + rightval1 = rightval1 / ((float) max_right_val - dc_offset_right); + if ((leftval1 - leftval0) < Lower_Threshold && (rightval1 - rightval0) > Upper_Threshold) // left channel less, right channel more + { bit = 0; + } + else if ((leftval1 - leftval0) > Upper_Threshold && (rightval1 - rightval0) < Lower_Threshold) // left channel more, right channel less + { bit = 1; + } + else + bit = -1; + if (bit != -1) + { if (Verbose > 2) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + } + else if (Entropy_Filter == 21) // pattern in individual channels, both normalized, one significantly changes relative to the other + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2) + { int32_t w1, w2, w3, w4; + float leftval0, leftval1, rightval0, rightval1; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w3 = ((int32_t *) input_buffer) [iii + 2]; + leftval0 = ((float) w1 - dc_offset_left); + if (leftval0 < 0.) + leftval0 = leftval0 / (dc_offset_left - (float) min_left_val); + else + leftval0 = leftval0 / ((float) max_left_val - dc_offset_left); + leftval1 = ((float) w3 - dc_offset_left); + if (leftval1 < 0.) + leftval1 = leftval1 / (dc_offset_left - (float) min_left_val); + else + leftval1 = leftval1 / ((float) max_left_val - dc_offset_left); + w2 = ((int32_t *) input_buffer) [iii + 1]; + w4 = ((int32_t *) input_buffer) [iii + 3]; + rightval0 = ((float) w2 - dc_offset_right); + if (rightval0 < 0.) + rightval0 = rightval0 / (dc_offset_right - (float) min_right_val); + else + rightval0 = rightval0 / ((float) max_right_val - dc_offset_right); + rightval1 = ((float) w4 - dc_offset_right); + if (rightval1 < 0.) + rightval1 = rightval1 / (dc_offset_right - (float) min_right_val); + else + rightval1 = rightval1 / ((float) max_right_val - dc_offset_right); + if (fabs (leftval1 - leftval0) < Lower_Threshold + && fabs (rightval1 - rightval0) > Upper_Threshold) // left channel minimal change, right channel significant change more or less + { bit = 0; + } else if (fabs (leftval1 - leftval0) > Upper_Threshold + && fabs (rightval1 - rightval0) < Lower_Threshold) // left channel significant change more or less, right channel minimal change + { bit = 1; + } else + bit = -1; + if (bit != -1) + { if (Verbose > 2) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 22) // pattern in individual channels, both normalized get less or both get more, use time mod 2 for bit + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2) + { int32_t w1, w2, w3, w4; + float leftval0, leftval1, rightval0, rightval1; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w3 = ((int32_t *) input_buffer) [iii + 2]; + leftval0 = ((float) w1 - dc_offset_left); + if (leftval0 < 0.) + leftval0 = leftval0 / (dc_offset_left - (float) min_left_val); + else + leftval0 = leftval0 / ((float) max_left_val - dc_offset_left); + leftval1 = ((float) w3 - dc_offset_left); + if (leftval1 < 0.) + leftval1 = leftval1 / (dc_offset_left - (float) min_left_val); + else + leftval1 = leftval1 / ((float) max_left_val - dc_offset_left); + if ((leftval1 - leftval0) != 0.) + { w2 = ((int32_t *) input_buffer) [iii + 1]; + w4 = ((int32_t *) input_buffer) [iii + 3]; + rightval0 = ((float) w2 - dc_offset_right); + if (rightval0 < 0.) + rightval0 = rightval0 / (dc_offset_right - (float) min_right_val); + else + rightval0 = rightval0 / ((float) max_right_val - dc_offset_right); + rightval1 = ((float) w4 - dc_offset_right); + if (rightval1 < 0.) + rightval1 = rightval1 / (dc_offset_right - (float) min_right_val); + else + rightval1 = rightval1 / ((float) max_right_val - dc_offset_right); + if (((leftval1 - leftval0) > Upper_Threshold && (rightval1 - rightval0) < Lower_Threshold) + || ((leftval1 - leftval0) < Lower_Threshold && (rightval1 - rightval0) > Upper_Threshold)) // either pattern of filter 20, make a bit + { clock_t used_time = clock (); + if (used_time != (clock_t) -1) + bit = (char) (used_time % 2); + else + { struct timespec current_time; + clock_gettime(CLOCK_REALTIME, ¤t_time); + bit = (char) current_time.tv_nsec % 2; + } + } + else + bit = -1; + if (bit != -1) + { if (Verbose > 2) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + } + else if (Entropy_Filter == 23) // pattern in individual channels, both normalized, one significantly changes relative to the other, use time mod 2 for bit + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2) + { int32_t w1, w2, w3, w4; + float leftval0, leftval1, rightval0, rightval1; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w3 = ((int32_t *) input_buffer) [iii + 2]; + leftval0 = ((float) w1 - dc_offset_left); + if (leftval0 < 0.) + leftval0 = leftval0 / (dc_offset_left - (float) min_left_val); + else + leftval0 = leftval0 / ((float) max_left_val - dc_offset_left); + leftval1 = ((float) w3 - dc_offset_left); + if (leftval1 < 0.) + leftval1 = leftval1 / (dc_offset_left - (float) min_left_val); + else + leftval1 = leftval1 / ((float) max_left_val - dc_offset_left); + w2 = ((int32_t *) input_buffer) [iii + 1]; + w4 = ((int32_t *) input_buffer) [iii + 3]; + rightval0 = ((float) w2 - dc_offset_right); + if (rightval0 < 0.) + rightval0 = rightval0 / (dc_offset_right - (float) min_right_val); + else + rightval0 = rightval0 / ((float) max_right_val - dc_offset_right); + rightval1 = ((float) w4 - dc_offset_right); + if (rightval1 < 0.) + rightval1 = rightval1 / (dc_offset_right - (float) min_right_val); + else + rightval1 = rightval1 / ((float) max_right_val - dc_offset_right); + if ((fabs (leftval1 - leftval0) <= Lower_Threshold && fabs (rightval1 - rightval0) >= Upper_Threshold) + || (fabs (leftval1 - leftval0) >= Upper_Threshold && fabs (rightval1 - rightval0) <= Lower_Threshold)) // either pattern of filter 21, make bit + { clock_t used_time = clock (); + if (used_time != (clock_t) -1) + bit = (char) (used_time % 2); + else + { struct timespec current_time; + clock_gettime(CLOCK_REALTIME, ¤t_time); + bit = (char) current_time.tv_nsec % 2; + } + } + else + bit = -1; + if (bit != -1) + { if (Verbose > 2) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + else if (Entropy_Filter == 30) // if absolute normalized delta greater or less than threshold, generate a bit using system time mod 2 + { for (iii = 0; iii < (Process_Frames*2) - 2; iii += 2) + { int32_t w1, w2; + float leftval, rightval, delta; + w1 = ((int32_t *) input_buffer) [iii + 0]; + w2 = ((int32_t *) input_buffer) [iii + 1]; + leftval = ((float) w1 - dc_offset_left); + if (leftval < 0.) + leftval = leftval / (dc_offset_left - (float) min_left_val); + else + leftval = leftval / ((float) max_left_val - dc_offset_left); + rightval = ((float) w2 - dc_offset_right); + if (rightval < 0.) + rightval = rightval / (dc_offset_right - (float) min_right_val); + else + rightval = rightval / ((float) max_right_val - dc_offset_right); + delta = fabs (leftval - rightval); + if (delta >= Upper_Threshold) // max delta is 2, min is 0. How different are channels in normalized terms? Above threshold, make a bit. + { clock_t used_time = clock (); + if (used_time != (clock_t) -1) + bit = (char) (used_time % 2); + else + { struct timespec current_time; + clock_gettime(CLOCK_REALTIME, ¤t_time); + bit = (char) current_time.tv_nsec % 2; + } + } + else + bit = -1; + if (bit != -1) + { if (Verbose > 2) + dolog(LOG_DEBUG, "bit %d", (int) bit); + add_entropy_bit (bit, output_buffer, n_output_bytes); + } + } + } + if (Verbose > 1) + dolog(LOG_DEBUG, "get_random_data() finished"); +} - if (verbose > 1) - dolog(LOG_DEBUG, "get_random_data() finished"); +void add_entropy_bit (char bit, unsigned char *output_buffer, int *n_output_bytes) +{ + static int bits_out=0; + static unsigned char byte_out=0; - free(input_buffer); + byte_out <<= 1; + byte_out += bit; + bits_out++; + if (bits_out>=8) + { if (Error_State == 0 || Internal_Test == 1) + { (output_buffer)[*n_output_bytes]=byte_out; + (*n_output_bytes)++; + } + bits_out=0; + RNGTEST_add(byte_out); + if (Internal_Test == 1 && RNGTEST() == -1) + { if (Error_State == 0) + dolog(LOG_CRIT, "test of random data failed, skipping %d bytes before re-using data-stream (%d bytes in flush)", RNGTEST_PENALTY, Error_State); + Error_State = RNGTEST_PENALTY; + *n_output_bytes = 0; + } else + { if (Error_State > 0) + { Error_State--; + if (Error_State == 0) + dolog(LOG_INFO, "Restarting fetching of entropy data"); + } + } + } } void usage(void) { - fprintf(stderr, "Usage: audio-entropyd [options]\n\n"); - fprintf(stderr, "Collect entropy from a soundcard and feed it into the kernel random pool.\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Options:\n"); - fprintf(stderr, "--device, -d [] Specify sound device to use. (Default %s)\n", cdevice); - fprintf(stderr, "--sample-rate, -N [] Audio sampling rate. (default %i)\n", DEFAULT_SAMPLE_RATE); - fprintf(stderr, "--skip-test, -s Do not check if data is random enough.\n"); - fprintf(stderr, "--do-not-fork -n Do not fork.\n"); - fprintf(stderr, "--verbose, -v Be verbose.\n"); - fprintf(stderr, "--help, -h This help.\n"); - fprintf(stderr, "\n"); + fprintf(stderr, "Usage: audio-entropyd [options]\n\n"); + fprintf(stderr, "Collect entropy from a soundcard and feed it into the kernel random pool.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, "--always_close, -a Always close sound device after use, even if pause-resume available. (Default no)\n"); + fprintf(stderr, "--device, -d [] Specify sound device to use. (Default %s)\n", Capture_Device); + fprintf(stderr, "--entropy_filter, -e [] Filter to use for extracting entropy from the capture data. (Default %i)\n", Entropy_Filter); + fprintf(stderr, "--lower_threshodd, -l [] When an entropy filter needs thresholds, this is the lower. (Default %5.3f)\n", Lower_Threshold); + fprintf(stderr, "--upper_threshodd, -u [] When an entropy filter needs thresholds, this is the upper. (Default %5.3f)\n", Upper_Threshold); + fprintf(stderr, "--sample-rate, -r [] Audio sampling rate. (Default %i)\n", Frame_Rate); + fprintf(stderr, "--sample-size, -z [] Size of sample to get for analysis each time. (Default %i)\n", Process_Frames); + fprintf(stderr, "--skip-size, -s [] Size of sample to skip each time device opened. No skip for pause-resume. (Default %i)\n", Skip_Frames); + fprintf(stderr, "--internal_test, -i [] Test the gathered entropy internally. (Default no)\n"); + fprintf(stderr, "--do-not-fork -n Do not fork. (Default fork)\n"); + fprintf(stderr, "--store_in_file, -f [] Path to save file. (Default no)\n"); + fprintf(stderr, "--verbose, -v Be Verbose, up to 3 times. (Default no)\n"); + fprintf(stderr, "--help, -h This help. (Default no)\n"); + fprintf(stderr, "Configuration file at /etc/sysconfig/audio-entropyd has more detail and sample values.\n"); + fprintf(stderr, "\n"); } void daemonise(void) { - if (become_daemon() == -1) - error_exit("cannot fork into the background"); + if (become_daemon() == -1) + error_exit("cannot fork into the background"); - if (write_pidfile(PID_FILE) == -1) - error_exit("Couldn't open PID file \"%s\" for writing: %m.", PID_FILE); + if (write_pidfile(PID_FILE) == -1) + error_exit("Couldn't open PID file \"%s\" for writing: %m.", PID_FILE); } void gracefully_exit(int signum) { - if (munlockall() == -1) - error_exit("problem unlocking pages"); - unlink(PID_FILE); - dolog(LOG_NOTICE, "audio-entropyd stopping due to signal %d", signum); - exit(0); + if (munlockall() == -1) + error_exit("problem unlocking pages"); + unlink(PID_FILE); + dolog(LOG_NOTICE, "audio-entropyd stopping due to signal %d", signum); + exit(0); } void logging_handler(int signum) { - if (signum == SIGUSR1) - { - loggingstate = 1; - dolog(LOG_WARNING, "Currently in flush state: entropy data is not random enough"); - } + if (signum == SIGUSR1) + { + loggingstate = 1; + dolog(LOG_WARNING, "Currently in flush state: entropy data is not random enough"); + } - if (signum == SIGUSR2) - loggingstate = 0; + if (signum == SIGUSR2) + loggingstate = 0; }