/* _______________________________________________________________________ * * RDPARM/PTRAJ: APR 2000 * _______________________________________________________________________ * * $Header: /thr/gamow/cvsroot/amber7/src/ptraj/io.c,v 1.10 2000/08/08 23:04:11 cheatham Exp $ * * Revision: $Revision: 1.10 $ * Date: $Date: 2000/08/08 23:04:11 $ * Last checked in by $Author: cheatham $ * * This source is now archived under CVS at Scripps in the amber7 tree. * * NOTE: this is a beta, pre-release version, is under constant development, * probably contains some bugs and is under constant revision; therefore * take care. Please report bugs (and fixes!) to cheatham@chpc.utah.edu or * cheatham@cgl.ucsf.edu * * Do not distribute this code without explicit permission. * Do not incorporate into other codes without explicit permission. * * Current contact information: * * Thomas Cheatham, III * 2000 East, 30 South, Skaggs Hall 201 * Department of Medicinal Chemistry * University of Utah * Salt Lake City, UT 84112-5820 * cheatham@chpc.utah.edu * (801) 587-9653 * FAX: (801) 585-5366 * * Other contributors: * * David Case (Scripps) * Michael Crowley (Scripps) * Jed Pitera (UCSF) * Vickie Tsui (Scripps) * _______________________________________________________________________ */ #include #include #include #define IO_MODULE #include "ptraj.h" /* * This routine defines the subroutines used in rdparm/ptraj for * various program input and output. */ /* ----------------------------------------------------------------- SUBROUTINE DEFINITIONS: void doSystem(char *command) ...a wrapper for the system(command) call with no error checking FILE * safe_open(char *buffer, char *mode, int is_popen) ...a routine to open a file of name "buffer" with mode "mode". If "is_popen" is not zero, then the popen() command is called instead of fopen() with the "buffer" and "mode". This routine maintains a fileType list of associated "buffer", "mode", FILE and popen() status which is used to closing and/or reopening files. If the file has previously been opened and is maintained on the fileStack fileType list, then the file will be closed and reopened. Files opened with safe_open should be closed using safe_close(), safe_fclose() or safe_fclose_buffer() in order to clean up the fileStack. FILE * safe_freopen(FILE *file) ...reopen a previously "safe" opened file FILE * safe_fopen(char *buffer, char *mode) ...a wrapper to safe_open above that calls it with is_popen == 0 FILE * safe_popen(char *buffer, char *mode) ...a wrapper to safe_open above that calls it with is_popen == 1 int safe_close(FILE *closed, char *buffer) ...will close FILE "closed" and update the fileStack if necessary. If only the "buffer" is passed in (representing the file name or popen command), then the fileStack will be searched for the appropriate FILE to close. If the FILE "closed" or "buffer" is present in the fileStack, the proper pclose() or fclose() will be called, else fclose() is called. int safe_fclose(FILE *closed) ...a wrapper to safe_close for the FILE "closed" int safe_fclose_buffer(char *buffer) n...a wrapper to safe_close() for the buffer "buffer" promptToOpenFile(fpp, filename, mode, prompt) ... attempts to open filename with mode. If a failure occurs, the user is prompted (with prompt) and asked to input a new filename. This continues until a sucessful open occurs, where upon the file is returned in fpp. int openFile(fpp, filename, mode) ...attempts to open the "filename" with "mode" returning 1 is successful int promptUserResponse(fpin, fpout, response, min_to_match) ...writes ``prompt'' to fpout, fget()'ing a response from fpin. The default response is in ``response'', where ``min_to_match'' is the minimum number of characters to match. 1 is returned upon successful match, 0 otherwise. int safe_fclose(FILE *closed) ...uses pclose or fclose to close a file in order to smoothly terminate popen operationa... -------------------------------------------------------------------------*/ void doSystem(char *command) { system(command); } #ifdef DEBUG_IO void printFileStack() { stackType *stack; fileType *file; int i; for (stack = fileStack, i = 0; stack != NULL; i++) { file = (fileType *) stack->entry; fprintf(stderr, " printFileStack: file list (%x) entry %i is %x (%s)\n", stack, i+1, file->file, file->buffer); stack = stack->next; if ( stack == fileStack ) break; } } #endif fileType * is_open_file_buffer(char *buffer) { stackType *sp; fileType *file; if ( buffer == NULL ) return (NULL); if ( fileStack == NULL ) return (NULL); sp = fileStack; do { file = (fileType *) sp->entry; if ( strcmp(file->buffer, buffer) == 0 ) { #ifdef DEBUG_IO fprintf(stderr, "Buffer search (%x:%s) has previously been %s\n", file->file, file->buffer, (file->popen ? "popened" : "opened")); #endif return (file); } sp = sp->next; } while ( sp != fileStack ); return (NULL); } stackType * is_open_file_buffer_stack(char *buffer) { stackType *sp; fileType *file; if ( buffer == NULL ) return (NULL); if ( fileStack == NULL ) return (NULL); sp = fileStack; do { file = (fileType *) sp->entry; if ( strcmp(file->buffer, buffer) == 0 ) { return (sp); } sp = sp->next; } while ( sp != fileStack ); return (NULL); } fileType * is_open_file(FILE *f) { stackType *sp; fileType *file; if ( f == NULL ) return NULL; if ( fileStack == NULL ) return NULL; sp = fileStack; do { file = (fileType *) sp->entry; if ( file->file == f ) { #ifdef DEBUG_IO fprintf(stderr, "File search (%x:%s) has previously been %s\n", file->file, file->buffer, (file->popen ? "popened" : "opened")); #endif return (file); } sp = sp->next; } while ( sp != fileStack ); return (NULL); } stackType * is_open_file_stack(FILE *f) { stackType *sp; fileType *file; if ( f == NULL ) return NULL; if ( fileStack == NULL ) return NULL; sp = fileStack; do { file = (fileType *) sp->entry; if ( file->file == f ) { return (sp); } sp = sp->next; } while ( sp != fileStack ); return (NULL); } FILE * safe_open(char *buffer, char *mode, int is_popen) { stackType *tmpStack, *sp; fileType *file; FILE *fp; int length; /* check to make sure that the file is not already opened and * close it if it is... */ if ( is_open_file_buffer(buffer) != NULL ) safe_fclose_buffer(buffer); fp = NULL; if (is_popen) { fp = popen(buffer, mode); } else { fp = fopen(buffer, mode); } if ( fp != NULL) { /* * file opened successfully, therefore save file information... */ file = (fileType *) safe_malloc(sizeof(fileType)); file->popen = is_popen; length = sizeof(char) * (strlen(buffer) + 1); file->buffer = (char *) safe_malloc( length ); bcopy(buffer, file->buffer, (size_t) length); length = sizeof(char) * (strlen(mode) + 1); file->mode = (char *) safe_malloc( length ); bcopy(mode, file->mode, (size_t) length); file->file = fp; /* * create an entry for the fileStack and add it */ tmpStack = (stackType *) safe_malloc(sizeof(stackType)); tmpStack->entry = (void *) file; tmpStack->next = NULL; if (fileStack == NULL) { /* * fileStack hasn't been initialized yet, therefore this is * the first entry and we need to make the list circular! */ fileStack = tmpStack; fileStack->next = fileStack; } else { /* * fileStack exists, hence insert the current entry as the next * entry and make sure to reset the next entry to retain the * list integrity */ if (fileStack->next == fileStack) { fileStack->next = tmpStack; tmpStack->next = fileStack; } else { sp = fileStack->next; fileStack->next = tmpStack; tmpStack->next = sp; } } } #ifdef DEBUG_IO fprintf(stderr, "Returning (%x) from safe_open(%s, %s, %i), fileStack follows:\n", fp, buffer, mode, is_popen); printFileStack(); #endif return( fp ); } /* wrappers to the safe_open call */ FILE * safe_freopen(FILE *f) { fileType *file; FILE *returnFile; char *buffer; char *mode; returnFile = NULL; file = is_open_file(f); if ( file == NULL ) warning("safe_freopen()", "Attempting to reopen a file not in the fileStack!\n"); /* * the safe_open will close the already open file and * deallocate the pointers file->buffer and file->mode * therefore copies of these need to be passed in which * can be deallocated AFTER the safe_open call... */ buffer = safe_malloc(sizeof(char) * (strlen(file->buffer)+1)); strcpy(buffer, file->buffer); mode = safe_malloc(sizeof(char) * (strlen(file->mode)+1)); strcpy(mode, file->mode); returnFile = safe_open(buffer, mode, file->popen); safe_free(buffer); safe_free(mode); return( returnFile ); } FILE * safe_fopen(char *buffer, char *mode) { return( safe_open(buffer, mode, 0) ); } FILE * safe_popen(char *buffer, char *mode) { return( safe_open(buffer, mode, 1) ); } int safe_close(FILE *closed, char *buffer) { stackType *sp, *destroy; fileType *file; int return_value; destroy = NULL; #ifdef DEBUG_IO fprintf(stderr, "safe_close(%x, %s) ", closed, buffer); #endif if ( closed == (FILE *) NULL && buffer == (char *) NULL ) { warning("safe_close()", "Attempting to close a NULL FILE and buffer!\n"); return -1; } if ( fileStack != NULL ) { if ( buffer == NULL ) { /* search based on FILE entry */ destroy = is_open_file_stack(closed); } else { /* search based on buffer entry */ destroy = is_open_file_buffer_stack(buffer); } } /* * if the FILE or buffer is not in the fileStack, close it anyways * if it is a file, otherwise simply return... */ if ( destroy == NULL ) { #ifdef DEBUG_IO fprintf(stderr, "entry not found in fileStack\n"); #endif if ( closed ) return ( fclose( closed ) ); else return -1; } /* * destroy the current entry... */ file = (fileType *) destroy->entry; if ( file->popen ) { return_value = pclose(file->file); } else return_value = fclose(file->file); file->file = NULL; safe_free( (void *) file->buffer ); safe_free( (void *) file->mode ); if ( destroy == fileStack && destroy == fileStack->next ) { /* * if there is only one entry, set the fileStack to NULL */ fileStack = NULL; } else { /* * if there are multiple entries, find the one previous * to destroy in order to properly set the next entries */ for (sp = fileStack;;) { if (sp->next == destroy) break; sp = sp->next; } sp->next = destroy->next; if ( destroy == fileStack ) fileStack = destroy->next; } #ifdef DEBUG_IO fprintf(stderr, "destroyed (%x), fileStack:\n", destroy); printFileStack(); #endif safe_free( (void *) destroy ); return( return_value ); } /* wrappers to safe_close */ int safe_fclose(FILE *closed) { return ( safe_close(closed, (char *) NULL) ); } int safe_fclose_buffer(char *buffer) { return ( safe_close( (FILE *) NULL, buffer) ); } #define COMMAND_SIZE 100 /* Attempts to open filename with mode, returning the result in fpp. * If failure occurs, the prompt is printed to stdout and the user * is prompted on stdin to input another filename... * * WARNING: the return value contains the opened file name and * is allocated; it is the callers responsibility to free up the * memory... * */ char * promptToOpenFile(FILE **fpp, char *filename, char *mode, char *prompt) { char buffer[LINE_SIZE]; char bufferp[LINE_SIZE+COMMAND_SIZE]; char *filename_ret; char *is_compressed; int reqprompt = FALSE; /* copy the input filename into a buffer */ if ( strcpy(buffer, filename) == NULL ) error("openFile()", "strcpy failure\n"); /* enter a "return" terminated loop which loops until * the file is successfully opened. */ for (;;) { /* print out the prompt if necessary... */ is_compressed = NULL; while (strcmp(buffer, "") == 0 || buffer[0] == '\n' || reqprompt ) { printf("%s", prompt); fflush(stdout); if ( fgets(buffer, LINE_SIZE, stdin) == NULL ) error("openFile()", "fgets returned NULL\n"); *strchr(buffer, '\n') = (char) 0; reqprompt = FALSE; } /* * Check to see if the files is compressed or supposed to be * compressed by looking for the ".Z" or ".gz" extension. * If it is present, use popen to open up the file and * the appropriate utility (depending on reading or writing) * which should be in your path or you are hosed... */ if ( (is_compressed = strstr(buffer, ".Z")) != NULL && (is_compressed[2] == (char) 0 || isspace(is_compressed[2])) ) { /* * .Z found: implied compressed with "compress", read with "zcat" */ if (mode[0] == 'r') sprintf(bufferp, "zcat %s", buffer); else if (mode[0] == 'w') sprintf(bufferp, "compress > %s", buffer); else if (mode[0] == 'a') sprintf(bufferp, "compress >> %s", buffer); else is_compressed = NULL; if (is_compressed) { fprintf(stderr, "Detected a .Z appended to the file name, hence using\n"); fprintf(stderr, "popen to open file...\n%s\n", bufferp); if ( ( *fpp = safe_popen(bufferp, mode) ) == NULL ) { fprintf(stderr, "\nCould not open compressed file (%s) with mode (%s), %s\n", buffer, mode, "try again...\n"); reqprompt = TRUE; } } } else if ( (is_compressed = strstr(buffer, ".gz")) != NULL && (is_compressed[3] == (char) 0 || isspace(is_compressed[3])) ) { if (mode[0] == 'r') sprintf(bufferp, "gunzip -c %s", buffer); else if (mode[0] == 'w') sprintf(bufferp, "gzip > %s", buffer); else if (mode[0] == 'a') sprintf(bufferp, "gzip >> %s", buffer); else is_compressed = NULL; fprintf(stderr, "Detected a .gz appended to the file name, hence using\n"); fprintf(stderr, "popen to open file...\n%s\n", bufferp); if ( ( *fpp = safe_popen(bufferp, mode) ) == NULL ) { fprintf(stderr, "\nCould not open compressed file (%s) with mode (%s), %s\n", buffer, mode, "try again...\n"); reqprompt = TRUE; } } if (is_compressed == NULL) { /* * otherwise, try simply opening up the file */ if ( ( *fpp = safe_fopen(buffer, mode) ) == NULL ) { fprintf(stderr, "\nCould not open file (%s) with mode (%s), try again...\n", buffer, mode); reqprompt = TRUE; } } /* * if the file was successfully opened up, then print out * summary information otherwise we go back into the loop... */ if ( ! reqprompt ) { printf("Opened file %s with mode (%s)\n", buffer, mode); filename_ret = safe_malloc( sizeof( char ) * (strlen(buffer)+1) ); if ( strcpy(filename_ret, buffer) == NULL ) error("openFile()", "strcpy failure with %s\n", buffer); return( filename_ret ); } } } /* * Open file specified by filename with "mode" to the file pointer * fpp */ int openFile(FILE **fpp, char *filename, char *mode) { char *is_compressed; char buffer[BUFFER_SIZE]; /* * Check for NULL filename */ if ( strcmp(filename, "") == 0 || filename[0] == '\n' ) { fpp = NULL; return 0; } /* * Check to see if the file is compressed (or to be compressed) * by looking for the ".Z" or ".gz" extension. If it is present, * use popen to open up the file via the appropriate utility... * This assumes that "zcat" is in your path. */ is_compressed = NULL; if ( (is_compressed = strstr(filename, ".Z")) != NULL && (is_compressed[2] == (char) 0 || isspace(is_compressed[2])) ) { if (mode[0] == 'r') sprintf(buffer, "zcat %s", filename); else if (mode[0] == 'w') sprintf(buffer, "compress > %s", filename); else if (mode[0] == 'a') sprintf(buffer, "compress >> %s", filename); else is_compressed = NULL; } else if ( (is_compressed = strstr(filename, ".gz")) != NULL && (is_compressed[3] == (char) 0 || isspace(is_compressed[3])) ) if (mode[0] == 'r') sprintf(buffer, "gunzip -c %s", filename); else if (mode[0] == 'w') sprintf(buffer, "gzip > %s", filename); else if (mode[0] == 'a') sprintf(buffer, "gzip >> %s", filename); else is_compressed = NULL; if (is_compressed != NULL) { /* * trajectory is compressed, use popen() */ if (prnlev > 0) fprintf(stderr, "Opening compressed file: %s\n", buffer); if ( ( *fpp = safe_popen(buffer, mode) ) == NULL ) { fprintf(stderr, "\nCould not open compressed file (%s) with mode (%s)\n", buffer, mode); return 0; } } else { /* * trajectory is NOT compressed */ if ( ( *fpp = safe_fopen(filename, mode) ) == NULL ) { fprintf(stderr, "\nCould not open file (%s) with mode (%s)\n", filename, mode); return 0; } } return 1; } int promptUserResponse(FILE *fpin, FILE *fpout, char *prompt, char *response, int min_to_match) { char buffer[BUFFER_SIZE]; char *bufferp; fprintf(fpout, "%s", prompt); fflush(fpout); if ( fgets(buffer, BUFFER_SIZE, fpin) == NULL ) error("promptUserResponse()", "fgets returned NULL\n"); bufferp = buffer; skipWhitespace(bufferp); bufferp = toLowerCase(bufferp); if (strcmp(bufferp, "") == 0 || strncmp(bufferp, response, min_to_match) == 0) return 1; else return 0; } char * promptUser(FILE *fpin, FILE *fpout, char *prompt) { char buffer[BUFFER_SIZE]; char *bufferp; fprintf(fpout, "%s", prompt); fflush(fpout); if ( fgets(buffer, BUFFER_SIZE, fpin) == NULL ) error("promptUser()", "fgets returned NULL\n"); if (strcmp(buffer, "\n") == 0) return( (char *) NULL); bufferp = (char *) safe_malloc(sizeof(char) * (strlen(buffer)+1) ); strcpy(bufferp, buffer); return(bufferp); }