/* 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 | | ### TESTIT REVISION 5 DOS | | ### FILE filename )repeated for | )each file | | ### END */ #include /* for fprintf() etc */ #include /* for str...() */ #include /* 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 /* for printf() etc */ #include /* 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 /* for printf() etc */ #include /* 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 /* 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; }