diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/vvcode/vmcms.c |
Initial commit
Diffstat (limited to 'support/vvcode/vmcms.c')
-rw-r--r-- | support/vvcode/vmcms.c | 1829 |
1 files changed, 1829 insertions, 0 deletions
diff --git a/support/vvcode/vmcms.c b/support/vvcode/vmcms.c new file mode 100644 index 0000000000..7db9c298c1 --- /dev/null +++ b/support/vvcode/vmcms.c @@ -0,0 +1,1829 @@ +/*- +****************************************************************************** +****************************************************************************** +** +** ARCHIVE HEADER INFORMATION +** +** @C-file{ +** FILENAME = "vmcms.c", +** VERSION = "1.00", +** DATE = "", +** TIME = "", +** +** AUTHOR = "Niel Kempson and Rainer Schoepf", +** ADDRESS = "25 Whitethorn Drive, Cheltenham, GL52 5LL, England", +** TELEPHONE = "+44-242 579105", +** EMAIL = "kempson@tex.ac.uk (Internet), +** schoepf@sc.ZIB-Berlin.de (Internet", +** +** SUPPORTED = "yes", +** ARCHIVED = "tex.ac.uk, ftp.tex.ac.uk", +** KEYWORDS = "VVcode", +** +** CODETABLE = "ISO/ASCII", +** CHECKSUM = "51492 1481 5732 57976", +** +** DOCSTRING = { This file is part of VVcode. +** } +** } +** +** MODULE CONTENTS +** +** apply_defaults - Apply default file name and extension to a +** full file specification if either of these +** components is missing. +** confirm_yesno - Display a message to the user and wait for a +** yes/no answer. +** examine_file - Examine a file and determine its key features, +** including mode, format, record length and +** timestamp. +** explain_error - Explain the reason for an error. +** f_open_in - Open a file for input using the appropriate +** mode, format etc for the file. +** f_open_out - Open a file for output using the appropriate +** mode, format etc for the file. +** file_exists - Determine whether a file exists. +** force_file_ext - Force the file extension of a full file +** specification to a specified value. +** is_a_file - Determine whether a file stream is connected +** to a real file rather than a character +** device, pipe etc. +** legal_filespec - Takes an arbitrary string which may a file +** specification from another operating system +** and manipulates it to produce a legal file +** specification for the current operating +** system. +** make_filespec - Construct a full file specification from +** component parts. +** prompt_for_string - Present a prompt string and accept a string +** from the user. +** read_bytes - Read bytes from a currently open file. +** read_line - Read a line from a currently open (text) file. +** read_record - Read a record from a currently open file. +** scan_cmd_line - [tbs] +** set_ftime - Set the timestamp of a file to a specified +** value. +** set_pipe_mode - Set the mode of a file stream connected to a +** pipe, character device, redirected +** stdin/stdout/stderr, in fact any non-file. +** split_file_spec - Split a full file specification into its +** component parts. +** tz_offset - Determine the offset of local time from +** Greenwich Mean Time (Coordinated Universal +** Time) at a specified date and time. +** user_message - Present a message to the user. +** vv_exit - Exit the program, returning the appropriate +** status to the operating system. +** write_bytes - Write bytes to a currently open file. +** write_record - Write a record to a currently open file. +** +** COPYRIGHT +** +** Copyright (c) 1991-1993 by Niel Kempson <kempson@tex.ac.uk> +** and Rainer Schoepf <schoepf@sc.ZIB-Berlin.de> +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 1, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** In other words, you are welcome to use, share and improve this +** program. You are forbidden to forbid anyone else to use, share +** and improve what you give them. Help stamp out software-hoarding! +** +** CHANGE LOG +** +****************************************************************************** +****************************************************************************** +*/ +static char rcsid[] = "$Id$"; + +/*- +**---------------------------------------------------------------------------- +** Standard include files +**---------------------------------------------------------------------------- +*/ +#include <stdio.h> +#define MAX_CMD 128 + + +/*- +**---------------------------------------------------------------------------- +** Include files +**---------------------------------------------------------------------------- +*/ +#include "checkos.h" +#include "machine.h" +#include "local.h" +#include "globals.h" +#include "specific.h" +#include "vvutils.h" + + + +/*- +**============================================================================ +** +** FUNCTION +** +** apply_defaults +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void apply_defaults (CONST char *default_name, + CONST char *default_ext, + char *full_spec) +#else /* NOT (ANSI_SYNTAX) */ + void apply_defaults (default_name, default_ext, + full_spec) + CONST char *default_name; + CONST char *default_ext; + char *full_spec; +#endif /* (ANSI_SYNTAX) */ +{ + char name[MAX_NAME + 1]; + char extension[MAX_EXT + 1]; + Int16 path_parts; + char postamble[MAX_POSTAMBLE + 1]; + + path_parts = split_file_spec (full_spec, NULL, name, extension, + postamble); + + + if (((path_parts & FS_NAME) == 0) && (default_name != NULL)) + { + strncpy (name, default_name, MAX_NAME); + } + + if (((path_parts & FS_EXTENSION) == 0) && (default_ext != NULL)) + { + strncpy (extension, default_ext, MAX_EXT); + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if ((path_parts & FS_POSTAMBLE) == 0) + { + strcpy (postamble, ".A"); + } + + make_file_spec (NULL, name, extension, postamble, full_spec); +} /* apply_defaults */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** confirm_yesno +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Boolean confirm_yesno (CONST char *confirm_str) +#else /* NOT (ANSI_SYNTAX) */ + Boolean confirm_yesno (confirm_str) + CONST char *confirm_str; +#endif /* (ANSI_SYNTAX) */ +{ + int answer; + + FPRINTF (stderr, "\n%s [Y/N]:\n", confirm_str); + + do + { + answer = getchar (); + + if (answer == EOF) + { + ERRORMSG ("EOF detected on standard input"); + + answer = 'N'; + } + else + { + answer = TOUPPER (answer); + } + } while (!((answer == 'N') || (answer == 'Y'))); + + return (answer == 'Y' ? TRUE : FALSE); +} /* confirm_yesno */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** examine_file +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#define EX_SAMPLE_SIZE 512 + +#if (ANSI_SYNTAX) + void examine_file (File_Info *ex_file) +#else /* NOT (ANSI_SYNTAX) */ + void examine_file (ex_file) + File_Info *ex_file; +#endif /* (ANSI_SYNTAX) */ +{ + char tmp_buffer[EX_SAMPLE_SIZE]; + FILE *file_ptr; + int bytes_read; + int i, j; + char cmd_string[MAX_CMD]; + char dummy[9]; + char c; + int status; + struct tm tms; + + /*- + **------------------------------------------------------------------------ + ** Initialize the File_Info structure before starting work. If the input + ** file is not a real file (i.e. a device or pipe), these are the values + ** that will be returned. + **------------------------------------------------------------------------ + */ + ex_file->mode = INV_MODE; + ex_file->format = INV_FORMAT; + ex_file->max_rec_len = INV_RECORD_LEN; + ex_file->lng_rec_len = INV_RECORD_LEN; + ex_file->mod_time = INV_TIMESTAMP; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + sprintf (cmd_string, "LISTFILE %s (NOHEADER DATE LIFO", + ex_file->file_spec); + + for (i = 0; cmd_string[i] != '\0'; i++) + { + if (cmd_string[i] == '.') { + cmd_string[i] = ' '; + } + else if (islower (cmd_string[i])) { + cmd_string[i] = toupper (cmd_string[i]); + } + } + + DEBUG_1 ("examine_file: passing command `%s' to VM", cmd_string); + + status = system (cmd_string); + + if (status != 0) { + ERRORMSG_1 ("error reading info for file `%s'", + ex_file->file_spec); + explain_error (); + return; + } + + for (i = 1; i <=3; i++) { + status = scanf ("%s", dummy); + + DEBUG_1 ("examine_file: item skipped: `%s'", dummy); + + if (status != 1) { + ERRORMSG_1 ("error parsing info for file `%s'", + ex_file->file_spec); + explain_error (); + return; + } + } + + status = scanf (" %c %d %d %d", &c, &(ex_file->lng_rec_len), &i, &j); + + DEBUG_2 ("examine_file: record format: %c, record_length: %d", + c, ex_file->lng_rec_len); + + DEBUG_2 ("examine_file: number of records: %d, number of blocks: %d", + i, j); + + if (status != 4) { + ERRORMSG_2 ("error parsing record info for file `%s', only %d items parsed", + ex_file->file_spec, status); + explain_error (); + return; + } + + ex_file->max_rec_len = ex_file->lng_rec_len; + + switch (c) { + + case 'V': + ex_file->format = FMT_VARIABLE; + break; + + case 'F': + ex_file->format = FMT_FIXED; + break; + + default: + ERRORMSG_2 ("file `%s' has an unsupported record format (%c)", + ex_file->file_spec, c); + explain_error (); + return; + } + + status = scanf ("%d/%d/%d %d:%d:%d", + &tms.tm_mon, &tms.tm_mday, &tms.tm_year, + &tms.tm_hour, &tms.tm_min, &tms.tm_sec); + + DEBUG_3 ("examine_file: date as parsed: %02d/%02d/%02d", + tms.tm_mon, tms.tm_mday, tms.tm_year); + + DEBUG_3 ("examine_file: time as parsed: %02d:%02d:%02d", + tms.tm_hour, tms.tm_min, tms.tm_sec); + + + if (status == 5) { + tms.tm_sec = 0; + } + else if (status != 6) { + ERRORMSG_1 ("error parsing time info for file `%s'", + ex_file->file_spec); + explain_error (); + return; + } + + tms.tm_mon--; + + ex_file->mod_time = make_time (&tms); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + ex_file->file_ptr = fopen (ex_file->file_spec, "rb"); + + if (file_ptr == (FILE *) NULL) { + ERRORMSG_1 ("couldn't examine (open) file `%s'", ex_file->file_spec); + explain_error (); + return; + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + + bytes_read = fread (tmp_buffer, sizeof (char), EX_SAMPLE_SIZE, + ex_file->file_ptr); + + ex_file->mode = MODE_TEXT; /* default */ + + for (i = 0; i < bytes_read - 1; i++) { + if (!isprint(tmp_buffer[i])) { + ex_file->mode = MODE_BINARY; + break; + } + } + f_close (ex_file); + ex_file->file_ptr = (FILE *) NULL; + +} /* examine_file */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** explain_error +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void explain_error (void) +#else /* NOT (ANSI_SYNTAX) */ + void explain_error () +#endif /* (ANSI_SYNTAX) */ +{ + INFOMSG_1 ("Error number: %ld", (long) errno); +} /* explain_error */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** f_open_in +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + FILE *f_open_in (File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + FILE *f_open_in (ip_file) + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + FILE *file_ptr; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + +/* if ((ip_file->rec_length < MIN_RECORD_LEN) || (ip_file->rec_length > MAX_RECORD_LEN)) { + FATALMSG_1 ("invalid record length specified `%d'", ip_file->rec_length); + vv_exit (G_status); + }*/ + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + switch (ip_file->mode) { + case MODE_BINARY: + file_ptr = fopen (ip_file->file_spec, "rb"); + break; + case MODE_TEXT: + file_ptr = fopen (ip_file->file_spec, "r"); + break; + default: + ERRORMSG_1 ("invalid file mode specified (%d)", ip_file->mode); + return ((FILE *) NULL); + } + + if (file_ptr == (FILE *) NULL) { + ERRORMSG_1 ("error opening file `%s' for input", ip_file->file_spec); + explain_error (); + return ((FILE *) NULL); + } + return (file_ptr); +} /* f_open_in */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** f_open_out +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + FILE *f_open_out (CONST Int16 overwrite_files, + File_Info *op_file) +#else /* NOT (ANSI_SYNTAX) */ + FILE *f_open_out (overwrite_files, op_file) + CONST Int16 overwrite_files; + File_Info *op_file; +#endif /* (ANSI_SYNTAX) */ +{ + FILE *file_ptr; + char tmp_buffer[512]; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if ((overwrite_files != OVERWRITE_YES) + && (file_exists (op_file->file_spec))) + { + if (overwrite_files == OVERWRITE_ASK) { + SPRINTF (G_tmp_msg, "File `%s' exists. Overwrite ?", + op_file->file_spec); + + if (!confirm_yesno (G_tmp_msg)) + { + ERRORMSG ("operation cancelled"); + return ((FILE *) NULL); + } + } + else + { + ERRORMSG_1 ("file `%s' exists", op_file->file_spec); + return ((FILE *) NULL); + } + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + + + if (op_file->format == FMT_VARIABLE ) { + if (op_file->max_rec_len == INV_RECORD_LEN) { + op_file->max_rec_len = op_file->lng_rec_len = DEF_VARIABLE_RECORD_LEN; + } else if ((op_file->max_rec_len < MIN_VARIABLE_RECORD_LEN) || + (op_file->max_rec_len > MAX_VARIABLE_RECORD_LEN)) { + WARNMSG_1 ("invalid record length specified `%d'", op_file->max_rec_len); + WARNMSG_1 ("using default (%d) instead", DEF_VARIABLE_RECORD_LEN); + op_file->max_rec_len = op_file->lng_rec_len = DEF_VARIABLE_RECORD_LEN; + } + + sprintf (tmp_buffer, "%s, RECFM=V", + op_file->mode == MODE_BINARY ? "wb" : "w"); + + } else if (op_file->format == FMT_FIXED ) { + if (op_file->max_rec_len == INV_RECORD_LEN) { + op_file->max_rec_len = op_file->lng_rec_len = DEF_FIXED_RECORD_LEN; + } else if ((op_file->max_rec_len < MIN_FIXED_RECORD_LEN) || + (op_file->max_rec_len > MAX_FIXED_RECORD_LEN)) { + WARNMSG_1 ("invalid record length specified `%d'", op_file->max_rec_len); + WARNMSG_1 ("using default (%d) instead", DEF_FIXED_RECORD_LEN); + op_file->max_rec_len = op_file->lng_rec_len = DEF_FIXED_RECORD_LEN; + } + + sprintf (tmp_buffer, "%s, RECFM=F, LRECL=%d", + op_file->mode == MODE_BINARY ? "wb" : "w", + op_file->lng_rec_len); + } + + DEBUG_2 ("f_open_out: going to open file `%s' with specification `%s'", + op_file->file_spec, tmp_buffer); + + file_ptr = fopen (op_file->file_spec, tmp_buffer); + + if (file_ptr == (FILE *) NULL) + { + ERRORMSG_1 ("error opening file `%s' for output", op_file->file_spec); + explain_error (); + return ((FILE *) NULL); + } + return (file_ptr); +} /* f_open_out */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** file_exists +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Boolean file_exists (CONST char *file_spec) +#else /* NOT (ANSI_SYNTAX) */ + Boolean file_exists (file_spec) + CONST char *file_spec; +#endif /* (ANSI_SYNTAX) */ +{ + FILE *fp; + int result; + + fp = fopen (file_spec, "r"); + + DEBUG_2 ("file_exists: trial open of file `%s' in \"r\" mode returns file pointer `%lx'", + file_spec, (long) fp); + + result = (fp != (FILE *) NULL); + + DEBUG_1 ("file_exists: result = %d", result); + + fclose (fp); + + return (result); +} /* file_exists */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** force_file_ext +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void force_file_ext (CONST char *forced_ext, + char *full_spec) +#else /* NOT (ANSI_SYNTAX) */ + void force_file_ext (forced_ext, full_spec) + CONST char *forced_ext; + char *full_spec; +#endif /* (ANSI_SYNTAX) */ +{ + char name[MAX_NAME + 1]; + char postamble[MAX_POSTAMBLE + 1]; + + if (forced_ext == NULL) + { + return; + } + (void) split_file_spec (full_spec, NULL, name, NULL, postamble); + make_file_spec (NULL, name, forced_ext, postamble, full_spec); +} /* force_file_ext */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** is_a_file +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Boolean is_a_file (CONST File_Info *ex_file) +#else /* NOT (ANSI_SYNTAX) */ + Boolean is_a_file (ex_file) + CONST File_Info *ex_file; +#endif /* (ANSI_SYNTAX) */ +{ + return (TRUE); +} /* is_a_file */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** legal_filespec +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + char *legal_filespec (CONST char *hdrf_spec) +#else /* NOT (ANSI_SYNTAX) */ + char *legal_filespec (hdrf_spec) + CONST char *hdrf_spec; +#endif /* (ANSI_SYNTAX) */ +{ + char tmpf_name[MAX_NAME + 1]; + char tmpf_ext[MAX_EXT + 1]; + char *tmpf_spec; + char *tmp_ptr; + static char opf_spec[MAX_PATH + 1]; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + tmpf_spec = STRDUP (hdrf_spec); + tmp_ptr = strchr (tmpf_spec, '.'); + + if (tmp_ptr != NULL) { + strncpy (tmpf_ext, tmp_ptr, MAX_EXT); + tmpf_ext[MAX_EXT] = '\0'; + *tmp_ptr = '\0'; + } + else { + strcpy (tmpf_ext, ""); + } + strncpy (tmpf_name, tmpf_spec, MAX_NAME); + tmpf_name[MAX_NAME] = '\0'; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + for (tmp_ptr = tmpf_name; *tmp_ptr != '\0'; tmp_ptr++) + { + if (strchr (LEGAL_FILESPEC_CHARS, *tmp_ptr) == NULL) + { + *tmp_ptr = REPLACEMENT_FILESPEC_CHAR; + } + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + for (tmp_ptr = tmpf_ext + 1; *tmp_ptr != '\0'; tmp_ptr++) + { + if (strchr (LEGAL_FILESPEC_CHARS, *tmp_ptr) == NULL) + { + *tmp_ptr = REPLACEMENT_FILESPEC_CHAR; + } + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + strcpy (opf_spec, tmpf_name); + strcat (opf_spec, tmpf_ext); + + if (strcmp (hdrf_spec, opf_spec) != 0) { + WARNMSG_2 ("suspicious header file spec `%s' changed to `%s'", + hdrf_spec, opf_spec); + } + return (opf_spec); +} /* legal_filespec */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** make_file_spec +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void make_file_spec (CONST char *preamble, + CONST char *name, + CONST char *extension, + CONST char *postamble, + char *full_spec) +#else /* NOT (ANSI_SYNTAX) */ + void make_file_spec (preamble, name, extension, + postamble, full_spec) + CONST char *preamble; + CONST char *name; + CONST char *extension; + CONST char *postamble; + char *full_spec; +#endif /* (ANSI_SYNTAX) */ +{ + int len; + char *tmp_ptr; + + /*- + **------------------------------------------------------------------------ + ** Start with an empty string and append components of the file + ** specification only if they exist. + **------------------------------------------------------------------------ + */ + strcpy (full_spec, ""); + + /*- + **------------------------------------------------------------------------ + ** VM/CMS has no preamble component. + **------------------------------------------------------------------------ + */ + + + /*- + **------------------------------------------------------------------------ + ** Simply append the name if it is present. + **------------------------------------------------------------------------ + */ + if (name != NULL) + { + strncat (full_spec, name, MAX_NAME); + } + + /*- + **------------------------------------------------------------------------ + ** If the extension component does not begin with '.', prepend '.' before + ** appending the extension to the file specification. + **------------------------------------------------------------------------ + */ + if ((extension != NULL) && (*extension != '\0')) + { + if (*extension != '.') + { + strcat (full_spec, "."); + strncat (full_spec, extension, MAX_EXT - 1); + } + else + { + strncat (full_spec, extension, MAX_EXT); + } + } + + /*- + **------------------------------------------------------------------------ + ** If the postamble component does not begin with '.', prepend '.' before + ** appending the extension to the file specification. + **------------------------------------------------------------------------ + */ + if ((postamble != NULL) && (*postamble != '\0')) + { + if (*postamble != '.') + { + strcat (full_spec, "."); + strncat (full_spec, postamble, MAX_POSTAMBLE - 1); + } + else + { + strncat (full_spec, postamble, MAX_POSTAMBLE); + } + } +} /* make_file_spec */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** prompt_for_string +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void prompt_for_string (CONST char *confirm_str, + CONST Int16 buf_size, + char *return_buffer) +#else /* NOT (ANSI_SYNTAX) */ + void prompt_for_string (confirm_str, buf_size, + return_buffer) + CONST char *confirm_str; + CONST Int16 buf_size; + char *return_buffer; +#endif /* (ANSI_SYNTAX) */ +{ + char *status; + + FPRINTF (stderr, "\n%s", confirm_str); + status = fgets (return_buffer, (int) buf_size, stdin); + + if (status == NULL) + { + FATALMSG ("error reading string from stdin"); + explain_error (); + vv_exit (); + } + + status = STRCHR (return_buffer, '\n'); + if (status != NULL) + { + *status = '\0'; + } +} /* prompt_for_string */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** read_bytes +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Int32 read_bytes (CONST Int32 max_bytes, + char *buffer, + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + Int32 read_bytes (max_bytes, buffer, ip_file) + CONST Int32 max_bytes; + char *buffer; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + Int32 idx; + int temp; + + for (idx = 0L; idx < max_bytes; idx++) + { + temp = fgetc (ip_file->file_ptr); + if (temp == EOF) + { + return (idx); + } + buffer[(SIZE_T) idx] = (char) temp; + } + return (idx); +} /* read_bytes */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** read_line +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Int32 read_line (CONST Int32 max_bytes, + char *buffer, + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + Int32 read_line (max_bytes, buffer, ip_file) + CONST Int32 max_bytes; + char *buffer; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + char *tmp_ptr; + + tmp_ptr = fgets (buffer, (int) max_bytes, ip_file->file_ptr); + buffer[(SIZE_T) (max_bytes - 1)] = '\0'; + + if (tmp_ptr == NULL) + { + return (-1); + } + else + { + return ((Int32) strlen (buffer)); + } +} /* read_line */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** read_record +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Int32 read_record (CONST Int32 max_bytes, + char *buffer, + File_Info *ip_file) +#else /* NOT (ANSI_SYNTAX) */ + Int32 read_record (max_bytes, buffer, ip_file) + CONST Int32 max_bytes; + char *buffer; + File_Info *ip_file; +#endif /* (ANSI_SYNTAX) */ +{ + int i; + int c; + char *s; + + DEBUG_1 ("read_record: want to read record of with maximum size %d", + max_bytes); + + if (ip_file->mode == MODE_TEXT) { + s = fgets (buffer, max_bytes, ip_file->file_ptr); + + if (s == (char *) NULL) { + return (-1L); + } + + i = strlen (s); + } + else { + + if (feof (ip_file->file_ptr)) { + return (-1); + } + for (i = 0; i < max_bytes; i++) { + c = getc (ip_file->file_ptr); + if (c == EOF) { + break; + } + else { + buffer[i] = c; + } + } + } + + DEBUG_1 ("read_record: record with %d bytes read", i); + + return (i); +} /* read_record */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** scan_cmd_line +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void scan_cmd_line (CONST int qargc, + CONST char *qargv[], + CONST char *q_intro_str, + CONST char *q_sep_str, + Qualifier_Struct *qual_array, + Qualifier_Struct *qual_ipfile, + Qualifier_Struct *qual_opfile) +#else /* NOT (ANSI_SYNTAX) */ + void scan_cmd_line (qargc, qargv, q_intro_str, + q_sep_str, qual_array, qual_ipfile, + qual_opfile) + CONST int qargc; + CONST char *qargv[]; + CONST char *q_intro_str; + CONST char *q_sep_str; + Qualifier_Struct *qual_array; + Qualifier_Struct *qual_ipfile; + Qualifier_Struct *qual_opfile; +#endif /* (ANSI_SYNTAX) */ +{ + char *arg; + int arg_no; + int len; + int qual_found; + int q_no; + char *qsep_ptr; + char *qvalue_ptr; + char *tmp_qstr_ptr; + int paren_seen = 0; + char *file_specs[6]; + int i; + char tmp_buffer[512]; + + + /*- + **------------------------------------------------------------------------ + ** Initialize file spec array + **------------------------------------------------------------------------ + */ + + for (i = 0; i < 6; i++) { + file_specs[i] = NULL; + } + + /*- + **------------------------------------------------------------------------ + ** Loop through each of the user supplied command line arguments. + **------------------------------------------------------------------------ + */ + for (arg_no = 1; arg_no < qargc; arg_no++) { + arg = (char *) qargv[arg_no]; + + if (arg[0] == '(') { + paren_seen = 1; + break; + } + else if (arg_no > 6) { + USAGE ("too many arguments"); + } + else { + file_specs[arg_no - 1] = STRDUP (arg); + } + } + + if (arg_no == 1) { + USAGE ("too few arguments"); + } + + /* arg_no is now the first option argument */ + + strcpy (tmp_buffer, file_specs[0]); + if (arg_no > 2) { + strcat (tmp_buffer, "."); + strcat (tmp_buffer, file_specs[1]); + + if (arg_no > 3) { + strcat (tmp_buffer, "."); + strcat (tmp_buffer, file_specs[2]); + } + } + + for (i = 0; tmp_buffer[i] != '\0'; i++) { + if (islower (tmp_buffer[i])) { + tmp_buffer[i] = toupper (tmp_buffer[i]); + } + } + + qual_ipfile->present = TRUE; + qual_ipfile->value = STRDUP (tmp_buffer); + + if (arg_no > 4) { + if (strcmp (file_specs[3], "=") == 0) { + file_specs[3] = file_specs[0]; + } + strcpy (tmp_buffer, file_specs[3]); + if (arg_no > 5) { + if (strcmp (file_specs[4], "=") == 0) { + file_specs[4] = file_specs[1]; + } + strcat (tmp_buffer, "."); + strcat (tmp_buffer, file_specs[4]); + + if (arg_no > 6) { + if (strcmp (file_specs[5], "=") == 0) { + file_specs[5] = file_specs[2]; + } + strcat (tmp_buffer, "."); + strcat (tmp_buffer, file_specs[5]); + } + } + + for (i = 0; tmp_buffer[i] != '\0'; i++) { + if (islower (tmp_buffer[i])) { + tmp_buffer[i] = toupper (tmp_buffer[i]); + } + } + + qual_opfile->present = TRUE; + qual_opfile->value = STRDUP (tmp_buffer); + } + + for (; arg_no < qargc; arg_no++) { + arg = (char *) qargv[arg_no]; + + /*- + **-------------------------------------------------------------------- + ** + **-------------------------------------------------------------------- + */ + + DEBUG_1 ("scan_cmd_line: command line argument: `%s'", arg); + + if (*arg == '(') { + if (arg[1] == '\0') { + continue; + } + + ++arg; + + } + + /*- + **---------------------------------------------------------------- + ** Extract the component of the qualifier string before the + ** 'q_sep_str' character if it is present. + **---------------------------------------------------------------- + */ + tmp_qstr_ptr = STRDUP (arg); + qsep_ptr = STRSTR (tmp_qstr_ptr, q_sep_str); + qvalue_ptr = NULL; + + if (qsep_ptr != NULL) { + *qsep_ptr = '\0'; + qvalue_ptr = qsep_ptr + 1; + } + + /*- + **---------------------------------------------------------------- + ** Search the command qualifier structure array for this + ** qualifier string. + **---------------------------------------------------------------- + */ + len = strlen (tmp_qstr_ptr); + qual_found = -1; + + for (q_no = 0; qual_array[q_no].q_string != NULL; q_no++) { + + if (STRNCMPI (qual_array[q_no].q_string, tmp_qstr_ptr, len) == 0) { + + /*- + **-------------------------------------------------------- + ** + **-------------------------------------------------------- + */ + if (qual_found < 0) { + qual_found = q_no; + DEBUG_1 ("scan_cmd_line: matches option: `%s'", + qual_array[q_no].q_string); + } + else { + USAGE_1 ("ambiguous option `%s'", qargv[arg_no]); + } + } + } + + /*- + **---------------------------------------------------------------- + ** If the option string is unknown, return that status. + **---------------------------------------------------------------- + */ + if (qual_found < 0) { + USAGE_1 ("unknown option `%s'", qargv[arg_no]); + } + + /*- + **---------------------------------------------------------------- + ** + **---------------------------------------------------------------- + */ + if (qsep_ptr == NULL) { + if (qual_array[qual_found].val_needed == VALUE_NONE) { + qual_array[qual_found].present = TRUE; + qual_array[qual_found].value = NULL; + + if (qual_found == CMDQ_DEBUG) { + G_debugging = TRUE; + } + + continue; + } + else { + + /*- + **-------------------------------------------------------- + ** + **-------------------------------------------------------- + */ + if (((arg_no + 1) < qargc) && + (STRCHR (QUAL_INTRO, *qargv[arg_no + 1]) == NULL)) { + + /*- + **---------------------------------------------------- + ** + **---------------------------------------------------- + */ + qual_array[qual_found].present = TRUE; + qual_array[qual_found].value = STRDUP (qargv[++arg_no]); + DEBUG_1 ("scan_cmd_line: option value: `%s'", qargv[arg_no]); + } + else { + /*- + **---------------------------------------------------- + ** + **---------------------------------------------------- + */ + if (qual_array[qual_found].val_needed == VALUE_NEEDED) { + USAGE_2 ("option `%.1s%s' needs a value", + QUAL_INTRO, + qual_array[qual_found].q_string); + } + else { + qual_array[qual_found].present = TRUE; + qual_array[qual_found].value = NULL; + } + } + continue; + } + } + else { + /*- + **------------------------------------------------------------ + ** + **------------------------------------------------------------ + */ + if (*qvalue_ptr == '\0') { + USAGE_1 ("value missing for option `%.1s%s'", + qargv[arg_no]); + } + else if (qual_array[qual_found].val_needed == VALUE_NONE) { + USAGE_2 ("option `%.1s%s' does not take a value", + QUAL_INTRO, qual_array[qual_found].q_string); + } + else { + qual_array[qual_found].present = TRUE; + qual_array[qual_found].value = STRDUP (qvalue_ptr); + DEBUG_1 ("scan_cmd_line: option value: `%s'", + qual_array[qual_found].value); + continue; + } + } + } +} /* scan_cmd_line */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** set_ftime +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_ftime (File_Info *target_file) +#else /* NOT (ANSI_SYNTAX) */ + void set_ftime (target_file) + File_Info *target_file; +#endif /* (ANSI_SYNTAX) */ +{ + int status; + int i; + struct tm *tms; + char cmd_string[MAX_CMD]; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + DEBUG_2 ("set_ftime: setting file `%s' time to %s", + target_file->file_spec, ctime (&(target_file->mod_time))); + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + tms = localtime (&(target_file->mod_time)); + sprintf (cmd_string, "EXEC TOUCH %s (%02d/%02d/%02d %02d:%02d:%02d)", + target_file->file_spec, + tms->tm_mon + 1, tms->tm_mday, tms->tm_year, + tms->tm_hour, tms->tm_min, tms->tm_sec); + + for (i = 0; cmd_string[i] != '\0'; i++) + { + if (cmd_string[i] == '.') { + cmd_string[i] = ' '; + } + else if (islower (cmd_string[i])) { + cmd_string[i] = toupper (cmd_string[i]); + } + } + + DEBUG_1 ("set_ftime: passing command `%s' to VM", cmd_string); + + status = system (cmd_string); + + if (status != 0) { + ERRORMSG_2 ("error setting file `%s' time to %s", + target_file->file_spec, ctime (&(target_file->mod_time))); + explain_error (); + } + + return; +} /* set_ftime */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** set_pipe_mode +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void set_pipe_mode (File_Info *target_file) +#else /* NOT (ANSI_SYNTAX) */ + void set_pipe_mode (target_file) + File_Info *target_file; +#endif /* (ANSI_SYNTAX) */ +{ + return; +} /* set_pipe_mode */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** split_file_spec +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + Unsigned16 split_file_spec (CONST char *full_spec, + char *preamble, + char *name, + char *extension, + char *postamble) +#else /* NOT (ANSI_SYNTAX) */ + Unsigned16 split_file_spec (full_spec, preamble, name, + extension, postamble) + CONST char *full_spec; + char *preamble; + char *name; + char *extension; + char *postamble; +#endif /* (ANSI_SYNTAX) */ +{ + char tmp_full_spec[MAX_PATH + 1]; + char *start_ptr; + char *tmp_ptr; + char *tmp_ptr2; + int idx; + Int16 path_components; + + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (preamble != NULL) + { + *preamble = '\0'; + } + if (name != NULL) + { + *name = '\0'; + } + if (extension != NULL) + { + *extension = '\0'; + } + if (postamble != NULL) + { + *postamble = '\0'; + } + path_components = FS_NOTHING; + + if ((full_spec == NULL) || (*full_spec == '\0')) + { + return (path_components); + } + + strcpy (tmp_full_spec, full_spec); + start_ptr = (char *) tmp_full_spec; + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + tmp_ptr = STRCHR (start_ptr, '.'); + + if (tmp_ptr != NULL) + { + path_components |= FS_EXTENSION; + + tmp_ptr2 = tmp_ptr; + tmp_ptr2++; + while (*tmp_ptr2 != '\0') { + if (*tmp_ptr2 == '.') { + *tmp_ptr2 = '\0'; + + tmp_ptr2++; + if ((tmp_ptr2 != '\0') && isalpha (*tmp_ptr2)) { + path_components |= FS_POSTAMBLE; + if (postamble != NULL) { + postamble[0] = '.'; + postamble[1] = *tmp_ptr2; + tmp_ptr2++; + if (isdigit (*tmp_ptr2)) { + postamble[2] = *tmp_ptr2; + postamble[3] = '\0'; + } + else { + postamble[2] = '\0'; + } + } + } + + break; + } + tmp_ptr2++; + } + + if (extension != NULL) + { + strncpy (extension, tmp_ptr, MAX_EXT); + } + *tmp_ptr = '\0'; + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (*start_ptr != '\0') + { + path_components |= FS_NAME; + + if (name != NULL) + { + strncpy (name, start_ptr, MAX_NAME); + } + } + + return (path_components); +} /* split_file_spec */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** tz_offset +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + TIME_T tz_offset (TIME_T the_time) +#else /* NOT (ANSI_SYNTAX) */ + TIME_T tz_offset (the_time) + TIME_T the_time; +#endif /* (ANSI_SYNTAX) */ + +{ + /* struct tm *tm; + TIME_T timezone; + + tm = localtime (&the_time); + + if (tm->tm_isdst > 0) { + return (timezone - (TIME_T) 3600); + } + else { + return (timezone); + } */ + return ((TIME_T) 0); +} /* tz_offset */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** user_message +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void user_message (CONST Int16 status, + CONST char *msg_str, + File_Info *log_file) +#else /* NOT (ANSI_SYNTAX) */ + void user_message (status, msg_str, log_file) + CONST Int16 status; + CONST char *msg_str; + File_Info *log_file; +#endif /* (ANSI_SYNTAX) */ +{ + int to_stderr; + int to_logfile; + char *status_str; + + + /*- + **------------------------------------------------------------------------ + ** Check the value supplied for the message status and set the output + ** destinations accordingly. + **------------------------------------------------------------------------ + */ + to_logfile = TRUE; + to_stderr = FALSE; + + switch (status) + { + case NORMAL_STATUS: + case LOG_STATUS: + status_str = ""; + break; + case INFO_STATUS: + status_str = " -- "; + to_stderr = TRUE; + break; + case WARNING_STATUS: + status_str = "\nWARNING: "; + to_stderr = TRUE; + break; + case ERROR_STATUS: + status_str = "\nERROR: "; + to_stderr = TRUE; + break; + case FATAL_STATUS: + status_str = "\nFATAL: "; + to_stderr = TRUE; + break; + default: + INTERNAL_ERROR ("user_message"); + vv_exit (); + } + + /*- + **------------------------------------------------------------------------ + ** If the message is NULL, just update the status and/or the message + ** show status. + **------------------------------------------------------------------------ + */ + if ((msg_str == NULL) || (*msg_str == '\0')) + { + if (status > G_status) + { + G_status = status; + } + return; + } + + /*- + **------------------------------------------------------------------------ + ** Make sure that we don't try to write to a NULL log file pointer. + **------------------------------------------------------------------------ + */ + if (log_file->file_ptr == (FILE *) NULL) + { + to_logfile = FALSE; + } + + /*- + **------------------------------------------------------------------------ + ** If the message is to be sent to the log file and stderr, check whether + ** the log file output is also to stderr. If it is, disable the 'stderr' + ** output. + **------------------------------------------------------------------------ + */ + if (to_logfile && to_stderr) + { + if (log_file->file_ptr == stderr) + { + to_stderr = FALSE; + } + } + + /*- + **------------------------------------------------------------------------ + ** If the message is to be sent to stderr, output it here. + **------------------------------------------------------------------------ + */ + if (to_stderr) + { + FPRINTF (stderr, "%s%s\n", status_str, msg_str); + } + + /*- + **------------------------------------------------------------------------ + ** If the message is to be sent to the log file, output it here. If + ** debugging is enabled, report also the name of the calling function. + **------------------------------------------------------------------------ + */ + if (to_logfile) + { + FPRINTF (log_file->file_ptr, "%s%s\n", status_str, msg_str); + } + + /*- + **------------------------------------------------------------------------ + ** + **------------------------------------------------------------------------ + */ + if (status > G_status) + { + G_status = status; + } + +} /* user_message */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** vv_exit +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void vv_exit (void) +#else /* NOT (ANSI_SYNTAX) */ + void vv_exit () +#endif /* (ANSI_SYNTAX) */ +{ + switch (G_status) + { + case LOG_STATUS: + case NORMAL_STATUS: + exit (0); + break; + case WARNING_STATUS: + exit (1); + break; + case ERROR_STATUS: + exit (2); + break; + case FATAL_STATUS: + default: + exit (3); + break; + } +} /* vv_exit */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** write_bytes +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void write_bytes (CONST Int32 max_bytes, + CONST char *buffer, + File_Info *op_file) +#else /* NOT (ANSI_SYNTAX) */ + void write_bytes (max_bytes, buffer, op_file) + CONST Int32 max_bytes; + CONST char *buffer; + File_Info *op_file; +#endif /* (ANSI_SYNTAX) */ +{ + Int32 idx; + + for (idx = 0L; idx < max_bytes; idx++) + { + fputc (buffer[(SIZE_T) idx], op_file->file_ptr); + } +} /* write_bytes */ + + + +/*- +**============================================================================ +** +** FUNCTION +** +** write_record +** +** NOTE: see related file 'specific.h' for functional description. +** +**============================================================================ +*/ +#if (ANSI_SYNTAX) + void write_record (CONST Int32 max_bytes, + CONST char *buffer, + File_Info *op_file) +#else /* NOT (ANSI_SYNTAX) */ + void write_record (max_bytes, buffer, op_file) + CONST Int32 max_bytes; + CONST char *buffer; + File_Info *op_file; +#endif /* (ANSI_SYNTAX) */ +{ + Int32 no_bytes; + + no_bytes = max_bytes * sizeof (char); + fwrite (buffer, (Int16) no_bytes, 1, op_file->file_ptr); +} /* write_record */ |