Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #10091

Re: hexump.c

From jacob navia <jacob@spamsink.net>
Newsgroups comp.lang.c
Subject Re: hexump.c
Date 2011-09-10 12:46 +0200
Organization lccwin
Message-ID <j4ff5i$st9$1@speranza.aioe.org> (permalink)
References <j4ducg$lmn$1@speranza.aioe.org>

Show all headers | View raw


Here is the hexdump with code, commentaries and
exercises. I have incorporated most remarks and
again thanks for your help:

  1 #include <stdio.h>
   2 #include <stdlib.h>
   3 #include <string.h>
   4 #include <ctype.h>
   5 int main(int argc,char *argv[])
   6 {
   7    if (argc < 2) {
   8       fprintf(stderr,"Usage: %s <file name>\n",argv[0]);
   9       return EXIT_FAILURE;
  10    }
  11    FILE *file = fopen(argv[1],"rb");
  12    if (file == NULL) {
  13       fprintf(stderr,"Impossible to open %s for reading\n",argv[1]);
  14       return EXIT_FAILURE;
  15    }
  16    int oneChar = fgetc(file);
  17    int column = 0,line = 0;
  18    char tab[16+1];
  19    const char *hex = "0123456789abcdef";
  20    int address = 1;
  21
  22    while (oneChar != EOF) {
  23       if (column == 0) {
  24          memset(tab,'.',16);
  25          fprintf(stdout,"[%d] ",address);
  26       }
  27       if (isprint(oneChar)) {
  28          tab[column] = oneChar;
  29       }
  30       fputc(hex[(oneChar >> 4)&4],stdout);
  31       fputc(hex[oneChar&4],stdout);
  32       fputc(' ',stdout);
  33       column++;
  34       if (column == 16) {
  35          fputc(' ',stdout);
  36          tab[column]=0;
  37          fputs(tab,stdout);
  38          column = 0;
  39          line++;
  40          if (line == 16) {
  41             fputc('\n',stdout);
  42             line=0;
  43          }
  44          fputc('\n',stdout);
  45       }
  46       oneChar = fgetc(file);
  47       address++;
  48    }
  49    fclose(file);
  50    address--;
  51    if (column > 0 ) {
  52       while (column < 16) {
  53          fprintf(stdout,"   ");
  54          tab[column]=' ';
  55          column++;
  56       }
  57       tab[16]=0;
  58       fprintf(stdout," %s\n[%d]\n",tab,address);
  59    }
  60    else fprintf(stdout,"[%d]\n",address);
  61    return EXIT_SUCCESS;
  62 }

Analysis:
--------
The program should be called (in its present form) like this:
    hexdump <file name>
i.e. it needs at least one argument: the name of the file to dump.
We test for this in line 7 and if the name is missing we issue a
warning and exit with  a failure value. When printing the warning
we use the value stored in argv[0] as the name of the program.
This is generally the case, most systems will store the name of the
program in argv[0]. It could be however, that a malicious user
calls this program constructing its command line for an "execv" call
and leaves argv[0] empty. In that case our program would crash.

Is that possibility a real one? Should we guard against it?
It is highly unlikely that a user that has already enough
access to the machine to write (and compile) programs would
bother to crash our minuscule hexdump utility.. But anyway
the guard would need a tiny change only. Line 8 would need
to be changed to:

8        if (argv[0]) fprintf(stderr,"...message",argv[0]);

Now we know that we have at least an argument. In line 11 we
try to open the file that we should dump. Note that we use the
binary form of the fopen call "rb" (read binary) to dump
exactly each byte in the file.

If we can't open the file (fopen returns NULL) we print a
warning message into the error output file and return a
failure value.

Now we know we have an open file to dump (line 16) so we
start initializing stuff for the main part of the program.
We read the first character into a variable that will hold
each character in the loop (line 16). We will count columns
and lines, so we initialize the counters to zero (line 17).
We need a table of characters to hold the ASCII equivalences
of each byte (line 18). That table should be a string, so
we dimension it to one character more than the required
length.

We need a table of hexadecimal letters (line 19) that shouldn't
be changed, it is a constant "variable". We tell the compiler
this fact. And then we need to know at what position we are
in the file, so we declare an "address" counter. It is initialized
to one since we have already read one character in line 16.

Now we arrive at our loop. We will read and display characters
until the last character of the file, i.e. until we hit the
end of file condition (line 22).

If we are at the start of a line, i.e. when our "column" variable
is at the start of a line we set the table of ASCII equivalences
to '.' and we put out the position of the file where we are.
We use a one based index for our position so that the first character
is 1. But maybe that is not what the user of an hexdump utility
expects, we can change that to a different address field display,
see the exercises at the end.

We should put the contents of our character into the table if
it is printable. We use the 'isprint' function (line 27) to
determine that, and if true we store the value of our character
into the table.

Then, we output the value of our character. We print in hexadecimal
first the higher 4 bits, then the lower 4 bits. Since 4 bit
numbers can only go from zero to 15, we index directly our "hex" table
with the value of those 4 bits lines 30 and 31.

Note that we mask the bits with the value 0xf, i.e. 15. This means
that we ensure that only the lower 4 bits are used. This is important
to avoid making an index error when we access our "hex" table.
We assume that characters are 8 bits. See exercise 6.

We separate each character with a space (line 32) update our column
counter and test if we have arrived at the end of our dump line.

If that is the case we put an extra blank, finish the table with zero
and print it. We bump our "line" counter, and if we have arrived
at a block of 16 lines, we put an extra empty line (line 41).

We separate lines (line 44) and read the next character (line 46).

When we arrive at the end of file the loop stops, and execution
continues with line 49, where we close the file we have opened.
This is not strictly necessary in this case since when a program
exits all the files it has opened are close automatically in most
systems, but it is better to do it since if we later want to use
our dump routine as a part of a bigger software package we would
leave a file open.

We adjust the address since we have counted the EOF as a character
in line 50.

We are at the end of the file we output the last line, if any. If
the file size is not a multiple of 16, we have already put some
characters: we complete the last line with blanks. If the file
size is exactly a multiple of 16 we just output our address variable
to indicate to the user the exact size of the file.

Exercises:
---------

1: Add an optional argument so that an output file can be specified.
2: You should have noticed that between the 9th and the 10th line
    the output is not aligned since 10 has one more character than
    9. Fix this. All lines should be aligned.
3: Add an option (call it -hexaddress) to write file addresses in
    hexadecimal instead of decimal as shown.
4: Add another option (call it -column:XXX) todisplay more or less
    text positions in a line. For instance -column:80 would fix the
    display to 80 columns. Adjust the number of characters displayed
    accordingly. Note that you should not make the number of characters
    less than 4 or greater than 512.
5: Add an option to display 32 bits instead of just 8 at a time.
6: What would happen if you are working in a machine where the
    characters are 16 bits wide? What needs to be changed in the
    above program?

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

hexump.c jacob navia <jacob@spamsink.net> - 2011-09-09 22:53 +0200
  Re: hexump.c tea strainer <nospam@nospam.com> - 2011-09-09 21:06 +0000
    Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-09 23:57 +0200
    Re: hexump.c NicStevens <nic.stevens@gmail.com> - 2011-09-12 13:22 -0700
  Re: hexump.c Ian Collins <ian-news@hotmail.com> - 2011-09-10 09:18 +1200
    Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-09 23:59 +0200
  Re: hexump.c Ike Naar <ike@iceland.freeshell.org> - 2011-09-09 22:29 +0000
    Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-10 00:39 +0200
      Re: hexump.c Ike Naar <ike@iceland.freeshell.org> - 2011-09-09 22:53 +0000
        Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-10 00:58 +0200
        Re: hexump.c Seebs <usenet-nospam@seebs.net> - 2011-09-13 06:44 +0000
          Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-13 10:33 +0200
            Re: hexump.c Fritz Wuehler <fritz@spamexpire-201109.rodent.frell.theremailer.net> - 2011-09-13 18:02 +0200
            Teaching C (was Re: hexump.c) Kenneth Brody <kenbrody@spamcop.net> - 2011-09-13 16:36 -0400
              Re: Teaching C (was Re: hexump.c) jacob navia <jacob@spamsink.net> - 2011-09-13 22:44 +0200
                Re: Teaching C (was Re: hexump.c) Nobody <nobody@nowhere.com> - 2011-09-14 13:31 +0100
                Re: Teaching C (was Re: hexump.c) jacob navia <jacob@spamsink.net> - 2011-09-14 15:27 +0200
                Re: Teaching C (was Re: hexump.c) Richard Damon <news.x.richarddamon@xoxy.net> - 2011-09-14 11:49 -0400
                Re: Teaching C (was Re: hexump.c) Keith Thompson <kst-u@mib.org> - 2011-09-14 13:27 -0700
                Re: Teaching C (was Re: hexump.c) pacman@kosh.dhis.org (Alan Curry) - 2011-09-14 20:59 +0000
                Re: Teaching C (was Re: hexump.c) Nobody <nobody@nowhere.com> - 2011-09-14 22:20 +0100
                Re: Teaching C (was Re: hexump.c) James Kuyper <jameskuyper@verizon.net> - 2011-09-14 17:20 -0400
                Re: Teaching C (was Re: hexump.c) pacman@kosh.dhis.org (Alan Curry) - 2011-09-15 01:51 +0000
                Re: Teaching C (was Re: hexump.c) Keith Thompson <kst-u@mib.org> - 2011-09-14 19:29 -0700
                Re: Teaching C (was Re: hexump.c) Keith Thompson <kst-u@mib.org> - 2011-09-14 19:21 -0700
                Re: Teaching C Ben Pfaff <blp@cs.stanford.edu> - 2011-09-14 19:58 -0700
                Re: Teaching C Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2011-09-14 21:55 -0600
                Re: Teaching C James Kuyper <jameskuyper@verizon.net> - 2011-09-15 06:54 -0400
                Re: Teaching C Keith Thompson <kst-u@mib.org> - 2011-09-15 11:58 -0700
                Re: Teaching C Tim Rentsch <txr@alumni.caltech.edu> - 2012-01-24 12:57 -0800
                Re: Teaching C Nobody <nobody@nowhere.com> - 2011-09-15 14:25 +0100
                Re: Teaching C Seebs <usenet-nospam@seebs.net> - 2011-09-16 22:00 +0000
                Re: Teaching C (was Re: hexump.c) Kenneth Brody <kenbrody@spamcop.net> - 2011-09-14 12:54 -0400
                Re: Teaching C (was Re: hexump.c) James Kuyper <jameskuyper@verizon.net> - 2011-09-14 13:26 -0400
                Re: Teaching C (was Re: hexump.c) jacob navia <jacob@spamsink.net> - 2011-09-14 19:33 +0200
                Re: Teaching C (was Re: hexump.c) jameskuyper <jameskuyper@verizon.net> - 2011-09-14 11:33 -0700
                Re: Teaching C (was Re: hexump.c) jacob navia <jacob@spamsink.net> - 2011-09-14 21:17 +0200
                Re: Teaching C (was Re: hexump.c) Kenneth Brody <kenbrody@spamcop.net> - 2011-09-16 11:47 -0400
                Re: Teaching C (was Re: hexump.c) Seebs <usenet-nospam@seebs.net> - 2011-09-14 20:43 +0000
                Re: Teaching C (was Re: hexump.c) Nobody <nobody@nowhere.com> - 2011-09-14 22:35 +0100
                Re: Teaching C (was Re: hexump.c) gordonb.8a7i1@burditt.org (Gordon Burditt) - 2011-09-14 17:31 -0500
                Re: Teaching C (was Re: hexump.c) jacob navia <jacob@spamsink.net> - 2011-09-14 19:32 +0200
                Re: Teaching C (was Re: hexump.c) Kenneth Brody <kenbrody@spamcop.net> - 2011-09-16 11:27 -0400
                Re: Teaching C (was Re: hexump.c) Malcolm McLean <malcolm.mclean5@btinternet.com> - 2011-09-16 08:49 -0700
                Re: Teaching C (was Re: hexump.c) James Kuyper <jameskuyper@verizon.net> - 2011-09-17 15:04 -0400
            Re: hexump.c Keith Thompson <kst-u@mib.org> - 2011-09-13 20:31 -0700
              Re: hexump.c Malcolm McLean <malcolm.mclean5@btinternet.com> - 2011-09-14 03:22 -0700
              Re: hexump.c "BartC" <bc@freeuk.com> - 2011-09-14 11:40 +0100
                Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-14 13:54 +0200
                Re: hexump.c Nobody <nobody@nowhere.com> - 2011-09-14 13:50 +0100
                Re: hexump.c Keith Thompson <kst-u@mib.org> - 2011-09-14 11:35 -0700
                Re: hexump.c Seebs <usenet-nospam@seebs.net> - 2011-09-14 19:12 +0000
                Re: hexump.c John Bode <jfbode1029@gmail.com> - 2011-09-14 15:31 -0700
                Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-15 00:59 +0200
                Re: hexump.c Kleuskes & Moos <kleuske@somewhere.else.net> - 2011-09-14 23:14 +0000
                Re: hexump.c John Bode <jfbode1029@gmail.com> - 2011-09-15 08:52 -0700
                Re: hexump.c Jens Gustedt <jens.gustedt@loria.fr> - 2011-09-14 21:22 +0200
                Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-14 21:26 +0200
                Re: hexump.c Ian Collins <ian-news@hotmail.com> - 2011-09-15 07:32 +1200
                Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-14 21:44 +0200
                Re: hexump.c Keith Thompson <kst-u@mib.org> - 2011-09-14 13:49 -0700
                Re: hexump.c Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2011-09-16 00:50 +0300
                Re: hexump.c Keith Thompson <kst-u@mib.org> - 2011-09-15 18:34 -0700
                Re: hexump.c Keith Thompson <kst-u@mib.org> - 2011-09-14 12:16 -0700
                Hypocrites jacob navia <jacob@spamsink.net> - 2011-09-14 21:40 +0200
                Re: Hypocrites Keith Thompson <kst-u@mib.org> - 2011-09-14 19:11 -0700
                Re: hexump.c Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-14 15:05 +0100
                Re: hexump.c Malcolm McLean <malcolm.mclean5@btinternet.com> - 2011-09-14 07:56 -0700
                Re: hexump.c "BartC" <bc@freeuk.com> - 2011-09-14 17:23 +0100
              Re: hexump.c Seebs <usenet-nospam@seebs.net> - 2011-09-14 19:12 +0000
              Re: hexump.c John Bode <jfbode1029@gmail.com> - 2011-09-14 15:24 -0700
      Re: hexump.c gordonb.ik17p@burditt.org (Gordon Burditt) - 2011-09-09 18:16 -0500
        Re: hexump.c Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-09-12 22:24 +0000
  Re: hexump.c "Morris Keesan" <mkeesan@post.harvard.edu> - 2011-09-09 20:33 -0400
    Re: hexump.c Ian Collins <ian-news@hotmail.com> - 2011-09-10 12:42 +1200
      Re: hexump.c "Morris Keesan" <mkeesan@post.harvard.edu> - 2011-09-10 17:16 -0400
    Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-10 10:03 +0200
  Re: hexump.c Nobody <nobody@nowhere.com> - 2011-09-10 10:04 +0100
    Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-10 11:41 +0200
      Re: hexump.c pete <pfiland@mindspring.com> - 2011-09-10 05:51 -0400
        Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-10 12:38 +0200
          Re: hexump.c Nobody <nobody@nowhere.com> - 2011-09-10 17:53 +0100
  Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-10 12:46 +0200
    Re: hexump.c Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-10 13:03 +0100
      Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-10 15:34 +0200
    Re: hexump.c "Morris Keesan" <mkeesan@post.harvard.edu> - 2011-09-10 17:37 -0400
      Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-11 00:10 +0200
        Re: hexump.c Patrick Scheible <kkt@zipcon.net> - 2011-09-10 21:03 -0700
  Re: hexump.c Barry Schwarz <schwarz45@yahoo.com> - 2011-09-11 00:37 -0700
    Re: hexump.c jacob navia <jacob@spamsink.net> - 2011-09-11 13:56 +0200

csiph-web