Home | History | Annotate | Download | only in modules
      1 #include <stddef.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <ctype.h>
      6 #include <console.h>
      7 #include <errno.h>
      8 #include <syslinux/loadfile.h>
      9 
     10 /* Macros */
     11 #define ROWS_PER_PAGE 24
     12 #define COLS_PER_ROW 16
     13 #define BYTES_PER_PAGE (ROWS_PER_PAGE * COLS_PER_ROW)
     14 
     15 /* Functions declarations */
     16 static int usage(void);
     17 static void eat_stdin(void);
     18 static int do_page(void);
     19 static void hexdump(const void *memory, size_t bytes);
     20 
     21 /* Objects */
     22 static const char *prog_name;
     23 static int opt_page;
     24 static int opt_no_buffer;
     25 static int opt_extended_ascii;
     26 
     27 int main(int argc, char **argv)
     28 {
     29     int rc;
     30     const char *filename;
     31     int i;
     32     void *file_data;
     33     size_t file_sz;
     34     FILE *f;
     35     size_t len;
     36     const char *cur_pos;
     37 
     38     /* Assume failure */
     39     rc = EXIT_FAILURE;
     40 
     41     /* Determine the program name, as invoked */
     42     if (argc < 1 || !argv || !argv[0]) {
     43 	fprintf(stderr, "argc or argv failure!\n");
     44 	goto err_prog_name;
     45     }
     46     prog_name = argv[0];
     47 
     48     /* Process arguments */
     49     filename = NULL;
     50     for (i = 1; i < argc; ++i) {
     51 	if (!argv[i]) {
     52 	    fprintf(stderr, "argc and argv mismatch!\n");
     53 	    goto err_argv;
     54 	}
     55 
     56 	if (!strncmp(argv[i], "--page", sizeof "--page") ||
     57 	    !strncmp(argv[i], "-p", sizeof "-p")) {
     58 	    opt_page = 1;
     59 	    continue;
     60 	}
     61 
     62 	if (!strncmp(argv[i], "--no-buffer", sizeof "--no-buffer")) {
     63 	    opt_no_buffer = 1;
     64 	    continue;
     65 	}
     66 
     67 	if (!strncmp(argv[i], "--extended-ascii", sizeof "--extended-ascii")) {
     68 	    opt_extended_ascii = 1;
     69 	    continue;
     70 	}
     71 
     72 	if (!strncmp(argv[i], "--help", sizeof "--help") ||
     73 	    !strncmp(argv[i], "-h", sizeof "-h") ||
     74 	    !strncmp(argv[i], "-?", sizeof "-?"))
     75 	    return usage();
     76 
     77 	/* Otherwise, interpret as a filename, but only accept one */
     78 	if (filename)
     79 	    return usage();
     80 	filename = argv[i];
     81     }
     82     if (!filename)
     83 	return usage();
     84     fprintf(stdout, "Dumping file: %s\n", filename);
     85 
     86     /* Either fetch the whole file, or just allocate a buffer */
     87     f = NULL;
     88     if (opt_no_buffer) {
     89 	errno = 0;
     90 	if (loadfile(filename, &file_data, &file_sz)) {
     91 	    fprintf(stderr, "Couldn't load file.  Error: %d\n", errno);
     92 	    goto err_file_data;
     93 	}
     94     } else {
     95 	file_sz = BYTES_PER_PAGE;
     96 	file_data = malloc(file_sz);
     97 	if (!file_data) {
     98 	    fprintf(stderr, "Couldn't allocate file data buffer\n");
     99 	    goto err_file_data;
    100 	}
    101 	errno = 0;
    102 	f = fopen(filename, "r");
    103 	if (!f) {
    104 	    fprintf(stderr, "Couldn't open file.  Error: %d\n", errno);
    105 	    goto err_f;
    106 	}
    107     }
    108 
    109     /* Dump the data */
    110     len = BYTES_PER_PAGE;
    111     cur_pos = file_data;
    112     do {
    113 	if (f) {
    114 	    /* Buffered */
    115 	    len = fread(file_data, 1, file_sz, f);
    116 	    cur_pos = file_data;
    117 	} else {
    118 	    /* Non-buffered */
    119 	    if (file_sz < len)
    120 		len = file_sz;
    121 	}
    122 	if (!len)
    123 	    break;
    124 
    125 	hexdump(cur_pos, len);
    126 
    127 	/* Pause, if requested */
    128 	if (opt_page) {
    129 	    /* The user might choose to quit */
    130 	    if (do_page())
    131 		break;
    132 	}
    133 
    134 	/* Reduce file_sz for non-buffered mode */
    135 	if (!f)
    136 	    file_sz -= len;
    137     } while (cur_pos += len);
    138 
    139     rc = EXIT_SUCCESS;
    140 
    141     if (f)
    142 	fclose(f);
    143     err_f:
    144 
    145     free(file_data);
    146     err_file_data:
    147 
    148     err_argv:
    149 
    150     err_prog_name:
    151 
    152     return rc;
    153 }
    154 
    155 static int usage(void)
    156 {
    157     static const char usage[] =
    158 	"Usage: %s [<option> [...]] <filename> [<option> [...]]\n"
    159 	"\n"
    160 	"Options: -p\n"
    161 	"         --page . . . . . . . Pause output every 24 lines\n"
    162 	"         --no-buffer . . . .  Load the entire file before dumping\n"
    163 	"         --extended-ascii . . Use extended ASCII chars in dump\n"
    164 	"         -?\n"
    165 	"         -h\n"
    166 	"         --help  . . . . . .  Display this help\n";
    167 
    168     fprintf(stderr, usage, prog_name);
    169     return EXIT_FAILURE;
    170 }
    171 
    172 static void eat_stdin(void)
    173 {
    174     int i;
    175 
    176     while (1) {
    177 	i = fgetc(stdin);
    178 	if (i == EOF || i == '\n')
    179 	    return;
    180     }
    181 }
    182 static int do_page(void)
    183 {
    184     int i;
    185 
    186     while (1) {
    187 	fprintf(stdout, "Continue? [Y|n]: ");
    188 	i = fgetc(stdin);
    189 	switch (i) {
    190 	    case 'n':
    191 	    case 'N':
    192 	    eat_stdin();
    193 	    return 1;
    194 
    195 	    case EOF:
    196 	    fprintf(stderr, "No response.  Continuing...\n");
    197 	    /* Fall through to "yes" */
    198 
    199 	    case 'y':
    200 	    case 'Y':
    201 	    eat_stdin();
    202 	    case '\n':
    203 	    return 0;
    204 
    205 	    default:
    206 	    fprintf(stderr, "Invalid choice\n");
    207 	    eat_stdin();
    208 	}
    209     }
    210 }
    211 
    212 static void hexdump(const void *memory, size_t bytes)
    213 {
    214     const unsigned char *p, *q;
    215     int i;
    216 
    217     p = memory;
    218     while (bytes) {
    219         q = p;
    220         printf("%p: ", (void *) p);
    221         for (i = 0; i < 16 && bytes; ++i) {
    222             printf("%02X ", *p);
    223             ++p;
    224             --bytes;
    225           }
    226         bytes += i;
    227         while (i < 16) {
    228             printf("XX ");
    229             ++i;
    230           }
    231         printf("| ");
    232         p = q;
    233         for (i = 0; i < 16 && bytes; ++i) {
    234             printf("%c", isprint(*p) && !isspace(*p) ? *p : ' ');
    235             ++p;
    236             --bytes;
    237           }
    238         while (i < 16) {
    239             printf(" ");
    240             ++i;
    241           }
    242         printf("\n");
    243       }
    244     return;
    245 }
    246