/*
* Copyright (c) 2002, The Tendra Project <http://www.ten15.org/>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Crown Copyright (c) 1997
*
* This TenDRA(r) Computer Program is subject to Copyright
* owned by the United Kingdom Secretary of State for Defence
* acting through the Defence Evaluation and Research Agency
* (DERA). It is made available to Recipients with a
* royalty-free licence for its use, reproduction, transfer
* to other parties and amendment for any purpose not excluding
* product development provided that any such use et cetera
* shall be deemed to be acceptance of the following conditions:-
*
* (1) Its Recipients shall ensure that this Notice is
* reproduced upon any copies or amended versions of it;
*
* (2) Any amended version of it shall be clearly marked to
* show both the nature of and the organisation responsible
* for the relevant amendment or amendments;
*
* (3) Its onward transfer from a recipient to another
* party shall be deemed to be that party's acceptance of
* these conditions;
*
* (4) DERA gives no warranty or assurance as to its
* quality or suitability for any purpose and DERA accepts
* no liability whatsoever in relation to any use to which
* it may be put.
*
* $TenDRA: tendra/src/producers/common/utility/system.c,v 1.12 2004/08/21 15:31:42 stefanf Exp $
*/
#include "config.h"
#include "producer.h"
#include "cstring.h"
#include "fmm.h"
#include "system.h"
#include "c_types.h"
#include "error.h"
#include "file.h"
#include "ustring.h"
/*
* FILE SEEKING FLAG
*
* The flag good_fseek is true if a simple fseek on the byte count has
* the desired effect, and false otherwise (for example on DOS machines).
* Similarly binary_mode is true if there are separate text and binary
* file modes. The flag good_stat is true if the st_dev and st_ino
* fields of struct stat are sufficient to uniquely identify a file
* (this may not be true for machines with small ino_t types and
* file systems mounted from machines with large ino_t types).
*/
int good_fseek = 1;
int good_stat = 0;
int text_mode = 0;
int binary_mode = 0;
int file_sep = '/';
int drive_sep = 0;
/*
* SEEK A POSITION IN A FILE
*
* This routine seeks a position n bytes from the start of the file f.
* It returns 0 if good_fseek is false, otherwise it returns 1 for
* successful seeks and -1 otherwise.
*/
int
file_seek(FILE *f, long n)
{
if (n == 0) {
/* Can always rewind a file */
rewind (f);
return (1);
}
if (good_fseek) {
/* Use fseek if it works */
int s = fseek (f, n, SEEK_SET);
if (s == -1) return (-1);
return (1);
}
return (0);
}
/*
* CONVERT A TIME TO AN UNSIGNED LONG
*
* This macro converts the time_t value A to an unsigned long. Since
* time_t may be any arithmetic type, this may not be totally portable.
*/
#define time_value(A) ((unsigned long) (A))
/*
* CURRENT TIME
*
* These variables are used to hold the current time as a struct tm.
* The date is also used to form a string which is unique for each
* translation unit.
*/
char uniq_string [50];
unsigned long crt_time = 0;
static int have_crt_time = 0;
static struct tm crt_time_str;
/*
* FIND THE CURRENT TIME
*
* This routine assigns the current time to the variables above, returning
* a pointer to crt_time_str. Note that the actual time is taken only the
* first time the function is called.
*/
static struct tm
*get_crt_time()
{
if (!have_crt_time) {
const char *s1, *s2;
time_t t = time (NULL);
if (t == (time_t) -1) {
/* Use a (seemingly) random date if time fails */
struct tm *st = &crt_time_str;
st->tm_mday = 24;
st->tm_mon = 6 /* July */;
st->tm_year = 62;
st->tm_hour = 23;
st->tm_min = 30;
st->tm_sec = 0;
error (ERROR_INTERNAL, "Can't find current date");
} else {
struct tm *st = localtime (&t);
crt_time_str = *st;
crt_time = time_value (t);
}
have_crt_time = 1;
s1 = find_time ("%.2d%.2d%.2d");
s2 = find_date ("%s%.2d_%d");
sprintf_v (uniq_string, "%s_%s", s1, s2);
}
return (&crt_time_str);
}
/*
* PRINT THE CURRENT DATE
*
* This routine returns a string giving the current date in the form
* given by fmt. This is used in the __DATE__ built-in macro.
*/
const char
*find_date(const char *fmt)
{
static char buff [20];
static const char *month_name [12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
struct tm *st = get_crt_time ();
int day = st->tm_mday;
const char *month = month_name [ st->tm_mon ];
int year = 1900 + st->tm_year;
sprintf_v (buff, fmt, month, day, year);
return (buff);
}
/*
* PRINT THE CURRENT TIME
*
* This routine returns a string giving the current time in the form
* given by fmt. This is used in the __TIME__ built-in macro.
*/
const char
*find_time(const char *fmt)
{
static char buff [20];
struct tm *st = get_crt_time ();
int hour = st->tm_hour;
int min = st->tm_min;
int sec = st->tm_sec;
sprintf_v (buff, fmt, hour, min, sec);
return (buff);
}
/*
* FIND FILE STATISTICS
*
* This routine finds the file statistics for the file with pathname nm
* and assigns them into fs. It returns fs if this is successful and the
* null pointer otherwise.
*/
STAT_TYPE
*stat_func(char *nm, STAT_TYPE *fs)
{
#if FS_POSIX
int s = stat (nm, fs);
if (s != -1) return (fs);
#endif
UNUSED (nm);
return (NULL);
}
/*
* FIND A FILE DATE
*
* This routine converts the date from the file statistics fs to an
* unsigned long.
*/
unsigned long
stat_date(STAT_TYPE *fs)
{
unsigned long date = 0;
if (fs) date = time_value (fs->st_mtime);
return (date);
}
/*
* ARE TWO FILES EQUAL?
*
* This routine checks whether the files given by the statistics fs and
* gs represent the same file. Two files are the same if their device
* and inode numbers are equal (except on machines where good_stat is
* false).
*/
int
stat_equal(STAT_TYPE *fs, STAT_TYPE *gs)
{
if (fs && gs) {
if (fs->st_dev == gs->st_dev && fs->st_ino == gs->st_ino) {
return (good_stat);
}
}
return (0);
}
/*
* FIND THE CURRENT WORKING DIRECTORY
*
* This routine finds the current working directory, returning '.' if
* this cannot be found.
*/
const char
*find_cwd()
{
static const char *crt_directory = NULL;
if (crt_directory == NULL) {
#if FS_POSIX
char buff [1024];
char *nm = getcwd (buff, 1024);
if (nm) {
/* Copy result */
string dir = ustrlit (string_copy (nm));
dir = make_pathname (dir);
crt_directory = strlit (dir);
} else {
crt_directory = ".";
}
#else
crt_directory = ".";
#endif
}
return (crt_directory);
}
/*
* FIND THE CURRENT MACHINE
*
* This routine finds the name of the machine on which the program is
* running, returning the empty string if this cannot be found.
*/
const char
*find_machine()
{
static const char *machine_name = NULL;
if (machine_name == NULL) {
#if FS_UTSNAME
struct utsname un;
if (uname (&un) != -1) {
machine_name = string_copy (un.nodename);
return (machine_name);
}
#endif
machine_name = "";
}
return (machine_name);
}
syntax highlighted by Code2HTML, v. 0.9.1