%% 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_ed_can_continue = 1; /** Read volatile integer. @param vip Address to read from. @return Result. */ static dk3_sig_atomic_t dkt_ed_read_volatile_int(DK3_VOLATILE dk3_sig_atomic_t *vip) { return (*vip); } /** Pass pointer for volatile data. @param vp Pointer to a volatile variable. @return Pointer vp. */ static DK3_VOLATILE dk3_sig_atomic_t *dkt_ed_pass_vol_pointer(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 pass; /**< Pass number. */ int exval; /**< Exit status code. */ } DKT_ED_J; /** Data for the option set. */ static dk3_option_t const dkt_ed_options[] = { { dkT('p'), dkT("pass"), 1 }, { dkT('b'), dkT("block-size"), 1 }, { dkT('n'), dkT("number"), 1 } }; /** Number of options in the dkt_ed_options array. */ static size_t const dkt_ed_szoptions = sizeof(dkt_ed_options)/sizeof(dk3_option_t); /** Signal handler function. @param signo Signal number. */ static dk3_signal_ret_t dkt_ed_sig_handler(int signo) { dk3signal_refresh(signo,dkt_ed_sig_handler); #if 0 dkt_ed_can_continue = 0; #else *dkt_ed_pass_vol_pointer(&dkt_ed_can_continue) = 0; #endif } /** Initialize job structure. @param j Job structure. */ static void dkt_ed_job_init(DKT_ED_J *j) { j->app = NULL; j->opt = NULL; j->msg = NULL; j->kwnl = NULL; j->exval = DKT_RESULT_ERR_UNSPECIFIC; j->nb = DK3_UM_0; j->bs = 512; j->pass = 0; } /** Clean up job structure. @param j Job structure. */ static void dkt_ed_job_cleanup(DKT_ED_J *j) { if(j->opt) { dk3opt_close(j->opt); } j->opt = NULL; } /** Process command line arguments. @param j Job structure. */ static int dkt_ed_process_arguments(DKT_ED_J *j) { dk3_um_t um; int back = 0; int xargc = 0; /* Number of cmd line args. */ int pass = 0; /* Pass number. */ #if VERSION_BEFORE_20140808 unsigned bs = 512; /* Block size. */ #endif dkChar const *arg = NULL; /* Current argument. */ dkChar const * const *xargv = NULL; /* Cmd line args array. */ $? "+ dkt_ed_process_arguments" xargc = dk3app_get_argc(j->app); xargv = dk3app_get_argv(j->app); xargc--; xargc--; xargv++; xargv++; j->opt = dk3opt_open_app( dkt_ed_options, dkt_ed_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('p'))) { arg = dk3opt_get_short_arg(j->opt, dkT('p')); if(arg) { #if VERSION_BEFORE_20140716 if(dk3sf_sscanf3(arg, dkT("%d"), &pass) == 1) #else if(0 != dk3ma_i_from_string(&pass, arg, NULL)) #endif { j->pass = pass; } 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; } } 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 /* 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_ed_process_arguments %d", back return back; } /** Set buffer to a byte value. @param bu Buffer start address. @param sz Number of bytes. @param va Byte value. */ static void dkt_ed_memset(char *bu, size_t sz, char va) { char *ptr; size_t s; ptr = bu; s = sz; while(s--) { *(ptr++) = va; } } /** Run and write output. @param j Job structure. */ static void dkt_ed_run_with_buffer(DKT_ED_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_ed_run_with_buffer" /* Set new signal dispositions, save old dispositions. */ #ifdef SIGINT disp_int = dk3signal_set(SIGINT, dkt_ed_sig_handler); #endif #ifdef SIGQUIT disp_quit = dk3signal_set(SIGQUIT, dkt_ed_sig_handler); #endif #ifdef SIGTERM disp_term = dk3signal_set(SIGTERM, dkt_ed_sig_handler); #endif #ifdef SIGHUP disp_hup = dk3signal_set(SIGHUP, dkt_ed_sig_handler); #endif #ifdef SIGPIPE disp_pipe = dk3signal_set(SIGPIPE, dkt_ed_sig_handler); #endif /* Initialize buffer. */ switch(j->pass) { case 7: { dkt_ed_memset(j->b, j->bs, 0xAA); } break; case 6: { dkt_ed_memset(j->b, j->bs, 0x55); } break; case 5: { dkt_ed_memset(j->b, j->bs, 0xCC); } break; case 4: { dkt_ed_memset(j->b, j->bs, 0x33); } break; case 3: { dkt_ed_memset(j->b, j->bs, 0xF0); } break; case 2: { dkt_ed_memset(j->b, j->bs, 0x0F); } break; case 1: { dkt_ed_memset(j->b, j->bs, 0xFF); } break; default: { dkt_ed_memset(j->b, j->bs, 0x00); } break; } /* Write buffer to standard output. */ #if DK3_ON_WINDOWS oldmode = _setmode(1, _O_BINARY); #endif do { $? ". yet another write attempt" (void)dk3sf_write_app(1, j->b, j->bs, j->app); blocks++; if(j->nb) { if(blocks >= j->nb) { #if 0 dkt_ed_can_continue = 0; $? ". finished" #else *dkt_ed_pass_vol_pointer(&dkt_ed_can_continue) = 0; $? ". finished" #endif } } } while(dkt_ed_read_volatile_int(&dkt_ed_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 $? "- dkt_ed_run_with_buffer" } /** Run with a built-in buffer (for usual/small buffer sizes). @param j Job structure. */ static void dkt_ed_run_with_builtin_buffer(DKT_ED_J *j) { char bu[DKT_ED_BUFFER_SIZE]; $? "+ dkt_ed_run_with_builtin_buffer" j->b = bu; dkt_ed_run_with_buffer(j); j->b = NULL; $? "- dkt_ed_run_with_builtin_buffer" } /** Allocate buffer and run (for large buffer sizes). @param j Job structure. */ static void dkt_ed_run_with_allocated_buffer (DKT_ED_J *j) { char *bu = NULL; $? "+ dkt_ed_run_with_allocated_buffer" bu = dk3_new_app(char,j->bs,j->app); if(bu) { $? ". buffer ok" j->b = bu; dkt_ed_run_with_buffer(j); j->b = NULL; dk3_delete(bu); } else { $? "! no buffer" j->exval = DKT_RESULT_ERR_MEMORY; } $? "- dkt_ed_run_with_allocated_buffer" } /** Run and produce output. @param j Job structure. */ static void dkt_ed_run(DKT_ED_J *j) { $? "+ dkt_ed_run" if(j->bs > 0) { if(j->bs > DKT_ED_BUFFER_SIZE) { dkt_ed_run_with_allocated_buffer(j); } else { dkt_ed_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_ed_run" } int dkt_ed( dk3_app_t *app, dkChar const *sn, dkChar const * const *msg, dkChar const * const *kwnl ) { int back = DKT_RESULT_ERR_UNSPECIFIC; DKT_ED_J j; $? "+ dkt_ed" dkt_ed_job_init(&j); j.app = app; j.msg = msg; j.kwnl = kwnl; if(dkt_ed_process_arguments(&j)) { $? ". now really run" j.exval = DKT_RESULT_OK; dkt_ed_run(&j); } back = j.exval; dkt_ed_job_cleanup(&j); $? "- dkt_ed %d", back return back; } /* vim: set ai sw=2 : */