summaryrefslogtreecommitdiff
path: root/support/vvcode/unix.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/unix.c
Initial commit
Diffstat (limited to 'support/vvcode/unix.c')
-rw-r--r--support/vvcode/unix.c1681
1 files changed, 1681 insertions, 0 deletions
diff --git a/support/vvcode/unix.c b/support/vvcode/unix.c
new file mode 100644
index 0000000000..9630af200e
--- /dev/null
+++ b/support/vvcode/unix.c
@@ -0,0 +1,1681 @@
+/*-
+******************************************************************************
+******************************************************************************
+**
+** ARCHIVE HEADER INFORMATION
+**
+** @C-file{
+** FILENAME = "unix.c",
+** VERSION = "1.00",
+** DATE = "",
+** TIME = "",
+**
+** AUTHOR = "Niel Kempson",
+** ADDRESS = "25 Whitethorn Drive, Cheltenham, GL52 5LL, England",
+** TELEPHONE = "+44-242 579105",
+** EMAIL = "kempson@tex.ac.uk (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>
+**
+** 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>
+
+/*-
+**----------------------------------------------------------------------------
+** Include files
+**----------------------------------------------------------------------------
+*/
+#include "checkos.h"
+#include "machine.h"
+#include "local.h"
+#include "globals.h"
+#include "specific.h"
+#include "vvutils.h"
+
+/*-
+**----------------------------------------------------------------------------
+** Implementation (compiler) specific include files. The default
+**----------------------------------------------------------------------------
+*/
+# if (UNIX_BSD)
+# include <sys/timeb.h>
+
+# ifndef HAS_UTIME_H
+# undef HAS_SYSUTIME_H
+# define HAS_SYSUTIME_H 1
+# endif /* HAS_UTIME_H */
+# endif /* (UNIX_BSD) */
+
+# if (UNIX_SYSV)
+# ifndef HAS_SYSUTIME_H
+# undef HAS_UTIME_H
+# define HAS_UTIME_H 1
+# endif
+# endif /* UNIX_SYSV */
+
+#ifdef HAS_UTIME_H
+# include <utime.h>
+#endif /* HAS_UTIME_H */
+
+#ifdef HAS_SYSUTIME_H
+# include <sys/utime.h>
+#endif /* HAS_SYSUTIME_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];
+ Unsigned16 path_parts;
+ char preamble[MAX_PREAMBLE + 1];
+
+ path_parts = split_file_spec (full_spec, preamble, name, extension, NULL);
+
+
+ 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);
+ }
+
+ make_file_spec (preamble, name, extension, NULL, 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]: ", confirm_str);
+ fflush (stderr);
+
+ 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') ? (Boolean) TRUE : (Boolean) 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];
+ int bytes_read;
+ int ctrl_count;
+ int eol_count;
+ int i;
+ struct stat stat_buffer;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** 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;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ ex_file->file_ptr = fopen (ex_file->file_spec, "r");
+
+ if (ex_file->file_ptr == (FILE *) NULL)
+ {
+ ERRORMSG_1 ("couldn't examine (open) file `%s'", ex_file->file_spec);
+ explain_error ();
+ return;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Test to see if the file is 'real'.
+ **------------------------------------------------------------------------
+ */
+ if (is_a_file (ex_file) == FALSE)
+ {
+ DEBUG_1 ("examine_file: `%s' is not a regular file",
+ ex_file->file_spec);
+ f_close (ex_file);
+ ex_file->pipe_flag = TRUE;
+ ex_file->file_ptr = (FILE *) NULL;
+ return;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ bytes_read = fread (tmp_buffer, sizeof (char), EX_SAMPLE_SIZE,
+ ex_file->file_ptr);
+ eol_count = 0;
+ ctrl_count = 0;
+
+ for (i = 0; i < (bytes_read - 1); i++)
+ {
+ if (tmp_buffer[i + 1] == '\n')
+ {
+ ++eol_count;
+ }
+ if (tmp_buffer[i + 1] < 0x08)
+ {
+ ++ctrl_count;
+ }
+ }
+ f_close (ex_file);
+ ex_file->file_ptr = (FILE *) NULL;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if ((bytes_read > (80 * eol_count)) || (bytes_read < (80 * ctrl_count)))
+ {
+ ex_file->mode = MODE_BINARY;
+ ex_file->format = DEF_BINARY_FMT;
+ }
+ else
+ {
+ ex_file->mode = MODE_TEXT;
+ ex_file->format = DEF_TEXT_FMT;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ i = stat (ex_file->file_spec, &stat_buffer);
+
+ if (i != FALSE)
+ {
+ ERRORMSG_1 ("couldn't examine (stat) file `%s'", ex_file->file_spec);
+ explain_error ();
+ return;
+ }
+ ex_file->mod_time = stat_buffer.st_mtime;
+
+} /* 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;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ switch (ip_file->mode)
+ {
+ case MODE_BINARY:
+ case MODE_TEXT:
+ file_ptr = fopen (ip_file->file_spec, "rb");
+ 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;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ 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))
+ {
+ INFOMSG ("operation cancelled");
+ return ((FILE *) NULL);
+ }
+ }
+ else
+ {
+ ERRORMSG_1 ("file `%s' exists", op_file->file_spec);
+ return ((FILE *) NULL);
+ }
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ switch (op_file->mode)
+ {
+ case MODE_BINARY:
+ case MODE_TEXT:
+ file_ptr = fopen (op_file->file_spec, "wb");
+ break;
+ default:
+ ERRORMSG_1 ("invalid file mode specified (%d)", op_file->mode);
+ return ((FILE *) NULL);
+ }
+
+ 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) */
+{
+ return ((Boolean) (access ((char *) file_spec, 0) == 0));
+} /* 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 preamble[MAX_PREAMBLE + 1];
+
+ if (forced_ext == NULL)
+ {
+ return;
+ }
+ (void) split_file_spec (full_spec, preamble, name, NULL, NULL);
+ make_file_spec (preamble, name, forced_ext, NULL, 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) */
+{
+ int file_handle;
+ int status;
+
+ file_handle = fileno (ex_file->file_ptr);
+ status = isatty (file_handle);
+
+ if (status == 0)
+ {
+ return (TRUE);
+ }
+ else
+ {
+ return (FALSE);
+ }
+} /* 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, "");
+
+ /*-
+ **------------------------------------------------------------------------
+ ** The preamble component corresponds to the Unix network node and/or path
+ ** components in the form:
+ **
+ ** node: node:dir1 node:/dir1 node:/dir1/
+ ** node:/dir1/dir2 dir1 /dir1 /dir1/dir2
+ **
+ **
+ ** If the preamble component does not end in '/' or ':', '/' is appended
+ ** only if the component is not empty.
+ **------------------------------------------------------------------------
+ */
+ if ((preamble != NULL) && (*preamble != '\0'))
+ {
+ strncat (full_spec, preamble, MAX_PREAMBLE);
+ len = strlen (preamble);
+ tmp_ptr = STRCHR ("/:", preamble[len - 1]);
+
+ if ((tmp_ptr == NULL) && (len < MAX_PREAMBLE))
+ {
+ strcat (full_spec, "/");
+ }
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** 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);
+ }
+ }
+} /* 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);
+ fflush (stderr);
+ 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)
+ {
+ if (ferror (ip_file->file_ptr))
+ {
+ return (-2L);
+ }
+
+ if (idx == 0)
+ {
+ return (-1L);
+ }
+ break;
+ }
+ 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)
+ {
+ if (ferror (ip_file->file_ptr))
+ {
+ return (-2L);
+ }
+
+ if (feof (ip_file->file_ptr))
+ {
+ return (-1L);
+ }
+ }
+ 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) */
+{
+ INTERNAL_ERROR ("read_record");
+ return (-2L);
+} /* 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;
+
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Loop through each of the user supplied command line arguments.
+ **------------------------------------------------------------------------
+ */
+ tmp_qstr_ptr = NULL;
+
+ for (arg_no = 1; arg_no < qargc; arg_no++)
+ {
+ arg = (char *) qargv[arg_no];
+
+ /*-
+ **--------------------------------------------------------------------
+ **
+ **--------------------------------------------------------------------
+ */
+ if (qual_array[CMDQ_DEBUG].present == TRUE)
+ {
+ G_debugging = TRUE;
+ }
+ DEBUG_1 ("scan_cmd_line: command line argument: `%s'", arg);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** If the first character of the argument is one of the allowable
+ ** 'q_intro_str' characters then parse it as a qualifier, unless
+ ** the argument is the 'STDIO_SYMBOL' string when it is interpreted as
+ ** the standard input or output file.
+ **--------------------------------------------------------------------
+ */
+ if (((STRCHR (q_intro_str, *arg) != NULL)
+ && STRCMP (arg, STDIO_SYMBOL) != 0))
+ {
+
+ /*-
+ **----------------------------------------------------------------
+ ** Extract the component of the qualifier string after the
+ ** 'q_intro_str' character before the 'q_sep_str' character
+ ** if it is present.
+ **----------------------------------------------------------------
+ */
+ if (tmp_qstr_ptr != NULL)
+ {
+ free (tmp_qstr_ptr);
+ }
+ tmp_qstr_ptr = STRDUP (arg + 1);
+ 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, (Int16) len) == 0)
+ {
+
+ /*-
+ **--------------------------------------------------------
+ **
+ **--------------------------------------------------------
+ */
+ if (qual_found < 0)
+ {
+ qual_found = q_no;
+ DEBUG_1 ("scan_cmd_line: matches qualifier: `%s'",
+ qual_array[q_no].q_string);
+ }
+ else
+ {
+ USAGE_1 ("ambiguous qualifier `%s'", qargv[arg_no]);
+ }
+ }
+ }
+
+ /*-
+ **----------------------------------------------------------------
+ ** If the qualifier string is unknown, return that status.
+ **----------------------------------------------------------------
+ */
+ if (qual_found < 0)
+ {
+ USAGE_1 ("unknown qualifier `%s'", qargv[arg_no]);
+ }
+
+ /*-
+ **----------------------------------------------------------------
+ **
+ **----------------------------------------------------------------
+ */
+ if (qsep_ptr == NULL)
+ {
+ if (qual_array[qual_found].val_needed == VALUE_NEEDED)
+ {
+ if ((arg_no + 1) < qargc)
+ {
+ qual_array[qual_found].present = TRUE;
+ qual_array[qual_found].value = STRDUP (qargv[++arg_no]);
+ DEBUG_1 ("scan_cmd_line: qualifier value: `%s'",
+ qual_array[qual_found].value);
+ }
+ else
+ {
+ USAGE_2 ("qualifier `%.1s%s' must take a value",
+ QUAL_INTRO, qual_array[qual_found].q_string);
+ }
+ }
+ else
+ {
+ qual_array[qual_found].present = TRUE;
+ qual_array[qual_found].value = NULL;
+ }
+ }
+ else
+ {
+ /*-
+ **------------------------------------------------------------
+ **
+ **------------------------------------------------------------
+ */
+ if (*qvalue_ptr == '\0')
+ {
+ USAGE_1 ("value missing after qualifier `%s'",
+ qargv[arg_no]);
+ }
+ else if (qual_array[qual_found].val_needed == VALUE_NONE)
+ {
+ USAGE_2 ("qualifier `%.1s%s' does not take a value",
+ QUAL_INTRO, qual_array[qual_found].q_string);
+ }
+ else
+ {
+ qual_array[qual_found].value = STRDUP (qvalue_ptr);
+ qual_array[qual_found].present = TRUE;
+ DEBUG_1 ("scan_cmd_line: qualifier value: `%s'",
+ qual_array[qual_found].value);
+ }
+ }
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ **
+ **--------------------------------------------------------------------
+ */
+ else
+ {
+ if (qual_ipfile->present == FALSE)
+ {
+ qual_ipfile->present = TRUE;
+ qual_ipfile->value = STRDUP (qargv[arg_no]);
+ }
+ else if (qual_opfile->present == FALSE)
+ {
+ qual_opfile->present = TRUE;
+ qual_opfile->value = STRDUP (qargv[arg_no]);
+ }
+ else
+ {
+ USAGE ("too many file names specified");
+ }
+ }
+ }
+} /* 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;
+
+#if (UNIX_BSD)
+ TIME_T timep[2];
+#endif /* (UNIX_BSD) */
+
+#if (UNIX_SYSV)
+ struct utimbuf utb;
+#endif /* (UNIX_SYSV) */
+
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ DEBUG_2 ("set_ftime: setting file `%s' time to %.24s",
+ target_file->file_spec, ctime (&(target_file->mod_time)));
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+#if (UNIX_SYSV)
+ utb.actime = target_file->mod_time;
+ utb.modtime = target_file->mod_time;
+ status = utime ((char *) target_file->file_spec, &utb);
+#endif /* (UNIX_SYSV) */
+
+#if (UNIX_BSD)
+ timep[0] = target_file->mod_time;
+ timep[1] = target_file->mod_time;
+ status = utime ((char *) target_file->file_spec, timep);
+#endif /* (UNIX_BSD) */
+
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (status != 0)
+ {
+ ERRORMSG_2 ("error setting file `%s' time to %.24s",
+ 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;
+ int idx;
+ Unsigned16 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 = STRRSTR (start_ptr, ":/");
+
+ if (tmp_ptr != NULL)
+ {
+ path_components |= FS_PREAMBLE;
+
+ if (preamble != NULL)
+ {
+ for (idx = 0; ((idx < MAX_PREAMBLE) && (start_ptr <= tmp_ptr));
+ idx++)
+ {
+ *preamble++ = *start_ptr++;
+ }
+ *preamble = '\0';
+ }
+ start_ptr = ++tmp_ptr;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ tmp_ptr = STRCHR (start_ptr, '.');
+
+ if (tmp_ptr != NULL)
+ {
+ path_components |= FS_EXTENSION;
+
+ 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;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+#if (UNIX_BSD)
+ TIME_T timezone;
+ struct timeb timeb_struct;
+
+ ftime (&timeb_struct);
+ timezone = (TIME_T) timeb_struct.timezone * (TIME_T) 60;
+#endif /* (UNIX_BSD) */
+
+ tm = localtime (&the_time);
+
+ if (tm->tm_isdst > 0)
+ {
+ return (timezone - (TIME_T) 3600);
+ }
+ else
+ {
+ return (timezone);
+ }
+} /* 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) */
+{
+ INTERNAL_ERROR ("write_record");
+} /* write_record */