Files
org-hyperion-cules/hmacros.h
2015-01-24 21:50:20 -08:00

848 lines
31 KiB
C

/* HMACROS.H (c) Copyright Roger Bowler, 1999-2012 */
/* Hercules macros... */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
// This header auto-#included by 'hercules.h'...
//
// The <config.h> header and other required headers are
// presumed to have already been #included ahead of it...
#ifndef _HMACROS_H
#define _HMACROS_H
#include "hercules.h"
/*-------------------------------------------------------------------*/
/* Compiler unused function warning */
/*-------------------------------------------------------------------*/
#undef UNUSED_FUNCTION_WARNING
#if defined(__GNUC__)
#if __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ > 5 )
#define UNUSED_FUNCTION_WARNING
#endif
#endif
/*-------------------------------------------------------------------*/
/* UNREACHABLE_CODE code that should NEVER be reached */
/*-------------------------------------------------------------------*/
#ifdef _MSVC_
#define UNREACHABLE_CODE() __assume(0)
#elif defined(__GNUC__)
#define UNREACHABLE_CODE() __builtin_unreachable()
#else
#define UNREACHABLE_CODE()
#endif
/*-------------------------------------------------------------------*/
/* Define INLINE attributes by compiler */
/*-------------------------------------------------------------------*/
#if !defined(INLINE)
#if defined(__GNUC__)
#define INLINE __inline
#else
#define INLINE __inline
#endif
#endif
/*-------------------------------------------------------------------*/
/* Use '__noop()' to disable code generating macros */
/*-------------------------------------------------------------------*/
#if !defined(_MSVC_)
#if !defined(__noop)
#define __noop(...) do{;}while(0) /* (i.e. do nothing) */
#endif
#endif
/*-------------------------------------------------------------------*/
/* Round a value up to the next boundary */
/*-------------------------------------------------------------------*/
#define ROUND_UP(x,y) ((((x)+((y)-1))/(y))*(y))
/*-------------------------------------------------------------------*/
/* Define min/max macros */
/*-------------------------------------------------------------------*/
#if !defined(min)
#define min(_x, _y) ((_x) < (_y) ? (_x) : (_y))
#endif
#if !defined(max)
#define max(_x, _y) ((_x) > (_y) ? (_x) : (_y))
#endif
#if !defined(MIN)
#define MIN(_x,_y) min((_x),(_y))
#endif
#if !defined(MAX)
#define MAX(_x,_y) max((_x),(_y))
#endif
/*-------------------------------------------------------------------*/
/* MINMAX ensures var x remains within range y to z */
/*-------------------------------------------------------------------*/
#if !defined(MINMAX)
#define MINMAX(_x,_y,_z) ((_x) = MIN(MAX((_x),(_y)),(_z)))
#endif
/*-------------------------------------------------------------------*/
/* some handy array/struct macros... */
/*-------------------------------------------------------------------*/
#ifndef _countof
#define _countof(x) ( sizeof(x) / sizeof(x[0]) )
#endif
#ifndef arraysize
#define arraysize(x) _countof(x)
#endif
#ifndef sizeof_member
#define sizeof_member(_struct,_member) sizeof(((_struct*)0)->_member)
#endif
#ifndef offsetof
#define offsetof(_struct,_member) (size_t)&(((_struct*)0)->_member)
#endif
/*-------------------------------------------------------------------*/
/* CASSERT macro a compile time assertion check */
/*-------------------------------------------------------------------*/
/**
* Validates at compile time whether condition is true without
* generating code. It can be used at any point in a source file
* where typedefs are legal.
*
* On success, compilation proceeds normally.
*
* Sample usage:
*
* CASSERT(sizeof(struct foo) == 76, demo_c)
*
* On failure, attempts to typedef an array type of negative size
* resulting in a compiler error message that might look something
* like the following:
*
* demo.c:32: error: size of array 'assertion_failed_demo_c_32' is negative
*
* The offending line itself will look something like this:
*
* typedef assertion_failed_demo_c_32[-1]
*
* where demo_c is the content of the second parameter which should
* typically be related in some obvious way to the containing file
* name, 32 is the line number in the file on which the assertion
* appears, and -1 is the result of a calculation based on the cond
* failing.
*
* \param cond The predicate to test. It should evaluate
* to something which can be coerced into a
* normal C boolean.
*
* \param file A sequence of legal identifier characters
* that should uniquely identify the source
* file where the CASSERT statement appears.
*/
#if !defined(CASSERT)
#define CASSERT(cond, file) _CASSERT_LINE(cond,__LINE__,file)
#define _CASSERT_PASTE(a,b) a##b
#define _CASSERT_LINE(cond, line, file) \
typedef char _CASSERT_PASTE(assertion_failed_##file##_,line)[2*!!(cond)-1];
#endif
/*-------------------------------------------------------------------*/
/* compiler optimization hints (for performance) */
/*-------------------------------------------------------------------*/
#undef likely
#undef unlikely
#ifdef _MSVC_
#define likely(_c) ( (_c) ? ( __assume((_c)), 1 ) : 0 )
#define unlikely(_c) ( (_c) ? 1 : ( __assume(!(_c)), 0 ) )
#else // !_MSVC_
#if __GNUC__ >= 3
#define likely(_c) __builtin_expect((_c),1)
#define unlikely(_c) __builtin_expect((_c),0)
#else
#define likely(_c) (_c)
#define unlikely(_c) (_c)
#endif
#endif // _MSVC_
/*-------------------------------------------------------------------*/
/* _MSVC_ portability macros */
/*-------------------------------------------------------------------*/
/* PROGRAMMING NOTE: the following 'tape' portability macros are
only for physical (SCSI) tape devices, not emulated aws files */
#ifdef _MSVC_
#define open_tape w32_open_tape
#define read_tape w32_read_tape
#define write_tape w32_write_tape
#define ioctl_tape w32_ioctl_tape
#define close_tape w32_close_tape
#else
#define open_tape open
#define read_tape read
#define write_tape write
#define ioctl_tape ioctl
#define close_tape close
#endif
#ifdef _MSVC_
#define create_pipe(a) socketpair(AF_INET,SOCK_STREAM,IPPROTO_IP,a)
#define read_pipe(f,b,n) recv(f,b,n,0)
#define write_pipe(f,b,n) send(f,b,(int)n,0)
#define close_pipe(f) closesocket(f)
#else
#define create_pipe(f) pipe(f)
#define read_pipe(f,b,n) read(f,b,n)
#define write_pipe(f,b,n) write(f,b,n)
#define close_pipe(f) close(f)
#endif
#ifdef _MSVC_
#define socket w32_socket
/* Now defined in hsocket.h
int read_socket(int fd, char *ptr, int nbytes);
int write_socket(int fd, const char *ptr, int nbytes);
*/
#define close_socket w32_close_socket
#define hif_nametoindex w32_if_nametoindex
#define hinet_ntop w32_inet_ntop
#define hinet_pton w32_inet_pton
#else
/* Now defined in hsocket.h
int read_socket(int fd, char *ptr, int nbytes);
int write_socket(int fd, const char *ptr, int nbytes);
*/
#define close_socket(f) close(f)
#define hif_nametoindex if_nametoindex
#define hinet_ntop inet_ntop
#define hinet_pton inet_pton
#endif
#ifdef _MSVC_
#undef FD_SET
#undef FD_ISSET
#define FD_SET w32_FD_SET
#define FD_ISSET w32_FD_ISSET
#define select(n,r,w,e,t) w32_select((n),(r),(w),(e),(t),__FILE__,__LINE__)
#define fdopen w32_fdopen
#define fwrite w32_fwrite
#define fprintf w32_fprintf
#define fclose w32_fclose
#define basename w32_basename
#define dirname w32_dirname
#ifndef strcasestr
#define strcasestr w32_strcasestr
#endif
#endif
#ifdef _MSVC_
#define fdatasync _commit
#define atoll _atoi64
#else /* !_MSVC_ */
#if !defined(HAVE_FDATASYNC_SUPPORTED)
#ifdef HAVE_FSYNC
#define fdatasync fsync
#else
#error Required 'fdatasync' function is missing and alternate 'fsync' function also missing
#endif
#endif
#define atoll(s) strtoll(s,NULL,0)
#endif
/*-------------------------------------------------------------------*/
/* Portable macro for copying 'va_list' variable arguments variable */
/*-------------------------------------------------------------------*/
// ZZ FIXME: this should probably be handled in configure.ac...
#if !defined( va_copy )
#if defined( __va_copy )
#define va_copy __va_copy
#elif defined( _MSVC_ )
#define va_copy(to,from) (to) = (from)
#else
#define va_copy(to,from) memcpy((to),(from),sizeof(va_list))
#endif
#endif
/*-------------------------------------------------------------------*/
/* Handle newer RUSAGE_THREAD definition for older Linux levels */
/* before 2.6.4 along with *nix systems not supporting... */
/*-------------------------------------------------------------------*/
// ZZ FIXME: this should probably be handled in configure.ac...
#if !defined(RUSAGE_THREAD) && !defined(_MSVC_)
#define RUSAGE_THREAD thread_id()
#endif
/*-------------------------------------------------------------------*/
/* Some handy quantity definitions */
/*-------------------------------------------------------------------*/
#define ONE_KILOBYTE ((U32) (1024)) /* 2^10 (16^2) * 4 */
#define TWO_KILOBYTE ((U32)(2 * 1024)) /* 2^11 (16^2) * 8 */
#define FOUR_KILOBYTE ((U32)(4 * 1024)) /* 2^12 (16^3) */
#define _64_KILOBYTE ((U32)(64 * 1024)) /* 2^16 (16^4) */
#define HALF_MEGABYTE ((U32)(512 * 1024)) /* 2^19 (16^4) * 8 */
#define ONE_MEGABYTE ((U32)(1024 * 1024)) /* 2^20 (16^5) */
#define ONE_GIGABYTE ((U64)ONE_MEGABYTE * (U64) (1024)) /* 2^30 (16^7) * 4 */
#define ONE_TERABYTE (ONE_GIGABYTE * (U64) (1024)) /* 2^40 (16^10) */
#define ONE_PETABYTE (ONE_TERABYTE * (U64) (1024)) /* 2^50 (16^12) * 4 */
#define ONE_EXABYTE (ONE_PETABYTE * (U64) (1024)) /* 2^60 (16^15) */
#if defined(U128)
#define ONE_ZETTABYTE (ONE_EXABYTE * (U128)(1024)) /* 2^70 (16^17) * 4 */
#define ONE_YOTTABYTE (ONE_ZETTABYTE * (U128)(1024)) /* 2^80 (16^20) */
#endif
#define SHIFT_KILOBYTE 10
#define SHIFT_64KBYTE 16
#define SHIFT_MEGABYTE 20
#define SHIFT_GIGABYTE 30
#define SHIFT_TERABYTE 40
#define SHIFT_PETABYTE 50
#define SHIFT_EXABYTE 60
#define SHIFT_ZETTABYTE 70
#define SHIFT_YOTTABYTE 80
/* IEC Binary Prefixes, etc */
#define ONE_KIBIBYTE ((U32) (1024)) /* 2^10 (16^2) * 4 */
#define TWO_KIBIBYTE ((U32)(2 * 1024)) /* 2^11 (16^2) * 8 */
#define FOUR_KIBIBYTE ((U32)(4 * 1024)) /* 2^12 (16^3) */
#define _64_KIBIBYTE ((U32)(64 * 1024)) /* 2^16 (16^4) */
#define HALF_MEBIBYTE ((U32)(512 * 1024)) /* 2^19 (16^4) * 8 */
#define ONE_MEBIBYTE ((U32)(1024 * 1024)) /* 2^20 (16^5) */
#define ONE_GIBIBYTE ((U64)ONE_MEBIBYTE * (U64) (1024)) /* 2^30 (16^7) * 4 */
#define ONE_TEBIBYTE (ONE_GIBIBYTE * (U64) (1024)) /* 2^40 (16^10) */
#define ONE_PEBIBYTE (ONE_TEBIBYTE * (U64) (1024)) /* 2^50 (16^12) * 4 */
#define ONE_EXBIBYTE (ONE_PEBIBYTE * (U64) (1024)) /* 2^60 (16^15) */
#if defined(U128)
#define ONE_ZEBIBYTE (ONE_EXBIBYTE * (U128)(1024)) /* 2^70 (16^17) * 4 */
#define ONE_YOBIBYTE (ONE_ZEBIBYTE * (U128)(1024)) /* 2^80 (16^20) */
#endif
#define SHIFT_KIBIBYTE 10
#define SHIFT_MEBIBYTE 20
#define SHIFT_GIBIBYTE 30
#define SHIFT_TEBIBYTE 40
#define SHIFT_PEBIBYTE 50
#define SHIFT_EXBIBYTE 60
#define SHIFT_ZEBIBYTE 70
#define SHIFT_YOBIBYTE 80
/* US VERSIONS */
#define ONE_HUNDRED ((U32) (100)) /* zeros = 2 */
#define ONE_THOUSAND ((U32) (1000)) /* zeros = 3 */
#define ONE_MILLION ((U32)(1000 * 1000)) /* zeros = 6 */
#define ONE_BILLION ((U64)ONE_MILLION * (U64)(1000)) /* zeros = 9 */
#define ONE_TRILLION ((U64)ONE_BILLION * (U64)(1000)) /* zeros = 12 */
#define ONE_QUADRILLION ((U64)ONE_TRILLION * (U64)(1000)) /* zeros = 15 */
#define ONE_QUINTILLION ((U64)ONE_QUADRILLION * (U64)(1000)) /* zeros = 18 */
#define ONE_SEXTILLION ((U64)ONE_QUINTILLION * (U64)(1000)) /* zeros = 21 */
#define ONE_SEPTILLION ((U64)ONE_SEXTILLION * (U64)(1000)) /* zeros = 24 */
/*-------------------------------------------------------------------*/
/* Some handy memory/string comparison macros */
/*-------------------------------------------------------------------*/
#define mem_eq(_a,_b,_n) (!memcmp(_a,_b,_n))
#define mem_ne(_a,_b,_n) ( memcmp(_a,_b,_n))
#define str_eq(_a,_b) (!strcmp(_a,_b))
#define str_ne(_a,_b) ( strcmp(_a,_b))
#define str_eq_n(_a,_b,_n) (!strncmp(_a,_b,_n))
#define str_ne_n(_a,_b,_n) ( strncmp(_a,_b,_n))
#define str_caseless_eq(_a,_b) (!strcasecmp(_a,_b))
#define str_caseless_ne(_a,_b) ( strcasecmp(_a,_b))
#define str_caseless_eq_n(_a,_b,_n) (!strncasecmp(_a,_b,_n))
#define str_caseless_ne_n(_a,_b,_n) ( strncasecmp(_a,_b,_n))
/*-------------------------------------------------------------------*/
/* Large File Support portability */
/*-------------------------------------------------------------------*/
#ifdef _MSVC_
/* "Native" 64-bit Large File Support */
#define off_t __int64
#if (_MSC_VER >= VS2005)
#define ftruncate _chsize_s
#define ftell _ftelli64
#define fseek _fseeki64
#else // (_MSC_VER < VS2005)
#define ftruncate w32_ftrunc64
#define ftell w32_ftelli64
#define fseek w32_fseeki64
#endif
#define lseek _lseeki64
#define fstat _fstati64
#define stat _stati64
#elif defined(_LFS_LARGEFILE) || ( defined(SIZEOF_OFF_T) && SIZEOF_OFF_T > 4 )
/* Native 64-bit Large File Support */
#if defined(HAVE_FSEEKO)
#define ftell ftello
#define fseek fseeko
#else
#if defined(SIZEOF_LONG) && SIZEOF_LONG <= 4
#warning fseek/ftell use offset arguments of insufficient size
#endif
#endif
#elif defined(_LFS64_LARGEFILE)
/* Transitional 64-bit Large File Support */
#define off_t off64_t
#define ftruncate ftruncate64
#define ftell ftello64
#define fseek fseeko64
#define lseek lseek64
#define fstat fstat64
#define stat stat64
#else // !defined(_LFS_LARGEFILE) && !defined(_LFS64_LARGEFILE) && (!defined(SIZEOF_OFF_T) || SIZEOF_OFF_T <= 4)
/* No 64-bit Large File Support at all */
#warning Large File Support missing
#endif
// Hercules low-level file open...
// PROGRAMMING NOTE: the "##" preceding "__VA_ARGS__" is required for compat-
// ibility with gcc/MSVC compilers and must not be removed
#ifdef _MSVC_
#define HOPEN(_p,_o,...) w32_hopen ((_p),(_o), ## __VA_ARGS__)
#else
#define HOPEN(_p,_o,...) hopen ((_p),(_o), ## __VA_ARGS__)
#endif
/*-------------------------------------------------------------------*/
/* Macro for command parsing with variable length */
/*-------------------------------------------------------------------*/
#define CMD(str,cmd,min) ( strcaseabbrev(#cmd,str,min) )
#define NCMP(_lvar,_rvar,_svar) ( !memcmp( _lvar, _rvar, _svar ) )
#define SNCMP(_lvar,_rvar,_svar) ( !strncasecmp( _lvar, _rvar, _svar ) )
/*-------------------------------------------------------------------*/
/* Script processing constants */
/*-------------------------------------------------------------------*/
#define MAX_SCRIPT_STMT 1024 /* Max script stmt length */
#define MAX_SCRIPT_DEPTH 10 /* Max script nesting depth */
/*-------------------------------------------------------------------*/
/* Debugging / Tracing macros. */
/*-------------------------------------------------------------------*/
#define MLVL( _lvl) \
(sysblk.msglvl & (MLVL_ ## _lvl))
/* Obsolete NLS support macro */
#define _(_string) _string
/* Opcode routing table function pointer */
typedef void (ATTR_REGPARM(2)*FUNC)();
/* Program Interrupt function pointer */
typedef void (ATTR_REGPARM(2) *pi_func) (REGS *regs, int pcode);
/* trace_br function */
typedef U32 (*s390_trace_br_func) (int amode, U32 ia, REGS *regs);
typedef U64 (*z900_trace_br_func) (int amode, U64 ia, REGS *regs);
/* qsort comparison function typedef */
typedef int CMPFUNC(const void*, const void*);
/*-------------------------------------------------------------------*/
/* CPU state related macros and constants */
/*-------------------------------------------------------------------*/
/* Definitions for CPU state */
#define CPUSTATE_STARTED 1 /* CPU is started */
#define CPUSTATE_STOPPING 2 /* CPU is stopping */
#define CPUSTATE_STOPPED 3 /* CPU is stopped */
#define IS_CPU_ONLINE(_cpu) \
(sysblk.regs[(_cpu)] != NULL)
/* Instruction count for a CPU */
#define INSTCOUNT(_regs) \
((_regs)->hostregs->prevcount + (_regs)->hostregs->instcount)
/*-------------------------------------------------------------------*/
/* Obtain/Release mainlock */
/* mainlock is only obtained by a CPU thread */
/*-------------------------------------------------------------------*/
#define OBTAIN_MAINLOCK(_regs) \
do { \
if ((_regs)->hostregs->cpubit != (_regs)->sysblk->started_mask) { \
obtain_lock(&(_regs)->sysblk->mainlock); \
(_regs)->sysblk->mainowner = regs->hostregs->cpuad; \
} \
} while (0)
#define RELEASE_MAINLOCK(_regs) \
do { \
if ((_regs)->sysblk->mainowner == (_regs)->hostregs->cpuad) { \
(_regs)->sysblk->mainowner = LOCK_OWNER_NONE; \
release_lock(&(_regs)->sysblk->mainlock); \
} \
} while (0)
/*-------------------------------------------------------------------*/
/* Obtain/Release crwlock */
/* crwlock can be obtained by any thread */
/*-------------------------------------------------------------------*/
#define OBTAIN_CRWLOCK() obtain_lock( &sysblk.crwlock )
#define RELEASE_CRWLOCK() release_lock( &sysblk.crwlock )
/*-------------------------------------------------------------------*/
/* Returns when all other CPU threads are blocked on intlock */
/*-------------------------------------------------------------------*/
#ifdef OPTION_SYNCIO
#define AT_SYNCPOINT(_regs) ((_regs)->intwait || (_regs)->syncio)
#else // OPTION_NOSYNCIO
#define AT_SYNCPOINT(_regs) ((_regs)->intwait)
#endif // OPTION_SYNCIO
/*-------------------------------------------------------------------*/
/* Synchronize CPUS */
/* Locks used: INTLOCK(regs) */
/*-------------------------------------------------------------------*/
#define SYNCHRONIZE_CPUS(_regs) \
synchronize_cpus(_regs)
/*-------------------------------------------------------------------*/
/* Macro to check if DEVBLK is for an existing device */
/*-------------------------------------------------------------------*/
#if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
#define IS_DEV(_dev) \
((_dev)->allocated && (((_dev)->pmcw.flag5 & PMCW5_V) || (_dev) == sysblk.sysgdev))
#else // !defined(_FEATURE_INTEGRATED_3270_CONSOLE)
#define IS_DEV(_dev) \
((_dev)->allocated && ((_dev)->pmcw.flag5 & PMCW5_V))
#endif // defined(_FEATURE_INTEGRATED_3270_CONSOLE)
/*-------------------------------------------------------------------*/
/* HDL macro to call optional function override */
/*-------------------------------------------------------------------*/
#if defined(OPTION_DYNAMIC_LOAD)
#define HDC1(_func, _arg1) \
((_func) ? (_func) ((_arg1)) : (NULL))
#define HDC2(_func, _arg1,_arg2) \
((_func) ? (_func) ((_arg1),(_arg2)) : (NULL))
#define HDC3(_func, _arg1,_arg2,_arg3) \
((_func) ? (_func) ((_arg1),(_arg2),(_arg3)) : (NULL))
#define HDC4(_func, _arg1,_arg2,_arg3,_arg4) \
((_func) ? (_func) ((_arg1),(_arg2),(_arg3),(_arg4)) : (NULL))
#define HDC5(_func, _arg1,_arg2,_arg3,_arg4,_arg5) \
((_func) ? (_func) ((_arg1),(_arg2),(_arg3),(_arg4),(_arg5)) : (NULL))
#define HDC6(_func, _arg1,_arg2,_arg3,_arg4,_arg5,_arg6) \
((_func) ? (_func) ((_arg1),(_arg2),(_arg3),(_arg4),(_arg5),(_arg6)) : (NULL))
#else
#define HDC1(_func, _arg1) \
(NULL)
#define HDC2(_func, _arg1,_arg2) \
(NULL)
#define HDC3(_func, _arg1,_arg2,_arg3) \
(NULL)
#define HDC4(_func, _arg1,_arg2,_arg3,_arg4) \
(NULL)
#define HDC5(_func, _arg1,_arg2,_arg3,_arg4,_arg5) \
(NULL)
#define HDC6(_func, _arg1,_arg2,_arg3,_arg4,_arg5,_arg6) \
(NULL)
#endif
/*-------------------------------------------------------------------*/
/* Sleep for as long as we like (whole number of seconds) */
/*-------------------------------------------------------------------*/
#define SLEEP(_n) \
do { \
unsigned int rc = (_n); \
while (rc) \
if ((rc = sleep (rc))) \
sched_yield(); \
} while (0)
/*-------------------------------------------------------------------*/
/* CRASH (with hopefully a dump) */
/*-------------------------------------------------------------------*/
#ifdef _MSVC_
#define CRASH() \
do { \
BYTE *p = NULL; \
*p=0; \
} while (0)
#else
#define CRASH() \
do { \
abort(); \
} while (0)
#endif
/*-------------------------------------------------------------------*/
/* Perform standard utility initialization */
/*-------------------------------------------------------------------*/
#if !defined(EXTERNALGUI)
#define INITIALIZE_EXTERNAL_GUI()
#else
#define INITIALIZE_EXTERNAL_GUI() \
do { \
if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0) { \
extgui = 1; \
argv[argc-1] = NULL; \
argc--; \
setvbuf(stderr, NULL, _IONBF, 0); \
setvbuf(stdout, NULL, _IONBF, 0); \
} \
} while (0)
#endif
#if defined(OPTION_MSGLCK)
#define INIT_MSGLCK initialize_lock (&sysblk.msglock);
#else
#define INIT_MSGLCK
#endif
#if defined(OPTION_CONFIG_SYMBOLS)
#define INIT_UTILMSGLVL \
do \
{ \
char *msglvl = (char *)get_symbol( "HERCULES_UTIL_MSGLVL" );\
if ( msglvl != NULL ) \
{ \
sysblk.emsg = EMSG_ON; \
if ( strcasestr(msglvl, "all") ) \
sysblk.msglvl |= MLVL_ANY; \
if ( strcasestr(msglvl, "debug") ) \
sysblk.msglvl |= MLVL_DEBUG | MLVL_DEVICES; \
if ( strcasestr(msglvl, "verbose") )\
sysblk.msglvl |= MLVL_VERBOSE; \
if ( strcasestr(msglvl, "tape") ) \
sysblk.msglvl |= MLVL_TAPE; \
if ( strcasestr(msglvl, "dasd") ) \
sysblk.msglvl |= MLVL_DASD; \
if ( strcasestr(msglvl, "time") ) \
sysblk.emsg |= EMSG_TS; \
} \
} while (0)
#else
#define INIT_UTILMSGLVL
#endif
#define INITIALIZE_UTILITY(name) \
do { \
SET_THREAD_NAME(name); \
INITIALIZE_EXTERNAL_GUI(); \
memset (&sysblk, 0, sizeof(SYSBLK)); \
INIT_MSGLCK \
initialize_detach_attr (DETACHED); \
initialize_join_attr (JOINABLE); \
set_codepage(NULL); \
init_hostinfo( &hostinfo ); \
INIT_UTILMSGLVL; \
} while (0)
/*-------------------------------------------------------------------*/
/* Assign name to thread (debugging aid) */
/*-------------------------------------------------------------------*/
#ifdef _MSVC_
#define SET_THREAD_NAME_ID(t,n) w32_set_thread_name((t),(n))
#define SET_THREAD_NAME(n) SET_THREAD_NAME_ID(GetCurrentThreadId(),(n))
#else
#define SET_THREAD_NAME_ID(t,n)
#define SET_THREAD_NAME(n)
#endif
#if !defined(NO_SETUID)
/* SETMODE(INIT)
* sets the saved uid to the effective uid, and
* sets the effective uid to the real uid, such
* that the program is running with normal user
* attributes, other then that it may switch to
* the saved uid by SETMODE(ROOT). This call is
* usually made upon entry to the setuid program.
*
* SETMODE(ROOT)
* sets the saved uid to the real uid, and
* sets the real and effective uid to the saved uid.
* A setuid root program will enter 'root mode' and
* will have all the appropriate access.
*
* SETMODE(USER)
* sets the real and effective uid to the uid of the
* caller. The saved uid will be the effective uid
* upon entry to the program (as before SETMODE(INIT))
*
* SETMODE(TERM)
* sets real, effective and saved uid to the real uid
* upon entry to the program. This call will revoke
* any setuid access that the thread/process has. It
* is important to issue this call before an exec to a
* shell or other program that could introduce integrity
* exposures when running with root access.
*/
#if defined(HAVE_SYS_CAPABILITY_H) && defined(HAVE_SYS_PRCTL_H) && defined(OPTION_CAPABILITIES)
#define SETMODE(_x)
#define DROP_PRIVILEGES(_capa) drop_privileges(_capa)
#define DROP_ALL_CAPS() drop_all_caps()
#else
#define DROP_PRIVILEGES(_capa)
#define DROP_ALL_CAPS()
#if defined(HAVE_SETRESUID)
#define _SETMODE_INIT \
do { \
getresuid(&sysblk.ruid,&sysblk.euid,&sysblk.suid); \
getresgid(&sysblk.rgid,&sysblk.egid,&sysblk.sgid); \
setresuid(sysblk.ruid,sysblk.ruid,sysblk.euid); \
setresgid(sysblk.rgid,sysblk.rgid,sysblk.egid); \
} while(0)
#define _SETMODE_ROOT \
do { \
setresuid(sysblk.suid,sysblk.suid,sysblk.ruid); \
} while(0)
#define _SETMODE_USER \
do { \
setresuid(sysblk.ruid,sysblk.ruid,sysblk.suid); \
} while(0)
#define _SETMODE_TERM \
do { \
setresuid(sysblk.ruid,sysblk.ruid,sysblk.ruid); \
setresgid(sysblk.rgid,sysblk.rgid,sysblk.rgid); \
} while(0)
#elif defined(HAVE_SETREUID)
#define _SETMODE_INIT \
do { \
sysblk.ruid = getuid(); \
sysblk.euid = geteuid(); \
sysblk.rgid = getgid(); \
sysblk.egid = getegid(); \
setreuid(sysblk.euid, sysblk.ruid); \
setregid(sysblk.egid, sysblk.rgid); \
} while (0)
#define _SETMODE_ROOT \
do { \
setreuid(sysblk.ruid, sysblk.euid); \
setregid(sysblk.rgid, sysblk.egid); \
} while (0)
#define _SETMODE_USER \
do { \
setregid(sysblk.egid, sysblk.rgid); \
setreuid(sysblk.euid, sysblk.ruid); \
} while (0)
#define _SETMODE_TERM \
do { \
setuid(sysblk.ruid); \
setgid(sysblk.rgid); \
} while (0)
#else /* defined(HAVE_SETRESUID) || defined(HAVE_SETEREUID) */
#error Cannot figure out how to swap effective UID/GID, maybe you should define NO_SETUID?
#endif /* defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) */
#define SETMODE(_func) _SETMODE_ ## _func
#endif /* !defined(HAVE_SYS_CAPABILITY_H) */
#else /* !defined(NO_SETUID) */
#define SETMODE(_func)
#define DROP_PRIVILEGES(_capa)
#define DROP_ALL_CAPS()
#endif /* !defined(NO_SETUID) */
/*-------------------------------------------------------------------*/
/* Pipe signaling (thread signaling via pipe) */
/*-------------------------------------------------------------------*/
#define RECV_PIPE_SIGNAL( rfd, lock, flag ) \
do { \
int f; int saved_errno=get_HSO_errno(); BYTE c=0; \
obtain_lock(&(lock)); \
if ((f=(flag))>=1) (flag)=0; \
release_lock(&(lock)); \
if (f>=1) \
VERIFY(read_pipe((rfd),&c,1)==1); \
set_HSO_errno(saved_errno); \
} while (0)
#define SEND_PIPE_SIGNAL( wfd, lock, flag ) \
do { \
int f; int saved_errno=get_HSO_errno(); BYTE c=0; \
obtain_lock(&(lock)); \
if ((f=(flag))<=0) (flag)=1; \
release_lock(&(lock)); \
if (f<=0) \
VERIFY(write_pipe((wfd),&c,1)==1); \
set_HSO_errno(saved_errno); \
} while (0)
#define SUPPORT_WAKEUP_SELECT_VIA_PIPE( pipe_rfd, maxfd, prset ) \
FD_SET((pipe_rfd),(prset)); \
(maxfd)=(maxfd)>(pipe_rfd)?(maxfd):(pipe_rfd)
#define SUPPORT_WAKEUP_CONSOLE_SELECT_VIA_PIPE( maxfd, prset ) SUPPORT_WAKEUP_SELECT_VIA_PIPE( sysblk.cnslrpipe, (maxfd), (prset) )
#define SUPPORT_WAKEUP_SOCKDEV_SELECT_VIA_PIPE( maxfd, prset ) SUPPORT_WAKEUP_SELECT_VIA_PIPE( sysblk.sockrpipe, (maxfd), (prset) )
#define RECV_CONSOLE_THREAD_PIPE_SIGNAL() RECV_PIPE_SIGNAL( sysblk.cnslrpipe, sysblk.cnslpipe_lock, sysblk.cnslpipe_flag )
#define RECV_SOCKDEV_THREAD_PIPE_SIGNAL() RECV_PIPE_SIGNAL( sysblk.sockrpipe, sysblk.sockpipe_lock, sysblk.sockpipe_flag )
#define SIGNAL_CONSOLE_THREAD() SEND_PIPE_SIGNAL( sysblk.cnslwpipe, sysblk.cnslpipe_lock, sysblk.cnslpipe_flag )
#define SIGNAL_SOCKDEV_THREAD() SEND_PIPE_SIGNAL( sysblk.sockwpipe, sysblk.sockpipe_lock, sysblk.sockpipe_flag )
/*********************************************************************/
/* */
/* Define compiler error bypasses */
/* */
/*********************************************************************/
/* MS VC Bug ID 363375 Bypass
*
* Note: This error, or similar, also occurs at VS 2010 and
* VS 2012.
*
* TODO: Verify if fixed in VS 2013 and/or VS 2014.
*
*/
#if defined( _MSC_VER ) && ( _MSC_VER >= VS2008 )
# define ENABLE_VS_BUG_ID_363375_BYPASS \
__pragma( optimize( "", off ) ) \
__pragma( optimize( "t", on ) )
# define DISABLE_VS_BUG_ID_363375_BYPASS \
__pragma( optimize( "", on ) )
#else
# define ENABLE_VS_BUG_ID_363375_BYPASS
# define DISABLE_VS_BUG_ID_363375_BYPASS
#endif
#endif // _HMACROS_H