/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
AZA File Reversal Program v1.0
by Russ Weathersby [SiGod via AOL]
circa June 1995
Compilation Notes:
This program was originally written for and compiled using the
Borland C++ 4.0 compiler on a PC compatible P75 with MSDOS 6.0.
It contains no C++ specific code. The code can be compiled for
non-DOS operating systems (i.e. UNIX) with little or no change.
I suggest using the compact memory model when compiling on a
PC compatible. You may receive warning messages during compilation
regarding assignments within conditional expressions. These
warnings can be safely ignored.
Program Creation Notes:
Compile with REVERSED #defined to zero to create the normal
text 'AZ' executable, then with REVERSED set to one to create
the reverse text 'ZA' version. Run AZ on 'za.exe' to reverse
the code, then use an OS command or other utility to splice
the two (binary) files, as with this DOS command:
COPY /B AZ.EXE + ZA.EXE AZA.EXE
DOS driven machines will accept this .EXE doubling without choking.
Other Notes:
-File I/O is performed in chunks, obviating the need for large
ammounts of memory. Console I/O is monolithic in nature,
so it is limited by available memory.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include <alloc.h>
#include <ctype.h>
#include <limits.h>
/*-----------------------------Macros-------------------------------*/
/* set REVERSED to 0 to print program text normally */
/* set REVERSED to 1 to print program text backward */
#define REVERSED 0
#if REVERSED
#define STR "s%"
#else
#define STR "%s"
#endif
#define PErr(S,V) fprintf(IOType == CONSOLE ? stderr : stdout, RForm(S),V);
#if defined(__COMPACT__) || defined(__LARGE__) || defined(__HUGE__)
#define BUFFPTR char huge *
#define malloc farmalloc
#define free farfree;
#else
#define BUFFPTR char *
#endif
#define FBUFFSIZE 4096 /* for setvbuf() */
/*--------------------Enumerations and Typedefs---------------------*/
enum rtype{FAIL, SUCCESS};
enum iotype{CONSOLE, SAME_FILE, DIFF_FILES};
typedef enum rtype RTYPE;
typedef enum iotype IOTYPE;
typedef unsigned long ULONG;
/*-----------------------Global Declarations------------------------*/
ULONG GetSize(FILE*);
ULONG MakeBuff(ULONG);
FILE *OpenIn(char*);
FILE *OpenOut(char*, ULONG, FILE*);
void FreeBuff(void);
char *RForm(char*);
void *Buffer;
int _RV_ = REVERSED;
IOTYPE IOType = CONSOLE;
char orig_author[] = "Russell S. Weathersby"; /* not used in program */
char date[] = "June 1995";
/*------------------------Beginning of Code-------------------------*/
/*--------------------------------------------------------------------
main
--------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
RTYPE init(int, char**, char*, char*);
ULONG readin(FILE*, ULONG, ULONG, ULONG);
ULONG writeout(FILE*, ULONG, ULONG, ULONG);
FILE *fpin, *fpout;
char infile[FILENAME_MAX + 1], outfile[FILENAME_MAX + 1];
ULONG filesize, buffsize, left;
int retval;
Buffer = (void *)NULL;
retval = 1;
if(init(argc, argv, infile, outfile) == SUCCESS)
if(fpin = OpenIn(infile)) {
if(left = filesize = GetSize(fpin))
if(buffsize = MakeBuff(filesize))
if(fpout = OpenOut(outfile, filesize, fpin)) {
while(buffsize = readin(fpin, filesize, buffsize, left))
left -= writeout(fpout, filesize, buffsize, left);
retval = 0;
}
fcloseall();
}
FreeBuff();
return retval;
} /* end main() */
/*-------------------------------------------------------------------
init
-------------------------------------------------------------------*/
RTYPE init(int argc, char *argv[], char *infile, char *outfile)
{
void print_usage(void);
char *chptr;
if(argc == 1)
return SUCCESS;
for(chptr = argv[argc - 1]; *chptr++ = toupper(*chptr););
if((argc == 3 || argc == 4) && !strcmp(argv[argc - 1], "AZA")) {
strncpy(infile, _RV_ ? argv[argc - 2] : argv[1], FILENAME_MAX);
strncpy(outfile, _RV_ ? argv[1] : argv[argc - 2], FILENAME_MAX);
IOType = strcmp(infile, outfile) ? DIFF_FILES : SAME_FILE;
}
else {
print_usage();
return FAIL;
}
return SUCCESS;
} /* end init() */
/*-------------------------------------------------------------------
print_usage
-------------------------------------------------------------------*/
void print_usage(void)
{
char *cptr;
if(_RV_) {
_RV_ = 0; /* prevent RForm function from reversing this. */
PErr("\n< Insert sordid satanic messages here. ;) >\n", NULL);
PErr("Continuing...", NULL);
_RV_ = 1;
}
cptr = "\nAZA v1.0 - File Reversal Program\n\n"
"Purpose: Reads the source file and writes it in\n"
" reverse order to the destination file.\n\n"
"Usage: aza [sourcefile [destfile] aza]\n"
"Note: The additional \"aza\" simply preserves symmetry.\n\n"
"example1: \"aza letter.doc reverse.doc aza\"\n"
"example2: \"aza aza.exe aza\"\n"
"example3: \"aza < some.txt > emos.txt\"\n\n";
PErr(cptr, NULL);
return;
} /* end print_usage() */
/*-------------------------------------------------------------------
OpenIn
-------------------------------------------------------------------*/
FILE *OpenIn(char *infile)
{
static FILE *fpin;
char *opentype;
if(IOType == CONSOLE)
fpin = stdin;
else {
opentype = (IOType == DIFF_FILES) ? "rb" : "r+b";
if((fpin = fopen(RForm(infile), opentype)) == NULL) {
PErr("\nAZA:Unable to open \""STR"\" for read.\n", infile);
return (FILE*)NULL;
}
if(setvbuf(fpin, NULL, _IOFBF, FBUFFSIZE)) {
PErr("\nAZA:Not enough memory for operation.\n", NULL);
fclose(fpin);
return (FILE*)NULL;
}
}
return fpin;
} /* end OpenIn() */
/*-------------------------------------------------------------------
GetSize
-------------------------------------------------------------------*/
ULONG GetSize(FILE *fpin)
{
ULONG filesize;
if(IOType != CONSOLE) {
fseek(fpin, 0, SEEK_END);
filesize = ftell(fpin);
}
else
filesize = 0xFFFFFUL;
return filesize;
} /* end GetSize() */
/*-------------------------------------------------------------------
MakeBuff
-------------------------------------------------------------------*/
ULONG MakeBuff(ULONG size)
{
while(((Buffer = malloc(size)) == NULL) && (size > 2))
size = (size >> 2 << 1) + 2; /* halve it, make it even */
if(size < 0x400UL) {
if(Buffer)
free(Buffer);
PErr("\nAZA:Not enough memory for operation.\n", NULL);
size = 0UL;
}
return size;
} /* end MakeBuff() */
/*-------------------------------------------------------------------
OpenOut
-------------------------------------------------------------------*/
FILE *OpenOut(char *outfile, ULONG filesize, FILE *fpin)
{
static FILE *fpout;
char *opentype;
if(IOType == CONSOLE)
fpout = stdout;
else {
if(IOType == SAME_FILE)
return fpin;
if((fpout = fopen(RForm(outfile), "wb")) == NULL) {
PErr("\nAZA:Unable to open \""STR"\" for write.\n", outfile);
return (FILE*)NULL;
}
if(setvbuf(fpout, NULL, _IOFBF, FBUFFSIZE)) {
PErr("\nAZA:Not enough memory for operation.\n", NULL);
return (FILE*)NULL;
}
while(filesize && (fputc(0x00, fpout) != EOF))
filesize--;
if(filesize > 0) {
PErr("\nAZA:Disk full.(File created)\n", NULL);
return (FILE*)NULL;
}
}
return fpout;
} /* end OpenOut() */
/*-------------------------------------------------------------------
readin
-------------------------------------------------------------------*/
ULONG readin(FILE *fpin, ULONG filesize, ULONG buffsize, ULONG left)
{
BUFFPTR buffptr;
ULONG readlen, length, i;
long offset;
char ch;
if(!left)
return 0UL;
buffptr = (char *)Buffer;
if(IOType == CONSOLE) {
length = 0;
while(((ch = getchar()) != EOF) && buffsize) {
*buffptr++ = ch;
length++;
buffsize--;
}
if(buffsize == 0)
PErr("\nAZA:Not enough workspace available for completion.\n", NULL);
}
else {
offset = (filesize - left + 2) / 2 - 1;
readlen = (left > buffsize) ? buffsize / 2 : left;
fseek(fpin, offset, SEEK_SET);
for(i = readlen; i; --i)
*buffptr++ = fgetc(fpin);
length = readlen;
if(left > buffsize) {
fseek(fpin, -offset - readlen, SEEK_END);
for(i = readlen; i; --i)
*buffptr++ = fgetc(fpin);
length += readlen;
}
}
return length;
} /* end readin() */
/*-------------------------------------------------------------------
writeout
-------------------------------------------------------------------*/
ULONG writeout(FILE *fpout, ULONG filesize, ULONG buffsize, ULONG left)
{
BUFFPTR buffptr;
ULONG writelen, length, i;
long offset;
buffptr = (char *)Buffer;
buffptr += buffsize;
if(IOType == CONSOLE) {
while(buffsize--)
fputc(*--buffptr, fpout);
length = left;
}
else {
offset = (filesize - left + 2) / 2 - 1;
writelen = (left > buffsize) ? buffsize / 2 : left;
fseek(fpout, offset, SEEK_SET);
for(i = writelen; i; --i)
fputc(*--buffptr, fpout);
length = writelen;
if(left > buffsize) {
fseek(fpout, -offset - writelen, SEEK_END);
for(i = writelen; i; --i)
fputc(*--buffptr, fpout);
length += writelen;
}
}
return length;
} /* end writeout() */
/*-------------------------------------------------------------------
FreeBuff
-------------------------------------------------------------------*/
void FreeBuff(void)
{
if(Buffer != NULL)
free(Buffer);
return;
} /* end FreeBuff() */
/*-------------------------------------------------------------------
RForm
-------------------------------------------------------------------*/
char *RForm(char *text)
{
#define TB_MAX 1000
static char txt_buff[TB_MAX + 1];
char *chptr;
int len;
if(_RV_ && text) {
len = ((len = strlen(text)) < TB_MAX) ? len : TB_MAX;
chptr = text;
txt_buff[len] = '\0';
while(len)
txt_buff[--len] = *chptr++;
text = txt_buff;
}
return text;
} /* end RForm() */
/* end source for AZA */