#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <linux/coff.h>

int nCode = COFF_SHMAGIC;
char *pszProgram;

/*
 *  Stamp the object file to be a shared library.
 */

void useage (void)
    {
    printf ("useage: %s <file_name>\n", pszProgram);
    }

int check_header (COFF_FILHDR *pHdr)
    {
    char *szError = NULL;

    if (COFF_SHORT (pHdr->f_magic) != COFF_I386MAGIC)
        {
	szError = "bad magic";
        }

    if (szError == NULL && COFF_SHORT (pHdr->f_opthdr) < COFF_AOUTSZ)
        {
	szError = "missing aout hdr";
        }

    if (szError == NULL && (COFF_SHORT (pHdr->f_flags) & COFF_F_EXEC) == 0)
        {
	szError = "missing externals";
        }
/*
 *  If successful then return the proper status
 */
    if (szError == NULL)
        {
	return (0);
        }

    printf ("%s: bad file format (%s)\n", pszProgram, szError);
    return (1);
    }

int process_file (FILE *fp)
    {
    COFF_FILHDR  file_hdr;
    COFF_AOUTHDR aout_hdr;
    int          answer = 0;
/*
 * Read the file header
 */
    if (fread (&file_hdr, 1, sizeof(file_hdr), fp) != sizeof(file_hdr))
        {
	if (ferror (fp))
	    {
	    perror ("error reading file");
	    }
	else
	    {
	    printf ("%s: read of library is short\n", pszProgram);
	    }
	answer = 1;
        }
    else
        {
	answer = check_header (&file_hdr);
        }

    if (answer == 0)
        {
	if (fread (&aout_hdr, 1, sizeof(aout_hdr), fp) != sizeof(aout_hdr))
	    {
	    if (ferror (fp))
	        {
		perror ("error reading file");
	        }
	    else
	        {
		printf ("%s: read of library is short\n", pszProgram);
	        }
	    answer = 1;
	    }
        }

    if (answer == 0)
        {
	aout_hdr.magic[0] = nCode & 0xFF;
	aout_hdr.magic[1] = (nCode >> 8) & 0xFF;
	
	if (fseek (fp, (long) COFF_FILHSZ, SEEK_SET) != 0)
	    {
	    perror ("error seeking on library");
	    answer = 1;
	    }
        }

    if (answer == 0)
        {
	if (fwrite (&aout_hdr, 1, sizeof (aout_hdr), fp) != sizeof (aout_hdr))
	    {
	    if (ferror (fp))
	        {
		perror ("error writing to library file");
	        }
	    else
	        {
		printf ("%s: no space left on output device ???\n",
			pszProgram);
	        }
	    answer = 1;
	    }
        }

    return (answer);
    }

int main (int argc, char **argv)
    {
    FILE   *fp = NULL;
    static char szOpt[] = "";
    int    opt;
    int    answer = 0;
/*
 *  Decode the options.
 */
    pszProgram = argv[0];
    opt = getopt (argc, argv, szOpt);
    while (opt != EOF && answer == 0)
        {
	switch (opt)
	    {
	default:
	    printf ("unkown option -%c\n", opt);
	    useage();
	    answer = 1;
	    break;
	    }
	opt = getopt (argc, argv, szOpt);
        }
/*
 *  Complain if the library name was not given
 */
    if (optind >= argc && answer == 0)
        {
	printf ("%s: missing library name\n", pszProgram);
	useage();
	answer = 1;
        }
/*
 * Open the library file.
 */
    if (answer == 0)
        {
	fp = fopen (argv[optind++], "r+");
	if (fp == NULL)
	    {
	    perror ("stampit: unable to open input file");
	    answer = 1;
	    }
        }
/*
 * Process the file
 */
    if (answer == 0)
        {
	answer = process_file (fp);
        }

    if (fp != NULL)
        {
	fclose (fp);
        }

    return (answer);
    }
