Merge pull request #392 from unix-ninja/master
authorJens Steube <jens.steube@gmail.com>
Mon, 27 Jun 2016 16:51:00 +0000 (18:51 +0200)
committerGitHub <noreply@github.com>
Mon, 27 Jun 2016 16:51:00 +0000 (18:51 +0200)
Various refactor changes

1  2 
include/shared.h
include/types.h
src/hashcat.c
src/shared.c

diff --combined include/shared.h
@@@ -46,7 -46,7 +46,7 @@@
  #define hc_thread_mutex_delete(m)   pthread_mutex_destroy  (&m)
  #endif
  
- #ifdef OSX
+ #ifdef DARWIN
  typedef struct cpu_set
  {
    uint32_t count;
@@@ -1668,8 -1668,7 +1668,8 @@@ int veracrypt_parse_hash_327661   (cha
  int veracrypt_parse_hash_655331   (char *input_buf, uint input_len, hash_t *hash_buf);
  int win8phone_parse_hash          (char *input_buf, uint input_len, hash_t *hash_buf);
  
 -void naive_escape (const char *cpath_real, char *cpath_escaped, const size_t cpath_escaped_len);
 +void naive_replace (char *s, const u8 key_char, const u8 replace_char);
 +void naive_escape (char *s, size_t s_max, const u8 key_char, const u8 escape_char);
  void load_kernel (const char *kernel_file, int num_devices, size_t *kernel_lengths, const u8 **kernel_sources);
  void writeProgramBin (char *dst, u8 *binary, size_t binary_size);
  
diff --combined include/types.h
@@@ -6,6 -6,12 +6,12 @@@
  #ifndef TYPES_H
  #define TYPES_H
  
+ #ifdef _WIN
+ #define EOL "\r\n"
+ #else
+ #define EOL "\n"
+ #endif
  typedef struct
  {
    uint salt_buf[16];
@@@ -936,6 -942,7 +942,6 @@@ struct __hc_device_para
    uint    kernel_exec_timeout;
  
    uint    device_processors;
 -  uint    device_processor_cores;
    u64     device_maxmem_alloc;
    u64     device_global_mem;
    u32     device_maxclock_frequency;
@@@ -1123,9 -1130,6 +1129,9 @@@ typedef struc
  
    hc_device_param_t *devices_param;
  
 +  uint    shutdown_inner;
 +  uint    shutdown_outer;
 +
    /**
     * workload specific
     */
diff --combined src/hashcat.c
@@@ -1,4 -1,4 +1,4 @@@
 - /**
 +/**
   * Authors.....: Jens Steube <jens.steube@gmail.com>
   *               Gabriele Gristina <matrix@hashcat.net>
   *               magnum <john.magnum@hushmail.com>
@@@ -6,7 -6,7 +6,7 @@@
   * License.....: MIT
   */
  
- #ifdef OSX
+ #ifdef DARWIN
  #include <stdio.h>
  #endif
  
@@@ -78,7 -78,7 +78,7 @@@ double TARGET_MS_PROFILE[4]     = { 2, 
  #define NVIDIA_SPIN_DAMP        100
  #define GPU_TEMP_DISABLE        0
  #define GPU_TEMP_ABORT          90
 -#define GPU_TEMP_RETAIN         65
 +#define GPU_TEMP_RETAIN         75
  #define WORKLOAD_PROFILE        2
  #define KERNEL_ACCEL            0
  #define KERNEL_LOOPS            0
@@@ -362,7 -362,7 +362,7 @@@ const char *USAGE_BIG[] 
    "- [ Options ] -",
    "",
    " Options Short / Long          | Type | Description                                          | Example",
 -  "===============================|======|======================================================|=======================",
 +  "===============================+======+======================================================+=======================",
    " -m, --hash-type               | Num  | Hash-type, see references below                      | -m 1000",
    " -a, --attack-mode             | Num  | Attack-mode, see references below                    | -a 3",
    " -V, --version                 |      | Print version                                        |",
    "     --outfile-check-timer     | Num  | Sets seconds between outfile checks to X             | --outfile-check=30",
    " -p, --separator               | Char | Separator char for hashlists and outfile             | -p :",
    "     --stdout                  |      | Do not crack a hash, instead print candidates only   |",
 -  "     --show                    |      | Show cracked passwords only                          |",
 -  "     --left                    |      | Show un-cracked passwords only                       |",
 +  "     --show                    |      | Compare hashlist with potfile; Show cracked hashes   |",
 +  "     --left                    |      | Compare hashlist with potfile; Show uncracked hashes |",
    "     --username                |      | Enable ignoring of usernames in hashfile             |",
    "     --remove                  |      | Enable remove of hash once it is cracked             |",
    "     --remove-timer            | Num  | Update input hash file each X seconds                | --remove-timer=30",
    " -s, --skip                    | Num  | Skip X words from the start                          | -s 1000000",
    " -l, --limit                   | Num  | Limit X words from the start + skipped words         | -l 1000000",
    "     --keyspace                |      | Show keyspace base:mod values and quit               |",
 -  " -j, --rule-left               | Rule | Single Rule applied to each word from left wordlist  | -j 'c'",
 -  " -k, --rule-right              | Rule | Single Rule applied to each word from right wordlist | -k '^-'",
 -  " -r, --rules-file              | File | Multiple Rules applied to each word from wordlists   | -r rules/best64.rule",
 +  " -j, --rule-left               | Rule | Single rule applied to each word from left wordlist  | -j 'c'",
 +  " -k, --rule-right              | Rule | Single rule applied to each word from right wordlist | -k '^-'",
 +  " -r, --rules-file              | File | Multiple rules applied to each word from wordlists   | -r rules/best64.rule",
    " -g, --generate-rules          | Num  | Generate X random rules                              | -g 10000",
    "     --generate-rules-func-min | Num  | Force min X funcs per rule                           |",
    "     --generate-rules-func-max | Num  | Force max X funcs per rule                           |",
    "  3 | High        |  96 ms  | High              | Unresponsive",
    "  4 | Nightmare   | 480 ms  | Insane            | Headless",
    "",
 -  "If you have no idea what just happened then visit the following pages:",
 +  "- [ Basic Examples ] -",
 +  "",
 +  "  Attack-          | Hash- |",
 +  "  Mode             | Type  | Example command",
 +  " ==================+=======+==================================================================",
 +  "  Wordlist         | $P$   | %s -a 0 -m 400 example400.hash example.dict",
 +  "  Wordlist + Rules | MD5   | %s -a 0 -m 0 example0.hash example.dict -r rules/best64.rule",
 +  "  Brute-Force      | MD5   | %s -a 3 -m 0 example0.hash ?a?a?a?a?a?a",
 +  "  Combinator       | MD5   | %s -a 1 -m 0 example0.hash example.dict example.dict",
 +  "",
 +  "If you still have no idea what just happened try following pages:",
    "",
    "* https://hashcat.net/wiki/#howtos_videos_papers_articles_etc_in_the_wild",
    "* https://hashcat.net/wiki/#frequently_asked_questions",
 -  "",
    NULL
  };
  
@@@ -916,15 -907,7 +916,7 @@@ void status_display_machine_readable (
     * flush
     */
  
-   #ifdef _WIN
-   fputc ('\r', out);
-   fputc ('\n', out);
-   #endif
-   #ifdef _POSIX
-   fputc ('\n', out);
-   #endif
+   fputs (EOL, out);
    fflush (out);
  }
  
@@@ -932,6 -915,7 +924,6 @@@ void status_display (
  {
    if (data.devices_status == STATUS_INIT)     return;
    if (data.devices_status == STATUS_STARTING) return;
 -  if (data.devices_status == STATUS_BYPASS)   return;
  
    if (data.machine_readable == 1)
    {
@@@ -1690,6 -1674,7 +1682,6 @@@ static void status_benchmark (
  {
    if (data.devices_status == STATUS_INIT)     return;
    if (data.devices_status == STATUS_STARTING) return;
 -  if (data.devices_status == STATUS_BYPASS)   return;
  
    if (data.machine_readable == 1)
    {
@@@ -3045,7 -3030,6 +3037,7 @@@ static void choose_kernel (hc_device_pa
        if (data.devices_status == STATUS_CRACKED) break;
        if (data.devices_status == STATUS_ABORTED) break;
        if (data.devices_status == STATUS_QUIT)    break;
 +      if (data.devices_status == STATUS_BYPASS)  break;
  
        /**
         * speed
@@@ -3702,7 -3686,6 +3694,7 @@@ static void run_cracker (hc_device_para
        if (data.devices_status == STATUS_CRACKED) break;
        if (data.devices_status == STATUS_ABORTED) break;
        if (data.devices_status == STATUS_QUIT)    break;
 +      if (data.devices_status == STATUS_BYPASS)  break;
  
        /**
         * result
@@@ -4165,7 -4148,7 +4157,7 @@@ static void *thread_monitor (void *p
      return (p);
    }
  
 -  while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +  while (data.shutdown_inner == 0)
    {
      hc_sleep (sleep_time);
  
  
        time (&runtime_cur);
  
 -      int runtime_left = data.runtime_start + data.runtime - runtime_cur;
 +      int runtime_left = data.proc_start + data.runtime - runtime_cur;
  
        if (runtime_left <= 0)
        {
  
        if (status_left == 0)
        {
 -        //hc_thread_mutex_lock (mux_display);
 +        hc_thread_mutex_lock (mux_display);
  
          if (data.quiet == 0) clear_prompt ();
  
  
          if (data.quiet == 0) log_info ("");
  
 -        //hc_thread_mutex_unlock (mux_display);
 +        hc_thread_mutex_unlock (mux_display);
  
          status_left = data.status_timer;
        }
@@@ -4454,7 -4437,7 +4446,7 @@@ static void *thread_outfile_remove (voi
  
    uint check_left = outfile_check_timer; // or 1 if we want to check it at startup
  
 -  while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +  while (data.shutdown_inner == 0)
    {
      hc_sleep (1);
  
@@@ -4782,7 -4765,7 +4774,7 @@@ static uint get_work (hc_device_param_
    hc_thread_mutex_lock (mux_dispatcher);
  
    const u64 words_cur  = data.words_cur;
 -  const u64 words_base = (data.limit == 0) ? data.words_base : data.limit;
 +  const u64 words_base = (data.limit == 0) ? data.words_base : MIN (data.limit, data.words_base);
  
    device_param->words_off = words_cur;
  
@@@ -4832,7 -4815,7 +4824,7 @@@ static void *thread_calc_stdin (void *p
  
    const uint attack_kern = data.attack_kern;
  
 -  while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +  while ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
    {
      hc_thread_mutex_lock (mux_dispatcher);
  
@@@ -4960,7 -4943,7 +4952,7 @@@ static void *thread_calc (void *p
  
    if (attack_mode == ATTACK_MODE_BF)
    {
 -    while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +    while ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
      {
        const uint work = get_work (device_param, -1);
  
  
      u64 words_cur = 0;
  
 -    while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +    while ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
      {
        u64 words_off = 0;
        u64 words_fin = 0;
@@@ -6431,10 -6414,6 +6423,10 @@@ int main (int argc, char **argv
      {
        // do nothing
      }
 +    else if (keyspace == 1)
 +    {
 +      // do nothing
 +    }
      else
      {
        log_info ("%s (%s) starting...", PROGNAME, VERSION_TAG);
      }
    }
  
 +  /**
 +   * status, monitor and outfile remove threads
 +   */
 +
 +  uint wordlist_mode = ((optind + 1) < myargc) ? WL_MODE_FILE : WL_MODE_STDIN;
 +
 +  data.wordlist_mode = wordlist_mode;
 +
 +  if (wordlist_mode == WL_MODE_STDIN)
 +  {
 +    status = 1;
 +
 +    data.status = status;
 +  }
 +
 +  uint outer_threads_cnt = 0;
 +
 +  hc_thread_t *outer_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
 +
 +  data.shutdown_outer = 0;
 +
 +  if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
 +  {
 +    if ((data.wordlist_mode == WL_MODE_FILE) || (data.wordlist_mode == WL_MODE_MASK))
 +    {
 +      hc_thread_create (outer_threads[outer_threads_cnt], thread_keypress, NULL);
 +
 +      outer_threads_cnt++;
 +    }
 +  }
 +
    /**
     * config
     */
  
          if (cpu_rule_to_kernel_rule (rule_buf, rule_len, &kernel_rules_buf[kernel_rules_cnt]) == -1)
          {
 -          log_info ("WARNING: Cannot convert rule for use on device in file %s on line %u: %s", rp_file, rule_line, rule_buf);
 +          log_info ("WARNING: Cannot convert rule for use on OpenCL device in file %s on line %u: %s", rp_file, rule_line, rule_buf);
  
            memset (&kernel_rules_buf[kernel_rules_cnt], 0, sizeof (kernel_rule_t)); // needs to be cleared otherwise we could have some remaining data
  
          /* its so slow
          if (rulefind (&kernel_rules_buf[kernel_rules_cnt], kernel_rules_buf, kernel_rules_cnt, sizeof (kernel_rule_t), sort_by_kernel_rule))
          {
 -          log_info ("Duplicate rule for use on device in file %s in line %u: %s", rp_file, rule_line, rule_buf);
 +          log_info ("Duplicate rule for use on OpenCL device in file %s in line %u: %s", rp_file, rule_line, rule_buf);
  
            continue;
          }
       * generate NOP rules
       */
  
 -    if (kernel_rules_cnt == 0)
 +    if ((rp_files_cnt == 0) && (rp_gen == 0))
      {
        kernel_rules_buf = (kernel_rule_t *) mymalloc (sizeof (kernel_rule_t));
  
      data.kernel_rules_cnt = kernel_rules_cnt;
      data.kernel_rules_buf = kernel_rules_buf;
  
 +    if (kernel_rules_cnt == 0)
 +    {
 +      log_error ("ERROR: No valid rules left");
 +
 +      return (-1);
 +    }
 +
      /**
       * OpenCL platforms: detect
       */
  
          device_param->device_name_chksum = device_name_chksum;
  
 -        // device_processor_cores
 +        // vendor specific
  
          if (device_param->device_type & CL_DEVICE_TYPE_GPU)
          {
            }
          }
  
 -        // device_processor_cores
 -
 -        if (device_type & CL_DEVICE_TYPE_CPU)
 -        {
 -          cl_uint device_processor_cores = 1;
 -
 -          device_param->device_processor_cores = device_processor_cores;
 -        }
 -
          if (device_type & CL_DEVICE_TYPE_GPU)
          {
 -          if (device_vendor_id == VENDOR_ID_AMD)
 -          {
 -            cl_uint device_processor_cores = 0;
 -
 -            #define CL_DEVICE_WAVEFRONT_WIDTH_AMD               0x4043
 -
 -            hc_clGetDeviceInfo (data.ocl, device_param->device, CL_DEVICE_WAVEFRONT_WIDTH_AMD, sizeof (device_processor_cores), &device_processor_cores, NULL);
 -
 -            device_param->device_processor_cores = device_processor_cores;
 -          }
 -          else if (device_vendor_id == VENDOR_ID_NV)
 +          if (device_vendor_id == VENDOR_ID_NV)
            {
              cl_uint kernel_exec_timeout = 0;
  
  
              device_param->kernel_exec_timeout = kernel_exec_timeout;
  
 -            cl_uint device_processor_cores = 0;
 -
 -            #define CL_DEVICE_WARP_SIZE_NV                      0x4003
 -
 -            hc_clGetDeviceInfo (data.ocl, device_param->device, CL_DEVICE_WARP_SIZE_NV, sizeof (device_processor_cores), &device_processor_cores, NULL);
 -
 -            device_param->device_processor_cores = device_processor_cores;
 -
              cl_uint sm_minor = 0;
              cl_uint sm_major = 0;
  
  
              device_param->nvidia_spin_damp /= 100;
            }
 -          else
 -          {
 -            cl_uint device_processor_cores = 1;
 -
 -            device_param->device_processor_cores = device_processor_cores;
 -          }
          }
  
          // display results
  
              if (hm_NVML_nvmlDeviceGetFanSpeed (data.hm_nvml, 0, hm_adapters_nvml[i].nvml, &speed) == NVML_SUCCESS) hm_adapters_nvml[i].fan_get_supported = 1;
  
 -            hm_NVML_nvmlDeviceSetComputeMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_COMPUTEMODE_EXCLUSIVE_PROCESS);
 -
 -            hm_NVML_nvmlDeviceSetGpuOperationMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_GOM_ALL_ON);
 +            // doesn't seem to create any advantages
 +            //hm_NVML_nvmlDeviceSetComputeMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_COMPUTEMODE_EXCLUSIVE_PROCESS);
 +            //hm_NVML_nvmlDeviceSetGpuOperationMode (data.hm_nvml, 1, hm_adapters_nvml[i].nvml, NVML_GOM_ALL_ON);
            }
          }
        }
       * OpenCL devices: allocate buffer for device specific information
       */
  
 -    int *temp_retain_fanspeed_value  = (int *) mycalloc (data.devices_cnt, sizeof (int));
 -    int *temp_retain_fanpolicy_value = (int *) mycalloc (data.devices_cnt, sizeof (int));
 -
      ADLOD6MemClockState *od_clock_mem_status = (ADLOD6MemClockState *) mycalloc (data.devices_cnt, sizeof (ADLOD6MemClockState));
  
      int *od_power_control_status = (int *) mycalloc (data.devices_cnt, sizeof (int));
  
        const char *device_name_chksum      = device_param->device_name_chksum;
        const u32   device_processors       = device_param->device_processors;
 -      const u32   device_processor_cores  = device_param->device_processor_cores;
  
        /**
         * create context for each device
        if (hash_mode ==  3000) kernel_threads = 64; // DES
        if (hash_mode ==  3200) kernel_threads = 8;  // Blowfish
        if (hash_mode ==  7500) kernel_threads = 64; // RC4
 +      if (hash_mode ==  8900) kernel_threads = 32; // scrypt
        if (hash_mode ==  9000) kernel_threads = 8;  // Blowfish
 +      if (hash_mode ==  9300) kernel_threads = 32; // scrypt
        if (hash_mode ==  9700) kernel_threads = 64; // RC4
        if (hash_mode ==  9710) kernel_threads = 64; // RC4
        if (hash_mode ==  9800) kernel_threads = 64; // RC4
            }
          }
  
 +        device_param->kernel_accel_min = 1;
 +        device_param->kernel_accel_max = 8;
 +
          for (uint tmto = tmto_start; tmto < tmto_stop; tmto++)
          {
            // TODO: in theory the following calculation needs to be done per salt, not global
  
            size_scryptV /= 1 << tmto;
  
 -          size_scryptV *= device_processors * device_processor_cores;
 +          size_scryptV *= device_param->device_processors * device_param->kernel_threads * device_param->kernel_accel_max;
  
            if (size_scryptV > device_param->device_maxmem_alloc)
            {
            for (uint salts_pos = 0; salts_pos < data.salts_cnt; salts_pos++)
            {
              data.salts_buf[salts_pos].scrypt_tmto = tmto;
 -            data.salts_buf[salts_pos].scrypt_phy  = device_processors * device_processor_cores;
 +            data.salts_buf[salts_pos].scrypt_phy  = device_param->device_processors * device_param->kernel_threads * device_param->kernel_accel_max;
            }
  
            break;
          return -1;
        }
  
 +      naive_replace (cpath_real, '\\', '/');
 +
 +      // not escaping here, windows has quotes
 +
        snprintf (build_opts, sizeof (build_opts) - 1, "-I \"%s\"", cpath_real);
  
        myfree (cpath_real);
          return -1;
        }
  
 -      char cpath_escaped[1024] = { 0 };
 +      naive_escape (cpath_real, PATH_MAX,  ' ', '\\');
  
 -      naive_escape (cpath_real, cpath_escaped, sizeof (cpath_escaped));
 +      snprintf (build_opts, sizeof (build_opts) - 1, "-I %s", cpath_real);
  
        myfree (cpath_real);
  
 -      snprintf (build_opts, sizeof (build_opts) - 1, "-I %s", cpath_escaped);
 -
        #endif
  
        // we don't have sm_* on vendors not NV but it doesn't matter
  
        char build_opts_new[1024] = { 0 };
  
 -      snprintf (build_opts_new, sizeof (build_opts_new) - 1, "%s -D VENDOR_ID=%u -D CUDA_ARCH=%d -D VECT_SIZE=%u -D DEVICE_TYPE=%u -D KERN_TYPE=%u -D _unroll -cl-std=CL1.1", build_opts, device_param->device_vendor_id, (device_param->sm_major * 100) + device_param->sm_minor, device_param->vector_width, (u32) device_param->device_type, kern_type);
 +      snprintf (build_opts_new, sizeof (build_opts_new) - 1, "%s -D VENDOR_ID=%u -D CUDA_ARCH=%d -D VECT_SIZE=%u -D DEVICE_TYPE=%u -D DGST_R0=%u -D DGST_R1=%u -D DGST_R2=%u -D DGST_R3=%u -D DGST_ELEM=%u -D KERN_TYPE=%u -D _unroll -cl-std=CL1.1", build_opts, device_param->device_vendor_id, (device_param->sm_major * 100) + device_param->sm_minor, device_param->vector_width, (u32) device_param->device_type, data.dgst_pos0, data.dgst_pos1, data.dgst_pos2, data.dgst_pos3, data.dgst_size / 4, kern_type);
  
        strncpy (build_opts, build_opts_new, sizeof (build_opts));
  
              const int fanspeed  = hm_get_fanspeed_with_device_id  (device_id);
              const int fanpolicy = hm_get_fanpolicy_with_device_id (device_id);
  
 -            temp_retain_fanspeed_value[device_id]  = fanspeed;
 -            temp_retain_fanpolicy_value[device_id] = fanpolicy;
 -
              // we also set it to tell the OS we take control over the fan and it's automatic controller
              // if it was set to automatic. we do not control user-defined fanspeeds.
  
      wl_data->cnt   = 0;
      wl_data->pos   = 0;
  
 -    uint wordlist_mode = ((optind + 1) < myargc) ? WL_MODE_FILE : WL_MODE_STDIN;
 -
 -    data.wordlist_mode = wordlist_mode;
 -
      cs_t  *css_buf   = NULL;
      uint   css_cnt   = 0;
      uint   dictcnt   = 0;
       * status and monitor threads
       */
  
 -    if (data.devices_status != STATUS_CRACKED) data.devices_status = STATUS_STARTING;
 -
 -    uint i_threads_cnt = 0;
 -
 -    hc_thread_t *i_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
 -
 -    if ((data.wordlist_mode == WL_MODE_FILE) || (data.wordlist_mode == WL_MODE_MASK))
 +    if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
      {
 -      if (stdout_flag == 0)
 -      {
 -        hc_thread_create (i_threads[i_threads_cnt], thread_keypress, &benchmark);
 -
 -        i_threads_cnt++;
 -      }
 +      data.devices_status = STATUS_STARTING;
      }
  
 -    if (wordlist_mode == WL_MODE_STDIN) data.status = 1;
 -
 -    uint ni_threads_cnt = 0;
 +    uint inner_threads_cnt = 0;
  
 -    hc_thread_t *ni_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
 +    hc_thread_t *inner_threads = (hc_thread_t *) mycalloc (10, sizeof (hc_thread_t));
  
 -    if (stdout_flag == 0)
 -    {
 -      hc_thread_create (ni_threads[ni_threads_cnt], thread_monitor, NULL);
 -
 -      ni_threads_cnt++;
 -    }
 +    data.shutdown_inner = 0;
  
      /**
        * Outfile remove
        */
  
 -    if (keyspace == 0)
 +    if (keyspace == 0 && benchmark == 0 && stdout_flag == 0)
      {
 +      hc_thread_create (inner_threads[inner_threads_cnt], thread_monitor, NULL);
 +
 +      inner_threads_cnt++;
 +
        if (outfile_check_timer != 0)
        {
          if (data.outfile_check_directory != NULL)
                !((hash_mode >= 13700) && (hash_mode <= 13799)) &&
                (hash_mode != 9000))
            {
 -            hc_thread_create (ni_threads[ni_threads_cnt], thread_outfile_remove, NULL);
 +            hc_thread_create (inner_threads[inner_threads_cnt], thread_outfile_remove, NULL);
  
 -            ni_threads_cnt++;
 +            inner_threads_cnt++;
            }
            else
            {
  
      for (uint maskpos = rd->maskpos; maskpos < maskcnt; maskpos++)
      {
 -      if (data.devices_status == STATUS_CRACKED) break;
 -
 -      data.devices_status = STATUS_INIT;
 +      if (data.devices_status == STATUS_CRACKED) continue;
 +      if (data.devices_status == STATUS_ABORTED) continue;
 +      if (data.devices_status == STATUS_QUIT)    continue;
  
        if (maskpos > rd->maskpos)
        {
          }
        }
  
 -      for (uint dictpos = rd->dictpos; dictpos < dictcnt; )
 +      for (uint dictpos = rd->dictpos; dictpos < dictcnt; dictpos++)
        {
 +        if (data.devices_status == STATUS_CRACKED) continue;
 +        if (data.devices_status == STATUS_ABORTED) continue;
 +        if (data.devices_status == STATUS_QUIT)    continue;
 +
 +        rd->dictpos = dictpos;
 +
          char *subid = logfile_generate_subid ();
  
          data.subid = subid;
  
          logfile_sub_msg ("START");
  
 -        data.devices_status = STATUS_INIT;
 +        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +        {
 +          data.devices_status = STATUS_INIT;
 +        }
  
          memset (data.words_progress_done,     0, data.salts_cnt * sizeof (u64));
          memset (data.words_progress_rejected, 0, data.salts_cnt * sizeof (u64));
  
              if (data.words_cnt == 0)
              {
 -              if (data.devices_status == STATUS_CRACKED) break;
 -              if (data.devices_status == STATUS_ABORTED) break;
 -
 -              dictpos++;
 +              logfile_sub_msg ("STOP");
  
                continue;
              }
  
            if (data.words_cnt == 0)
            {
 -            if (data.devices_status == STATUS_CRACKED) break;
 -            if (data.devices_status == STATUS_ABORTED) break;
 -
 -            dictpos++;
 +            logfile_sub_msg ("STOP");
  
              continue;
            }
  
            if (data.words_cnt == 0)
            {
 -            if (data.devices_status == STATUS_CRACKED) break;
 -            if (data.devices_status == STATUS_ABORTED) break;
 -
 -            dictpos++;
 +            logfile_sub_msg ("STOP");
  
              continue;
            }
  
              // skip to next mask
  
 -            dictpos++;
 -
 -            rd->dictpos = dictpos;
 -
              logfile_sub_msg ("STOP");
  
              continue;
  
          hc_thread_t *c_threads = (hc_thread_t *) mycalloc (data.devices_cnt, sizeof (hc_thread_t));
  
 -        data.devices_status = STATUS_AUTOTUNE;
 +        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +        {
 +          data.devices_status = STATUS_AUTOTUNE;
 +        }
  
          for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
          {
           * create cracker threads
           */
  
 -        data.devices_status = STATUS_RUNNING;
 +        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +        {
 +          data.devices_status = STATUS_RUNNING;
 +        }
  
          if (initial_restore_done == 0)
          {
  
          local_free (c_threads);
  
 -        data.restore = 0;
 -
 -        // finalize task
 +        if ((data.devices_status != STATUS_BYPASS) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +        {
 +          data.devices_status = STATUS_EXHAUSTED;
 +        }
  
          logfile_sub_var_uint ("status-after-work", data.devices_status);
  
 -        if (data.devices_status == STATUS_STOP_AT_CHECKPOINT) check_checkpoint ();
 -
 -        if (data.devices_status == STATUS_CRACKED) break;
 -        if (data.devices_status == STATUS_ABORTED) break;
 -
 -        if (data.devices_status == STATUS_BYPASS)
 -        {
 -          data.devices_status = STATUS_RUNNING;
 -        }
 +        data.restore = 0;
  
          if (induction_dictionaries_cnt)
          {
            induction_dictionaries_cnt = count_dictionaries (induction_dictionaries);
          }
  
 -        if (benchmark == 0)
 +        if (benchmark == 1)
          {
 -          if (((dictpos + 1) < dictcnt) || ((maskpos + 1) < maskcnt) || induction_dictionaries_cnt)
 -          {
 -            if (quiet == 0) clear_prompt ();
 +          status_benchmark ();
  
 -            if (quiet == 0) log_info ("");
 -
 -            if (status == 1)
 -            {
 -              status_display ();
 -            }
 -            else
 -            {
 -              if (quiet == 0) status_display ();
 -            }
 -
 -            if (quiet == 0) log_info ("");
 +          if (machine_readable == 0)
 +          {
 +            log_info ("");
            }
          }
 -
 -        if (attack_mode == ATTACK_MODE_BF)
 -        {
 -          dictpos++;
 -
 -          rd->dictpos = dictpos;
 -        }
          else
          {
 -          if (induction_dictionaries_cnt)
 -          {
 -            qsort (induction_dictionaries, induction_dictionaries_cnt, sizeof (char *), sort_by_mtime);
 -          }
 -          else
 +          if (quiet == 0)
            {
 -            dictpos++;
 +            clear_prompt ();
 +
 +            log_info ("");
 +
 +            if (stdout_flag == 0) status_display ();
  
 -            rd->dictpos = dictpos;
 +            log_info ("");
            }
          }
  
 +        if (induction_dictionaries_cnt)
 +        {
 +          qsort (induction_dictionaries, induction_dictionaries_cnt, sizeof (char *), sort_by_mtime);
 +        }
 +
          time_t runtime_stop;
  
          time (&runtime_stop);
          logfile_sub_msg ("STOP");
  
          global_free (subid);
 -      }
  
 -      if (data.devices_status == STATUS_STOP_AT_CHECKPOINT) check_checkpoint ();
 +        // from this point we handle bypass as running
 +
 +        if (data.devices_status == STATUS_BYPASS)
 +        {
 +          data.devices_status = STATUS_RUNNING;
 +        }
 +
 +        // and overwrite benchmark aborts as well
 +
 +        if (data.benchmark == 1)
 +        {
 +          if (data.devices_status == STATUS_ABORTED)
 +          {
 +            data.devices_status = STATUS_RUNNING;
 +          }
 +        }
 +
 +        // finalize task
 +
 +        if (data.devices_status == STATUS_CRACKED) break;
 +        if (data.devices_status == STATUS_ABORTED) break;
 +        if (data.devices_status == STATUS_QUIT)    break;
 +      }
  
        if (data.devices_status == STATUS_CRACKED) break;
        if (data.devices_status == STATUS_ABORTED) break;
        if (data.devices_status == STATUS_QUIT)    break;
 -
 -      if (data.devices_status == STATUS_BYPASS)
 -      {
 -        data.devices_status = STATUS_RUNNING;
 -      }
      }
  
      // problems could occur if already at startup everything was cracked (because of .pot file reading etc), we must set some variables here to avoid NULL pointers
 -
      if (attack_mode == ATTACK_MODE_STRAIGHT)
      {
        if (data.wordlist_mode == WL_MODE_FILE)
        }
      }
  
 -    if ((data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 -    {
 -      data.devices_status = STATUS_EXHAUSTED;
 -    }
 -
      // if cracked / aborted remove last induction dictionary
  
      for (int file_pos = 0; file_pos < induction_dictionaries_cnt; file_pos++)
        }
      }
  
 -    // wait for non-interactive threads
 -
 -    for (uint thread_idx = 0; thread_idx < ni_threads_cnt; thread_idx++)
 -    {
 -      hc_thread_wait (1, &ni_threads[thread_idx]);
 -    }
 +    // wait for inner threads
  
 -    local_free (ni_threads);
 +    data.shutdown_inner = 1;
  
 -    // wait for interactive threads
 -
 -    for (uint thread_idx = 0; thread_idx < i_threads_cnt; thread_idx++)
 +    for (uint thread_idx = 0; thread_idx < inner_threads_cnt; thread_idx++)
      {
 -      hc_thread_wait (1, &i_threads[thread_idx]);
 +      hc_thread_wait (1, &inner_threads[thread_idx]);
      }
  
 -    local_free (i_threads);
 +    local_free (inner_threads);
  
      // we dont need restore file anymore
      if (data.restore_disable == 0)
       * Clean up
       */
  
 -    if (benchmark == 1)
 -    {
 -      status_benchmark ();
 -
 -      if (machine_readable == 0)
 -      {
 -        log_info ("");
 -      }
 -    }
 -    else
 -    {
 -      if (quiet == 0) clear_prompt ();
 -
 -      if (quiet == 0) log_info ("");
 -
 -      if (status == 1)
 -      {
 -        status_display ();
 -      }
 -      else
 -      {
 -        if (quiet == 0) status_display ();
 -      }
 -
 -      if (quiet == 0) log_info ("");
 -    }
 -
      for (uint device_id = 0; device_id < data.devices_cnt; device_id++)
      {
        hc_device_param_t *device_param = &data.devices_param[device_id];
        if (device_param->skipped) continue;
  
        local_free (device_param->combs_buf);
 -
        local_free (device_param->hooks_buf);
 -
        local_free (device_param->device_name);
 -
        local_free (device_param->device_name_chksum);
 -
        local_free (device_param->device_version);
 -
        local_free (device_param->driver_version);
  
        if (device_param->pws_buf)            myfree                    (device_param->pws_buf);
      #ifdef HAVE_HWMON
      if (gpu_temp_disable == 0)
      {
 -      if (gpu_temp_retain != 0) // VENDOR_ID_AMD is implied here
 +      if (gpu_temp_retain != 0)
        {
          hc_thread_mutex_lock (mux_adl);
  
  
            if (data.hm_device[device_id].fan_set_supported == 1)
            {
 -            int fanspeed  = temp_retain_fanspeed_value[device_id];
 -            int fanpolicy = temp_retain_fanpolicy_value[device_id];
 +            int rc = -1;
  
 -            if (fanpolicy == 1)
 +            if (device_param->device_vendor_id == VENDOR_ID_AMD)
              {
 -              int rc = -1;
 -
 -              if (device_param->device_vendor_id == VENDOR_ID_AMD)
 -              {
 -                rc = hm_set_fanspeed_with_device_id_adl (device_id, fanspeed, 0);
 -              }
 -              else if (device_param->device_vendor_id == VENDOR_ID_NV)
 -              {
 -                #ifdef LINUX
 -                rc = set_fan_control (data.hm_xnvctrl, data.hm_device[device_id].xnvctrl, NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE);
 -                #endif
 -
 -                #ifdef WIN
 -                rc = hm_set_fanspeed_with_device_id_nvapi (device_id, fanspeed, fanpolicy);
 -                #endif
 -              }
 +              rc = hm_set_fanspeed_with_device_id_adl (device_id, 100, 0);
 +            }
 +            else if (device_param->device_vendor_id == VENDOR_ID_NV)
 +            {
 +              #ifdef LINUX
 +              rc = set_fan_control (data.hm_xnvctrl, data.hm_device[device_id].xnvctrl, NV_CTRL_GPU_COOLER_MANUAL_CONTROL_FALSE);
 +              #endif
  
 -              if (rc == -1) log_info ("WARNING: Failed to restore default fan speed and policy for device #%", device_id + 1);
 +              #ifdef WIN
 +              rc = hm_set_fanspeed_with_device_id_nvapi (device_id, 100, 0);
 +              #endif
              }
 +
 +            if (rc == -1) log_info ("WARNING: Failed to restore default fan speed and policy for device #%", device_id + 1);
            }
          }
  
  
      // reset power tuning
  
 -    if (powertune_enable == 1) // VENDOR_ID_AMD is implied here
 +    if (powertune_enable == 1)
      {
        hc_thread_mutex_lock (mux_adl);
  
      local_free (bitmap_s2_d);
  
      #ifdef HAVE_HWMON
 -    local_free (temp_retain_fanspeed_value);
      local_free (od_clock_mem_status);
      local_free (od_power_control_status);
      local_free (nvml_power_limit);
      if (data.devices_status == STATUS_QUIT) break;
    }
  
 +  // wait for outer threads
 +
 +  data.shutdown_outer = 1;
 +
 +  for (uint thread_idx = 0; thread_idx < outer_threads_cnt; thread_idx++)
 +  {
 +    hc_thread_wait (1, &outer_threads[thread_idx]);
 +  }
 +
 +  local_free (outer_threads);
 +
    // destroy others mutex
  
    hc_thread_mutex_delete (mux_dispatcher);
diff --combined src/shared.c
@@@ -6,7 -6,7 +6,7 @@@
   * License.....: MIT
   */
  
- #ifdef OSX
+ #ifdef DARWIN
  #include <stdio.h>
  #endif
  
@@@ -2382,7 -2382,7 +2382,7 @@@ int tty_fix(
  }
  #endif
  
- #ifdef OSX
+ #ifdef DARWIN
  static struct termios savemodes;
  static int havemodes = 0;
  
@@@ -3402,17 -3402,11 +3402,17 @@@ int hm_get_throttle_with_device_id (con
      if (hm_NVML_nvmlDeviceGetCurrentClocksThrottleReasons   (data.hm_nvml, 1, data.hm_device[device_id].nvml, &clocksThrottleReasons)    != NVML_SUCCESS) return -1;
      if (hm_NVML_nvmlDeviceGetSupportedClocksThrottleReasons (data.hm_nvml, 1, data.hm_device[device_id].nvml, &supportedThrottleReasons) != NVML_SUCCESS) return -1;
  
 -    clocksThrottleReasons &= supportedThrottleReasons;
 -
 +    clocksThrottleReasons &=  supportedThrottleReasons;
 +    clocksThrottleReasons &= ~nvmlClocksThrottleReasonGpuIdle;
 +    clocksThrottleReasons &= ~nvmlClocksThrottleReasonApplicationsClocksSetting;
      clocksThrottleReasons &= ~nvmlClocksThrottleReasonUnknown;
  
 -    return (clocksThrottleReasons > 0);
 +    if (data.kernel_power_final)
 +    {
 +      clocksThrottleReasons &= ~nvmlClocksThrottleReasonHwSlowdown;
 +    }
 +
 +    return (clocksThrottleReasons != nvmlClocksThrottleReasonNone);
    }
  
    return -1;
@@@ -3424,51 -3418,33 +3424,51 @@@ int hm_set_fanspeed_with_device_id_adl 
    {
      if (data.hm_adl)
      {
 -      if (data.hm_device[device_id].od_version == 5)
 +      if (fanpolicy == 1)
        {
 -        ADLFanSpeedValue lpFanSpeedValue;
 +        if (data.hm_device[device_id].od_version == 5)
 +        {
 +          ADLFanSpeedValue lpFanSpeedValue;
  
 -        memset (&lpFanSpeedValue, 0, sizeof (lpFanSpeedValue));
 +          memset (&lpFanSpeedValue, 0, sizeof (lpFanSpeedValue));
  
 -        lpFanSpeedValue.iSize      = sizeof (lpFanSpeedValue);
 -        lpFanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
 -        lpFanSpeedValue.iFlags     = (fanpolicy == 1) ? ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED : 0;
 -        lpFanSpeedValue.iFanSpeed  = fanspeed;
 +          lpFanSpeedValue.iSize      = sizeof (lpFanSpeedValue);
 +          lpFanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
 +          lpFanSpeedValue.iFlags     = ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
 +          lpFanSpeedValue.iFanSpeed  = fanspeed;
  
 -        if (hm_ADL_Overdrive5_FanSpeed_Set (data.hm_adl, data.hm_device[device_id].adl, 0, &lpFanSpeedValue) != ADL_OK) return -1;
 +          if (hm_ADL_Overdrive5_FanSpeed_Set (data.hm_adl, data.hm_device[device_id].adl, 0, &lpFanSpeedValue) != ADL_OK) return -1;
  
 -        return 0;
 -      }
 -      else // od_version == 6
 -      {
 -        ADLOD6FanSpeedValue fan_speed_value;
 +          return 0;
 +        }
 +        else // od_version == 6
 +        {
 +          ADLOD6FanSpeedValue fan_speed_value;
  
 -        memset (&fan_speed_value, 0, sizeof (fan_speed_value));
 +          memset (&fan_speed_value, 0, sizeof (fan_speed_value));
  
 -        fan_speed_value.iSpeedType = ADL_OD6_FANSPEED_TYPE_PERCENT;
 -        fan_speed_value.iFanSpeed  = fanspeed;
 +          fan_speed_value.iSpeedType = ADL_OD6_FANSPEED_TYPE_PERCENT;
 +          fan_speed_value.iFanSpeed  = fanspeed;
  
 -        if (hm_ADL_Overdrive6_FanSpeed_Set (data.hm_adl, data.hm_device[device_id].adl, &fan_speed_value) != ADL_OK) return -1;
 +          if (hm_ADL_Overdrive6_FanSpeed_Set (data.hm_adl, data.hm_device[device_id].adl, &fan_speed_value) != ADL_OK) return -1;
  
 -        return 0;
 +          return 0;
 +        }
 +      }
 +      else
 +      {
 +        if (data.hm_device[device_id].od_version == 5)
 +        {
 +          if (hm_ADL_Overdrive5_FanSpeedToDefault_Set (data.hm_adl, data.hm_device[device_id].adl, 0) != ADL_OK) return -1;
 +
 +          return 0;
 +        }
 +        else // od_version == 6
 +        {
 +          if (hm_ADL_Overdrive6_FanSpeed_Reset (data.hm_adl, data.hm_device[device_id].adl) != ADL_OK) return -1;
 +
 +          return 0;
 +        }
        }
      }
    }
@@@ -3482,25 -3458,16 +3482,25 @@@ int hm_set_fanspeed_with_device_id_nvap
    {
      if (data.hm_nvapi)
      {
 -      NV_GPU_COOLER_LEVELS CoolerLevels = { 0 };
 +      if (fanpolicy == 1)
 +      {
 +        NV_GPU_COOLER_LEVELS CoolerLevels = { 0 };
  
 -      CoolerLevels.Version = GPU_COOLER_LEVELS_VER | sizeof (NV_GPU_COOLER_LEVELS);
 +        CoolerLevels.Version = GPU_COOLER_LEVELS_VER | sizeof (NV_GPU_COOLER_LEVELS);
  
 -      CoolerLevels.Levels[0].Level  = fanspeed;
 -      CoolerLevels.Levels[0].Policy = fanpolicy;
 +        CoolerLevels.Levels[0].Level  = fanspeed;
 +        CoolerLevels.Levels[0].Policy = 1;
  
 -      if (hm_NvAPI_GPU_SetCoolerLevels (data.hm_nvapi, data.hm_device[device_id].nvapi, 0, &CoolerLevels) != NVAPI_OK) return -1;
 +        if (hm_NvAPI_GPU_SetCoolerLevels (data.hm_nvapi, data.hm_device[device_id].nvapi, 0, &CoolerLevels) != NVAPI_OK) return -1;
  
 -      return 0;
 +        return 0;
 +      }
 +      else
 +      {
 +        if (hm_NvAPI_GPU_RestoreCoolerSettings (data.hm_nvapi, data.hm_device[device_id].nvapi, 0) != NVAPI_OK) return -1;
 +
 +        return 0;
 +      }
      }
    }
  
@@@ -4358,7 -4325,7 +4358,7 @@@ char *get_exec_path (
  
    const int len = GetModuleFileName (NULL, exec_path, exec_path_len - 1);
  
-   #elif OSX
+   #elif DARWIN
  
    uint size = exec_path_len;
  
@@@ -4495,7 -4462,7 +4495,7 @@@ void truecrypt_crc32 (const char *filen
    myfree (buf);
  }
  
- #ifdef OSX
+ #ifdef DARWIN
  int pthread_setaffinity_np (pthread_t thread, size_t cpu_size, cpu_set_t *cpu_set)
  {
    int core;
@@@ -5763,7 -5730,7 +5763,7 @@@ char **scan_directory (const char *path
  
    if ((d = opendir (tmp_path)) != NULL)
    {
-     #ifdef OSX
+     #ifdef DARWIN
      struct dirent e;
  
      for (;;) {
@@@ -9162,32 -9129,36 +9162,32 @@@ void to_hccap_t (hccap_t *hccap, uint s
  
  void SuspendThreads ()
  {
 -  if (data.devices_status == STATUS_RUNNING)
 -  {
 -    hc_timer_set (&data.timer_paused);
 +  if (data.devices_status != STATUS_RUNNING) return;
  
 -    data.devices_status = STATUS_PAUSED;
 +  hc_timer_set (&data.timer_paused);
  
 -    log_info ("Paused");
 -  }
 +  data.devices_status = STATUS_PAUSED;
 +
 +  log_info ("Paused");
  }
  
  void ResumeThreads ()
  {
 -  if (data.devices_status == STATUS_PAUSED)
 -  {
 -    double ms_paused;
 +  if (data.devices_status != STATUS_PAUSED) return;
  
 -    hc_timer_get (data.timer_paused, ms_paused);
 +  double ms_paused;
  
 -    data.ms_paused += ms_paused;
 +  hc_timer_get (data.timer_paused, ms_paused);
  
 -    data.devices_status = STATUS_RUNNING;
 +  data.ms_paused += ms_paused;
  
 -    log_info ("Resumed");
 -  }
 +  data.devices_status = STATUS_RUNNING;
 +
 +  log_info ("Resumed");
  }
  
  void bypass ()
  {
 -  if (data.devices_status != STATUS_RUNNING) return;
 -
    data.devices_status = STATUS_BYPASS;
  
    log_info ("Next dictionary / mask in queue selected, bypassing current one");
@@@ -9235,54 -9206,39 +9235,54 @@@ void stop_at_checkpoint (
  
  void myabort ()
  {
 -  if (data.devices_status == STATUS_INIT)     return;
 -  if (data.devices_status == STATUS_STARTING) return;
 -
    data.devices_status = STATUS_ABORTED;
  }
  
  void myquit ()
  {
 -  if (data.devices_status == STATUS_INIT)     return;
 -  if (data.devices_status == STATUS_STARTING) return;
 -
    data.devices_status = STATUS_QUIT;
  }
  
 -void naive_escape (const char *cpath_real, char *cpath_escaped, const size_t cpath_escaped_len)
 +void naive_replace (char *s, const u8 key_char, const u8 replace_char)
  {
 -  const size_t len = strlen (cpath_real);
 +  const size_t len = strlen (s);
 +
 +  for (size_t in = 0; in < len; in++)
 +  {
 +    const u8 c = s[in];
 +
 +    if (c == key_char)
 +    {
 +      s[in] = replace_char;
 +    }
 +  }
 +}
 +
 +void naive_escape (char *s, size_t s_max, const u8 key_char, const u8 escape_char)
 +{
 +  char s_escaped[1024] = { 0 };
 +
 +  size_t s_escaped_max = sizeof (s_escaped);
 +
 +  const size_t len = strlen (s);
  
    for (size_t in = 0, out = 0; in < len; in++, out++)
    {
 -    const u8 c = cpath_real[in];
 +    const u8 c = s[in];
  
 -    if (c == ' ')
 +    if (c == key_char)
      {
 -      cpath_escaped[out] = '\\';
 +      s_escaped[out] = escape_char;
  
        out++;
      }
  
 -    if (out == cpath_escaped_len) break;
 +    if (out == s_escaped_max - 2) break;
  
 -    cpath_escaped[out] = c;
 +    s_escaped[out] = c;
    }
 +
 +  strncpy (s, s_escaped, s_max - 1);
  }
  
  void load_kernel (const char *kernel_file, int num_devices, size_t *kernel_lengths, const u8 **kernel_sources)
@@@ -20727,7 -20683,7 +20727,7 @@@ BOOL WINAPI sigHandler_benchmark (DWOR
    {
      case CTRL_CLOSE_EVENT:
  
 -      myabort ();
 +      myquit ();
  
        SetConsoleCtrlHandler (NULL, TRUE);
  
@@@ -20792,11 -20748,13 +20792,11 @@@ void status_display ()
  
  void *thread_keypress (void *p)
  {
 -  int benchmark = *((int *) p);
 -
    uint quiet = data.quiet;
  
    tty_break();
  
 -  while ((data.devices_status != STATUS_EXHAUSTED) && (data.devices_status != STATUS_CRACKED) && (data.devices_status != STATUS_ABORTED) && (data.devices_status != STATUS_QUIT))
 +  while (data.shutdown_outer == 0)
    {
      int ch = tty_getchar();
  
  
          log_info ("");
  
 -        if (benchmark == 1) break;
 -
          stop_at_checkpoint ();
  
          log_info ("");
  
          log_info ("");
  
 -        if (benchmark == 1)
 -        {
 -          myquit ();
 -        }
 -        else
 -        {
 -          myabort ();
 -        }
 +        myabort ();
  
          break;
      }