summaryrefslogtreecommitdiff
path: root/support/vvcode/vmcms.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/vvcode/vmcms.c
Initial commit
Diffstat (limited to 'support/vvcode/vmcms.c')
-rw-r--r--support/vvcode/vmcms.c1829
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 */