316 lines
7.4 KiB
C++
316 lines
7.4 KiB
C++
/************************************************************************
|
|
*
|
|
* util.cpp - Utility function definitions for the exec utility
|
|
*
|
|
* $Id: util.cpp 590510 2007-10-30 23:30:35Z sebor $
|
|
*
|
|
************************************************************************
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* permissions and limitations under the License.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#include <assert.h> /* for assert */
|
|
#include <errno.h> /* for errno */
|
|
#include <signal.h> /* for sigaction(), signal() */
|
|
#include <stdio.h> /* for vfprintf */
|
|
#include <stdlib.h> /* for exit, malloc */
|
|
#include <stdarg.h> /* for va_* */
|
|
#include <string.h> /* for strerror */
|
|
|
|
#include <sys/stat.h> /* for stat() */
|
|
#include <sys/types.h> /* for size_t */
|
|
|
|
#ifndef _WIN32
|
|
# include <unistd.h> /* for sleep() */
|
|
#else
|
|
# include <windows.h> /* for Sleep() */
|
|
#endif /* _WIN{32,64} */
|
|
|
|
|
|
#include "cmdopt.h" /* for exe_name, target_name */
|
|
|
|
#include "util.h"
|
|
|
|
|
|
#ifdef _WIN32
|
|
# define DEV_NULL "NUL:"
|
|
#else
|
|
# define DEV_NULL "/dev/null"
|
|
#endif // _WIN32
|
|
|
|
|
|
void
|
|
warn (const char* const format, ...)
|
|
{
|
|
const char* const target_name = get_target ();
|
|
va_list args;
|
|
|
|
assert (0 != format);
|
|
|
|
if (target_name)
|
|
fprintf (stderr, "%s (%s): ", exe_name, target_name);
|
|
else
|
|
fprintf (stderr, "%s: ", exe_name);
|
|
|
|
va_start (args, format);
|
|
vfprintf (stderr, format, args);
|
|
va_end (args);
|
|
}
|
|
|
|
void
|
|
terminate (const int state, const char* const format, ...)
|
|
{
|
|
const char* const target_name = get_target ();
|
|
va_list args;
|
|
|
|
assert (0 != format);
|
|
assert (0 != state);
|
|
|
|
if (target_name)
|
|
fprintf (stderr, "%s (%s): ", exe_name, target_name);
|
|
else
|
|
fprintf (stderr, "%s: ", exe_name);
|
|
|
|
va_start (args, format);
|
|
vfprintf (stderr, format, args);
|
|
va_end (args);
|
|
|
|
exit (state);
|
|
}
|
|
|
|
void*
|
|
guarded_malloc (const size_t size, const char* const file, const unsigned line)
|
|
{
|
|
void* alloc;
|
|
|
|
assert (0 != file);
|
|
assert (0 < size);
|
|
|
|
alloc = malloc (size);
|
|
|
|
if (0 == alloc)
|
|
terminate (1, "malloc (%lu) at line %u of %s failed: %s\n",
|
|
(unsigned long)size, line, file, strerror (errno));
|
|
|
|
return alloc;
|
|
}
|
|
|
|
void*
|
|
guarded_realloc (void* source, const size_t size, const char* const file,
|
|
const unsigned line)
|
|
{
|
|
void* alloc;
|
|
|
|
assert (0 != file);
|
|
assert (0 < size);
|
|
|
|
alloc = realloc (source, size);
|
|
|
|
if (0 == alloc)
|
|
terminate (1, "malloc(%lu) at line %u of %s failed: %s\n",
|
|
(unsigned long)size, line, file, strerror (errno));
|
|
|
|
return alloc;
|
|
}
|
|
|
|
char*
|
|
reference_name (const char* data_dir, const char* subdir, const char* mode)
|
|
{
|
|
size_t root_len, cmp_len, dir_len, mode_len, net_len;
|
|
char* ref_name;
|
|
char* tail;
|
|
const char* const target_name = get_target ();
|
|
|
|
assert (0 != target_name);
|
|
assert (0 != subdir);
|
|
assert (0 != mode);
|
|
|
|
root_len = data_dir ? strlen (data_dir) : 0;
|
|
cmp_len = strlen (target_name) - exe_suffix_len;
|
|
dir_len = strlen (subdir);
|
|
mode_len = strlen (mode);
|
|
net_len = root_len + cmp_len + dir_len + mode_len * 2 + 5;
|
|
/* 5 comes from 3 path seperator characters, the suffix seperator
|
|
character, and the trailing null */
|
|
tail = ref_name = (char*)RW_MALLOC (net_len);
|
|
|
|
memcpy (tail, data_dir, root_len);
|
|
tail += root_len;
|
|
*tail++ = default_path_sep;
|
|
memcpy (tail , subdir, dir_len);
|
|
tail += dir_len;
|
|
*tail++ = default_path_sep;
|
|
memcpy (tail , mode, mode_len);
|
|
tail += mode_len;
|
|
*tail++ = default_path_sep;
|
|
memcpy (tail , target_name, cmp_len);
|
|
tail += cmp_len;
|
|
*tail++ = suffix_sep;
|
|
memcpy (tail , mode, mode_len);
|
|
tail += mode_len;
|
|
*tail = '\0';
|
|
|
|
return ref_name;
|
|
}
|
|
|
|
|
|
/**
|
|
Composes the name of an input file, based on target
|
|
|
|
Takes a data directory and an executable name, and tries to open an input
|
|
file based on these variables. If a file is found in neither of two
|
|
locattions derived from these variables, this method tries to fall back on
|
|
/dev/null.
|
|
|
|
Source file locations:
|
|
- [data_dir]/manual/in/[target].in
|
|
- [data_dir]/tutorial/in/[target].in
|
|
- /dev/null
|
|
|
|
@param data_dir the path of the reference data directory
|
|
@param target the name of executable being run
|
|
@returns the name of the file
|
|
*/
|
|
char*
|
|
input_name (const char* data_dir, const char* target)
|
|
{
|
|
char* fname = 0;
|
|
int stat_result = 0;
|
|
struct stat sb;
|
|
|
|
assert (0 != target);
|
|
|
|
if (data_dir && *data_dir) {
|
|
|
|
/* Try data_dir/manual/in/target.in */
|
|
fname = reference_name (data_dir, "manual", "in");
|
|
stat_result = stat (fname, &sb);
|
|
|
|
if (0 == stat_result)
|
|
return fname;
|
|
|
|
free (fname);
|
|
|
|
/* Try data_dir/tutorial/in/target.in */
|
|
fname = reference_name (data_dir, "tutorial", "in");
|
|
stat_result = stat (fname, &sb);
|
|
|
|
if (0 == stat_result)
|
|
return fname;
|
|
|
|
free (fname);
|
|
}
|
|
|
|
/* If we didn't find a source file, use /dev/null */
|
|
fname = (char*)RW_MALLOC (sizeof DEV_NULL);
|
|
strcpy (fname, DEV_NULL);
|
|
return fname;
|
|
}
|
|
|
|
|
|
char*
|
|
output_name (const char* target)
|
|
{
|
|
const char* suffix = "out";
|
|
const size_t sfx_len = strlen (suffix);
|
|
const size_t exe_len = strlen (target) - exe_suffix_len;
|
|
char* const tmp_name = (char*)RW_MALLOC (exe_len + sfx_len + 2);
|
|
|
|
memcpy (tmp_name, target, exe_len);
|
|
*(tmp_name + exe_len) = suffix_sep;
|
|
memcpy (tmp_name + exe_len + 1, suffix, sfx_len + 1);
|
|
return tmp_name;
|
|
}
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
void
|
|
rw_sleep (int seconds)
|
|
{
|
|
sleep (seconds);
|
|
}
|
|
|
|
|
|
# ifndef _RWSTD_EDG_ECCP
|
|
|
|
# ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
# endif /* __cplusplus */
|
|
|
|
int
|
|
rw_signal (int signo, void (*func)(int))
|
|
{
|
|
struct sigaction act;
|
|
memset (&act, 0, sizeof act);
|
|
|
|
/* avoid extern "C"/"C++" mismatch due to an HP aCC 6 bug
|
|
(see STDCXX-291) */
|
|
if (func)
|
|
memcpy (&act.sa_handler, &func, sizeof func);
|
|
else
|
|
act.sa_handler = 0;
|
|
|
|
return 0 > sigaction (signo, &act, 0);
|
|
}
|
|
|
|
# ifdef __cplusplus
|
|
|
|
} /* extern "C" */
|
|
|
|
# endif /* __cplusplus */
|
|
|
|
# else /* if defined (_RWSTD_EDG_ECCP) */
|
|
|
|
# ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
# endif /* __cplusplus */
|
|
|
|
int
|
|
rw_signal (int signo, void (*func)(int))
|
|
{
|
|
return SIG_ERR == signal (signo, func);
|
|
}
|
|
|
|
# ifdef __cplusplus
|
|
|
|
} /* extern "C" */
|
|
|
|
# endif /* __cplusplus */
|
|
# endif /* _RWSTD_EDG_ECCP */
|
|
#else /* if defined (_WIN32) || defined (_WIN64) */
|
|
|
|
void
|
|
rw_sleep (int seconds)
|
|
{
|
|
Sleep (seconds * 1000);
|
|
}
|
|
|
|
|
|
int
|
|
rw_signal (int signo, void (*func)(int))
|
|
{
|
|
return SIG_ERR == signal (signo, func);
|
|
}
|
|
|
|
#endif /* _WIN32 */
|