// ---------------------------------------------------------------------------
// - csys.cxx -
// - standard system library - c system function implementation -
// ---------------------------------------------------------------------------
// - This program is free software; you can redistribute it and/or modify -
// - it provided that this copyright notice is kept intact. -
// - -
// - 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. In no event shall -
// - the copyright holder be liable for any direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software. -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch -
// ---------------------------------------------------------------------------
#include "csys.hpp"
#include "cstr.hpp"
#include "cthr.hpp"
#include "csys.hxx"
namespace afnix {
// static mutex creation function
static void* mtx_create (void);
// mutex for various calls
static void* mtx = mtx_create ();
// this function destroy the mutex at exit
static void mtx_destroy (void) {
c_mtxdestroy (mtx);
}
// this function initialize a mutex statically and register its
// destruction to be done at exit
static void* mtx_create (void) {
void* mtx = c_mtxcreate ();
c_atexit (mtx_destroy);
return mtx;
}
// the program name
static char* pgm = nilp;
// this function destroy the program name
static void pgm_destroy (void) {
delete [] pgm;
}
// return true if the system is 32 bit
bool c_is32 (void) {
return (sizeof (long) == 4);
}
// return true if the system is 64 bit
bool c_is64 (void) {
return (sizeof (long) == 8);
}
// return a unique id
t_long c_uniqid (void) {
// the global unique id
static t_long uniqid = 0;
// lock the mutex before access
c_mtxlock (mtx);
t_long result = ++uniqid;
c_mtxunlock (mtx);
return result;
}
// set the program name
void c_setpgm (const char* name) {
if (pgm == nilp) c_atexit (pgm_destroy);
if (pgm != nilp) delete [] pgm;
pgm = c_strdup (name);
}
// return the program name
char* c_getpgm (void) {
return c_strdup (pgm);
}
// return a temporary name
char* c_tempnam (const char* prefix) {
static long tcnt = 0;
// lock the mutex
c_mtxlock (mtx);
// control the final prefix
char* base = c_strtrc (prefix, 64);
char buffer[512];
sprintf (buffer, "%s-%ld-%ld", base, c_getpid (), tcnt++);
delete [] base;
// unlock the mutex
c_mtxunlock (mtx);
return c_strdup (buffer);
}
// return the os name
const char* c_osname (void) {
return AFNIX_PLATFORM_NAME;
}
// return the os type
const char* c_ostype (void) {
return AFNIX_PLATFORM_TYPE;
}
// return the native option separator
const char c_optsep (void) {
return AFNIX_PLATFORM_OSEP;
}
// exit without executing the register code
void c_abort (void) {
_exit (1);
}
// exit unconditionnaly with a status code
void c_exit (int status) {
exit (status);
}
// register a function to execute at exit
void c_atexit (void (*func) (void)) {
atexit (func);
}
// return the process id
long c_getpid (void) {
return getpid ();
}
// return an environment variable value
const char* c_getenv (const char* name) {
if (c_strlen (name) == 0) return nilp;
return getenv (name);
}
}
#ifdef AFNIX_HAVE_HOSTNAME
namespace afnix {
// return the host name
char* c_hostname (void) {
char name[1024];
if (gethostname (name,1024) != 0) return nilp;
return c_strdup (name);
}
}
#endif
#ifdef AFNIX_HAVE_SYSINFO
namespace afnix {
// return the host name
char* c_hostname (void) {
char name[1024];
if (sysinfo (SI_HOSTNAME, name,1024) == -1) return nilp;
return c_strdup (name);
}
}
#endif
#ifdef AFNIX_HAVE_UID
namespace afnix {
// return the user name
char* c_username (void) {
// get the user id
uid_t uid = getuid ();
// get the password line entry
struct passwd* data = getpwuid (uid);
if (data == nilp) return c_strdup (c_getenv ("USER"));
return c_strdup (data->pw_name);
}
}
#endif
#ifdef AFNIX_HAVE_BACKTRACE
#ifdef __GNUC__
#define GET_CALLER_FRAME __builtin_frame_address(1);
#else
#define GET_CALLER_FRAME 0
#endif
namespace afnix {
// the begining of the frame
struct s_frame {
s_frame* p_prev;
void* p_pc;
};
struct s_finfo {
void* p_pc;
int d_fidx;
const char* p_name;
s_finfo* p_prev;
// simple constructor
s_finfo (void) {
p_pc = 0;
p_name = 0;
p_prev = 0;
d_fidx = 0;
}
// simple destructor
~s_finfo (void) {
delete p_name;
delete p_prev;
}
};
// this function resolve the pc name from its address
static inline const char* get_pc_name (void* pc) {
if (pc == 0) return 0;
Dl_info dlinfo;
if (dladdr (pc, &dlinfo) == 0) return 0;
return c_strdup (dlinfo.dli_sname);
}
// return the backtrace of the calling function
void* c_backtrace (void) {
// get the caller frame
s_frame* frame = (s_frame*) GET_CALLER_FRAME;
s_finfo* finfo = 0;
int index = 0;
// loop in the frame
while (frame != 0) {
s_finfo* data = new s_finfo;
data->p_pc = frame->p_pc;
data->p_name = get_pc_name (data->p_pc);
data->p_prev = finfo;
data->d_fidx = index++;
finfo = data;
frame = frame->p_prev;
if (data->p_name == 0) break;
}
return finfo;
}
// print the stack trace
void c_printtrace (void* bptr) {
if (bptr == 0) return;
// get to the first frame
s_finfo* finfo = (s_finfo*) bptr;
if (finfo->p_prev != 0) c_printtrace (finfo->p_prev);
// print frame info
int fidx = finfo->d_fidx;
if (fidx == 0)
fprintf (stderr, "\n\t%d: %s\n", fidx, finfo->p_name);
else
fprintf (stderr, "\t%d: %s\n", fidx, finfo->p_name);
}
// destroy a stack trace
void c_destroytrace (void* bptr) {
if (bptr == 0) return;
s_finfo* finfo = (s_finfo*) bptr;
delete finfo;
}
}
#else
namespace afnix {
// return the stack trace
void* c_backtrace (void) {
return 0;
}
// print the stack trace
void c_printtrace (void*) {
return;
}
// destroy a stack trace
void c_destroytrace (void*) {
return;
}
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1