#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <console.h> #include <errno.h> #include <syslinux/loadfile.h> /* 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 [<option> [...]] <filename> [<option> [...]]\n" "\n" "Options: -p\n" " --page . . . . . . . Pause output every 24 lines\n" " --no-buffer . . . . Load the entire file before dumping\n" " --extended-ascii . . Use extended ASCII chars in dump\n" " -?\n" " -h\n" " --help . . . . . . Display this help\n"; fprintf(stderr, usage, prog_name); return EXIT_FAILURE; } static void eat_stdin(void) { int i; while (1) { i = fgetc(stdin); if (i == EOF || i == '\n') return; } } static int do_page(void) { int i; while (1) { fprintf(stdout, "Continue? [Y|n]: "); i = fgetc(stdin); switch (i) { case 'n': case 'N': eat_stdin(); return 1; case EOF: fprintf(stderr, "No response. Continuing...\n"); /* Fall through to "yes" */ case 'y': case 'Y': eat_stdin(); case '\n': return 0; default: fprintf(stderr, "Invalid choice\n"); eat_stdin(); } } } static void hexdump(const void *memory, size_t bytes) { const unsigned char *p, *q; int i; p = memory; while (bytes) { q = p; printf("%p: ", (void *) p); for (i = 0; i < 16 && bytes; ++i) { printf("%02X ", *p); ++p; --bytes; } bytes += i; while (i < 16) { printf("XX "); ++i; } printf("| "); p = q; for (i = 0; i < 16 && bytes; ++i) { printf("%c", isprint(*p) && !isspace(*p) ? *p : ' '); ++p; --bytes; } while (i < 16) { printf(" "); ++i; } printf("\n"); } return; }