|
|
1.1 ! root 1: /* genwrap.c */ ! 2: ! 3: /* General cross-platform development wrappers */ ! 4: ! 5: /* $Id: genwrap.c,v 1.47 2004/10/27 22:00:28 rswindell Exp $ */ ! 6: ! 7: /**************************************************************************** ! 8: * @format.tab-size 4 (Plain Text/Source Code File Header) * ! 9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * ! 10: * * ! 11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html * ! 12: * * ! 13: * This library is free software; you can redistribute it and/or * ! 14: * modify it under the terms of the GNU Lesser General Public License * ! 15: * as published by the Free Software Foundation; either version 2 * ! 16: * of the License, or (at your option) any later version. * ! 17: * See the GNU Lesser General Public License for more details: lgpl.txt or * ! 18: * http://www.fsf.org/copyleft/lesser.html * ! 19: * * ! 20: * Anonymous FTP access to the most recent released source is available at * ! 21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net * ! 22: * * ! 23: * Anonymous CVS access to the development source and modification history * ! 24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: * ! 25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login * ! 26: * (just hit return, no password is necessary) * ! 27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src * ! 28: * * ! 29: * For Synchronet coding style and modification guidelines, see * ! 30: * http://www.synchro.net/source.html * ! 31: * * ! 32: * You are encouraged to submit any modifications (preferably in Unix diff * ! 33: * format) via e-mail to [email protected] * ! 34: * * ! 35: * Note: If this box doesn't appear square, then you need to fix your tabs. * ! 36: ****************************************************************************/ ! 37: ! 38: #include <string.h> /* strlen() */ ! 39: #include <stdarg.h> /* vsnprintf() */ ! 40: #include <stdlib.h> /* RAND_MAX */ ! 41: #include <fcntl.h> /* O_NOCTTY */ ! 42: #include <time.h> /* clock() */ ! 43: #include <errno.h> /* errno */ ! 44: #include <ctype.h> /* toupper/tolower */ ! 45: ! 46: #if defined(__unix__) ! 47: #include <sys/ioctl.h> /* ioctl() */ ! 48: #include <sys/utsname.h> /* uname() */ ! 49: /* KIOCSOUND */ ! 50: #if defined(__FreeBSD__) ! 51: #include <sys/kbio.h> ! 52: #elif defined(__linux__) ! 53: #include <sys/kd.h> ! 54: #elif defined(__solaris__) ! 55: #include <sys/kbio.h> ! 56: #include <sys/kbd.h> ! 57: #endif ! 58: #if defined(__OpenBSD__) || defined(__NetBSD__) ! 59: #include <machine/spkr.h> ! 60: #elif defined(__FreeBSD__) ! 61: #include <machine/speaker.h> ! 62: #endif ! 63: #endif /* __unix__ */ ! 64: ! 65: #include "genwrap.h" /* Verify prototypes */ ! 66: ! 67: /****************************************************************************/ ! 68: /* Used to replace snprintf() guarantees to terminate. */ ! 69: /****************************************************************************/ ! 70: int DLLCALL safe_snprintf(char *dst, size_t size, const char *fmt, ...) ! 71: { ! 72: va_list argptr; ! 73: int numchars; ! 74: ! 75: va_start(argptr,fmt); ! 76: numchars= vsnprintf(dst,size,fmt,argptr); ! 77: va_end(argptr); ! 78: dst[size-1]=0; ! 79: #ifdef _MSC_VER ! 80: if(numchars==-1) ! 81: numchars=strlen(dst); ! 82: #endif ! 83: if(numchars>=(int)size && numchars>0) ! 84: numchars=size-1; ! 85: return(numchars); ! 86: } ! 87: ! 88: /****************************************************************************/ ! 89: /* Return last character of string */ ! 90: /****************************************************************************/ ! 91: char* DLLCALL lastchar(const char* str) ! 92: { ! 93: size_t len; ! 94: ! 95: len = strlen(str); ! 96: ! 97: if(len) ! 98: return((char*)&str[len-1]); ! 99: ! 100: return((char*)str); ! 101: } ! 102: ! 103: /****************************************************************************/ ! 104: /* Return character value of C-escaped (\) character */ ! 105: /****************************************************************************/ ! 106: char DLLCALL unescape_char(char ch) ! 107: { ! 108: switch(ch) { ! 109: case '\\': return('\\'); ! 110: case '\'': return('\''); ! 111: case '"': return('"'); ! 112: case '?': return('?'); ! 113: case 'a': return('\a'); ! 114: case 'b': return('\b'); ! 115: case 'f': return('\f'); ! 116: case 'n': return('\n'); ! 117: case 'r': return('\r'); ! 118: case 't': return('\t'); ! 119: case 'v': return('\v'); ! 120: } ! 121: return(ch); ! 122: } ! 123: ! 124: /****************************************************************************/ ! 125: /* Return character value of C-escaped (\) character sequence */ ! 126: /* (supports \Xhh and \0ooo escape sequences) */ ! 127: /* This code currently has problems with sequences like: "\x01blue" */ ! 128: /****************************************************************************/ ! 129: char DLLCALL unescape_char_ptr(const char* str, char** endptr) ! 130: { ! 131: char ch; ! 132: ! 133: if(toupper(*str)=='X') ! 134: ch=(char)strtol(++str,endptr,16); ! 135: else if(isdigit(*str)) ! 136: ch=(char)strtol(++str,endptr,8); ! 137: else { ! 138: ch=unescape_char(*(str++)); ! 139: if(endptr!=NULL) ! 140: *endptr=(char*)str; ! 141: } ! 142: ! 143: return(ch); ! 144: } ! 145: ! 146: /****************************************************************************/ ! 147: /* Unescape a C string, in place */ ! 148: /****************************************************************************/ ! 149: char* DLLCALL unescape_cstr(char* str) ! 150: { ! 151: char ch; ! 152: char* buf; ! 153: char* src; ! 154: char* dst; ! 155: ! 156: if(str==NULL || (buf=strdup(str))==NULL) ! 157: return(NULL); ! 158: ! 159: src=buf; ! 160: dst=str; ! 161: while((ch=*(src++))!=0) { ! 162: if(ch=='\\') /* escape */ ! 163: ch=unescape_char_ptr(src,&src); ! 164: *(dst++)=ch; ! 165: } ! 166: *dst=0; ! 167: free(buf); ! 168: return(str); ! 169: } ! 170: ! 171: /****************************************************************************/ ! 172: /* Convert ASCIIZ string to upper case */ ! 173: /****************************************************************************/ ! 174: #if defined(__unix__) ! 175: char* DLLCALL strupr(char* str) ! 176: { ! 177: char* p=str; ! 178: ! 179: while(*p) { ! 180: *p=toupper(*p); ! 181: p++; ! 182: } ! 183: return(str); ! 184: } ! 185: /****************************************************************************/ ! 186: /* Convert ASCIIZ string to lower case */ ! 187: /****************************************************************************/ ! 188: char* DLLCALL strlwr(char* str) ! 189: { ! 190: char* p=str; ! 191: ! 192: while(*p) { ! 193: *p=tolower(*p); ! 194: p++; ! 195: } ! 196: return(str); ! 197: } ! 198: /****************************************************************************/ ! 199: /* Reverse characters of a string (provided by amcleod) */ ! 200: /****************************************************************************/ ! 201: char* strrev(char* str) ! 202: { ! 203: char t, *i=str, *j=str+strlen(str); ! 204: ! 205: while (i<j) { ! 206: t=*i; *(i++)=*(--j); *j=t; ! 207: } ! 208: return str; ! 209: } ! 210: ! 211: /****************************************************************************/ ! 212: /* Generate a tone at specified frequency for specified milliseconds */ ! 213: /* Thanks to Casey Martin for this code */ ! 214: /****************************************************************************/ ! 215: void DLLCALL unix_beep(int freq, int dur) ! 216: { ! 217: static int console_fd=-1; ! 218: ! 219: #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) ! 220: int speaker_fd=-1; ! 221: tone_t tone; ! 222: ! 223: speaker_fd = open("/dev/speaker", O_WRONLY|O_APPEND); ! 224: if(speaker_fd != -1) { ! 225: tone.frequency=freq; ! 226: tone.duration=dur; ! 227: ioctl(speaker_fd,SPKRTONE,&tone); ! 228: close(speaker_fd); ! 229: return; ! 230: } ! 231: #endif ! 232: ! 233: #if !defined(__GNU__) && !defined(__QNX__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__APPLE__) ! 234: if(console_fd == -1) ! 235: console_fd = open("/dev/console", O_NOCTTY); ! 236: ! 237: if(console_fd != -1) { ! 238: #if defined(__solaris__) ! 239: ioctl(console_fd, KIOCCMD, KBD_CMD_BELL); ! 240: #else ! 241: if(freq != 0) /* Don't divide by zero */ ! 242: ioctl(console_fd, KIOCSOUND, (int) (1193180 / freq)); ! 243: #endif /* solaris */ ! 244: SLEEP(dur); ! 245: #if defined(__solaris__) ! 246: ioctl(console_fd, KIOCCMD, KBD_CMD_NOBELL); /* turn off tone */ ! 247: #else ! 248: ioctl(console_fd, KIOCSOUND, 0); /* turn off tone */ ! 249: #endif /* solaris */ ! 250: } ! 251: #endif ! 252: } ! 253: #endif ! 254: ! 255: /****************************************************************************/ ! 256: /* Return random number between 0 and n-1 */ ! 257: /****************************************************************************/ ! 258: int DLLCALL xp_random(int n) ! 259: { ! 260: float f; ! 261: static BOOL initialized; ! 262: ! 263: if(!initialized) { ! 264: srand(time(NULL)); /* seed random number generator */ ! 265: rand(); /* throw away first result */ ! 266: initialized=TRUE; ! 267: } ! 268: if(n<2) ! 269: return(0); ! 270: f=(float)rand()/(float)RAND_MAX; ! 271: ! 272: return((int)(n*f)); ! 273: } ! 274: ! 275: /****************************************************************************/ ! 276: /* Return ASCII string representation of ulong */ ! 277: /* There may be a native GNU C Library function to this... */ ! 278: /****************************************************************************/ ! 279: #if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__WATCOMC__) ! 280: char* DLLCALL ultoa(ulong val, char* str, int radix) ! 281: { ! 282: switch(radix) { ! 283: case 8: ! 284: sprintf(str,"%lo",val); ! 285: break; ! 286: case 10: ! 287: sprintf(str,"%lu",val); ! 288: break; ! 289: case 16: ! 290: sprintf(str,"%lx",val); ! 291: break; ! 292: default: ! 293: sprintf(str,"bad radix: %d",radix); ! 294: break; ! 295: } ! 296: return(str); ! 297: } ! 298: #endif ! 299: ! 300: /****************************************************************************/ ! 301: /* Write the version details of the current operating system into str */ ! 302: /****************************************************************************/ ! 303: char* DLLCALL os_version(char *str) ! 304: { ! 305: #if defined(__OS2__) && defined(__BORLANDC__) ! 306: ! 307: sprintf(str,"OS/2 %u.%u (%u.%u)",_osmajor/10,_osminor/10,_osmajor,_osminor); ! 308: ! 309: #elif defined(_WIN32) ! 310: ! 311: /* Windows Version */ ! 312: char* winflavor=""; ! 313: OSVERSIONINFO winver; ! 314: ! 315: winver.dwOSVersionInfoSize=sizeof(winver); ! 316: GetVersionEx(&winver); ! 317: ! 318: switch(winver.dwPlatformId) { ! 319: case VER_PLATFORM_WIN32_NT: ! 320: winflavor="NT "; ! 321: break; ! 322: case VER_PLATFORM_WIN32s: ! 323: winflavor="Win32s "; ! 324: break; ! 325: case VER_PLATFORM_WIN32_WINDOWS: ! 326: winver.dwBuildNumber&=0xffff; ! 327: break; ! 328: } ! 329: ! 330: sprintf(str,"Windows %sVersion %u.%u (Build %u) %s" ! 331: ,winflavor ! 332: ,winver.dwMajorVersion, winver.dwMinorVersion ! 333: ,winver.dwBuildNumber,winver.szCSDVersion); ! 334: ! 335: #elif defined(__unix__) ! 336: ! 337: struct utsname unixver; ! 338: ! 339: if(uname(&unixver)<0) ! 340: sprintf(str,"Unix (uname errno: %d)",errno); ! 341: else ! 342: sprintf(str,"%s %s %s" ! 343: ,unixver.sysname /* e.g. "Linux" */ ! 344: ,unixver.release /* e.g. "2.2.14-5.0" */ ! 345: ,unixver.machine /* e.g. "i586" */ ! 346: ); ! 347: ! 348: #else /* DOS */ ! 349: ! 350: sprintf(str,"DOS %u.%02u",_osmajor,_osminor); ! 351: ! 352: #endif ! 353: ! 354: return(str); ! 355: } ! 356: ! 357: #if !defined(__unix__) ! 358: ! 359: /****************************************************************************/ ! 360: /* Win32 implementations of the recursive (thread-safe) versions of std C */ ! 361: /* time functions (gmtime, localtime, ctime, and asctime) used in Unix. */ ! 362: /* The native Win32 versions of these functions are already thread-safe. */ ! 363: /****************************************************************************/ ! 364: ! 365: struct tm* DLLCALL gmtime_r(const time_t* t, struct tm* tm) ! 366: { ! 367: struct tm* tmp = gmtime(t); ! 368: ! 369: if(tmp==NULL) ! 370: return(NULL); ! 371: ! 372: *tm = *tmp; ! 373: return(tm); ! 374: } ! 375: ! 376: struct tm* DLLCALL localtime_r(const time_t* t, struct tm* tm) ! 377: { ! 378: struct tm* tmp = localtime(t); ! 379: ! 380: if(tmp==NULL) ! 381: return(NULL); ! 382: ! 383: *tm = *tmp; ! 384: return(tm); ! 385: } ! 386: ! 387: char* DLLCALL ctime_r(const time_t *t, char *buf) ! 388: { ! 389: char* p = ctime(t); ! 390: ! 391: if(p==NULL) ! 392: return(NULL); ! 393: ! 394: strcpy(buf,p); ! 395: return(buf); ! 396: } ! 397: ! 398: char* DLLCALL asctime_r(const struct tm *tm, char *buf) ! 399: { ! 400: char* p = asctime(tm); ! 401: ! 402: if(p==NULL) ! 403: return(NULL); ! 404: ! 405: strcpy(buf,p); ! 406: return(buf); ! 407: } ! 408: ! 409: #endif /* !defined(__unix__) */ ! 410: ! 411: /********************************************/ ! 412: /* Hi-res real-time clock implementation. */ ! 413: /********************************************/ ! 414: #ifdef __unix__ ! 415: clock_t DLLCALL msclock(void) ! 416: { ! 417: long long int usecs; ! 418: struct timeval tv; ! 419: if(gettimeofday(&tv,NULL)==1) ! 420: return(-1); ! 421: usecs=tv.tv_sec*1000000+tv.tv_usec; ! 422: return((clock_t)(usecs/(1000000/MSCLOCKS_PER_SEC))); ! 423: } ! 424: #endif ! 425: ! 426: /****************************************************************************/ ! 427: /* Truncates all white-space chars off end of 'str' (needed by STRERRROR) */ ! 428: /****************************************************************************/ ! 429: char* DLLCALL truncsp(char* str) ! 430: { ! 431: size_t i,len; ! 432: ! 433: i=len=strlen(str); ! 434: while(i && (str[i-1]==' ' || str[i-1]=='\t' || str[i-1]=='\r' || str[i-1]=='\n')) ! 435: i--; ! 436: if(i!=len) ! 437: str[i]=0; /* truncate */ ! 438: ! 439: return(str); ! 440: } ! 441: ! 442: /****************************************************************************/ ! 443: /* Truncates all white-space chars off end of \n-terminated lines in 'str' */ ! 444: /****************************************************************************/ ! 445: char* DLLCALL truncsp_lines(char* dst) ! 446: { ! 447: char* sp; ! 448: char* dp; ! 449: char* src; ! 450: ! 451: if((src=strdup(dst))==NULL) ! 452: return(dst); ! 453: ! 454: for(sp=src, dp=dst; *sp!=0; sp++) { ! 455: if(*sp=='\n') ! 456: while(dp!=dst ! 457: && (*(dp-1)==' ' || *(dp-1)=='\t' || *(dp-1)=='\r') && *(dp-1)!='\n') ! 458: dp--; ! 459: *(dp++)=*sp; ! 460: } ! 461: *dp=0; ! 462: ! 463: free(src); ! 464: return(dst); ! 465: } ! 466: ! 467: /****************************************************************************/ ! 468: /* Truncates carriage-return and line-feed chars off end of 'str' */ ! 469: /****************************************************************************/ ! 470: char* DLLCALL truncnl(char* str) ! 471: { ! 472: size_t i,len; ! 473: ! 474: i=len=strlen(str); ! 475: while(i && (str[i-1]=='\r' || str[i-1]=='\n')) ! 476: i--; ! 477: if(i!=len) ! 478: str[i]=0; /* truncate */ ! 479: ! 480: return(str); ! 481: } ! 482: ! 483: /****************************************************************************/ ! 484: /* Return errno from the proper C Library implementation */ ! 485: /* (single/multi-threaded) */ ! 486: /****************************************************************************/ ! 487: int DLLCALL get_errno(void) ! 488: { ! 489: return(errno); ! 490: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.