%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% module #include "dk3all.h" #include "dkt.h" $!trace-include /** Flag: Can continue. This is reset by the signal handlers. */ static DK3_VOLATILE dk3_sig_atomic_t dkt_rnd_can_continue = 1; /** Read volatile integer. @param vip Address to read from. @return Result. */ static dk3_sig_atomic_t dkt_rnd_read_volatile_int(DK3_VOLATILE dk3_sig_atomic_t *vip) { return (*vip); } /** Pass through volatile pointer. @param vp Pointer to volatile variable. @return Pointer vp. */ static DK3_VOLATILE dk3_sig_atomic_t * dkt_rnd_pass_volatile_ptr(DK3_VOLATILE dk3_sig_atomic_t *vp) { return vp; } /** Job structure for dkt erase-disk. */ typedef struct { dk3_app_t *app; /**< Application. */ dk3_option_set_t *opt; /**< Option set. */ dkChar const * const *msg; /**< Localized messages. */ dkChar const * const *kwnl; /**< Keywords, not localized. */ char *b; /**< Buffer. */ dk3_um_t nb; /**< Number of blocks. */ size_t bs; /**< Block size. */ int exval; /**< Exit status code. */ } DKT_RND_J; /** Data for the option set. */ static dk3_option_t const dkt_rnd_options[] = { { dkT('b'), dkT("block-size"), 1 }, { dkT('n'), dkT("number"), 1 } }; /** Number of options in the dkt_rnd_options array. */ static size_t const dkt_rnd_szoptions = sizeof(dkt_rnd_options)/sizeof(dk3_option_t); /** Signal handler. @param signo Signal number. */ static dk3_signal_ret_t dkt_rnd_sig_handler(int signo) { dk3signal_refresh(signo,dkt_rnd_sig_handler); #if 0 dkt_rnd_can_continue = 0; #else *dkt_rnd_pass_volatile_ptr(&dkt_rnd_can_continue) = 0; #endif } /** Initialize job structure. @param j Job structure. */ static void dkt_rnd_job_init(DKT_RND_J *j) { dk3_um_t um = DK3_UM_0; j->app = NULL; j->opt = NULL; j->msg = NULL; j->kwnl = NULL; j->exval = DKT_RESULT_ERR_UNSPECIFIC; um++; j->nb = um; j->bs = 512; } /** Clean up job structure. @param j Job structure. */ static void dkt_rnd_job_cleanup(DKT_RND_J *j) { if(j->opt) { dk3opt_close(j->opt); } j->opt = NULL; } /** Process command line arguments. @param j Job structure. @return 1 on success (can continue), 0 on error (abort). */ static int dkt_rnd_process_arguments(DKT_RND_J *j) { dk3_um_t um; int back = 0; int xargc = 0; /* Number of cmd line args. */ unsigned bs = 512; /* Block size. */ dkChar const *arg = NULL; /* Current argument. */ dkChar const * const *xargv = NULL; /* Cmd line args array. */ $? "+ dkt_rnd_process_arguments" xargc = dk3app_get_argc(j->app); xargv = dk3app_get_argv(j->app); xargc--; xargc--; xargv++; xargv++; j->opt = dk3opt_open_app( dkt_rnd_options, dkt_rnd_szoptions, dkT('\0'), NULL, xargc, xargv, j->app ); if(j->opt) { if(0 == dk3opt_get_error_code(j->opt)) { back = 1; if(dk3opt_is_set(j->opt, dkT('b'))) { arg = dk3opt_get_short_arg(j->opt, dkT('b')); if(arg) { #if VERSION_BEFORE_20140808 #if VERSION_BEFORE_20140716 if(dk3sf_sscanf3(arg, dkT("%u"), &bs) == 1) #else if(0 != dk3ma_ui_from_string(&bs, arg, NULL)) #endif { j->bs = (size_t)bs; } else { /* ERROR: Not numeric! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 141, 142, arg); back = 0; j->exval = DKT_RESULT_ERR_OPTION; } #else /* 2014-08-27 Use dkt_tool_set_size(). */ if (0 == dkt_tool_set_size(&(j->bs), arg, j->msg, j->kwnl, j->app, &(j->exval))) { back = 0; } #endif } else { back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } if(dk3opt_is_set(j->opt, dkT('n'))) { arg = dk3opt_get_short_arg(j->opt, dkT('n')); if(arg) { #if VERSION_BEFORE_20140716 if(dk3ma_string_to_um(&um, arg)) #else if (0 != dk3ma_um_from_string(&um, arg, NULL)) #endif { j->nb = um; } else { /* ERROR: Not numeric! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 141, 142, arg); back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } else { back = 0; j->exval = DKT_RESULT_ERR_OPTION; } } } else { j->exval = DKT_RESULT_ERR_OPTION; } } else { j->exval = DKT_RESULT_ERR_OPTION; } $? "- dkt_rnd_process_arguments %d", back return back; } /** Run with buffer set up. @param j Job structure. */ static void dkt_rnd_run_with_buffer(DKT_RND_J *j) { dk3_um_t blocks = DK3_UM_0; #ifdef SIGINT dk3_signal_disp_t disp_int; #endif #ifdef SIGQUIT dk3_signal_disp_t disp_quit; #endif #ifdef SIGTERM dk3_signal_disp_t disp_term; #endif #ifdef SIGHUP dk3_signal_disp_t disp_hup; #endif #ifdef SIGPIPE dk3_signal_disp_t disp_pipe; #endif #if DK3_ON_WINDOWS int oldmode; #endif $? "+ dkt_rnd_run_with_buffer" if(dk3app_rand_init(j->app, NULL)) { /* Set new signal dispositions, save old dispositions. */ #ifdef SIGINT disp_int = dk3signal_set(SIGINT, dkt_rnd_sig_handler); #endif #ifdef SIGQUIT disp_quit = dk3signal_set(SIGQUIT, dkt_rnd_sig_handler); #endif #ifdef SIGTERM disp_term = dk3signal_set(SIGTERM, dkt_rnd_sig_handler); #endif #ifdef SIGHUP disp_hup = dk3signal_set(SIGHUP, dkt_rnd_sig_handler); #endif #ifdef SIGPIPE disp_pipe = dk3signal_set(SIGPIPE, dkt_rnd_sig_handler); #endif /* Write buffer to standard output. */ #if DK3_ON_WINDOWS oldmode = _setmode(1, _O_BINARY); #endif do { $? ". yet another write attempt" if(dk3app_rand_bytes(j->app, (void *)(j->b), j->bs)) { (void)dk3sf_write_app(1, j->b, j->bs, j->app); blocks++; if(j->nb) { if(blocks >= j->nb) { #if 0 dkt_rnd_can_continue = 0; $? ". finished" #else *dkt_rnd_pass_volatile_ptr(&dkt_rnd_can_continue) = 0; #endif } } } else { /* ERROR: Failed to obtain random bytes! */ dk3app_log_i1(j->app, DK3_LL_ERROR, 177); } } while(dkt_rnd_read_volatile_int(&dkt_rnd_can_continue)); #if DK3_ON_WINDOWS _setmode(1, oldmode); #endif /* Restore old signal dispositions. */ #ifdef SIGINT dk3signal_set(SIGINT, disp_int); #endif #ifdef SIGQUIT dk3signal_set(SIGQUIT, disp_quit); #endif #ifdef SIGTERM dk3signal_set(SIGTERM, disp_term); #endif #ifdef SIGHUP dk3signal_set(SIGHUP, disp_hup); #endif #ifdef SIGPIPE dk3signal_set(SIGPIPE, disp_pipe); #endif dk3app_rand_end(j->app); } $? "- dkt_rnd_run_with_buffer" } /** Run with built-in buffer. @param j Job structure. */ static void dkt_rnd_run_with_builtin_buffer(DKT_RND_J *j) { char bu[DKT_RND_BUFFER_SIZE]; $? "+ dkt_rnd_run_with_builtin_buffer" j->b = bu; dkt_rnd_run_with_buffer(j); j->b = NULL; $? "- dkt_rnd_run_with_builtin_buffer" } /** Allocate buffer and run. @param j Job structure. */ static void dkt_rnd_run_with_allocated_buffer (DKT_RND_J *j) { char *bu = NULL; $? "+ dkt_rnd_run_with_allocated_buffer" bu = dk3_new_app(char,j->bs,j->app); if(bu) { $? ". buffer ok" j->b = bu; dkt_rnd_run_with_buffer(j); j->b = NULL; dk3_delete(bu); } else { $? "! no buffer" j->exval = DKT_RESULT_ERR_MEMORY; } $? "- dkt_rnd_run_with_allocated_buffer" } /** Produce the random output. @param j Job structure. */ static void dkt_rnd_run(DKT_RND_J *j) { $? "+ dkt_rnd_run" if(j->bs > 0) { if(j->bs > DKT_RND_BUFFER_SIZE) { dkt_rnd_run_with_allocated_buffer(j); } else { dkt_rnd_run_with_builtin_buffer(j); } } else { /* ERROR: Invalid buffer size! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 61); j->exval = DKT_RESULT_ERR_OPTION; } $? "- dkt_rnd_run" } int dkt_rnd( dk3_app_t *app, dkChar const *sn, dkChar const * const *msg, dkChar const * const *kwnl ) { int back = DKT_RESULT_ERR_UNSPECIFIC; DKT_RND_J j; $? "+ dkt_rnd" dkt_rnd_job_init(&j); j.app = app; j.msg = msg; j.kwnl = kwnl; if(dkt_rnd_process_arguments(&j)) { $? ". now really run" j.exval = DKT_RESULT_OK; dkt_rnd_run(&j); } back = j.exval; dkt_rnd_job_cleanup(&j); $? "- dkt_rnd %d", back return back; } /* vim: set ai sw=2 : */