diff --git a/xtrn/sdk/xsdkwrap.c b/xtrn/sdk/xsdkwrap.c index 18a491c1816a2cddb1dab4240629f69da7b09480..c642a31b10a1ae48215eb96e358c1778e3d67326 100644 --- a/xtrn/sdk/xsdkwrap.c +++ b/xtrn/sdk/xsdkwrap.c @@ -1,6 +1,6 @@ /* xsdkwrap.c */ -/* Synchronet XSDK system-call wrappers */ +/* Synchronet XSDK system-call wrappers (compiler & platform portability) */ /* $Id$ */ @@ -42,6 +42,13 @@ #include <string.h> /* strlen() */ #include <unistd.h> /* getpid() */ #include <fcntl.h> /* fcntl() file/record locking */ +#include <stdlib.h> +#include <unistd.h> +#include <termios.h> +#include <sys/kd.h> +#include <sys/time.h> +#include <sys/types.h> +#include <signal.h> #endif @@ -59,6 +66,100 @@ #define STAT struct stat #endif +#ifdef __unix__ + +struct termios current; // our current term settings +struct termios original; // old termios settings +struct timeval timeout = {0, 0}; // passed in select() call +fd_set inp; // ditto +static int beensetup = 0; // has _termios_setup() been called? + +/* + I'm using a variable function here simply for the sake of speed. The + termios functions must be called before a kbhit() can be successful, so + on the first call, we just set up the terminal, point to variable function + to kbhit_norm(), and then call the new function. Otherwise, testing would + be required on every call to determine if termios has already been setup. + + Maybe I'm being way too anal, though. +*/ + +/* Resets the termios to its previous state */ +void _termios_reset(void) +{ + tcsetattr(0, TCSANOW, &original); +} + +/************************************************ + This pair of functions handles Ctrl-Z presses +************************************************/ + +void _sighandler_stop(int sig) +{ + // clean up the terminal + _termios_reset(); + + // ... and stop + kill(getpid(), SIGSTOP); +} + +void _sighandler_cont(int sig) +{ + // restore terminal + tcsetattr(0, TCSANOW, ¤t); +} + + +/* Prepares termios for non-blocking action */ +void _termios_setup(void) +{ + beensetup = 1; + + tcgetattr(0, &original); + + memcpy(¤t, &original, sizeof(struct termios)); + current.c_cc[VMIN] = 1; // read() will return with one char + current.c_cc[VTIME] = 0; // read() blocks forever + current.c_lflag &= ~ICANON; // character mode + current.c_lflag &= ~ECHO; // turn off echoing + tcsetattr(0, TCSANOW, ¤t); + + // Let's install an exit function, also. This way, we can reset + // the termios silently + atexit(_termios_reset); + + // install the Ctrl-Z handler + signal(SIGSTOP, _sighandler_stop); + signal(SIGCONT, _sighandler_cont); +} + + +int kbhit(void) +{ + // set up select() args + FD_ZERO(&inp); + FD_SET(0, &inp); + + return select(1, &inp, NULL, NULL, &timeout); +} + +int getch(void) +{ + char c; + + if (!beensetup) + // I hate to test for this every time, but this shouldn't be + // called that often anyway... + _termios_setup(); + + // get a char out of stdin + read(0, &c, 1); + + return c; +} + +#endif // __unix__ + /****************************************************************************/ /* Convert ASCIIZ string to upper case */ /****************************************************************************/ @@ -278,4 +379,29 @@ int unlock(int file, long offset, int size) return(i); } -#endif /* !Unix && (MSVC || MinGW) */ \ No newline at end of file +#endif /* !Unix && (MSVC || MinGW) */ + +/****************************************************************************/ +/* Return ASCII string representation of ulong */ +/* There may be a native GNU C Library function to this... */ +/****************************************************************************/ +#if !defined _MSC_VER && !defined __BORLANDC__ +char* ultoa(unsigned long val, char* str, int radix) +{ + switch(radix) { + case 8: + sprintf(str,"%lo",val); + break; + case 10: + sprintf(str,"%lu",val); + break; + case 16: + sprintf(str,"%lx",val); + break; + default: + sprintf(str,"bad radix: %d",radix); + break; + } + return(str); +} +#endif diff --git a/xtrn/sdk/xsdkwrap.h b/xtrn/sdk/xsdkwrap.h index e9781d848c7102ce6538ec5e551d2ed4e0334845..fa1af1e6d9c44c9a7933b3a0d773f163f83dc430 100644 --- a/xtrn/sdk/xsdkwrap.h +++ b/xtrn/sdk/xsdkwrap.h @@ -38,9 +38,16 @@ #ifndef _XSDKWRAP_H #define _XSDKWRAP_H -/**********/ -/* Macros */ -/**********/ +#if defined(__unix__) + + int kbhit(void); + int getch(void); + +#else /* DOS-Based */ + + #include <conio.h> + +#endif #if defined(_WIN32) @@ -78,6 +85,66 @@ #endif +#ifdef __unix__ + + #include <pthread.h> /* POSIX threads and mutexes */ + #include <semaphore.h> /* POSIX semaphores */ + ulong _beginthread(void( *start_address )( void * ) + ,unsigned stack_size, void *arglist); + +#elif defined(_WIN32) + + /* POIX semaphores */ + typedef HANDLE sem_t; + #define sem_init(psem,ps,v) ResetEvent(*(psem)) + #define sem_wait(psem) WaitForSingleObject(*(psem),INFINITE) + #define sem_post(psem) SetEvent(*(psem)) + #define sem_destroy(psem) CloseHandle(*(psem)) + + /* POIX mutexes */ + typedef HANDLE pthread_mutex_t; + #define pthread_mutex_init(pmtx,v) *(pmtx)=CreateMutex(NULL,FALSE,NULL) + #define pthread_mutex_lock(pmtx) WaitForSingleObject(*(pmtx),INFINITE) + #define pthread_mutex_unlock(pmtx) ReleaseMutex(*(pmtx)) + #define pthread_mutex_destroy(pmtx) CloseHandle(*(pmtx)) + +#else + + #warning "Need semaphore wrappers." + +#endif + + +#if defined(_WIN32) + + #define mswait(x) Sleep(x) + +#elif defined(__OS2__) + + #define mswait(x) DosSleep(x) + +#elif defined(__unix__) + + #define mswait(x) usleep(x*1000) + #define _mkdir(dir) mkdir(dir,0777) + #define _rmdir(dir) rmdir(dir) + #define tell(fd) lseek(fd,0,SEEK_CUR) + + char* _fullpath(char* absPath, const char* relPath + ,size_t maxLength); + +#elif defined(__MSDOS__) + + void mswait(int ms); /* Wait a specific number of milliseconds */ + +#else /* Unsupported OS */ + + #warning "Unsupported Target: Need some macros of function prototypes here." + +#endif + + + #ifndef BOOL #define BOOL int #endif @@ -106,6 +173,10 @@ extern "C" { char* strlwr(char* str); #endif +#if !defined(_MSC_VER) && !defined(__BORLANDC__) + char* ultoa(unsigned long val, char* str, int radix); +#endif + BOOL fexist(char *filespec); long flength(char *filename);