Prepared hexio for somewhat less ad hoc environments.
authorRick van Rein <rick@openfortress.nl>
Thu, 19 May 2016 21:26:26 +0000 (22:26 +0100)
committerRick van Rein <rick@openfortress.nl>
Thu, 19 May 2016 21:26:26 +0000 (22:26 +0100)
The hexio toolkit is for developers, and not primarly focussed on end users
or intended for packaging.  Still, if anyone cares, then the utilities are
hereby available to them.

13 files changed:
LICENSE [new file with mode: 0644]
Makefile
README.MD [new file with mode: 0644]
configure [new file with mode: 0644]
derdump [new file with mode: 0755]
derdump.py [deleted file]
devio.c
hexin.c [new file with mode: 0644]
hexout.c [new file with mode: 0644]
inputter.c [deleted file]
llcio.c
outputter.c [deleted file]
pcscio.c

diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..8124e0e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2016, OpenFortress Digital signatures,
+                    http://openfortress.nl
+                    All rights reserved.
+
+Redistribution and use in source and binary forms, with or  with‐
+out  modification, are permitted provided that the following con‐
+ditions are met:
+
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+2.  Redistributions in binary form must reproduce the above copy‐
+right notice, this list of  conditions  and  the  following  dis‐
+claimer in the documentation and/or other materials provided with
+the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND  CONTRIBU‐
+TORS  "AS  IS"  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS  FOR  A  PARTICULAR  PURPOSE  ARE DISCLAIMED. IN NO EVENT
+SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY  DI‐
+RECT,  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS IN‐
+TERRUPTION) HOWEVER  CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,
+WHETHER  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLI‐
+GENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF  THE  USE  OF  THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
index 4055db4..42c7d11 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,20 @@
-all: inputter outputter devio llcio pcscio
+PREFIX ?= /usr/local
+DESTDIR ?=
+
+TARGETS=hexin hexout devio llcio pcscio
+LITERAL=derdump
+
+all: $(TARGETS)
+
+CC=gcc -Wall
 
 PCSCFLAGS=-D_THREAD_SAFE -I/usr/local/include/PCSC/ -L/usr/local/lib -L/usr/local/lib/pth -ggdb3 -pthread
 
-inputter: inputter.c
-       $(CC) $(CFLAGS) -o inputter inputter.c
+hexin: hexin.c
+       $(CC) $(CFLAGS) -o hexin hexin.c
 
-outputter: outputter.c
-       $(CC) $(CFLAGS) -o outputter outputter.c
+hexout: hexout.c
+       $(CC) $(CFLAGS) -o hexout hexout.c
 
 devio: devio.c
        $(CC) $(CFLAGS) -o devio devio.c
@@ -15,12 +23,18 @@ llcio: llcio.c
        $(CC) $(CFLAGS) -o llcio llcio.c
 
 pcscio: pcscio.c
-       $(CC) $(CFLAGS) $(PCSCFLAGS) -o pcscio pcscio.c -lpcsclite
+       $(CC) -I /usr/include/PCSC $(CFLAGS) $(PCSCFLAGS) -o pcscio pcscio.c -lpcsclite
+
+install: all
+       install $(TARGETS) $(LITERAL) "$(DESTDIR)$(PREFIX)/sbin"
+
+uninstall:
+       cd "$(DESTDIR)$(PREFIX)/sbin" ; rm -f $(TARGETS)
 
 clean:
+       rm -f $(TARGETS)
 
 very:
-       rm inputter outputter
 
 veryclean: very clean
 
diff --git a/README.MD b/README.MD
new file mode 100644 (file)
index 0000000..56e0f98
--- /dev/null
+++ b/README.MD
@@ -0,0 +1,26 @@
+# Package Description: hexio
+
+This is a very simple package of developer utilities.  They are targeted
+at binary/hexadecimal interaction with low-down parts of a system, so
+ideal for various reverse engineering tasks.  In spite of their utter
+simplicity, they can be true life savers.
+
+  * **hexin** reads hexadecimal input on `stdin` and outputs it in binary
+    on `stdout`; it will prompt with an address (or input offset) printed
+    in hexadecimal on the tty
+  * **hexout** reads binary input on `stdin` and outputs it in hexadecimal
+    form on `stdout`
+  * **devio** reads from `stdin` and passes what it finds to a given device;
+    anything returned by the device is passed on to `stdout`
+  * **llcio** reads from `stdin` and passes what it finds to a networked
+    device over LLC; anything returned over that LLC channel is passed on
+    to `stdout`
+  * **pcscio** uses the PC/SC smart card interface to pass what it finds
+    on `stdin` to a smart card as PDU codes; anything returned by that
+    smart card is passed on to `stdout`
+  * **derdump** parses DER structures (distinguished ASN.1 encoding) from
+    a file and shows the structure in great detail on `stdout`.  Special
+    about this utility is that it will work hard to print input that is
+    full of errors; the utility will complain loudly, but continue instead
+    of failing fatally; this makes it a very useful developer tool.
+
diff --git a/configure b/configure
new file mode 100644 (file)
index 0000000..616a143
--- /dev/null
+++ b/configure
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo 'Configuration is not needed, just run "make all"'
diff --git a/derdump b/derdump
new file mode 100755 (executable)
index 0000000..eb7b7e3
--- /dev/null
+++ b/derdump
@@ -0,0 +1,155 @@
+#!/usr/bin/python
+
+import sys
+
+if len (sys.argv) != 2:
+       print 'Usage: ' + sys.argv [0] + 'file.der'
+       sys.exit (1)
+
+der = open (sys.argv [1], 'r').read (65537)
+ofs = 0
+
+def eof ():
+       global ofs, der
+       return ofs >= len (der)
+
+def read1 ():
+       global ofs, der
+       if eof ():
+               print 'ATTEMPTED READ BEYOND EOF (RETURNING 0x00)'
+               return 0
+       else:
+               ofs = ofs + 1
+               return ord (der [ofs-1])
+
+nesting = []
+
+class2str = {
+       0: 'Universal',
+       1: 'Application',
+       2: 'Contextual',
+       3: 'Private'
+}
+
+pc2str = {
+       0: 'Primitive',
+       1: 'Constructed'
+}
+
+universal2str = {
+       0: 'End-Of-Content',
+       1: 'BOOLEAN',
+       2: 'INTEGER',
+       3: 'BITSTRING',
+       4: 'OCTETSTRING',
+       5: 'NULL',
+       6: 'OID',
+       7: 'Object-Descriptor',
+       8: 'EXTERNAL',
+       9: 'REAL',
+       10: 'ENUMERATED',
+       11: 'EMBEDDED PDV',
+       12: 'UTF8String',
+       13: 'RELATIVE-OID',
+       14: '*****',
+       15: '*****',
+       16: 'SEQUENCE (OF)',
+       17: 'SET (OF)',
+       18: 'NumericString',
+       19: 'PrintableString',
+       20: 'T61String',
+       21: 'VideotexString',
+       22: 'IA5String',
+       23: 'UTCTime',
+       24: 'GeneralizedTime',
+       25: 'GraphicString',
+       26: 'VisibleString',
+       27: 'GeneralString',
+       28: 'UniversalString',
+       29: 'CHARACTER STRING',
+       30: 'BMPString',
+       31: '*****'
+}
+
+while not eof ():
+
+       while nesting != [] and ofs >= nesting [-1]:
+               if ofs > nesting [-1]:
+                       print 'READ OFFSET %d EXCEEDS ENCAPSULATION %d (RETURNING)' % (ofs, nesting [-1])
+               ofs = nesting.pop ()
+
+       tag = read1 ()
+       tag_class = (tag & 0xc0) >> 6
+       tag_pc = (tag & 0x20) != 0
+       tag_num = tag & 0x1f
+
+       lenlen = read1 ()
+       if lenlen & 0x80 == 0:
+               leng = lenlen
+               lenlen = 1
+       else:
+               lenlen = lenlen - 0x80 + 1
+               leng = 0
+               i = 1
+               while i < lenlen:
+                       leng <<= 8
+                       leng = leng + read1 ()
+                       i = i + 1
+
+       if tag_class == 0:
+               meaning = universal2str [tag_num]
+       elif tag_class == 1:
+               meaning = '[APPLICATION ' + str (tag_num) + ']'
+       elif tag_class == 2:
+               meaning = '[' + str (tag_num) + ']'
+       else:
+               meaning = '[PRIVATE ' + str (tag_num) + ']'
+
+       print '%s%s: tag 0x%02x %s%d @%d ^%d, %s, %s' % (
+                       '  ' * len (nesting),
+                       meaning, tag,
+                       '#' * lenlen, leng,
+                       ofs - lenlen - 1,
+                       len (nesting),
+                       class2str [tag_class],
+                       pc2str [tag_pc] )
+
+       if tag_pc == 0 and leng > 0:
+               print '  ' * ( len (nesting) + 1 ),
+               cstr = '"'
+               ival = 0
+               ostr = ''
+               oval = None
+               while leng > 0:
+                       ch = read1 ()
+                       print '%02x' % ch,
+                       if 32 <= ch < 127:
+                               cstr = cstr + chr (ch)
+                       else:
+                               cstr = cstr + '.'
+                       ival = (ival << 8) | ch
+                       if oval is None:
+                               ostr = str (ch / 40) + '.' + str (ch % 40)
+                               oval = 0
+                       else:
+                               oval = (oval << 7) | (ch & 0x7f)
+                               if ch & 0x80 == 0:
+                                       ostr = ostr + '.' + str (oval)
+                                       oval = 0
+                       leng = leng - 1
+               cstr = cstr + '"'
+               if tag == 0x06:
+                       cstr = ostr
+               elif tag == 0x02:
+                       cstr = str (ival)
+               print '==', cstr
+
+       if tag_pc != 0:
+               # print 'Now at', ofs, 'adding', leng, 'pushing', ofs + leng
+               nesting.append (ofs + leng)
+
+while nesting != []:
+       if ofs != nesting [-1]:
+               print 'NESTING NOT ENDED CORRECTLY, OFFSET IS %d INSTEAD OF %d (CONTINUING)' % (ofs, nesting [-1])
+       nesting.pop ()
+
diff --git a/derdump.py b/derdump.py
deleted file mode 100755 (executable)
index eb7b7e3..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/python
-
-import sys
-
-if len (sys.argv) != 2:
-       print 'Usage: ' + sys.argv [0] + 'file.der'
-       sys.exit (1)
-
-der = open (sys.argv [1], 'r').read (65537)
-ofs = 0
-
-def eof ():
-       global ofs, der
-       return ofs >= len (der)
-
-def read1 ():
-       global ofs, der
-       if eof ():
-               print 'ATTEMPTED READ BEYOND EOF (RETURNING 0x00)'
-               return 0
-       else:
-               ofs = ofs + 1
-               return ord (der [ofs-1])
-
-nesting = []
-
-class2str = {
-       0: 'Universal',
-       1: 'Application',
-       2: 'Contextual',
-       3: 'Private'
-}
-
-pc2str = {
-       0: 'Primitive',
-       1: 'Constructed'
-}
-
-universal2str = {
-       0: 'End-Of-Content',
-       1: 'BOOLEAN',
-       2: 'INTEGER',
-       3: 'BITSTRING',
-       4: 'OCTETSTRING',
-       5: 'NULL',
-       6: 'OID',
-       7: 'Object-Descriptor',
-       8: 'EXTERNAL',
-       9: 'REAL',
-       10: 'ENUMERATED',
-       11: 'EMBEDDED PDV',
-       12: 'UTF8String',
-       13: 'RELATIVE-OID',
-       14: '*****',
-       15: '*****',
-       16: 'SEQUENCE (OF)',
-       17: 'SET (OF)',
-       18: 'NumericString',
-       19: 'PrintableString',
-       20: 'T61String',
-       21: 'VideotexString',
-       22: 'IA5String',
-       23: 'UTCTime',
-       24: 'GeneralizedTime',
-       25: 'GraphicString',
-       26: 'VisibleString',
-       27: 'GeneralString',
-       28: 'UniversalString',
-       29: 'CHARACTER STRING',
-       30: 'BMPString',
-       31: '*****'
-}
-
-while not eof ():
-
-       while nesting != [] and ofs >= nesting [-1]:
-               if ofs > nesting [-1]:
-                       print 'READ OFFSET %d EXCEEDS ENCAPSULATION %d (RETURNING)' % (ofs, nesting [-1])
-               ofs = nesting.pop ()
-
-       tag = read1 ()
-       tag_class = (tag & 0xc0) >> 6
-       tag_pc = (tag & 0x20) != 0
-       tag_num = tag & 0x1f
-
-       lenlen = read1 ()
-       if lenlen & 0x80 == 0:
-               leng = lenlen
-               lenlen = 1
-       else:
-               lenlen = lenlen - 0x80 + 1
-               leng = 0
-               i = 1
-               while i < lenlen:
-                       leng <<= 8
-                       leng = leng + read1 ()
-                       i = i + 1
-
-       if tag_class == 0:
-               meaning = universal2str [tag_num]
-       elif tag_class == 1:
-               meaning = '[APPLICATION ' + str (tag_num) + ']'
-       elif tag_class == 2:
-               meaning = '[' + str (tag_num) + ']'
-       else:
-               meaning = '[PRIVATE ' + str (tag_num) + ']'
-
-       print '%s%s: tag 0x%02x %s%d @%d ^%d, %s, %s' % (
-                       '  ' * len (nesting),
-                       meaning, tag,
-                       '#' * lenlen, leng,
-                       ofs - lenlen - 1,
-                       len (nesting),
-                       class2str [tag_class],
-                       pc2str [tag_pc] )
-
-       if tag_pc == 0 and leng > 0:
-               print '  ' * ( len (nesting) + 1 ),
-               cstr = '"'
-               ival = 0
-               ostr = ''
-               oval = None
-               while leng > 0:
-                       ch = read1 ()
-                       print '%02x' % ch,
-                       if 32 <= ch < 127:
-                               cstr = cstr + chr (ch)
-                       else:
-                               cstr = cstr + '.'
-                       ival = (ival << 8) | ch
-                       if oval is None:
-                               ostr = str (ch / 40) + '.' + str (ch % 40)
-                               oval = 0
-                       else:
-                               oval = (oval << 7) | (ch & 0x7f)
-                               if ch & 0x80 == 0:
-                                       ostr = ostr + '.' + str (oval)
-                                       oval = 0
-                       leng = leng - 1
-               cstr = cstr + '"'
-               if tag == 0x06:
-                       cstr = ostr
-               elif tag == 0x02:
-                       cstr = str (ival)
-               print '==', cstr
-
-       if tag_pc != 0:
-               # print 'Now at', ofs, 'adding', leng, 'pushing', ofs + leng
-               nesting.append (ofs + leng)
-
-while nesting != []:
-       if ofs != nesting [-1]:
-               print 'NESTING NOT ENDED CORRECTLY, OFFSET IS %d INSTEAD OF %d (CONTINUING)' % (ofs, nesting [-1])
-       nesting.pop ()
-
diff --git a/devio.c b/devio.c
index fa34876..cc35934 100644 (file)
--- a/devio.c
+++ b/devio.c
@@ -59,4 +59,5 @@ int main (int argc, char *argv []) {
                
        }
        close (fd);
+       return 0;
 }
diff --git a/hexin.c b/hexin.c
new file mode 100644 (file)
index 0000000..15d3832
--- /dev/null
+++ b/hexin.c
@@ -0,0 +1,85 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define BYTES_PER_LINE 35
+
+enum status { normal, endline, error, endfile };
+enum status status = normal;
+
+void ch2hex (unsigned char *output, int ch) {
+       if ((ch >= '0') && (ch <= '9')) {
+               *output <<= 4;
+               *output += ch - '0';
+       } else {
+               ch = toupper (ch);
+               if ((ch < 'A') || (ch > 'F')) {
+                       fprintf (stderr, "Illegal char '%c'\n", ch);
+                       status = error;
+               } else {
+                       *output <<= 4;
+                       *output += ch - 'A' + 10;
+               }
+       }
+}
+
+int getbyte (unsigned char *output) {
+       int ch;
+
+       *output = 0;
+
+       if (status == error) {
+               return 0;
+       }
+
+       do {
+               if ((ch = getchar ()) < 0) {
+                       status = endfile;
+                       return 0;
+               }
+               if (ch == '\n') {
+                       status = endline;
+                       return 0;
+               }
+       } while ((ch == ' ') || (ch == ':'));
+
+       if (status == normal) {
+               ch2hex (output, ch);
+               ch = getchar ();
+               ch2hex (output, ch);
+       }
+
+       return (status == normal);
+}
+
+int main (int argc, char *argv []) {
+       size_t offset = 0;
+       size_t len;
+       unsigned char buf [BYTES_PER_LINE];
+       char ch;
+
+       while (status != endfile) {
+               if (status == endline) {
+                       status = normal;
+               }
+               usleep (1000000L); // Yield to others -- better prompt printing
+               fprintf (stderr, "%08lx>", offset);
+               fflush (stderr);
+               len = 0;
+               while ((len < BYTES_PER_LINE) && (status == normal)) {
+                       if (getbyte (&buf [len])) {
+                               len++;
+                               offset++;
+                       }
+               }
+               write (1, buf, len);
+               if (status == error) {
+                       while (ch = getchar (), (ch >=0) && (ch!='\n')) {
+                               ;
+                       }
+                       fprintf (stderr, "*** skipped remainder of line ***\n");
+                       status = normal;
+               }
+       }
+       return 0;
+}
diff --git a/hexout.c b/hexout.c
new file mode 100644 (file)
index 0000000..d2e4746
--- /dev/null
+++ b/hexout.c
@@ -0,0 +1,78 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <errno.h>
+
+
+/* Outputter reads input from stdin and prints it in hex on stdout.
+ * It will collect lines of one character plus anything that arrives
+ * within a second after that first character, limited to a maximum
+ * number of characters that just fits on a 80-char wide display.
+ */
+
+
+#define BYTES_PER_LINE 24
+
+unsigned long timersofar = 123;
+
+void tick (int signal) {
+       timersofar++;
+}
+
+struct itimerval tickival = { { 0, 0 } , { 1, 0 } };
+struct itimerval stopival = { { 0, 0 } , { 0, 0 } };
+
+int main (int argc, char *argv []) {
+       unsigned char buf [BYTES_PER_LINE];
+/*
+       unsigned long timer;
+*/
+       size_t len;
+       size_t offset = 0;
+       if (signal (SIGALRM, tick) == SIG_ERR) {
+               perror ("Failed to install interval handler");
+               exit (1);
+       }
+       system ("stty raw -echo");
+       printf ("*** outputter starts -- in hex mode ***\r\n");
+       fflush (stdout);
+/*
+       while (timersofar = timer,
+                       len = read (0, buf, BYTES_PER_LINE),
+                       (len > 0) || ( errno == SIGALRM ) ) {
+*/
+       while (len = read (0, buf, 1), len > 0) {
+               size_t i;
+               int len2;
+               /* Set a timeout before reading more; ignore problems */
+               setitimer (ITIMER_REAL, &tickival, NULL);
+               len2 = read (0, buf + 1, BYTES_PER_LINE - 1);
+               setitimer (ITIMER_REAL, &stopival, NULL);
+               if ((len2 == -1) && (errno == EINTR)) {
+                       len2 = 0;
+               }
+               if (len2 >= 0) {
+                       len += len2;
+               }
+               printf ("%08lx", offset);
+               offset += len;
+               for (i=0; i<len; i++) {
+                       printf (" %02x", buf [i]);
+               }
+               printf ("\r\n");
+               fflush (stdout);
+               if (len2 < 0) {
+                       len = -1;
+                       break;
+               }
+       }
+       if (len < 0) {
+               perror ("read(2) failed");
+       } else {
+               printf ("*** outputter ends ***\r\n");
+       }
+       system ("stty cooked echo");
+       return 0;
+}
diff --git a/inputter.c b/inputter.c
deleted file mode 100644 (file)
index 408673d..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#define BYTES_PER_LINE 35
-
-enum status { normal, endline, error, endfile };
-enum status status = normal;
-
-void ch2hex (char *output, int ch) {
-       if ((ch >= '0') && (ch <= '9')) {
-               *output <<= 4;
-               *output += ch - '0';
-       } else {
-               ch = toupper (ch);
-               if ((ch < 'A') || (ch > 'F')) {
-                       fprintf (stderr, "Illegal char '%c'\n", ch);
-                       status = error;
-               } else {
-                       *output <<= 4;
-                       *output += ch - 'A' + 10;
-               }
-       }
-}
-
-int getbyte (char *output) {
-       int ch;
-
-       *output = 0;
-
-       if (status == error) {
-               return 0;
-       }
-
-       do {
-               if ((ch = getchar ()) < 0) {
-                       status = endfile;
-                       return 0;
-               }
-               if (ch == '\n') {
-                       status = endline;
-                       return 0;
-               }
-       } while ((ch == ' ') || (ch == ':'));
-
-       if (status == normal) {
-               ch2hex (output, ch);
-               ch = getchar ();
-               ch2hex (output, ch);
-       }
-
-       return (status == normal);
-}
-
-int main (int argc, char *argv []) {
-       size_t offset = 0;
-       size_t len;
-       unsigned char buf [BYTES_PER_LINE];
-       char ch;
-
-       while (status != endfile) {
-               if (status == endline) {
-                       status = normal;
-               }
-               usleep (1000000L); // Yield to others -- better prompt printing
-               fprintf (stderr, "%08x>", offset);
-               fflush (stderr);
-               len = 0;
-               while ((len < BYTES_PER_LINE) && (status == normal)) {
-                       if (getbyte (&buf [len])) {
-                               len++;
-                               offset++;
-                       }
-               }
-               write (1, buf, len);
-               if (status == error) {
-                       while (ch = getchar (), (ch >=0) && (ch!='\n')) {
-                               ;
-                       }
-                       fprintf (stderr, "*** skipped remainder of line ***\n");
-                       status = normal;
-               }
-       }
-}
diff --git a/llcio.c b/llcio.c
index 1d8ba17..ae2ae01 100644 (file)
--- a/llcio.c
+++ b/llcio.c
@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <net/if.h>
 #include <net/if_arp.h>
diff --git a/outputter.c b/outputter.c
deleted file mode 100644 (file)
index 73b7b42..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-
-
-/* Outputter reads input from stdin and prints it in hex on stdout.
- * It will collect lines of one character plus anything that arrives
- * within a second after that first character, limited to a maximum
- * number of characters that just fits on a 80-char wide display.
- */
-
-
-#define BYTES_PER_LINE 24
-
-unsigned long timersofar = 123;
-
-void tick (int signal) {
-       timersofar++;
-}
-
-struct itimerval tickival = { { 0, 0 } , { 1, 0 } };
-struct itimerval stopival = { { 0, 0 } , { 0, 0 } };
-
-int main (int argc, char *argv []) {
-       unsigned char buf [BYTES_PER_LINE];
-       unsigned long timer;
-       size_t len;
-       size_t offset = 0;
-       if (signal (SIGALRM, tick) == SIG_ERR) {
-               perror ("Failed to install interval handler");
-               exit (1);
-       }
-       system ("stty raw -echo");
-       printf ("*** outputter starts -- in hex mode ***\r\n");
-       fflush (stdout);
-/*
-       while (timersofar = timer,
-                       len = read (0, buf, BYTES_PER_LINE),
-                       (len > 0) || ( errno == SIGALRM ) ) {
-*/
-       while (len = read (0, buf, 1), len > 0) {
-               size_t i;
-               int len2;
-               /* Set a timeout before reading more; ignore problems */
-               setitimer (ITIMER_REAL, &tickival, NULL);
-               len2 = read (0, buf + 1, BYTES_PER_LINE - 1);
-               setitimer (ITIMER_REAL, &stopival, NULL);
-               if ((len2 == -1) && (errno == EINTR)) {
-                       len2 = 0;
-               }
-               if (len2 >= 0) {
-                       len += len2;
-               }
-               printf ("%08x", offset);
-               offset += len;
-               for (i=0; i<len; i++) {
-                       printf (" %02x", buf [i]);
-               }
-               printf ("\r\n");
-               fflush (stdout);
-               if (len2 < 0) {
-                       len = -1;
-                       break;
-               }
-       }
-       if (len < 0) {
-               perror ("read(2) failed");
-       } else {
-               printf ("*** outputter ends ***\r\n");
-       }
-       system ("stty cooked echo");
-       return 0;
-}
index 83f2835..1c217c7 100644 (file)
--- a/pcscio.c
+++ b/pcscio.c
@@ -4,6 +4,7 @@
 #include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <string.h>
 
 #include <sys/types.h>
 #include <sys/select.h>
@@ -85,4 +86,5 @@ int main (int argc, char *argv []) {
                }
        }
        SCardReleaseContext (ctx);
+       return 0;
 }