Add some comments plus fix a possible mem leak
[eleutheria.git] / fileops / hexdump.c
blobaa95435025631f57b3bb595d90f11e294a9ed14a
1 /*
2 * Compile with:
3 * gcc hexdump.c -o hexdump -Wall -W -Wextra -ansi -pedantic
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h> /* for memset() */
9 #include <getopt.h> /* FIXME: make it portable */
11 /* Function prototypes */
12 void diep(const char *s);
13 void dieu(const char *pname);
15 #define BUFSIZE 20 /* Must be dividable by 2 */
17 int main(int argc, char *argv[])
19 unsigned char buf[BUFSIZE + 1]; /* +1 for the '\0' */
20 FILE *fp;
21 int caps, cnt, i, j, len, opt, skip;
22 int readbytes, totalbytes;
23 char *fpath;
25 /* Parse arguments */
26 caps = 0;
27 len = -1;
28 skip = 0;
29 fpath = NULL;
30 while ((opt = getopt(argc, argv, "Cn:s:f:")) != -1) {
31 switch (opt) {
32 case 'C':
33 caps = 1;
34 break;
35 case 'n':
36 len = atoi(optarg);
37 break;
38 case 's':
39 skip = atoi(optarg);
40 break;
41 case 'f':
42 fpath = optarg;
43 break;
44 default: /* '?' */
45 dieu(argv[0]);
49 /* optind shows to the argv[] index of the first non-option element */
50 if (optind < argc) {
51 fprintf(stderr, "non-option argv[]-elements: ");
52 while (optind < argc)
53 fprintf(stderr, "%s ", argv[optind++]);
54 fprintf(stderr, "\n");
55 exit(EXIT_FAILURE);
58 if (fpath == NULL)
59 dieu(argv[0]);
61 /* Open file */
62 if ((fp = fopen(fpath, "r")) == NULL)
63 diep("open");
65 /* Skip `skip' bytes */
66 fseek(fp, skip, SEEK_SET);
68 /* Loop */
69 cnt = 0;
70 totalbytes = 0;
71 while(!feof(fp) && (totalbytes < len || len == -1)) {
72 /* Initialize buffer */
73 memset(buf, 0, BUFSIZE);
75 /* Read `BUFSIZE' elements of 1 byte long from file */
76 readbytes = fread(buf, 1, BUFSIZE, fp);
78 /* Print buffer */
79 printf(caps == 1 ? "%08lX " : "%08lx ", (unsigned long)cnt * BUFSIZE + skip);
80 for (i = 0; i < readbytes && (totalbytes < len || len == -1); i++, totalbytes++) {
81 printf(caps == 1 ? "%02X " : "%02x ", buf[i]);
82 if (i == (BUFSIZE / 2) - 1)
83 printf(" ");
86 /* Fill in the blanks */
87 for (j = 0; j < (BUFSIZE - i); j++) {
88 printf(" ");
89 if (j == (BUFSIZE/2) - 1)
90 printf(" ");
94 * Print the output characters in the default character set.
95 * Nonprinting characters are displayed as a single `.'
97 printf(" |");
98 for (j = 0; j < i; j++) {
99 if (buf[j] >= 32 && buf[j] <= 127)
100 printf("%c", buf[j]);
101 else
102 printf(".");
104 printf("|");
106 /* New line */
107 printf("\n");
109 cnt++;
112 /* Close device file */
113 (void)fclose(fp);
115 return EXIT_SUCCESS;
118 void diep(const char *s)
120 perror(s);
121 exit(EXIT_FAILURE);
124 void dieu(const char *pname)
126 fprintf(stderr, "Usage: %s [-C] [-n length] [-s skip] -f file\n", pname);
127 exit(EXIT_FAILURE);