/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department, 
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.  
 * No use of the CONDOR Software Program Source Code is authorized 
 * without the express consent of the CONDOR Team.  For more information 
 * contact: CONDOR Team, Attention: Professor Miron Livny, 
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685, 
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure 
 * by the U.S. Government is subject to restrictions as set forth in 
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer 
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and 
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR 
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron 
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison, 
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

/*
This file contains the collected Condor wisdom of what mechanism is best of trapping and re-invoking each UNIX system call.  This is definitely a work in progress -- entries are added here as we attempt to work with new systems calls and then run into difficulty.
*/

/* Each item in this default rule applies when nothing else has matched.  By default, generate additional entry points beginning with _ and __, and use internal names matching the procedure.  Assume that named functions are system calls, but fall back on a libcall.  HPUX requires that the complete path to a library must be given, while IRIX requires an incomplete path to select the correct ABI.  Other platforms are flexible.  */

options "*"
	entry "_*" "__*" "__libc_*"
	local_name "*"
	remote_name "*"
	syscall
	#ifdef hpux
		library "/usr/lib/libc"
	#else
		library "libc"
	#endif
	;


/* exit() runs all the atexit functions, then calls _exit() which does further cleanup.  _exit() is well-documented, so we don't want the entry feature to interfere with it.  On HPUX, ___exit() is the internal interface to "normal exit", and _exit is the interface to "fast exit". */

options "exit"
	libcall
	#ifdef hpux
		entry "___exit"
	#else
		entry "none"
	#endif
	;

/* These functions have unusual calling conventions, so we must always use the library */

options "mmap" libcall;
options "pipe" libcall;
options "fork" libcall;
options "getuid" libcall;
options "truncate" libcall;
options "getppid" libcall;
options "geteuid" libcall;
options "getegid" libcall;

options "open"
	entry "_open" "__open" "open64" "_open64" "__open64"
	external "char *" "open_flags_t"
	also
	{{
		int creat( const char *path, mode_t mode ) {
			return open( path, O_CREAT|O_WRONLY|O_TRUNC, mode );
		}
		int _creat( const char *path, mode_t mode ) {
			return creat( path, mode );
		}
		int __creat( const char *path, mode_t mode ) {
			return creat( path, mode );
		}
		int creat64( const char *path, mode_t mode ) {
			return creat( path, mode );
		}
		int _creat64( const char *path, mode_t mode ) {
			return creat( path, mode );
		}
		int __creat64( const char *path, mode_t mode ) {
			return creat( path, mode );
		}
	}}
	;

options "fcntl"
	external "int" "fcntl_cmd_t"
	;

options "lseek"
	entry "_lseek" "__lseek"
	also
	{{
		long long llseek( int fd, long long offset, int whence ) {
			return lseek( fd, offset, whence );
		}
		long long _llseek( int fd, long long offset, int whence ) {
			return lseek( fd, offset, whence );
		}
		long long __llseek( int fd, long long offset, int whence ) {
			return lseek( fd, offset, whence );
		}
		long long lseek64( int fd, long long offset, int whence ) {
			return lseek( fd, offset, whence );
		}
		long long _lseek64( int fd, long long offset, int whence ) {
			return lseek( fd, offset, whence );
		}
		long long __lseek64( int fd, long long offset, int whence ) {
			return lseek( fd, offset, whence );
		}
	}};


#if defined(sun) || defined(sgi) || defined(linux)

agent_prologue {{

	extern "C" {
		@include <sys/types.h>
		@include <sys/stat.h>
		@include <string.h>
		@include <sys/time.h>
	}

	#ifdef linux
		struct stat64
		{
			unsigned long long st_dev;
			unsigned short int __pad1;
			unsigned long int st_ino;
			unsigned long int  st_mode;
			unsigned long int  st_nlink;
			unsigned long int  st_uid;
			unsigned long int  st_gid;
			unsigned long long st_rdev;
			unsigned short int __pad2;
			unsigned long long st_size;
			unsigned long int  st_blksize;
			unsigned long long st_blocks;
			unsigned long int  st_atime;
			unsigned long int  __unused1;
			unsigned long int  st_mtime;
			unsigned long int  __unused2;
			unsigned long int  st_ctime;
			unsigned long int  __unused3;
			unsigned long int  __unused4;
			unsigned long int  __unused5;
		};

		@define st_atim st_atime
		@define st_mtim st_mtime
		@define st_ctim st_ctime

		@define TRAP_STAT64

		@ifndef _STAT_VER
			@define _STAT_VER 3
		@endif
	#endif

	#if defined(sun) || defined(sgi)
		@ifdef _STAT_VER
			@define TRAP_STAT64
		@else
			@define _STAT_VER 2
			@define TRAP_STAT
		@endif
	#endif

	@ifdef TRAP_STAT64
		static void convert_stat64( int version, struct stat *source, struct stat64 *target )
		{
			memset( target, 0, sizeof(*target) );
			target->st_dev = source->st_dev;
			target->st_ino = source->st_ino;
			target->st_mode = source->st_mode;
			target->st_nlink = source->st_nlink;
			target->st_uid = source->st_uid;
			target->st_gid = source->st_gid;
			target->st_rdev = source->st_rdev;
			target->st_size = source->st_size;
			target->st_atim = source->st_atim;
			target->st_mtim = source->st_mtim;
			target->st_ctim = source->st_ctim;
			target->st_blksize = source->st_blksize;
			target->st_blocks = source->st_blocks;
			#ifdef sun
				strcpy(target->st_fstype,source->st_fstype);
			#endif
		}
	@endif

	static void convert_stat( int version, struct stat *source, struct stat *dest )
	{
		#if defined(sun) || defined(sgi)
			@ifdef TRAP_STAT64
				if( version==3 ) {
					convert_stat64( version, source, (struct stat64 *)dest );
				} else {
					memcpy( dest, source, sizeof(*dest) );
				}
			@else
				memcpy( dest, source, sizeof(*dest) );
			@endif				
		#else
			memcpy( dest, source, sizeof(*dest) );
		#endif

	}

	@define XSTAT_SWITCH( entry, name, qname, type_one, type_two, type_three, cast, convert ) \
		extern "C" int entry ( type_one v, type_two n, type_three * s )\
		{\
			int result;\
			struct stat buf;\
			\
			if( bypass_mode_get() == BYPASS_MODE_REMOTE ) {\
				int bypass_mode = bypass_mode_set(BYPASS_MODE_LOCAL);\
				result = bypass_agent_action_##name( (cast) n, &buf );\
				bypass_mode_set(bypass_mode);\
				convert ( v, &buf, s );\
			} else {\
				static void *handle = 0;\
				if(!handle) handle = bypass_library_open("libc.so");\
				if(!handle) handle = bypass_library_open("libc.so.6");\
				if(!handle) bypass_handle_error(BYPASS_CALL_##name,BYPASS_ERROR_CANNOT_FIND_LIBRARY);\
				static int (*fptr)( type_one v, type_two n, type_three * s ) = 0;\
				if(!fptr) fptr = (int(*)(type_one v, type_two n, type_three * s)) bypass_library_lookup(handle,qname);\
				if(!fptr) bypass_handle_error(BYPASS_CALL_##name,BYPASS_ERROR_CANNOT_FIND_PROCEDURE);\
				result = fptr( v, n, s );\
			}\
			return result;\
		}

	@define PLAIN_SWITCH( entry, type_one, type_two, cast ) \
		extern "C" int entry ( type_one n, type_two *s ) \
		{\
			int result;\
			if( bypass_mode_get() == BYPASS_MODE_REMOTE ) {\
				int bypass_mode = bypass_mode_set(BYPASS_MODE_LOCAL);\
				result = bypass_agent_action_##entry( (cast) n, s );\
				bypass_mode_set(bypass_mode);\
			} else {\
				result = syscall( SYS_##entry, n, s );\
			}\
			return result;\
		}

	@define PLAIN_ENTRIES( entry, type_one, type_two ) \
		extern "C" int _##entry ( type_one path, type_two * buf ) {\
			return entry ( path, buf );\
		}\
		extern "C" int __##entry ( type_one path, type_two * buf ) {\
			return entry ( path, buf );\
		}

	@define XSTAT_ENTRIES( entry, type_one, type_two, calls, version, cast ) \
		extern "C" int entry ( type_one path, type_two * buf ) {\
			return calls ( version, path, (cast) buf );\
		}\
		extern "C" int _##entry ( type_one path, type_two * buf ) {\
			return calls ( version, path, (cast) buf );\
		}\
		extern "C" int __##entry ( type_one path, type_two * buf ) {\
			return calls ( version, path, (cast) buf );\
		}
}};


options "stat"
	switch_code
	{{
		@ifdef __GLIBC__
			XSTAT_SWITCH( __xstat, stat, "__xstat", int, const char *, struct stat, char *, convert_stat )
			XSTAT_SWITCH( __xstat64, stat, "__xstat64", int, const char *, struct stat64, char *, convert_stat64 )
		@else
			XSTAT_SWITCH( _xstat, stat, "_xstat", int, const char *, struct stat, char *, convert_stat )
		@endif

		@ifdef TRAP_STAT
			PLAIN_SWITCH( stat, const char *, struct stat, char * )
			PLAIN_ENTRIES( stat, const char *, struct stat )
		@endif

		@ifdef TRAP_STAT64
			@ifdef __GLIBC__
				XSTAT_ENTRIES( stat64, const char *, struct stat64, __xstat64, _STAT_VER, struct stat64 * )
			@else
				XSTAT_ENTRIES( stat64, const char *, struct stat64, _xstat, 3, struct stat *)
			@endif
		@endif
	}}
	;


options "lstat"
	switch_code
	{{
		@ifdef __GLIBC__
			XSTAT_SWITCH( __lxstat, lstat, "__lxstat", int, const char *, struct stat, char *, convert_stat )
			XSTAT_SWITCH( __lxstat64, lstat, "__lxstat64", int, const char *, struct stat64, char *, convert_stat64 )
		@else
			XSTAT_SWITCH( _lxstat, lstat, "_lxstat", int, const char *, struct stat, char *, convert_stat )
		@endif

		@ifdef TRAP_STAT
			PLAIN_SWITCH( lstat, const char *, struct stat, char * )
			PLAIN_ENTRIES( lstat, const char *, struct stat )
		@endif

		@ifdef TRAP_STAT64
			@ifdef __GLIBC__
				XSTAT_ENTRIES( lstat64, const char *, struct stat64, __lxstat64, _STAT_VER, struct stat64 * )
			@else
				XSTAT_ENTRIES( lstat64, const char *, struct stat64, _lxstat, 3, struct stat *)
			@endif
		@endif
	}}
	;

options "fstat"
	switch_code
	{{
		@ifdef __GLIBC__
			XSTAT_SWITCH( __fxstat, fstat, "__fxstat", int, int, struct stat, int, convert_stat )
			XSTAT_SWITCH( __fxstat64, fstat, "__fxstat64", int, int, struct stat64, int, convert_stat64 )
		@else
			XSTAT_SWITCH( _fxstat, fstat, "_fxstat", int, int, struct stat, int, convert_stat )
		@endif

		@ifdef TRAP_STAT
			PLAIN_SWITCH( fstat, int, struct stat, int )
			PLAIN_ENTRIES( fstat, int, struct stat )
		@endif

		@ifdef TRAP_STAT64
			@ifdef __GLIBC__
				XSTAT_ENTRIES( fstat64, int, struct stat64, __fxstat64, _STAT_VER, struct stat64 * )
			@else
				XSTAT_ENTRIES( fstat64, int, struct stat64, _fxstat, 3, struct stat *)
			@endif
		@endif
	}}
	;

#endif



/* In Solaris, the BSD socket functions are implemented on top of a different set of system calls.  So, all socket related calls are directed to libsocket. */

#ifdef sun
options "socket" libcall library "/lib/libsocket";
options "recvmsg" libcall library "/lib/libsocket";
options "sendmsg" libcall library "/lib/libsocket";
options "recvfrom" libcall library "/lib/libsocket";
options "accept" libcall library "/lib/libsocket";
options "getpeername" libcall library "/lib/libsocket";
options "getsockname" libcall library "/lib/libsocket";
options "connect" libcall library "/lib/libsocket";
options "send" libcall library "/lib/libsocket";
options "recv" libcall library "/lib/libsocket";
options "bind" libcall library "/lib/libsocket";
options "listen" libcall library "/lib/libsocket";
options "sendto" libcall library "/lib/libsocket";
options "shutdown" libcall library "/lib/libsocket";
options "socketpair" libcall library "/lib/libsocket";
options "getsockopt" libcall library "/lib/libsocket";
options "setsockopt" libcall library "/lib/libsocket";
#endif

/* In Linux, the BSD socket functions are indirect system calls through SYS_socketcall.  It turns out that these definitions are in different places in different versions, so we will just make this a libcall to be safe.  */

#ifdef linux

options "socket" libcall;
options "recvmsg" libcall;
options "sendmsg" libcall;
options "recvfrom" libcall;
options "accept" libcall;
options "getpeername" libcall;
options "getsockname" libcall;
options "connect" libcall;
options "send" libcall;
options "recv" libcall;
options "bind" libcall;
options "listen" libcall;
options "sendto" libcall;
options "shutdown" libcall;
options "socketpair" libcall;
options "getsockopt" libcall;
options "setsockopt" libcall;
#endif

options "gl*" libcall library "libGL";
options "glu*" libcall library "libGLU";
options "glut*" libcall library "libglut";

