/* testit.c - builds a mail file for test/assignment submission */
/*
        You should save this message as a text file, then compile it
        then use (i.e. run) it to prepare/package your work to submit
        your assignments.  You may compile it as one source file or
        you may split it into several sources, split at the "============="
        markers and then separately compile and link the modules.

        This is Revision #5.  A substantial amount of up-front checking has 
        been added to this program to give you immediate feedback if you 
        make an error in using it TESTIT.  It *MAY* save you mailing a 
        message file that will subsequently be rejected.

        If you have any questions about how it works, please ask them in
        class.
*/
/*
  USAGE: ... at the DOS PROMPT

  dos_prompt>      testit COURSE function filename [filename...]

    COURSE      : must have the format like:  ISYS291-50 or CENG303-51
    function    : matches the function or assignment you are sending
    filename(s) : should be lower case

  this creates a temporary file "TESTIT.TMP" which is in the format
  required to submit as a mail message for testing assignments

  Revision 5 adds some checking, sufficient to avoid the most common
  submission errors and warn the user immediately. However, NO CHECK is
  done involving the CONTENTS of the files you list to be submitted.

*/
/*
  HISTORY
  =======

  19960925  original - DOS program duplicates funtion of testit shell
            script used in Unix course
  19961003  REVISION 2 - checked number of parameters on command line
  19970120  REVISION 3 - inserted ### END to stop the inclusion of
            signatures and other e-mail rubbish on the end of the last
            submitted file
  19980118  REVISION 4 - rewrite without using system() ... Borland seems
            to have decided that system() is not, after all, an ANSI
            function ... problem is present in BORLAND C++ v4.52, possibly
            v5.0 (though previouse students have definitely used 5.0,
            apparently without problem.) TURBOC C++ is happy with Revision 3
  19980306  REVISION 5 - add sufficient checking to detect common mistakes
            made by the casual user, the one who does not read instructions
            or is not an ace typist.
*/
/*
        STRATEGY:

        pick off the arguments one at time, check that they make sense, read
        the necessary files and write the output in the appropriate format for
        the mail message as follows:

  |     Subject: testing <course_id> <function>
  |
  |     ### TESTIT REVISION 5 DOS
  |
  |     ### FILE filename     )repeated for
  |       <contents of file>  )each file
  |
  |     ### END
*/

#include <stdio.h>   /* for fprintf() etc */
#include <string.h>  /* for str...() */
#include <ctype.h>   /* for toupper() */

/* --- global data */
/* current list of allowed courses */
char* course_list[] =
      {
        "CENG303-50",
        "ISYS290-04",
        "ISYS290-06",
        "ISYS291-01",
        "ISYS291-50",
        ""              /* end_of_list marked by empty entry */
      };

/* --- function prototypes */
int   process_file  (char* filename, FILE* out);
int   errhndlr      (char err_type, int err_code, char* other_info);
int   is_in_list    (char* arg, char* list_name[]);

int main(int argc, char *argv[])
{
  int k = 0;                /* index/loop control */
  int err = 0;              /* error indicator, zero = NO ERRROR */
  char temp[81] = "\0";     /* temporary_use string */
  FILE *out = NULL;                   /* output file pointer */

  /* check number of arguments */
  if (argc < 4)   errhndlr('E', 1, "");

  /*--- if enough arguments, do some checking */
  /* check course id */
  if (strlen(argv[1]) != 10) errhndlr('E', 4, argv[1]);
  /* change to upper case */
  strcpy(temp, argv[1]);
  for (k = 0; temp[k] != '\0'; k++)
  {
    temp[k] = toupper(temp[k]);
  }
  k = is_in_list(temp, course_list);
  if (k == 0) errhndlr('E', 4, argv[1]);   /* report original */

  /* check function name */
  strcpy(temp, argv[2]);
  for (k = 0; temp[k] != '\0'; k++)
  {
    /*  function name should **NOT** have a period.
        existence of a period possibly indicates missing function
        ... the first filename is being tested as if it were the
        function name
    */
    if (temp[k] == '.') errhndlr('E', 5, argv[2]); /* report original */
  }

  /*--- open output file */
  out = fopen("TESTIT.TMP", "w");
  if (out == NULL) errhndlr('E', 3, "TESTIT.TMP");

  /* --- write Subject and version announcement lines */
  fprintf(out, "Subject: testing %s %s\n\n", argv[1], argv[2]);
  fprintf(out, "### TESTIT REVISION 5 DOS\n\n");

  /* --- process each filename in list */
  for (k = 3; k < argc; k++)
  {
    err = process_file(argv[k], out);
    if (err) errhndlr('E', err, argv[k]);
  }

  /*--------- wrap up -------*/
  fprintf(out, "\n### END\n");
  fclose(out);
  errhndlr ('I', 0,
        "**OK --- output file TESTIT.TMP is mailable **\n");
  return 0;
}

/* =========================================================== */
#include <stdio.h>    /* for printf() etc */
#include <string.h>   /* for str...() etc */

#define MAXLEN 1024

int process_file(char* filename, FILE* out)
{
  char temp[MAXLEN+1];  /* holds various input lines */
  int k = 0;            /* loop control */
  FILE *in = NULL;                /* input file pointer */

  in = fopen(filename, "r");    /* open current input file */
  if (in == NULL)  return 3;    /* file open error */

  /* pick off only the actual file name - lose directory and/or drive letter */
  strcpy(temp, filename);
  for (k = strlen(temp); k != 0; k--)
  {
    if ((temp[k-1] == '\\') || (temp[k-1] == '/') || (temp[k-1] == ':'))
      break;
  }
  fprintf(out, "  ### FILE %s\n", temp+k);

  /* read/copy inpupt file */
  fgets(temp, MAXLEN, in);   /* read (next) line from input file */
  while (!feof(in))
  {
    fprintf(out, "%s", temp);   /* write out current source line */
    fgets(temp, MAXLEN, in);   /* read (next) line from input file */
  }
  /* wrap up */
  if (temp[strlen(temp)-1] != '\n')
    fprintf(out,"%s\n", temp);
  fclose (in);  /* close current input file */
  return 0;
  }

/* =========================================================== */
#include <stdio.h>    /* for printf() etc */
#include <stdlib.h>   /* for exit()       */

char *msgs[] =
{
  /* 0 */ "%s\n",         /* message 0 is a generic message */
  /* 1 */ "USAGE IS: testit course_id function filename [filename...]%s\n",
  /* 2 */ "**** INVALID OUTPUT ---- DO NOT MAIL ****%s\n",
  /* 3 */ "Can't open file %s\n",
  /* 4 */ "Invalid course id, %s\n",
  /* 5 */ "Invalid, possibly missing, function name, %s\n",
  /* 6 */ "%s\n",
  /* 7 */ "%s\n"          /* future messages must contain ONE %s */
};

int errhndlr(char type, int err, char *extra_data)
{
  fprintf(stderr, "\n%c %d ", type, err);
  fprintf(stderr, msgs[err], extra_data);
  fprintf(stderr, "\n");
  if ((type == 'E') || (type == 'F'))
  {
    exit (err);                     /* abort if fatal error */
  }
  return err;                       /* otherwise return     */
}

/* =========================================================== */
#include <string.h>   /* for str...() etc */
int is_in_list( char* item, char* list[])
{
  /*
    searches for item in list
    returns 1 if item is present in list, returns 0 otherwise
    end of list is marked by and empty entry ( == "")
  */
  int k = 0;
  for (k = 0; strcmp(list[k],""); k++)
  {
    if (!strcmp(item, list[k])) return 1;
  }
  return 0;
}

