• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
main(int argc,char ** argv)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 
usage(void)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 
eat_stdin(void)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 }
do_page(void)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 
hexdump(const void * memory,size_t bytes)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