/* * Copyright (c) 2002, The Tendra Project * 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); }