From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- support/vvcode/unix.c | 1681 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1681 insertions(+) create mode 100644 support/vvcode/unix.c (limited to 'support/vvcode/unix.c') 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 +** +** 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 + +/*- +**---------------------------------------------------------------------------- +** 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 + +# 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 +#endif /* HAS_UTIME_H */ + +#ifdef HAS_SYSUTIME_H +# include +#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 */ -- cgit v1.2.3