#include #include #include #include #include #include #include #include /* Macros */ #define ROWS_PER_PAGE 24 #define COLS_PER_ROW 16 #define BYTES_PER_PAGE (ROWS_PER_PAGE * COLS_PER_ROW) /* Functions declarations */ static int usage(void); static void eat_stdin(void); static int do_page(void); static void hexdump(const void *memory, size_t bytes); /* Objects */ static const char *prog_name; static int opt_page; static int opt_no_buffer; static int opt_extended_ascii; int main(int argc, char **argv) { int rc; const char *filename; int i; void *file_data; size_t file_sz; FILE *f; size_t len; const char *cur_pos; /* Assume failure */ rc = EXIT_FAILURE; /* Determine the program name, as invoked */ if (argc < 1 || !argv || !argv[0]) { fprintf(stderr, "argc or argv failure!\n"); goto err_prog_name; } prog_name = argv[0]; /* Process arguments */ filename = NULL; for (i = 1; i < argc; ++i) { if (!argv[i]) { fprintf(stderr, "argc and argv mismatch!\n"); goto err_argv; } if (!strncmp(argv[i], "--page", sizeof "--page") || !strncmp(argv[i], "-p", sizeof "-p")) { opt_page = 1; continue; } if (!strncmp(argv[i], "--no-buffer", sizeof "--no-buffer")) { opt_no_buffer = 1; continue; } if (!strncmp(argv[i], "--extended-ascii", sizeof "--extended-ascii")) { opt_extended_ascii = 1; continue; } if (!strncmp(argv[i], "--help", sizeof "--help") || !strncmp(argv[i], "-h", sizeof "-h") || !strncmp(argv[i], "-?", sizeof "-?")) return usage(); /* Otherwise, interpret as a filename, but only accept one */ if (filename) return usage(); filename = argv[i]; } if (!filename) return usage(); fprintf(stdout, "Dumping file: %s\n", filename); /* Either fetch the whole file, or just allocate a buffer */ f = NULL; if (opt_no_buffer) { errno = 0; if (loadfile(filename, &file_data, &file_sz)) { fprintf(stderr, "Couldn't load file. Error: %d\n", errno); goto err_file_data; } } else { file_sz = BYTES_PER_PAGE; file_data = malloc(file_sz); if (!file_data) { fprintf(stderr, "Couldn't allocate file data buffer\n"); goto err_file_data; } errno = 0; f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Couldn't open file. Error: %d\n", errno); goto err_f; } } /* Dump the data */ len = BYTES_PER_PAGE; cur_pos = file_data; do { if (f) { /* Buffered */ len = fread(file_data, 1, file_sz, f); cur_pos = file_data; } else { /* Non-buffered */ if (file_sz < len) len = file_sz; } if (!len) break; hexdump(cur_pos, len); /* Pause, if requested */ if (opt_page) { /* The user might choose to quit */ if (do_page()) break; } /* Reduce file_sz for non-buffered mode */ if (!f) file_sz -= len; } while (cur_pos += len); rc = EXIT_SUCCESS; if (f) fclose(f); err_f: free(file_data); err_file_data: err_argv: err_prog_name: return rc; } static int usage(void) { static const char usage[] = "Usage: %s [