/* * techrep.c SUIT based utility to adminster a techreport archive * * First version by Jerome Terry - May 92 * * Mods and bug fixes: * Removal of listrefs system call: * Mid October 92 - Dallas Wrege and Tongtong Zhang * Various permission problems: * 22 Oct 92 - CLV * Bug in abstract handling : * 13 Nov 92 - CLV * More permission problems : * 13 Nov 92 - CLV * Split into modules : * 5 Jan 93 - CLV * Note: I have made an attempt to split techrep.c into separate * files that make some sort of sense, and to call these files * modules. However, there is still a fair amount of depend- * ence between modules. * Upgrade to SUIT v 2.3 * March 93 - Dennis Cosgrove with some help from CLV. * * New look. * Copy utility. * Multiple document types for posting, viewing, printing. * Robust remote by negotiating with ftp server, rather than pipes to * ftp client. * Simple WAIS interface to WATERS. * Search Capability. * April/May 1993 - CLV. * * Computing Categories and keywords * July 1993 - CLV * * Added translation routines using Mapfile instead of dir contents. * (see xlate.c&h, maplist.c&h) * * Added subdirectories for posting (see below and post.c). * October 1993 - CLV * * - Changed abstract checking from use of 'file' command * to a simple check for legal ASCII characters. (see post.c & sitespec.c) * - Deleted blank lines from abstract. (see post.c) * November 1993 CLV * Took SUIT out and implemented a command line interaction * - All browser functionality gutted (WWW browsers do better) * - Command line interface only * November 1994 - Jon Gabel * Various code clean-up * September 1995 - CLV * * Fixed return/exit brokenness * Fixed some close(FILE*) * Made it compile (almost) clean with gcc -Wall * September 1995 - Davin Milun * */ #include #include #include #include #include #include #include #include #include #include #include #include "techrep.h" #include "util.h" #include "com-util.h" #include "citation.h" #include "make_readme.h" #include "sitespec.h" #define N_ARGS 10 /* maximum number of args to exec'ed process */ void initMisc (int argc, char **argv); void delete_cit (char *trNumToDelete); void read_cit (); void no_citation_database(); char *findTechnicalReport (char *trId); int handle_post (CitationPtr newCit, char *trLocation); int handle_get (char *temp_filename); int handle_update (CitationPtr newCit, char *trLocation); int handle_delete (CitationPtr newCit); int handle_get_all (char *temp_filename); int handle_bulk_load(); void error_log (char *errormessage); CitationPtr lookup_trnum (char *trId); CitationPtr verifyArgs (char *filename, char *subDir); void usage (); /************************************************************************ * External Functions... * ************************************************************************/ int main(int argc, char *argv[], char *envp) { CitationPtr newCit; initEnvironment(); /* reads all site specific env variables */ initMisc (argc, argv); if (argc < 2) { usage(); error_log("bad command line"); exit(BAD_CMD_LINE); } if (strcmp (argv[1], "-b") != 0) { newCit = verifyArgs (argv[2], argv[3]); if (!newCit) { error_log ("Citation file or TR file not found or unreadable"); exit (DOC_DOES_NOT_EXIST); } } if (argv[1][1] == 'p') { return handle_post(newCit, argv[3]); } else if (argv[1][1] == 'g') { return handle_get(argv[2]); } else if (argv[1][1] == 'u') { return handle_update(newCit, argv[3]); } else if (argv[1][1] == 'd') { return handle_delete(newCit); } else if (argv[1][1] == 'b') { return handle_bulk_load(); } else if (argv[1][1] == 'a') { return handle_get_all(argv[2]); } else { usage(); error_log("bad first argument"); exit(BAD_CMD_LINE); } return 0; } void initMisc (int argc, char **argv) { /* saves big trouble later */ umask(022); } int handle_get_all(char *temp_filename) { fileCopy (temp_filename, getCitationDataFilePath(), 0644); return 0; } int handle_bulk_load() { CitationPtr C; FILE *citation_fp; /* open for reading */ if ((citation_fp = fopen(getCitationDataFilePath(), "r")) == NULL) { no_citation_database(); error_log( "get: no cit-dbase so TR not found"); return(DOC_DOES_NOT_EXIST); } while ((C = read_one_citation(citation_fp)) != NULL) { if (!C->trId) { fprintf (stderr, "Problem with Bulk Load - No report number\n"); return (1); } if (!C->title) { fprintf (stderr, "Problem with Bulk Load - No title\n"); return (1); } if (!C->author) { fprintf (stderr, "Problem with Bulk Load - No author\n"); return (1); } if (!C->date) { fprintf (stderr, "Problem with Bulk Load - No date\n"); return (1); } if (!C->modified) { C->modified = rfc1123date(); } write_one_citation(stdout, C); } fclose (citation_fp); update_readme(); return 0; } /* Note: trLocation is a subdirectory relative to the reports directory. It should be NULL if the TR is placed at top level. */ int handle_post (CitationPtr newCit, char *trLoc) { int answer, is_compressed; FILE *cit_dbase_fp; CitationPtr tr_exists; char *trId, fname[STRING_SIZE], url[STRING_SIZE]; char copy_filename[STRING_SIZE]; char command[STRING_SIZE]; char newDocFileName[STRING_SIZE]; char *fextention,*fnameonly,*all_extentions; char trLocation[STRING_SIZE]; /* makes trLocation a null string if it is a null pointer */ if (!trLoc) { strcpy(trLocation, ""); } else { strcpy(trLocation, trLoc); /* otherwise, makes sure trLocation ends in a slash */ if (trLocation[strlen(trLocation)-1] != '/') { strcat (trLocation, "/"); } } trId=getTrId(newCit); if (get_semaphore(getSemaphoreFilePath()) == ERROR) { error_log("You have been denied exclusive access to the citation data base. Please try your operation again.\n"); return(ACCESS_DENIED); } tr_exists=lookup_trnum(trId); if (tr_exists) { free (tr_exists); error_log("TR already exists\n"); fprintf (stderr, "%s already exists so cannot be post-ed. Try update.\n", trId); release_semaphore(getSemaphoreFilePath()); return(DOC_EXISTS); } /* * Build filename for Citation database */ strcpy(fname, getCitationDataFilePath()); if ((cit_dbase_fp = fopen(fname, "a")) == NULL) { /* open file */ release_semaphore(getSemaphoreFilePath()); error_log("no citation database creating one..."); no_citation_database(); } /* * if copying file create url and add to cit dbase */ if (newCit->url) { strcpy (copy_filename, newCit->url); fextention = strrchr(copy_filename,'.'); fnameonly = strrchr(copy_filename,'/'); if (fnameonly ==NULL) { fnameonly=copy_filename; } else { fnameonly++; /* gets rid of slash, don't have to do this really */ } all_extentions = strchr(fnameonly,'.'); if (all_extentions == NULL) { all_extentions = strdup(""); } is_compressed=FALSE; if (fextention != NULL) { if ((strcmp(fextention,".tiff") == 0) || (strcmp(fextention,".TIFF") == 0) || (strcmp(fextention,".Z") == 0) || (strcmp(fextention,".z") == 0) || (strcmp(fextention,".gz") == 0) || (strcmp(fextention,".GZ") == 0) ) { is_compressed=TRUE; } } /* * Compress and move file to reports directory */ sprintf(newDocFileName, "%s", getReportDirectoryPath()); strcat(newDocFileName, trLocation); strcat(newDocFileName, trId); strcat(newDocFileName, all_extentions); if( fileCopy(newDocFileName, copy_filename, 0644) == -1 ) { release_semaphore(getSemaphoreFilePath()); error_log("Unable to copy and compress file"); return( FILE_NOT_COPIED ); } if (is_compressed==FALSE) { /* compress if not already */ sprintf(command, "%s -f %s", getCompressPath(), newDocFileName); system(command); /* this assumes compression will add a .Z */ sprintf(url, "%s%s%s%s.Z", getUrlPrefix(), trLocation, trId, all_extentions); } else { sprintf(url, "%s%s%s%s", getUrlPrefix(), trLocation, trId, all_extentions); } newCit->url = strdup(url); } newCit->modified = rfc1123date(); write_one_citation (cit_dbase_fp, newCit); freeCitation(newCit); fclose(cit_dbase_fp); release_semaphore(getSemaphoreFilePath()); /* * Update the Index file in the reports directory. */ if ((answer = update_readme()) == NO_README) { error_log("Could not open README file. This is normal if no documents have been posted or the README file has been deleted."); } else if (answer == NO_TMP_README) { error_log("Could not open temporary README file."); } free(trLocation); return 0; } int handle_get(char *temp_filename) { FILE *temp_fp, *citation_fp; CitationPtr Cit,C; char *trId; /* open temp_filename file */ temp_fp = fopen(temp_filename, "r"); Cit = read_one_citation(temp_fp); fclose(temp_fp); trId=getTrId(Cit); if (get_semaphore(getSemaphoreFilePath()) == ERROR) { error_log("You have been denied exclusive access to the citation data base. Please try your operation again.\n"); return(ACCESS_DENIED); } /* open citation file */ if ((citation_fp = fopen(getCitationDataFilePath(), "r")) == NULL) { no_citation_database(); error_log( "get: no cit-dbase so TR not found"); release_semaphore(getSemaphoreFilePath()); return(DOC_DOES_NOT_EXIST); } while ((C = read_one_citation(citation_fp)) != NULL) { /* copy the citation to the tempfile */ if (strcmp(trId, getTrId(C)) == 0) { temp_fp = fopen(temp_filename, "w"); /* write cit-data to temp file */ write_one_citation (temp_fp, C); fclose(citation_fp); fclose(temp_fp); release_semaphore(getSemaphoreFilePath()); freeCitation (C); return 0; } freeCitation (C); } fclose(citation_fp); error_log("TR doesn't exist\n"); release_semaphore(getSemaphoreFilePath()); return(DOC_DOES_NOT_EXIST); } int handle_update (CitationPtr newCit, char *trLocation) { int retval; retval = handle_delete(newCit); if (retval != DOC_DOES_NOT_EXIST) { handle_post(newCit, trLocation); } return 0; } int handle_delete(CitationPtr newCit) { int result; char *trId, *url, *trLocation; FILE *citation_fp; CitationPtr Cit, tr_exists; char *StandardUrl; char fullname[STRING_SIZE]; /* Get a valid technical report number */ trId=getTrId(newCit); /* delete citation */ if (get_semaphore(getSemaphoreFilePath()) == ERROR) { error_log("You have been denied exclusive access to the citation data base. Please try your operation again."); return(ACCESS_DENIED); } /* open citation file */ if ((citation_fp = fopen(getCitationDataFilePath(), "r")) == NULL) { no_citation_database(); error_log("no cit dbase created one (in delete)"); return(DOC_DOES_NOT_EXIST); } /* Search for TR number */ tr_exists=NULL; while ((Cit = read_one_citation(citation_fp)) != NULL) { /* check to see if correct technical report */ if (strcmp(trId, getTrId(Cit)) == 0) { tr_exists = Cit; break; } } fclose(citation_fp); if (!tr_exists) { error_log("TR doesn't exist\n"); release_semaphore(getSemaphoreFilePath()); fprintf (stderr, "TR %s does not exist so cannot be deleted\n", trId); return(DOC_DOES_NOT_EXIST); } /* delete the file if it exists */ url = Cit->url; if (url != NULL) { StandardUrl = strdup(getUrlPrefix()); if (strncmp(StandardUrl,url,strlen(StandardUrl)) == 0) { trLocation = url+strlen(StandardUrl); strcpy (fullname,getReportDirectoryPath()); strcat(fullname,trLocation); unlink(fullname); } } /* remove citation from bib file */ delete_cit(trId); release_semaphore(getSemaphoreFilePath()); /* update index file */ if((result = update_readme()) == NO_README) { error_log("Could not open README file. This is normal if no documents have been posted or the README file has been deleted."); } else if (result == NO_TMP_README) { error_log("Could not open temporary README file."); } return 0; } /* * Checks to see if the requested trnum is there. */ CitationPtr lookup_trnum(char *trId) { FILE *citation_fp; CitationPtr C; /* open citation file */ if ((citation_fp = fopen(getCitationDataFilePath(), "r")) == NULL) { no_citation_database(); return(FALSE); } /* * Search for TR number */ while ((C = read_one_citation(citation_fp)) != NULL) { /* check to see if correct technical report */ if (strcmp(trId, getTrId(C)) == 0) { fclose(citation_fp); return (C); } freeCitation (C); } fclose(citation_fp); return (NULL); } void delete_cit(char *trId) { FILE *cit_dbase_fp; FILE *new_dbase_fp; char citFileName[STRING_SIZE]; char tmpCitFileName[STRING_SIZE]; CitationPtr C; sprintf(tmpCitFileName, "/tmp/%d-tmp-cit-dbase", (int)getpid()); if ((new_dbase_fp = fopen(tmpCitFileName, "w")) == NULL) { error_log("Can't open tmp citation DB"); return; } strcpy(citFileName, getCitationDataFilePath()); if ((cit_dbase_fp = fopen(citFileName, "r")) == NULL) { error_log("Can't open citation DB"); return; } /* printf ("Reading ...,"); fflush (stdout); */ while ((C = read_one_citation(cit_dbase_fp))) { /* printf ("Read %s,", getTrId(C)); fflush (stdout); */ if (strcmp (getTrId(C), trId)) { write_one_citation(new_dbase_fp, C); /* printf ("wrote %s\n", getTrId(C)); fflush (stdout); */ } } fclose (new_dbase_fp); fclose(cit_dbase_fp); fileCopy(citFileName, tmpCitFileName, 0644); unlink (tmpCitFileName); return; } void no_citation_database() { int f1; if ((f1 = creat(getCitationDataFilePath(), 0664)) == -1) error_log( "techrep:can`t create cit dbase\n"); close(f1); return; } void error_log(char *errormessage) { FILE *fp; char buf[1024]; time_t the_time; /* fprintf(stderr,"%s\n", errormessage);*/ the_time = time(0); strcpy(buf, ctime(&the_time)); fp = fopen(getErrorLogFile(),"a"); fprintf(fp,"\n----------------------------------\nCurrent time: %s",buf); fprintf(fp,"%s\n",errormessage); fclose(fp); } CitationPtr verifyArgs(char *filename, char *subDir) { CitationPtr C; FILE *fp; char trLocation[STRING_SIZE]; struct stat sbuf; /* Is the file there? */ if ((fp = fopen(filename, "r")) == NULL) { return NULL; } /* Check to make sure there is a citation there */ C = read_one_citation(fp); if (!C) { fclose (fp); return NULL; } fclose(fp); /* check url to make sure it's readable */ if (C->url) { /* printf ("%s\n", C->url); */ C->url = tilde_sub(C->url); /* printf ("%s\n", C->url); */ if ((fp = fopen(C->url, "r")) == NULL) { fprintf (stderr, "The TR file does not exist or is unreadable\n"); return NULL; } fclose (fp); } /* Finally, make sure the subdirectory exists */ if (subDir) { strcpy (trLocation, getReportDirectoryPath()); strcat (trLocation, subDir); if (stat(trLocation, &sbuf) == -1) { fprintf (stderr, "%s does not exist. You need to create it.\n", trLocation); return NULL; } } return C; } void usage() { fprintf(stderr, "Usage: techrep [-p|-g|-u|-d|-b] temp_filename [tr_location]\n"); fprintf(stderr, "\n"); fprintf(stderr, "'temp_filename' is a file that contains all of the citation \n"); fprintf(stderr, "information in it. This file is in refer format. For post \n"); fprintf(stderr, "and update, a minimal file should contain Author (%%A), \n"); fprintf(stderr, "Report ID (%%R), Title (%%T), Date (%%D), and the full path\n"); fprintf(stderr, "to the technical report (%%U). Omitting %%U means that only a\n"); fprintf(stderr, "citation for the report will be available. Optional fields \n"); fprintf(stderr, "are abstract (%%X), key words (%%K), and computing reviews \n"); fprintf(stderr, "categories (%%Y)\n"); fprintf(stderr, "\n"); fprintf(stderr, "For delete, 'temp_filename' only needs to contain the report ID\n"); fprintf(stderr, "\n"); fprintf(stderr, "'tr_location' is a subdirectory relative to the reports\n"); fprintf(stderr, "directory. Omit if you want the report at the root.\n"); fprintf(stderr, "The reports directory is located in\n\t%s\nfor this archive.\n", getReportDirectoryPath()); fprintf(stderr, "\n"); fprintf(stderr, "The -b option does not require a temp_filename. This option\n"); fprintf(stderr, "causes techrep to regenerate the README files. As a side effect,\n"); fprintf(stderr, "the bibliographic file is printed to stdout, with any\n"); fprintf(stderr, "citations previously without last-modified (%%Z) fields\n"); fprintf(stderr, "now containing them. The -b option is useful if you are\n"); fprintf(stderr, "going to add a bunch of citations directly to the biblio \n"); fprintf(stderr, "file and need the README files regenerated.\n"); }