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