blob: bc2c70dd82a8c5546a467504dc7f55cee31aafb7 [file] [log] [blame]
Greg Hartman76d05dc2016-11-23 15:51:27 -08001#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 */
16static int usage(void);
17static void eat_stdin(void);
18static int do_page(void);
19static void hexdump(const void *memory, size_t bytes);
20
21/* Objects */
22static const char *prog_name;
23static int opt_page;
24static int opt_no_buffer;
25static int opt_extended_ascii;
26
27int 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
155static 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
172static 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}
182static 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
212static 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}