Ejemplo n.º 1
0
static void
do_loop(void)
{
  unsigned char new_entry_name[EJ_PATH_MAX];
  unsigned char out_entry_name[EJ_PATH_MAX];
  unsigned char new_path[EJ_PATH_MAX];
  unsigned char out_path[EJ_PATH_MAX];
  int r;
  int serial = 0;

  while (1) {
    r = scan_dir(global->queue_dir, new_entry_name, sizeof(new_entry_name), 0);
    if (r < 0) {
      die("scan_dir failed on %s", global->queue_dir);
      /* FIXME: recover and continue */
    }

    if (!r) {
      os_Sleep(global->sleep_time);
      continue;
    }

    snprintf(out_entry_name, sizeof(out_entry_name), "%s_%s", os_NodeName(), new_entry_name);
    snprintf(new_path, sizeof(new_path), "%s/dir/%s", global->queue_dir, new_entry_name);
    snprintf(out_path, sizeof(out_path), "%s/out/%s", global->queue_dir, out_entry_name);

    while (rename(new_path, out_path) < 0) {
      if (errno == ENOENT) {
        err("file %s is stolen?", new_path);
        out_path[0] = 0;
        os_Sleep(global->sleep_time);
        break;
      }

      if (errno == ENOTEMPTY || errno == EEXIST) {
        err("directory %s already exists", out_path);
        snprintf(out_entry_name, sizeof(out_entry_name), "%s_%d_%s",
                 os_NodeName(), ++serial, new_entry_name);
        snprintf(out_path, sizeof(out_path), "%s/out/%s", global->queue_dir,
                 out_entry_name);
        continue;
      }

      die("rename: %s -> %s failed: %s", new_path, out_path, strerror(errno));
    }

    if (out_path[0]) {
      read_packet(out_path);
      remove_directory_recursively(out_path, 0);
    }
  }
}
Ejemplo n.º 2
0
/*! Remove a directory recursively like <tt>rm -r</tt>.
 *
 *  \return
 *      0 on success, -1 on failure
 *
 *  \param error
 *      On failure, \c error will be set to a newly allocated string
 *      that contains the error message.
 *      On success, or when out of memory,
 *      \c error will be set to \c NULL.
 *
 *  \param dirname
 *      the directory to remove
 */
static int remove_directory_recursively(char **error, const char *dirname)
{
    DIR *dir;
    struct dirent *entry;
    /* continue on errors and report only the first error that occured */
    *error = NULL;
    dir = opendir(dirname);
    if (dir == NULL && *error == NULL) {
        *error = sprintf_alloc("Unable to read directory entries of \"%s\": %s.",
                               dirname, strerror(errno));
    } else {
        for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) {
            char *name;
            if (   strcmp(entry->d_name, ".") == 0
                || strcmp(entry->d_name, "..") == 0) {
                continue;
            }
            name = sprintf_alloc("%s/%s", dirname, entry->d_name);
            if (name == NULL && *error == NULL) {
                *error = sprintf_alloc("Out of memory.");
                continue;
            }
            if (entry->d_type == DT_DIR) {
                char *sub_error;
                if (remove_directory_recursively(&sub_error, name) != 0 && *error == NULL) {
                    *error = sub_error;
                }
            } else {
                if (unlink(name) != 0 && *error == NULL) {
                    *error = sprintf_alloc("Unable to remove file \"%s\": %s.",
                                           name, strerror(errno));
                }
            }
            free(name);
        }
        if (closedir(dir) != 0 && *error == NULL) {
            *error = sprintf_alloc("Unable to close directory \"%s\": %s.",
                                   dirname, strerror(errno));
        }
    }
    if (rmdir(dirname) != 0) {
        if (*error == NULL) {
            *error = sprintf_alloc("Unable to remove directory \"%s\": %s.",
                                   dirname, strerror(errno));
        }
        return -1;
    }
    /* all previous errors are irrelevant because rmdir() was successful */
    *error = NULL;
    return 0;
}
Ejemplo n.º 3
0
/*! Convert a TeX or LaTeX source to DVI or PDF.
 */
void texcaller_convert(char **result, size_t *result_size, char **info, const char *source, size_t source_size, const char *source_format, const char *result_format, int max_runs)
{
    char *error;
    const char *cmd;
    const char *tmpdir;
    char *dir = NULL;
    char *dir_template = NULL;
    char *source_filename = NULL;
    char *aux_filename = NULL;
    char *log_filename = NULL;
    char *result_filename = NULL;
    char *aux = NULL;
    size_t aux_size = 0;
    char *aux_old = NULL;
    size_t aux_old_size = 0;
    int runs;
    *result = NULL;
    *result_size = 0;
    *info = NULL;
    /* check arguments */
    if        (strcmp(source_format, "TeX") == 0 && strcmp(result_format, "DVI") == 0) {
        cmd = "tex";
    } else if (strcmp(source_format, "TeX") == 0 && strcmp(result_format, "PDF") == 0) {
        cmd = "pdftex";
    } else if (strcmp(source_format, "LaTeX") == 0 && strcmp(result_format, "DVI") == 0) {
        cmd = "latex";
    } else if (strcmp(source_format, "LaTeX") == 0 && strcmp(result_format, "PDF") == 0) {
        cmd = "pdflatex";
    } else {
        *info = sprintf_alloc("Unable to convert from \"%s\" to \"%s\".",
                              source_format, result_format);
        goto cleanup;
    }
    if (max_runs < 2) {
        *info = sprintf_alloc("Argument max_runs is %i, but must be >= 2.",
                              max_runs);
        goto cleanup;
    }
    /* create temporary directory */
    tmpdir = getenv("TMPDIR");
    if (tmpdir == NULL || strcmp(tmpdir, "") == 0) {
        tmpdir = "/tmp";
    }
    dir_template = sprintf_alloc("%s/texcaller-temp-XXXXXX", tmpdir);
    if (dir_template == NULL) {
        goto cleanup;
    }
    dir = mkdtemp(dir_template);
    if (dir == NULL) {
        *info = sprintf_alloc("Unable to create temporary directory from template \"%s\": %s.",
                              dir_template, strerror(errno));
        goto cleanup;
    }
    source_filename = sprintf_alloc("%s/texput.tex", dir);
    if (source_filename == NULL) {
        goto cleanup;
    }
    aux_filename = sprintf_alloc("%s/texput.aux", dir);
    if (aux_filename == NULL) {
        goto cleanup;
    }
    log_filename = sprintf_alloc("%s/texput.log", dir);
    if (log_filename == NULL) {
        goto cleanup;
    }
    if (strcmp(result_format, "DVI") == 0) {
        result_filename = sprintf_alloc("%s/texput.dvi", dir);
    } else {
        result_filename = sprintf_alloc("%s/texput.pdf", dir);
    }
    if (result_filename == NULL) {
        goto cleanup;
    }
    /* create source file */
    if (write_file(&error, source_filename, source, source_size) != 0) {
        *info = error;
        goto cleanup;
    }
    /* run command as often as necessary */
    for (runs = 1; runs <= max_runs; runs++) {
        pid_t pid;
        pid = fork();
        if (pid == -1) {
            *info = sprintf_alloc("Unable to fork child process: %s.",
                                  strerror(errno));
            goto cleanup;
        }
        /* child process */
        if (pid == 0) {
            /* run command within the temporary directory */
            if (chdir(dir) != 0) {
                exit(1);
            }
            /* prevent access to stdin, stdout and stderr */
            fclose(stdin);
            fclose(stdout);
            fclose(stderr);
            /* execute command */
            execlp(cmd,
                   cmd,
                   "-interaction=batchmode",
                   "-halt-on-error",
                   "-file-line-error",
                   "-no-shell-escape",
                   "texput.tex",
                   NULL);
        }
        /* wait for child process */
        for (;;) {
            int status;
            pid_t wpid = waitpid(pid, &status, 0);
            if (wpid == -1) {
                *info = sprintf_alloc("Unable to wait for child process: %s.",
                                      strerror(errno));
                goto cleanup;
            }
            if (WIFSIGNALED(status)) {
                *info = sprintf_alloc("Command \"%s\" was terminated by signal %i.",
                                      cmd, (int)WTERMSIG(status));
                goto cleanup;
            }
            if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
                *info = sprintf_alloc("Command \"%s\" terminated with exit status %i.",
                                      cmd, (int)WEXITSTATUS(status));
                goto cleanup;
            }
            if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
                break;
            }
        }
        /* read new aux file, saving old one */
        free(aux_old);
        aux_old      = aux;
        aux_old_size = aux_size;
        read_file(&aux, &aux_size, &error, aux_filename);
        /* tolerate missing aux file */
        free(error);
        /* check whether aux file stabilized,
           which is also true if there isn't and wasn't any aux file */
        if (aux_size == aux_old_size && memcmp(aux, aux_old, aux_size) == 0) {
            read_file(result, result_size, &error, result_filename);
            if (*result == NULL) {
                *info = error;
                goto cleanup;
            }
            *info = sprintf_alloc("Generated %s (%lu bytes)"
                                  " from %s (%lu bytes) after %i runs.",
                                  result_format, (unsigned long)*result_size,
                                  source_format, (unsigned long)source_size, runs);
            goto cleanup;
        }
    }
    /* aux file didn't stabilize */
    *info = sprintf_alloc("Output didn't stabilize after %i runs.",
                          max_runs);
    goto cleanup;
    /* cleanup all used resources */
cleanup:
    if (log_filename != NULL) {
        char *log;
        size_t log_size;
        read_file(&log, &log_size, &error, log_filename);
        free(error);
        if (log != NULL) {
            if (*info == NULL) {
                *info = log;
            } else {
                char *info_old = *info;
                *info = sprintf_alloc("%s\n\n%s", info_old, log);
                free(info_old);
                free(log);
            }
        }
    }
    if (dir != NULL && remove_directory_recursively(&error, dir) != 0) {
        free(*result);
        *result = NULL;
        *result_size = 0;
        free(*info);
        *info = error;
    }
    free(dir_template);
    free(source_filename);
    free(aux_filename);
    free(log_filename);
    free(result_filename);
    free(aux);
    free(aux_old);
}
Ejemplo n.º 4
0
static void
read_packet(const unsigned char *dir_path)
{
  unsigned char packet_conf_file[EJ_PATH_MAX];
  FILE *f = 0;
  struct generic_section_config *packet_config = 0;
  struct nwrun_in_packet *packet = 0;
  unsigned char result_name[EJ_PATH_MAX];
  unsigned char result_in_dir[EJ_PATH_MAX];
  unsigned char result_dir_dir[EJ_PATH_MAX];
  unsigned char contest_dir[EJ_PATH_MAX];
  struct nwrun_out_packet result;
  unsigned char result_packet_path[EJ_PATH_MAX];
  int clean_result_dir = 0;

  memset(&result, 0, sizeof(result));

  snprintf(packet_conf_file,sizeof(packet_conf_file),"%s/packet.cfg",dir_path);
  packet_config = nwrun_in_packet_parse(packet_conf_file, &packet);
  if (!packet_config) goto cleanup;

  nwrun_in_packet_print(stderr, (const struct nwrun_in_packet *) packet_config);
  
  /* setup packet defaults */
  if (packet->contest_id <= 0) {
    err("contest_id is not set");
    goto cleanup;
  }
  if (packet->prob_id <= 0) {
    err("prob_id is not set");
    goto cleanup;
  }
  if (packet->test_num <= 0) {
    err("test_num is not set");
    goto cleanup;
  }
  if (packet->judge_id <= 0) {
    err("judge_id is not set");
    goto cleanup;
  }
  if (!packet->program_name[0]) {
    err("program_name is not set");
    goto cleanup;
  }
  if (!packet->test_file_name[0]) {
    err("test_file_name is not set");
    goto cleanup;
  }
  if (!packet->input_file_name[0]) {
    snprintf(packet->input_file_name, sizeof(packet->input_file_name),
             "%s", DEFAULT_INPUT_FILE_NAME);
  }
  if (!packet->result_file_name[0]) {
    err("result_file_name is not set");
    goto cleanup;
  }
  if (!packet->output_file_name[0]) {
    snprintf(packet->output_file_name, sizeof(packet->output_file_name),
             "%s", DEFAULT_OUTPUT_FILE_NAME);
  }
  if (!packet->error_file_name[0]) {
    snprintf(packet->error_file_name, sizeof(packet->error_file_name),
             "%s", DEFAULT_ERROR_FILE_NAME);
  }

  if (packet->max_output_file_size <= 0) {
    packet->max_output_file_size = DEFAULT_MAX_OUTPUT_FILE_SIZE;
  }
  if (packet->max_error_file_size <= 0) {
    packet->max_error_file_size = DEFAULT_MAX_ERROR_FILE_SIZE;
  }
  if (packet->time_limit_millis <= 0) {
    err("time_limit_millis is invalid (%d)", packet->time_limit_millis);
    goto cleanup;
  }

  /* create the output directory */
  snprintf(result_name, sizeof(result_name), "%c%c%d%c%d%c%d%c%d%c%d",
           get_priority_code(packet->priority - 17),
           get_num_prefix(packet->contest_id), packet->contest_id,
           get_num_prefix(packet->run_id - 1), packet->run_id - 1,
           get_num_prefix(packet->prob_id), packet->prob_id,
           get_num_prefix(packet->test_num), packet->test_num,
           get_num_prefix(packet->judge_id), packet->judge_id);
  if (packet->use_contest_id_in_reply) {
    snprintf(contest_dir, sizeof(contest_dir), "%s/%06d", global->result_dir, packet->contest_id);
    if (make_all_dir(contest_dir, 0777) < 0) {
      goto cleanup;
    }
    snprintf(result_in_dir, sizeof(result_in_dir), "%s/in/%s_%s",
             contest_dir, os_NodeName(), result_name);
    snprintf(result_dir_dir, sizeof(result_dir_dir), "%s/dir/%s",
             contest_dir, result_name);
  } else {
    snprintf(result_in_dir, sizeof(result_in_dir), "%s/in/%s_%s",
             global->result_dir, os_NodeName(), result_name);
    snprintf(result_dir_dir, sizeof(result_dir_dir), "%s/dir/%s",
             global->result_dir, result_name);
  }

  if (make_dir(result_in_dir, 0777) < 0) {
    goto cleanup;
  }
  clean_result_dir = 1;

  // set default values
  snprintf(result.hostname, sizeof(result.hostname), "%s", os_NodeName());
  result.contest_id = packet->contest_id;
  result.run_id = packet->run_id;
  result.prob_id = packet->prob_id;
  result.test_num = packet->test_num;
  result.judge_id = packet->judge_id;
  result.status = RUN_CHECK_FAILED;
  snprintf(result.comment, sizeof(result.comment), "Default status was not changed");

  handle_packet(dir_path, packet, result_in_dir, &result);

  snprintf(result_packet_path, sizeof(result_packet_path), "%s/packet.cfg",
           result_in_dir);
  if (!(f = fopen(result_packet_path, "wb"))) {
    err("cannot open file %s: %s", result_packet_path, os_ErrorMsg());
    goto cleanup;
  }
  nwrun_out_packet_print(f, &result);
  fclose(f); f = 0;

  nwrun_out_packet_print(stderr, &result); 

  if (rename(result_in_dir, result_dir_dir) < 0) {
    err("rename: %s -> %s failed: %s", result_in_dir, result_dir_dir, os_ErrorMsg());
    goto cleanup;
  }
  clean_result_dir = 0;

 cleanup:
  if (clean_result_dir) {
    remove_directory_recursively(result_in_dir, 0);
  }
  nwrun_in_packet_free(packet_config);
  if (f) fclose(f);
}
Ejemplo n.º 5
0
static void
handle_packet(
        const unsigned char *dir_path,
        const struct nwrun_in_packet *packet,
        const unsigned char *result_path,
        struct nwrun_out_packet *result)
{
  unsigned char dst_program_path[EJ_PATH_MAX];
  unsigned char src_program_path[EJ_PATH_MAX];
  unsigned char dst_input_path[EJ_PATH_MAX];
  unsigned char src_input_path[EJ_PATH_MAX];
  unsigned char run_output_path[EJ_PATH_MAX];
  unsigned char full_output_path[EJ_PATH_MAX];
  unsigned char run_error_path[EJ_PATH_MAX];
  //unsigned char log_file_path[EJ_PATH_MAX];
  unsigned char error_file_path[EJ_PATH_MAX];
  unsigned char result_file_path[EJ_PATH_MAX];

  ssize_t error_file_size;
  ssize_t output_file_size;

  FILE *f = 0;
  int cur_status = RUN_OK;

  /* copy the executable */
  snprintf(dst_program_path, sizeof(dst_program_path), "%s/%s",
           global->work_dir, packet->program_name);
  snprintf(src_program_path, sizeof(src_program_path), "%s/%s",
           dir_path, packet->program_name);
  if (fast_copy_file(src_program_path, dst_program_path) < 0) {
    snprintf(result->comment, sizeof(result->comment),
             "copy failed: %s -> %s", src_program_path, dst_program_path);
    goto cleanup;
  }

  /* copy the input file */
  snprintf(dst_input_path, sizeof(dst_input_path), "%s/%s",
           global->work_dir, packet->input_file_name);
  snprintf(src_input_path, sizeof(src_input_path), "%s/%s",
           dir_path, packet->test_file_name);
  if (packet->enable_unix2dos > 0) {
    if (generic_copy_file(CONVERT, "", src_input_path, "",
                          CONVERT, "", dst_input_path, "") < 0) {
      snprintf(result->comment, sizeof(result->comment),
               "unix2dos copy failed: %s -> %s", src_input_path, dst_input_path);
      goto cleanup;
    }
  } else {
    if (fast_copy_file(src_input_path, dst_input_path) < 0) {
      snprintf(result->comment, sizeof(result->comment),
               "copy failed: %s -> %s", src_input_path, dst_input_path);
      goto cleanup;
    }
  }

  if (packet->combined_stdin > 0) {
    snprintf(dst_input_path, sizeof(dst_input_path), "%s/%s.stdin",
             global->work_dir, packet->input_file_name);
    if (packet->enable_unix2dos > 0) {
      if (generic_copy_file(CONVERT, "", src_input_path, "",
                            CONVERT, "", dst_input_path, "") < 0) {
        snprintf(result->comment, sizeof(result->comment),
                 "unix2dos copy failed: %s -> %s", src_input_path,
                 dst_input_path);
        goto cleanup;
      }
    } else {
      if (fast_copy_file(src_input_path, dst_input_path) < 0) {
        snprintf(result->comment, sizeof(result->comment),
                 "copy failed: %s -> %s", src_input_path, dst_input_path);
        goto cleanup;
      }
    }
  }

  snprintf(run_output_path, sizeof(run_output_path), "%s/%s",
           global->work_dir, packet->output_file_name);
  if (packet->combined_stdout > 0) {
    snprintf(run_output_path, sizeof(run_output_path), "%s/%s.stdout",
             global->work_dir, packet->output_file_name);
  }

  snprintf(run_error_path, sizeof(run_error_path), "%s/%s",
           global->work_dir, packet->error_file_name);

  cur_status = run_program(packet, dst_program_path,
                           dst_input_path, run_output_path,
                           run_error_path, result);

  if (packet->combined_stdout > 0) {
    snprintf(full_output_path, sizeof(full_output_path), "%s/%s",
             global->work_dir, packet->output_file_name);
    concatenate_files(full_output_path, run_output_path);
    snprintf(run_output_path, sizeof(run_output_path), "%s", full_output_path);
  }

  info("Testing finished: CPU time = %d, real time = %d",
       result->cpu_time_millis, result->real_time_millis);

  /* copy the stderr output */
  result->error_file_existed = 0;
  if (packet->ignore_stderr <= 0) {
    error_file_size = generic_file_size("", run_error_path, "");
    if (error_file_size >= 0) {
      result->error_file_existed = 1;
      result->error_file_orig_size = error_file_size;
      if (error_file_size > packet->max_error_file_size) {
        result->error_file_truncated = 1;
        if (generic_truncate(run_error_path, packet->max_error_file_size) < 0) {
          snprintf(result->comment, sizeof(result->comment),
                   "truncate failed: %s", run_error_path);
          goto cleanup;
        }
        if (!(f = fopen(run_error_path, "a"))) {
          snprintf(result->comment, sizeof(result->comment),
                   "appending error file failed: %s", run_error_path);
          goto cleanup;
        }
        fprintf(f, "\n\nFile truncated!\n");
        fclose(f); f = 0;
        result->error_file_size = generic_file_size("", run_error_path, "");
      } else {
        result->error_file_truncated = 0;
        result->error_file_size = error_file_size;
      }

      if (packet->error_file_name[0]) {
        snprintf(error_file_path, sizeof(error_file_path), "%s/%s",
                 result_path, packet->error_file_name);
		info("Copy: %s -> %s", run_error_path, error_file_path);
        if (fast_copy_file(run_error_path, error_file_path) < 0) {
          snprintf(result->comment, sizeof(result->comment),
                   "copy failed: %s -> %s", run_error_path, error_file_path);
          goto cleanup;
        }
      }
    }
  }

  /* copy the program output */
  info("Copying program output");
  output_file_size = generic_file_size("", run_output_path, "");
  if (output_file_size < 0) {
    if (!result->comment[0]) {
      snprintf(result->comment, sizeof(result->comment),
               "no output file");
    }
    if (cur_status == RUN_OK) cur_status = RUN_PRESENTATION_ERR;
    result->status = cur_status;
    goto cleanup;
  }

  result->output_file_existed = 1;
  result->output_file_orig_size = output_file_size;
  if (output_file_size > packet->max_output_file_size) {
    result->output_file_too_big = 1;
    snprintf(result->comment, sizeof(result->comment),
             "output file is too big (%ld)", ((long) output_file_size));
    if (cur_status == RUN_OK) cur_status = RUN_PRESENTATION_ERR;
    result->status = cur_status;
    goto cleanup;
  }

  snprintf(result_file_path, sizeof(result_file_path), "%s/%s",
           result_path, packet->result_file_name);
  info("Copy: %s -> %s", run_output_path, result_file_path);
  if (fast_copy_file(run_output_path, result_file_path) < 0) {
    snprintf(result->comment, sizeof(result->comment),
             "copy failed: %s -> %s", run_output_path, result_file_path);
    result->status = RUN_CHECK_FAILED;
    goto cleanup;
  }

  result->status = cur_status;

 cleanup:
  if (f) fclose(f);
  remove_directory_recursively(global->work_dir, 1);
}
Ejemplo n.º 6
0
static int
run_all_tests(int argc, char *argv[])
{
  unsigned char tmp_work_dir[PATH_MAX];
  unsigned char abs_prog_name[PATH_MAX];
  unsigned char abs_test_dir[PATH_MAX];
  unsigned char abs_work_dir[PATH_MAX];
  unsigned char test_base[PATH_MAX];
  unsigned char test_path[PATH_MAX];
  unsigned char corr_base[PATH_MAX];
  unsigned char corr_path[PATH_MAX];
  unsigned char info_base[PATH_MAX];
  unsigned char info_path[PATH_MAX];
  unsigned char tgzdir_base[PATH_MAX];
  unsigned char tgzdir_path[PATH_MAX];
  const unsigned char *s;
  int pid = getpid(), serial = 0;
  int retval = 0, status;
  long cpu_time, real_time;

  tmp_work_dir[0] = 0;

  if (!working_dir || !*working_dir) {
    s = getenv("TMPDIR");
    if (!s) s = getenv("TEMPDIR");
#if defined P_tmpdir
    if (!s) s = P_tmpdir;
#endif
    if (!s) s = "/tmp";
    while (1) {
      snprintf(tmp_work_dir, sizeof(tmp_work_dir), "%s/%d.%d", s, pid, ++serial);
      if (mkdir(tmp_work_dir, 0700) >= 0) break;
      if (errno != EEXIST) {
        fatal("cannot create directory %s: %s", tmp_work_dir, os_ErrorMsg());
      }
    }
    working_dir = xstrdup(tmp_work_dir);
  }
  if (!os_IsAbsolutePath(working_dir)) {
    snprintf(abs_work_dir, sizeof(abs_work_dir), "%s/%s", current_dir, working_dir);
    working_dir = xstrdup(abs_work_dir);
  }

  if (!os_IsAbsolutePath(argv[0])) {
    snprintf(abs_prog_name, sizeof(abs_prog_name), "%s/%s", current_dir, argv[0]);
    argv[0] = xstrdup(abs_prog_name);
  }
  if (!os_IsAbsolutePath(test_dir)) {
    snprintf(abs_test_dir, sizeof(abs_test_dir), "%s/%s", current_dir, test_dir);
    test_dir = xstrdup(abs_test_dir);
  }

  serial = 0;
  while (1) {
    snprintf(test_base, sizeof(test_base), test_pattern, ++serial);
    snprintf(test_path, sizeof(test_path), "%s/%s", test_dir, test_base);
    test_file = xstrdup(test_path);
    if (os_CheckAccess(test_path, REUSE_F_OK) < 0) break;
    corr_path[0] = 0;
    info_path[0] = 0;
    corr_file = NULL;
    info_file = NULL;
    if (corr_pattern && corr_pattern[0]) {
      snprintf(corr_base, sizeof(corr_base), corr_pattern, serial);
      snprintf(corr_path, sizeof(corr_path), "%s/%s", test_dir, corr_base);
      corr_file = xstrdup(corr_path);
    }
    if (info_pattern && info_pattern[0]) {
      snprintf(info_base, sizeof(info_base), info_pattern, serial);
      snprintf(info_path, sizeof(info_path), "%s/%s", test_dir, info_base);
      info_file = xstrdup(info_path);
    }
    if (tgzdir_pattern && tgzdir_pattern[0]) {
      snprintf(tgzdir_base, sizeof(tgzdir_base), tgzdir_pattern, serial);
      snprintf(tgzdir_path, sizeof(tgzdir_path), "%s/%s", test_dir, tgzdir_path);
      tgzdir_file = xstrdup(tgzdir_path);
    }
    cpu_time = 0;
    real_time = 0;
    status = run_program(argc, argv, &cpu_time, &real_time);
    if (status == RUN_CHECK_FAILED) retval = RUN_CHECK_FAILED;
    if (status != RUN_OK && retval == RUN_OK) retval = RUN_PARTIAL;
    if (quiet_flag <= 0) {
      printf("%-8d%-8.8s%-8ld%-8ld\n", serial, get_run_status_str(status),
             cpu_time, real_time);
    }
  }

  if (tmp_work_dir[0]) {
    remove_directory_recursively(tmp_work_dir, 0);
  }
  return retval;
}