home *** CD-ROM | disk | FTP | other *** search
- /*
- * FILE
- * strings.c
- *
- * VERSION
- * V1.02, Not Released
- *
- * DESCRIPTION
- * A utility which prints out strings in binary files.
- *
- * This program can also be seen as a test for my "ALiLib"
- * project. The program relies on 1) The clop() function for
- * parsing options and
- * 2) My version of malloc/free is also used. I don't know wheter
- * or not it differs from the lattice version, but Lattice is
- * known not to be simple......
- *
- * STATUS
- * All rights reserved.
- *
- * AUTHOR
- * Anders 'ALi' Lindgren
- * Mälarblick 8
- * S-161 51 Bromma
- * Sweden
- *
- * CODE HISTORY
- * Some years ago Idea
- * 90-Dec-10 Preliminary specs written during some booring
- * army radio guard night-hours.
- * 90-Dec-16 Start of hacking, Program basically ready.
- * Several fancy details included, like ctrl-C.
- * 91-Jan-09 V1.01 Skip starting blanks
- * 92-Jan-12 V1.02 View only strings terminated by NIL, CR, LF or
- * TAB and long strings (which doesn't fit into
- * the buffer).
- * Static version string added.
- *
- * SEE ALSO
- * ALiLib-documentation
- * strings.doc
- *
- * TODO
- * ALiLib-interfacing.
- * A 0xFF (ÿ) remover? (option?)
- */
-
- static char * version_strings = "\0$VER: strings V1.02 (" __DATE__
- ") by Anders Lindgren.";
-
- #include <exec/types.h>
-
- #include <libraries/dos.h>
-
- #define _USEOLDEXEC_
- #include <proto/exec.h>
- #include <proto/dos.h>
-
- #include <ctype.h>
- #include "stdlib.h" /* It doesn't hurt if it's my own. */
-
- #include "clop.h"
-
-
- /*
- * DEFINITIONS
- */
-
- #define BUFSIZE 512 /* Remember, it's stored on the stack */
-
-
- /*
- * WARNING! These definitions corresponds to the clop_array below!
- */
-
- #define OPTION_SMALL 0
- #define OPTION_EXTENDED 1
- #define OPTION_BYTE 2
- #define OPTION_OUTPUT 3
- #define OPTION_USAGE 4
- #define OPTION_HELP 5
-
-
- #define DOS_PRINT(x) Write(Output(),(x),sizeof(x))
-
- #define tohex(x) ((x)>9?(x)+'A'-10:(x)+'0')
-
-
- /*
- * DEFINE
- * isprint()
- *
- * DESCRIPTION
- * A simple Amiga-specific isprint(). This is much shorter than
- * dragging in a _ctype array.
- */
-
- #ifdef isprint
- #undef isprint
- #endif
-
- #define isprint(c) ((((c)>=32) && ((c)<=126)) || (((c)>=160) && ((c)<=255)))
-
-
- /*
- * FORWARD REFERENCES
- */
-
- extern int parse_opts(char *, struct clop_array *);
- extern int aloha(BPTR, BPTR, int, int, int);
- extern void write_offset(BPTR, unsigned long);
-
-
- /*
- * GLOBAL VARIABLES
- */
-
- struct DosLibrary * DOSBase;
-
-
- /*
- * FUNCTION
- * not_main
- *
- * DESCRIPTION
- */
-
- int __saveds __asm
- not_main(register __a0 char * cline, register __d0 long len)
- {
- int rc;
- char * args;
-
- struct clop_list clop_list = { NULL, '\0' };
-
- struct clop_array clop_array [ ] = {
- { 'n', CLOPT_UNUMBER, 0, 0, 6L }, /* Shortest string to print */
- { 'e', CLOPT_BOOL, 0, 0, 0L }, /* Extended character set */
- { 'b', CLOPT_BOOL, 0, 0, 0L }, /* Byte offsets */
- { 'o', CLOPT_STRING, 0, 0, NULL }, /* Output file */
- { 'u', CLOPT_BOOL, 0, 0, 0L },
- { '?', CLOPT_BOOL, 0, 0, 0L }, /* Help page */
- { '\0', CLOPT_END, 0, 0, NULL }
- };
-
- rc = RETURN_FAIL;
-
- if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0L)) {
- cline[len - 1] = '\0';
- if (args = clop(cline, & clop_list, clop_array)) {
-
- if (clop_array[OPTION_HELP].value.bool ||
- clop_array[OPTION_USAGE].value.bool) {
-
- rc = RETURN_OK;
-
- DOS_PRINT(
- "Strings V1.01 Written by Anders Lindgren.\n"
- "usage: strings [-nX] [-e] [-b] [-ooutfile] [infile]\n"
- " -n Smallest string to print. (default 6)\n"
- " -e Use extended character set.(default disabled)\n"
- " -b Print out byte offset. (default disabled)\n"
- " -o Print out to a file insted of standard out.\n" );
-
- }
- else {
- rc = parse_opts( args, clop_array );
- }
-
- }
- else {
- if (clop_list.error == CLOPE_UNKNOWN_OPTION) {
- DOS_PRINT("strings:Unknown switch: -");
- Write(Output(), & clop_list.failing_opt, 1);
- DOS_PRINT("\n");
- }
- else {
- DOS_PRINT("strings:Incorrect usage of switch: -");
- Write(Output(), & clop_list.failing_opt, 1);
- DOS_PRINT("\n");
- }
- }
- /*
- * Free everything allocated.
- */
-
- freeclop(clop_array);
-
- CloseLibrary((struct Library *)DOSBase);
- }
- return (rc);
- }
-
-
- /*
- * FUNCTION
- * parse_opts
- *
- * DESCRIPTION
- * Open all files, and establish all flags etc.
- *
- * Rename function? Guess so....
- */
-
- int
- parse_opts( char * filename, struct clop_array * clop_array)
- {
- BPTR input;
- BPTR output;
-
- /* Flags, using opened input/output FH, instead of std* */
- int closein;
- int closeout;
-
- unsigned int smallest;
- char * ofn; /* Output file name */
- int rc; /* Returncode */
-
- rc = RETURN_FAIL;
-
- smallest = clop_array[OPTION_SMALL].value.unumber;
-
- if ((smallest < BUFSIZE) && (smallest > 0) ) {
-
- /*
- * Establish an input stream.
- */
-
- if (* filename) {
- if (input = Open(filename, MODE_OLDFILE)) {
- closein = TRUE;
- }
- else {
- DOS_PRINT("strings:Didn't find input file.\n");
- return (RETURN_FAIL);
- }
- }
- else {
- input = Input();
- closein = FALSE;
- }
-
- /*
- * Establish output stream.
- */
-
- if (ofn = clop_array[OPTION_OUTPUT].value.string) {
-
- if (* ofn) {
- closeout = TRUE;
- if ( (output = Open(ofn, MODE_NEWFILE)) == NULL) {
- if (closein) {
- Close(input);
- }
- DOS_PRINT("strings:Error opening output file.\n");
- return(RETURN_FAIL);
- }
- }
- else {
- if (closein) {
- Close(input);
- }
- DOS_PRINT("strings:Missing output filename.\n");
- return(RETURN_FAIL);
- }
- }
- else {
- output = Output();
- closeout = FALSE;
- }
-
- /*
- * Call the actual heart of the program, and serv it all
- * it want to know on a silver plate.
- */
-
- rc = aloha(input, output, smallest,
- clop_array[OPTION_EXTENDED].value.bool,
- clop_array[OPTION_BYTE].value.bool);
-
- /*
- * Clean up files
- */
-
- if (closein) {
- Close(input);
- }
-
- if (closeout) {
- Close(output);
- }
- }
- else {
- DOS_PRINT("strings:Illegal -n number.\n");
- }
- return(rc);
- }
-
-
- /*
- * FUNCTION
- * aloha
- *
- * DESCRIPTION
- * The actual main loop.
- *
- * The name? Naw, I really can't think of any good, since
- * it's only a main, level 3.
- *
- * SYNOPSIS
- * aloha(input, output, smallest, extended, byteflg)
- * input, output - AmigaDOS filehandlers.
- * smallest - Shortest length to bother to print
- * extended - (flag) Consider the extended characters.
- * byteflg - (flag) Print out the byteoffset.
- */
-
- int
- aloha(BPTR input, BPTR output, int smallest, int extended, int byteflg)
- {
- unsigned char inbuf [BUFSIZE];
- unsigned char outbuf[BUFSIZE];
-
- int soffset;
- int doffset = 0;
-
- long counter = 0;
- long byteoffset = 0;
- unsigned char ch;
-
-
- int al; /* Actual length read */
-
- /* A _very_ long output line, longer than one buffer. */
- int longflg = FALSE;
-
- int ctrlc = FALSE;
-
- do { /* Until eof, or ctrl-C pressed */
-
- al = Read(input, inbuf, BUFSIZE);
-
- /* Check each character in the input buffer */
- for (soffset = 0; ( (soffset < al) && ! ctrlc ); soffset++) {
-
- ch = inbuf[soffset];
-
- /*
- * Check if the character is printable.
- */
- if ( isprint(ch) && (extended || isascii(ch)) ) {
-
- /*
- * Don't register spaces if they start a string.
- */
- if (ch != ' ' || doffset != 0 || longflg) {
-
- /*
- * Save the position for this string
- */
- if ((doffset == 0) && (! longflg)) {
- byteoffset = counter;
- }
-
- outbuf[doffset++] = ch;
-
- /*
- * Is the output buffer full?
- * Let's empty it and flag.
- */
- if (doffset == BUFSIZE) {
- if ( (! longflg) && (byteflg) ) {
- write_offset(output, byteoffset);
- }
- Write(output, outbuf, BUFSIZE);
- longflg = TRUE;
- doffset = 0;
- }
- }
- }
- else {
-
- /*
- * A nonprintable character found, let's see
- * if the characters found before if it's long
- * enough to print, or if the characters in
- * the buffer is part of a earlier, very long,
- * string.
- *
- * 1992-01-12: Just strings which are terminated
- * by NIL, CR, LF or TAB are considered
- * strings, if the string aren't so
- * big so it doesn't fit the buffer,
- * in which case we will se it anyway.
- */
-
- if ( ( ((ch == '\0') ||
- (ch == 10) ||
- (ch == 13) ||
- (ch == 9)) && (doffset >= smallest) ) ||
- longflg ) {
- if ( (! longflg) && (byteflg) ) {
- write_offset(output, byteoffset);
- }
- Write(output, outbuf, doffset);
- Write(output, "\n", 1);
- }
- doffset = 0;
- longflg = FALSE;
- }
- counter++; /* Byte counter */
-
- if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) {
- ctrlc = TRUE;
- }
- }
- } while((al > 0) && (!ctrlc));
-
- /*
- * If the file ended, and we have a correct strings in our
- * buffer, print it out.
- */
-
- if (ctrlc) {
- DOS_PRINT("*** Break!\n");
- }
- else if ((doffset >= smallest) || longflg) {
- if ( (! longflg) && (byteflg) ) {
- write_offset(output, byteoffset);
- }
- Write(output, outbuf, doffset);
- Write(output, "\n", 1);
- }
-
- return(al >= 0 ? RETURN_OK : RETURN_ERROR);
- }
-
-
- /*
- * FUNCTION
- * write_offset
- *
- * DESCRIPTION
- * This function writes out the offset in the form:
- * "X:" where X are at four or eigth hexadecimal
- * digits.
- */
-
- void
- write_offset(BPTR output, unsigned long offset)
- {
- char outbuf[9];
-
- int i;
- int firstn0;
-
- outbuf[8] = ':';
-
- /*
- * Decide if we shall print out four hexadecial digits, or
- * if we need all eight.
- */
- firstn0 = offset & 0xFFFF0000 ? 0 : 4;
-
- for (i=7; i>=0; i--) {
- outbuf[i] = tohex(offset & 0x0F);
- offset >>= 4;
- }
-
- Write(output, & outbuf[firstn0], 9-firstn0);
-
- return;
- }
-