| #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; | 
 | } |