#include <stdio.h>
#include <fcntl.h>

long lseek();
long getprevword();
long jumpback();

/**********************************************************************/
/*  Version 1.00   Amiga Binary File Truncator/Fixer     02/15/86     */
/*                                                                    */
/*    This program fixes a problem with binary executable files that  */
/* are rounded up to the nearest multiple of 128 bytes by the XMODEM  */
/* file transfer protocol. The AmigaDOS loader fails to recognize a   */
/* a file as executable if it has additional zero bytes at the end.   */
/*                                                                    */
/*    There are several ways of fixing this, most of which have been  */
/* done by some other public domain program. This is the only program */
/* I know of that fixes the file in place. The others all copy the    */
/* during the fix, which is SLOW!                                     */
/*                                                                    */
/*    Method 1: Allow the user to specify the correct length and copy */
/* that many bytes from one file to another for him. It works, but it */
/* requires that the correct file length be posted on each bulletin   */
/* board that the file is uploaded to. This can lead to problems with */
/* multiple versions of the same program.                             */
/*                                                                    */
/*    Method 2: Analyze the file and copy each load module table over */
/* to another file as it is parsed. Upon encountering an unparsable   */
/* piece, discard the piece and close the output file. This is truly  */
/* automatic, but it still takes time to copy the file. Also, if the  */
/* internal format is really NOT a loadable module, it can lead to    */
/* to infinite loops and huge, invalid symbol tables.                 */
/*                                                                    */
/*    Method 3: (Used by This Program)                                */
/* Skip to the End-of-File mark, and move backward until the END-HUNK */
/* module piece is found. This represents the true end-of-program. To */
/* get rid of the trailing bytes WITHOUT copying the file, append an  */
/* empty symbol-table HUNK of exactly the size required to eliminate  */
/* trailing bytes. Now the AmigaDOS will just skip over the empty     */
/* symbol table entries and load the program fine. Also, this is a    */
/* fast operation. At first, it appeared possible to just write empty */
/* END-HUNK pieces at the end, but there is a counter buried in the   */
/* object code that specifies the number of hunks expected, and some  */
/* programs would not load due to the excessive number of hunks. The  */
/* symbol table method is much better.                                */
/*                                                                    */
/**********************************************************************/
/*    PUBLIC DOMAIN by Jeff Rush of the Rising Star FIDO BBS 124/15   */
/*      Call the BBS for Additional Amiga Software 1-214-231-1372     */
/**********************************************************************/
/*               PLEASE REPORT ANY BUGS OR ENHANCEMENTS               */
/**********************************************************************/
main(argc, argv)
int   argc;
char *argv[];
{
    int i, fd, curfile, extracount;
    long fpos, aword;

    if (argc < 2) {
        puts("Fastchop 1.00 by Jeff Rush of Rising Star Fido\n");
        puts("Usage: %s <filelist>\n",argv[0]);
        exit(1);
    }

    for(curfile = 1; curfile < argc; curfile++) {
        printf("Chopping File: %s...\n", argv[curfile]);

        extracount = 0;
        fd         = open(argv[curfile], O_RDWR);
        if (fd == -1) {
            printf("ERROR - Unable to Open %s, Skipping...\n",
                argv[curfile]);
            continue;
        }

        fpos = lseek(fd, 0L, 2);
        printf("    Found Physical EOF at %ld Bytes.\n", fpos);

        while (getprevword(fd, &aword) > 0L && aword == 0L) {
            extracount++;
        }

        if (extracount == 0) {
            printf("    File has no trailing bytes, no chopping is necessary.\n"
);
            continue;
        }

        printf("    Encountered End-Program Word, Beginning Overwrite.\n");
        extracount++; /* Account for hunk_end word too */

        if (extracount % 2 == 1) /* Round it up to multiple of two words */
            extracount++;

        for(i=0; i<extracount; i+=2) {
            putword(fd, 0x000003F0L);
            putword(fd, 0x00000000L);
        }
        putword(fd, 0x000003F2L);
        printf("    Chop Operation Complete.\n");

        close(fd);
    }
}
/**********************************************************************/
/*                                                                    */
/**********************************************************************/
long getprevword(fd, aword)
int   fd;
long *aword;
{
    jumpback(fd);
    read(fd, aword, 4);
    return jumpback(fd);
}
/**********************************************************************/
/*                                                                    */
/**********************************************************************/
putword(fd, aword)
int fd;
long aword;
{
    write(fd, &aword, 4);
}
/**********************************************************************/
/*                                                                    */
/**********************************************************************/
long jumpback(fd)
int fd;
{
    long curpos;

    curpos = lseek(fd, -4L, 1);
    return curpos; 
}
/**********************************************************************/
/*                                                                    */
/**********************************************************************/

