/*  Cat.c

    Takes two filenames as arguments and concatenates the first file
    onto the end of the second file. Avoids the problems of "join"
    not being able to copy into an existing file.

    Usage: cat [-a/-o/-s "string"] [file1 [,file2...]] [to] file

    written by: DM Brown
    date:       19 April 1988
*/

#include <stdio.h>
#include <dos.h>

#define FAILED 1

char APPEND[] = "a",
     WRITE[] = "w";

void main(argc, argv)
int argc;
char *argv[];
{
    int c, i, n;
    FILE *fin, *fout = NULL;
    char *mode = APPEND;
    void printCliArgs(), errmsg();

/*  Check for minimum number of arguments. At minimum, one source file and
    one destination file must be given.
*/
    if (argc < 3)
    {
        printf("Usage: cat [-a/-o/-s \"string\"] [file1 [,file2...]] [to] file\n");
        exit(FAILED);
    }

/*  Check that the output file name does not begin with '-', which probably
    means that no output file was given.
*/
    if (argv[argc-1][0] == '-')
    {
        printf("Error in arguments.\n");
        exit(FAILED);
    }

/*  Test for key word 'to' and cause it to be ignored   */

    if ((c = tolower(argv[argc-2][0])) == 't' && 
        (c = tolower(argv[argc-2][1])) == 'o')
        n = 2;
    else n = 1;

/*  Repeat for all the remaining arguments  */

    for (i = 1; i < argc - n; i++)
    {
        if (argv[i][0] == '-')
            switch(tolower(argv[i][1]))
            {
                case 's':

/*  Check that some text follows the '-s' option. Note that all quote
    marks are stripped BEFORE being placed in the argument list. Therefore
    cannot test for VALID text (ie - text following '-s' COULD be a file
    spec or another argument. This text would be interpreted as plain
    text and appended to the end of the file. This check avoids the problem
    of having the output filename immediately follow the -s option.
*/
                    if (++i < argc - n)
                    {
                        if (fout == NULL)
                        /*  Open output file and exit on failure    */
                            if ((fout = fopen(argv[argc-1], mode)) == NULL)
                                errmsg(argv[argc-1]);

                        fprintf(fout, "%s\n", argv[i]);
                    }
                    else
                    {
                        printf("Error in arguments.\n");
                        exit(FAILED);
                    }
                    break;

/*  Note that once writing has begun, the following two options will be
    read and handled, but will not have any effect.
*/
                case 'a':   /* set mode to append   */
                    mode = APPEND;
                    break;

                case 'o':   /* set mode to overwrite    */
                    mode = WRITE;
                    break;
            }
        else
        {
            if ((fin = fopen(argv[i], "r")) == NULL)
                errmsg(argv[i]);

            if (fout == NULL)
            /*  Open output file and exit on failure    */
                if ((fout = fopen(argv[argc-1], mode)) == NULL)
                    errmsg(argv[argc-1]);

            while ((c = getc(fin)) != EOF)
                putc(c, fout);

            fclose(fin);
        }
    }

/*  check to see if output file was even opened */
    if (fout == NULL)
        printf("Nothing to do.\n");
    else
        fclose(fout);
}

void errmsg(s)
char *s;
{
    char eline[256];

    sprintf(eline,"Cannot open %s", s);
    (void)poserr(eline);
    exit(FAILED);
}
