72 #include <sys/types.h> 75 #include <sys/sysctl.h> 84 #include "file_help.h" 87 #ifdef HAVE_MALLOC_USABLE_SIZE 89 #include <malloc_np.h> 93 #endif // HAVE_MALLOC_USABLE_SIZE 96 static char *pTempFileList = NULL, *pTempFileListEnd = NULL;
97 unsigned long cbTempFileList;
99 static volatile int fInterlockedRWLockInitFlag = 0;
100 static pthread_rwlock_t xInterlockedRWLock;
102 static void WBFreePointerHashes(
void);
103 static void __add_to_temp_file_list(
const char *szFile);
112 static char szAppName[PATH_MAX * 2]=
"";
127 #if !defined(DOXYGEN) && defined(_MSC_VER) 130 int __declspec(selectany) main(
int argc,
char *argv0[],
char *envp0[])
132 int main(
int argc,
char *argv0[],
char *envp0[]) __attribute__((weak)) __attribute__((section(
"text_main")))
143 iRval =
WBMain(argc, argv, envp);
145 if(envp && envp != envp0)
149 if(argv && argv != argv0)
164 #if !defined(DOXYGEN) && defined(_MSC_VER) 167 int __declspec(selectany) __WBMain__(
int argc,
char *argv0[],
char *envp0[])
169 int WBMain(
int argc,
char *argv0[],
char *envp0[]) __attribute__((weak)) __attribute__((section(
"text_wbmain")))
172 fputs(
"You need to define 'WBMain' in your code\n", stderr);
176 #if !defined(DOXYGEN) && defined(_MSC_VER) 179 void __declspec(selectany)
WBUsage(
void)
181 void WBUsage(
void) __attribute__((weak)) __attribute__((section(
"text_wbusage")))
195 if(!fInterlockedRWLockInitFlag)
197 pthread_rwlock_init(&xInterlockedRWLock, NULL);
201 pEnv = getenv(
"LC_ALL");
205 pEnv = getenv(
"LC_CTYPE");
213 pEnv = getenv(
"LANG");
219 if(!setlocale(iType, pEnv))
221 WB_ERROR_PRINT(
"ERROR: %s - cannot set locale \"%s\"\n", __FUNCTION__, pEnv);
229 setlocale(LC_ALL,
"");
240 for(p1 = pTempFileList; *p1; p1 += strlen(p1) + 1)
248 WBFreePointerHashes();
252 if(fInterlockedRWLockInitFlag)
254 pthread_rwlock_destroy(&xInterlockedRWLock);
255 fInterlockedRWLockInitFlag = 0;
258 #ifndef NO_DEBUG // I only do this for builds that have DEBUG capability 274 char **argv = *pargv;
275 char **envp = *penvp;
277 char **argvNew = NULL;
280 int iDebugLevelSeen = 0;
281 int argc_orig = argc;
282 char **argv_orig = argv;
284 static const char *
const aszCmdLineOptions[]=
286 "help",
"help-all",
"debug",
"subsys",
"display",
"minimize",
"maximize",
"geometry",
"no-antialias",
"no-imagecache",
290 static const uint8_t abCmdLineOptions[]=
292 0, 0, 1, 1, 1, 0, 0, 1, 0, 0,
296 static const char *
const aszDebugSubSys[]=
298 "init",
"application",
"window",
"menu",
"event",
299 "dialog",
"dialogctrl",
"frame",
"keyboard",
300 "mouse",
"font",
"settings",
"selection",
301 "pixmap",
"expose",
"editwindow",
"scrollbar",
302 "drawtext",
"clipboard",
"textobject",
318 option_no_image_cache
323 strncpy(szAppName, argv[0],
sizeof(szAppName));
324 szAppName[
sizeof(szAppName) - 1] = 0;
333 if(!strncmp(*p1,
"DISPLAY=", 8))
335 __internal_startup_display(*p1 + 8);
344 char *p1a = getenv(
"DISPLAY");
348 __internal_startup_display(p1a);
359 if(argv[1][0] !=
'-' || !argv[1][1] ||
360 (argv[1][1] ==
'-' && !argv[1][2]))
365 if(argv[1][1] !=
'-')
373 "%s.%d skipping over argument '%s'\n", __FUNCTION__, __LINE__, argv[0]);
378 "%s.%d unrecognized argument '%s'\n", __FUNCTION__, __LINE__, argv[1]);
385 for(i1=0; aszCmdLineOptions[i1]; i1++)
387 const char *szOpt = aszCmdLineOptions[i1];
388 int iLen = strlen(szOpt);
389 const char *szArg = argv[1] + 2;
390 const char *szVal = szArg + iLen;
392 if(!strncmp(szOpt, szArg, iLen) &&
393 (*szVal ==
'=' || !*szVal))
401 if(abCmdLineOptions[i1] && argc > 2)
423 case option_help_all:
432 if(*szVal < '0' || *szVal >
'7' || i2 < 0 || i2 > DebugLevel_MAXIMUM)
434 WBDebugPrint(
"Invalid debug level %s - must be between 0 and %d\n", szVal, DebugLevel_MAXIMUM);
435 goto argument_error_exit;
439 iWBDebugLevel = (iWBDebugLevel & DebugSubSystem_MASK)
440 | (atoi(szVal) & DebugLevel_MASK);
444 if(!strcmp(
"help", szVal))
449 " Subsystem Name Bit Value (hexadecimal)\n" 450 " ----------------------- ----------- -------------\n");
452 for(i2=0; aszDebugSubSys[i2]; i2++)
454 WBDebugPrint(
" %-24s%10ld %08lxH\n", aszDebugSubSys[i2],
455 1L << (i2 + DebugSubSystem_BITSHIFT),
456 1L << (i2 + DebugSubSystem_BITSHIFT));
461 " restrict 2147483648 80000000H\n\n" 462 "Specify 'restrict' in addition to one or more subsystems in order\n" 463 "to ONLY display debug output for the specified subsystem(s)\n\n");
467 else if(!strcmp(
"restrict", szVal))
469 iWBDebugLevel |= DebugSubSystem_RESTRICT;
471 else if(!strcmp(
"all", szVal))
473 iWBDebugLevel &= ~(DebugSubSystem_MASK | DebugSubSystem_RESTRICT);
477 for(i2=0; aszDebugSubSys[i2]; i2++)
479 if(!strcasecmp(aszDebugSubSys[i2], szVal))
481 iWBDebugLevel |= 1L << (i2 + DebugSubSystem_BITSHIFT);
485 if(!aszDebugSubSys[i2])
488 if(i2 > 0 && (i2 + DebugSubSystem_BITSHIFT) <= 32)
490 iWBDebugLevel |= 1L << (i2 + DebugSubSystem_BITSHIFT - 1);
496 goto argument_error_exit;
505 iWBDebugLevel = (iWBDebugLevel & DebugSubSystem_MASK)
506 | DebugLevel_Excessive;
512 __internal_startup_display(szVal);
515 case option_minimize:
516 __internal_startup_minimize();
518 case option_maximize:
519 __internal_startup_maximize();
521 case option_geometry:
522 __internal_startup_geometry(szVal);
525 case option_no_antialias:
526 __internal_disable_antialias();
529 case option_no_image_cache:
530 __internal_disable_imagecache();
534 WB_ERROR_PRINT(
"%s.%d - Internal error - unrecognized option: --%s\n",
535 __FUNCTION__, __LINE__, szArg);
560 "%s.%d allocating argvNew at '%s'\n", __FUNCTION__, __LINE__, argv[1]);
562 argvNew =
WBAlloc(
sizeof(*argvNew) * (argc + 2));
577 "%s.%d copying argv at '%s'\n", __FUNCTION__, __LINE__, argv_orig[argcNew]);
579 argvNew[argcNew] = argv_orig[argcNew];
587 argvNew[argcNew++] = argv[1];
590 "%s.%d. (2) copying argv at '%s'\n", __FUNCTION__, __LINE__, argv[1]);
603 if(argv[1][0] ==
'-' && argv[1][1] ==
'-' && !argv[1][2])
608 "%s.%d (3) skipping argv at '%s'\n", __FUNCTION__, __LINE__, argv[1]);
613 "%s.%d (3) copying argv at '%s'\n", __FUNCTION__, __LINE__, argv[1]);
615 argvNew[argcNew++] = argv[1];
626 if((iWBDebugLevel & DebugLevel_MASK) > 0)
628 WBDebugPrint(
"DebugLevel set to %d\n", (
int)(iWBDebugLevel & DebugLevel_MASK));
631 if((iWBDebugLevel & DebugSubSystem_MASK) != 0)
635 for(i1=0; aszDebugSubSys[i1]; i1++)
637 if(iWBDebugLevel & (1L << (i1 + DebugSubSystem_BITSHIFT)))
641 WBDebugPrint(
"Debug SubSystem: %s", aszDebugSubSys[i1]);
651 for(; (i1 + DebugSubSystem_BITSHIFT) < 32; i1++)
653 if((iWBDebugLevel & (1L << (i1 + DebugSubSystem_BITSHIFT))) == DebugSubSystem_RESTRICT)
665 else if(iWBDebugLevel & (1L << (i1 + DebugSubSystem_BITSHIFT)))
687 WBDebugPrint(
"Command line arguments passed to application:\n");
689 for(i1=0; i1 < *pargc; i1++)
702 fputs(
"X11 WorkBench Toolkit options (these should precede other options)\n" 703 " X11 STARTUP OPTIONS\n" 704 "--help Show the toolkit options\n" 705 "--display xx X11 display to use (default is DISPLAY env variable)\n" 706 "--minimize show minimized window on startup\n" 707 "--maximize show maximized window on startup\n" 708 "--geometry geom specify window geometry on startup\n" 709 " geometry spec as per X specification (see X man page)\n" 710 " typical value might be 800x600+100+50\n" 711 " (default centers window with reasonable size)\n" 713 "--debug n debug level (default 0, errors only)\n" 714 " 1 = minimal, 7 is maximum debug level\n" 715 "--subsys xx subsystem to debug (implies --debug 7 if not specified)\n" 716 " 'xx' is a subsystem name or bit value (see window_helper.h)\n" 717 " A bit value of 1 is equivalent to the lowest subsystem bit\n" 718 " NOTE: this option can be specified multiple times\n" 719 " (You can specify '--subsys help' to get a list of subsystems)\n" 721 "--no-antialias Disable anti-aliasing (may improve UI performance)\n" 722 "--no-imagecache Disable internal image cache for window paint/expose\n" 724 " NOTE: application options with separate parameters should appear after\n" 725 " any X11 Workbench Toolkit options, to avoid confusing the parser.\n" 749 iWBDebugLevel = iNew;
752 #if !defined(__GNUC__) && !defined(_MSVC_VER) 756 return iWBDebugLevel;
762 if(
WB_LIKELY((iWBDebugLevel & DebugLevel_MASK) < (dwLevel & DebugLevel_MASK)))
769 if(!(dwLevel & DebugSubSystem_MASK) )
777 if(((dwLevel & DebugSubSystem_MASK) & (iWBDebugLevel & DebugSubSystem_MASK))
786 #endif // !defined(__GNUC__) && !defined(_MSVC_VER) 794 vfprintf(stderr, fmt, va);
805 unsigned char *pX = (
unsigned char *)pData;
806 static const int nCols = 16;
808 WBDebugPrint(
"==========================================================================================\n" 811 for(i1=0; i1 < cbData; i1 += nCols, pX += nCols)
815 for(i2=0; i2 < nCols && (i1 + i2) < cbData; i2++)
820 for(; i2 < nCols; i2++)
827 for(i2=0; i2 < nCols && (i1 + i2) < cbData; i2++)
829 if(pX[i2] <
' ' || pX[i2] >= 0x80)
842 WBDebugPrint(
"==========================================================================================\n");
847 typedef struct __profile_info__
850 const char *szFunction;
853 #ifdef HAS_WB_UINT64_BUILTIN 858 #else // HAS_WB_UINT64_BUILTIN 863 #endif // HAS_WB_UINT64_BUILTIN 866 static PROFILE_INFO *paProfileInfo = NULL;
867 static int nProfileInfo = 0, nMaxProfileInfo = 0;
869 int WBRegisterProfileVar(
const char *szFile,
int nLine,
const char *szFunction,
const char *szName,
const char *szDesc)
875 nMaxProfileInfo = 256;
876 paProfileInfo = (PROFILE_INFO *)
WBAlloc((nMaxProfileInfo + 1) *
sizeof(*paProfileInfo));
882 bzero(paProfileInfo, (nMaxProfileInfo + 1) *
sizeof(*paProfileInfo));
884 else if(
WB_UNLIKELY((nProfileInfo + 1) >= nMaxProfileInfo))
888 int nOldMaxProfileInfo = nMaxProfileInfo;
890 nMaxProfileInfo = (nProfileInfo + 258) & 0xffffff00;
892 pTemp =
WBReAlloc(paProfileInfo, (nMaxProfileInfo + 1) *
sizeof(*paProfileInfo));
896 nMaxProfileInfo = nOldMaxProfileInfo;
900 paProfileInfo = (PROFILE_INFO *)pTemp;
901 bzero(paProfileInfo + nOldMaxProfileInfo,
902 (nMaxProfileInfo + 1 - nOldMaxProfileInfo) *
sizeof(*paProfileInfo));
905 iRval = nProfileInfo++;
907 paProfileInfo[iRval].szFile = szFile;
908 paProfileInfo[iRval].szFunction = szFunction;
909 paProfileInfo[iRval].szName = szName;
910 paProfileInfo[iRval].szDesc = szDesc;
911 paProfileInfo[iRval].nLine = nLine;
913 paProfileInfo[iRval].nTime = 0;
914 paProfileInfo[iRval].nCount = 0;
919 void WBStartProfile(
int nProfileID)
921 if(
WB_UNLIKELY(nProfileID < 0 || !paProfileInfo || nProfileID >= nMaxProfileInfo))
926 if(paProfileInfo[nProfileID].nCount >= 0)
929 paProfileInfo[nProfileID].nCount = -(paProfileInfo[nProfileID].nCount + 1);
933 void WBStopProfile(
int nProfileID)
935 if(
WB_UNLIKELY(nProfileID < 0 || !paProfileInfo || nProfileID >= nMaxProfileInfo))
940 if(paProfileInfo[nProfileID].nCount < 0)
943 paProfileInfo[nProfileID].nCount = -(paProfileInfo[nProfileID].nCount);
947 void WBDumpProfileData(
void)
956 for(i1=0; i1 < nProfileInfo; i1++)
967 paProfileInfo[i1].nCount = -(paProfileInfo[i1].nCount);
979 " nTime = %llu microseconds\n" 982 " nTime = %lu microseconds\n" 984 " Average microseconds per count: %0.1f\n\n",
985 paProfileInfo[i1].szFile,
986 (
int)paProfileInfo[i1].nLine,
987 paProfileInfo[i1].szFunction,
988 paProfileInfo[i1].szName,
989 paProfileInfo[i1].szDesc,
990 paProfileInfo[i1].nCount,
991 paProfileInfo[i1].nTime,
992 (
double)paProfileInfo[i1].nTime / (
double)paProfileInfo[i1].nCount);
996 paProfileInfo = NULL;
1015 #if defined(HAS_WB_UINT64_BUILTIN) || defined(__DOXYGEN__) 1017 #else // !defined(HAS_WB_UINT64_BUILTIN) && !defined(__DOXYGEN__) 1019 #endif // defined(HAS_WB_UINT64_BUILTIN) || defined(__DOXYGEN__) 1023 gettimeofday(&tv, NULL);
1025 #ifdef HAS_WB_UINT64_BUILTIN 1030 #else // WB_UINT64 is a structure typedef; just return a 32-bit value for now 1032 double d1 = tv.tv_sec * 1000000.0;
1035 return (
WB_UINT32)floor(fmod(d1, (
double)0xffffffff));
1044 #ifdef HAVE_NANOSLEEP 1045 struct timespec tsp;
1049 tsp.tv_sec = uiDelay / 1000000L;
1050 uiDelay = uiDelay % 1000000L;
1058 tsp.tv_nsec = uiDelay * 1000;
1060 nanosleep(&tsp, NULL);
1061 #else // HAVE_NANOSLEEP 1065 #endif // HAVE_NANOSLEEP 1076 #if defined(__FreeBSD__) 1082 if(sysctlbyname(
"hw.ncpu", &iCPU, &cb, NULL, 0))
1088 if(sysctlbyname(
"kern.smp.cpus", &iCPU, &cb, NULL, 0))
1099 #elif defined(linux) 1105 pF = fopen(
"/proc/cpuinfo",
"r");
1108 while(fgets(tbuf,
sizeof(tbuf), pF))
1114 while(*p1 && *p1 <=
' ')
1119 p2 = p1 + strlen(p1);
1120 while(p2 > p1 && *(p2 - 1) <=
' ')
1125 if(!strncmp(p1,
"processor", 9) &&
1126 p1[9] && p1[9] <=
' ')
1135 #elif defined(WIN32) 1139 #endif // all of that 1171 static const char szWBAllocTag[]=
"WB_M";
1172 #define WB_ALLOC_TAG (*((const unsigned int *)szWBAllocTag)) 1174 #define PMALLOC_FLAG (&mallocFlagMalloc) 1176 struct __malloc_header__
1178 struct __malloc_header__ *pPrev, *pNext;
1180 unsigned int cbSize;
1183 static struct __malloc_header__ mallocFlagMalloc;
1192 unsigned char *pRval;
1193 struct __malloc_header__ *pMH;
1194 unsigned int nAllocSize, nNewSize, nLimit;
1205 nAllocSize = nSize +
sizeof(*pMH);
1208 nLimit = nAllocSize + (nAllocSize >> 1);
1210 for(nNewSize=64; nNewSize < nLimit; nNewSize <<= 1)
1221 pRval = (
unsigned char *)malloc(nNewSize);
1225 #ifdef HAVE_MALLOC_USABLE_SIZE 1226 void *pActual = pRval;
1227 #endif // HAVE_MALLOC_USABLE_SIZE 1229 pMH = (
struct __malloc_header__ *)pRval;
1231 pRval +=
sizeof(*pMH);
1233 pMH->pPrev = PMALLOC_FLAG;
1234 pMH->pNext = PMALLOC_FLAG;
1235 pMH->iTag = WB_ALLOC_TAG;
1237 #ifdef HAVE_MALLOC_USABLE_SIZE 1238 nLimit = malloc_usable_size(pActual);
1239 if(nLimit > nNewSize)
1243 #endif // HAVE_MALLOC_USABLE_SIZE 1244 pMH->cbSize = nNewSize -
sizeof(*pMH);
1253 struct __malloc_header__ *pMH;
1264 pMH = ((
struct __malloc_header__ *)pBuf) - 1;
1266 if(pMH->iTag == WB_ALLOC_TAG)
1276 struct __malloc_header__ *pMH;
1286 pMH = ((
struct __malloc_header__ *)pBuf) - 1;
1288 if(pMH->iTag == WB_ALLOC_TAG)
1290 if(pMH->pPrev == PMALLOC_FLAG &&
1291 pMH->pNext == PMALLOC_FLAG)
1306 WB_ERROR_PRINT(
"TODO: %s 'pre-alloc' unimplemented - NOT freeing memory %p\n", __FUNCTION__, pBuf);
1311 WB_ERROR_PRINT(
"ERROR: %s NOT freeing (invalid) memory %p\n", __FUNCTION__, pBuf);
1317 struct __malloc_header__ *pMH;
1318 unsigned char *pRval = NULL;
1319 unsigned int nAllocSize, nNewNewSize, nLimit;
1322 if(!pBuf || nNewSize <= 0)
1330 pMH = ((
struct __malloc_header__ *)pBuf) - 1;
1332 if(pMH->iTag == WB_ALLOC_TAG)
1338 if(pMH->cbSize >= nNewSize)
1346 nAllocSize = nNewSize +
sizeof(*pMH);
1349 nLimit = nAllocSize + (nAllocSize >> 1);
1350 for(nNewNewSize=64; nNewNewSize < nLimit; nNewNewSize <<= 1) { }
1352 if(pMH->pPrev != PMALLOC_FLAG &&
1353 pMH->pNext != PMALLOC_FLAG)
1355 if(nNewNewSize >= 4096)
1365 memcpy(pRval, pBuf, pMH->cbSize);
1375 WB_ERROR_PRINT(
"TODO: %s - 'pre-alloc' is NOT implemented. Pointer %p NOT re-allocated\n", __FUNCTION__, pBuf);
1380 pRval = realloc(pMH, nNewNewSize);
1383 #ifdef HAVE_MALLOC_USABLE_SIZE 1384 void *pActual = pRval;
1385 #endif // HAVE_MALLOC_USABLE_SIZE 1387 pMH = (
struct __malloc_header__ *)pRval;
1388 pRval +=
sizeof(*pMH);
1390 #ifdef HAVE_MALLOC_USABLE_SIZE 1391 nLimit = malloc_usable_size(pActual);
1392 if(nLimit > nNewSize)
1396 #endif // HAVE_MALLOC_USABLE_SIZE 1397 pMH->cbSize = nNewNewSize -
sizeof(*pMH);
1402 WB_ERROR_PRINT(
"ERROR - %s NOT re-allocating memory %p\n", __FUNCTION__, pBuf);
1448 iLen = strlen(pSrc);
1454 memcpy(pDest, pSrc, iLen);
1479 for(p1 = pSrc, iLen = 0; iLen < nMaxChars && *p1; p1++, iLen++)
1486 memcpy(pDest, pSrc, iLen);
1501 if(!ppDest || !pSrc || !*pSrc)
1518 && (p2 - p1) < iMaxLen
1524 iLen2 = strlen(pSrc);
1525 iLen = iLen2 + (p2 - p1);
1527 if((iLen + 1) > iMaxLen)
1536 p2 = (p2 - p1) + *ppDest;
1539 memcpy(p2, pSrc, iLen2);
1556 if(!ppDest || !pSrc || !*pSrc)
1574 && (p2 - p1) < iMaxLen
1580 for(iLen2=0, p3 = pSrc; iLen2 < nMaxChars && *p3; p3++, iLen2++)
1583 iLen = iLen2 + (p2 - p1);
1585 if((iLen + 1) > iMaxLen)
1594 p2 = (p2 - p1) + *ppDest;
1597 memcpy(p2, pSrc, iLen2);
1610 p1 = pDest = pString;
1614 if(*p1 ==
'"' || *p1 ==
'\'')
1619 (*p1 != c1 || p1[1] == c1))
1626 *(pDest++) = *(p1++);
1649 static char __amp_char(
char **ppSpot)
1653 if(!memcmp(pS,
"&", 5))
1658 else if(!memcmp(pS,
"<", 4))
1663 else if(!memcmp(pS,
">", 4))
1680 p1 = pDest = pString;
1684 if(*p1 ==
'"' || *p1 ==
'\'')
1689 (*p1 != c1 || p1[1] == c1))
1697 c2 = __amp_char(&p1);
1708 *(pDest++) = *(p1++);
1718 c2 = __amp_char(&p1);
1749 if(!pSrc || (!nMaxChars && !*pSrc))
1756 nMaxChars = strlen(pSrc);
1769 }
while(pSrc && nMaxChars);
1790 nMaxChars = *pnMaxChars;
1798 nMaxChars = strlen(pSrc);
1803 while(nMaxChars > 0)
1810 if(nMaxChars > 0 && *pSrc ==
'\n')
1818 else if(*pSrc ==
'\n')
1823 if(nMaxChars > 0 && *pSrc ==
'\r')
1831 else if(*pSrc ==
'\f' ||
1855 *pnMaxChars = nMaxChars;
1875 typedef struct __pointer_hash__
1883 static POINTER_HASH *pPointerHashes = NULL;
1884 static int nPointerHash = 0, nMaxPointerHash = 0;
1886 static WB_UINT32 uiPointerHashSpinlock = 0;
1888 static void WBFreePointerHashes(
void)
1893 pPointerHashes = NULL;
1897 nMaxPointerHash = 0;
1899 uiPointerHashSpinlock = 0;
1909 #warning TODO: prevent hash-jamming attacks from external processes posting tainted events 1936 nMaxPointerHash = 512;
1937 pPointerHashes = (POINTER_HASH *)
WBAlloc(nMaxPointerHash *
sizeof(*pPointerHashes));
1946 else if(nPointerHash >= nMaxPointerHash)
1948 void *pTemp =
WBReAlloc(pPointerHashes, (nMaxPointerHash + 256) *
sizeof(*pPointerHashes));
1955 pPointerHashes = (POINTER_HASH *)pTemp;
1956 nMaxPointerHash += 256;
1962 for(i1=0, iFreeIndex = -1; i1 < nPointerHash; i1++)
1964 if(pPointerHashes[i1].pValue == pPointer)
1968 WB_ERROR_PRINT(
"ERROR: %s - matching 'pPointer' %p for multiple hash entries\n", __FUNCTION__, pPointer);
1972 uiRval = pPointerHashes[i1].uiHash;
1973 pPointerHashes[i1].dwTick = dwTick;
1974 pPointerHashes[i1].dwRefCount++;
1979 else if(!pPointerHashes[i1].pValue &&
1980 !pPointerHashes[i1].uiHash)
1999 pPointerHashes[i1].uiHash = 0;
2000 pPointerHashes[i1].dwTick = 0;
2001 pPointerHashes[i1].pValue = NULL;
2002 pPointerHashes[i1].dwRefCount = 0;
2021 iFreeIndex = nPointerHash++;
2024 pPointerHashes[iFreeIndex].pValue = pPointer;
2025 pPointerHashes[iFreeIndex].dwTick = dwTick;
2026 pPointerHashes[iFreeIndex].dwRefCount = 1;
2038 for(i1=0; i1 < nPointerHash; i1++)
2040 if(pPointerHashes[i1].uiHash == uiRval)
2046 if(i1 >= nPointerHash)
2056 pPointerHashes[iFreeIndex].uiHash = uiRval;
2089 for(i1=0; i1 < nPointerHash; i1++)
2091 if(!pPointerHashes[i1].pValue &&
2092 !pPointerHashes[i1].uiHash)
2110 pPointerHashes[i1].uiHash = 0;
2111 pPointerHashes[i1].dwTick = 0;
2112 pPointerHashes[i1].pValue = NULL;
2113 pPointerHashes[i1].dwRefCount = 0;
2115 else if(pPointerHashes[i1].uiHash == uiHash)
2121 if(pPointerHashes[i1].dwRefCount)
2123 pPointerHashes[i1].dwRefCount --;
2126 if(!(pPointerHashes[i1].dwRefCount))
2157 for(i1=0; i1 < nPointerHash; i1++)
2159 if(!pPointerHashes[i1].uiHash && !pPointerHashes[i1].pValue)
2175 pPointerHashes[i1].uiHash = 0;
2176 pPointerHashes[i1].dwTick = 0;
2177 pPointerHashes[i1].pValue = NULL;
2178 pPointerHashes[i1].dwRefCount = 0;
2181 else if(pPointerHashes[i1].pValue == pPointer)
2211 for(i1=0; i1 < nPointerHash; i1++)
2213 if(!pPointerHashes[i1].pValue ||
2214 pPointerHashes[i1].uiHash != uiHash)
2221 pRval = pPointerHashes[i1].pValue;
2279 static volatile WB_UINT32 lInternalAtomSpinner = 0L;
2280 static char **ppInternalAtoms = NULL;
2281 static char *pszAtomNames = NULL;
2282 static unsigned int cbAtomNames = 0, cbMaxAtomNames = 0;
2283 static unsigned int nInternalAtoms = 0, nMaxInternalAtoms = 0;
2285 #define INITIAL_INTERNAL_ATOM_SIZE 4096 2286 #define INITIAL_INTERNAL_ATOM_STRING_SIZE 262144 2296 if(!szAtomName || !*szAtomName)
2331 if(!ppInternalAtoms)
2333 ppInternalAtoms = (
char **)
WBAlloc(INITIAL_INTERNAL_ATOM_SIZE);
2335 if(!ppInternalAtoms)
2342 nMaxInternalAtoms = INITIAL_INTERNAL_ATOM_SIZE;
2345 else if((nInternalAtoms + 1) >= nMaxInternalAtoms)
2347 pTemp =
WBReAlloc(ppInternalAtoms, nMaxInternalAtoms + INITIAL_INTERNAL_ATOM_SIZE);
2355 ppInternalAtoms = (
char **)pTemp;
2356 nMaxInternalAtoms += INITIAL_INTERNAL_ATOM_SIZE;
2359 iLen = strlen(szAtomName) + 1;
2365 pszAtomNames =
WBAlloc(INITIAL_INTERNAL_ATOM_STRING_SIZE);
2373 cbMaxAtomNames = INITIAL_INTERNAL_ATOM_STRING_SIZE;
2376 else if((cbAtomNames + iLen + 1) >= cbMaxAtomNames)
2378 pTemp =
WBReAlloc(pszAtomNames, cbMaxAtomNames + INITIAL_INTERNAL_ATOM_STRING_SIZE);
2386 pszAtomNames = (
char *)pTemp;
2387 cbMaxAtomNames += INITIAL_INTERNAL_ATOM_STRING_SIZE;
2392 ppInternalAtoms[nInternalAtoms++] = pszAtomNames + cbAtomNames;
2394 memcpy(pszAtomNames + cbAtomNames, szAtomName, iLen);
2396 cbAtomNames += iLen;
2397 pszAtomNames[cbAtomNames] = 0;
2406 WB_ERROR_PRINT(
"ERROR: %s - could not allocate new atom %u for %s\n", __FUNCTION__, (
unsigned int)aRval, szAtomName);
2423 if(!szAtomName || !*szAtomName)
2445 if(ppInternalAtoms && pszAtomNames && nInternalAtoms > 0)
2450 for(i1=0; i1 < nInternalAtoms; i1++)
2452 if(!strcmp(szAtomName, ppInternalAtoms[i1]))
2469 aRval = XInternAtom(pDisplay, szAtomName, True);
2478 char *pRval, *pTemp;
2487 WB_WARN_PRINT(
"ERROR: %s - passed 'None' for aAtom\n", __FUNCTION__);
2493 WB_ERROR_PRINT(
"ERROR: %s - bad (internal) Atom: %u (%08xH)\n", __FUNCTION__, (
unsigned int)aAtom, (
unsigned int)aAtom);
2513 pTemp = XGetAtomName(pDisplay, aAtom);
2526 "INFO: %s - unknown Atom: %u (%08xH)\n",
2527 __FUNCTION__, (
unsigned int)aAtom, (
unsigned int)aAtom);
2539 if(ppInternalAtoms && pszAtomNames && nInternalAtoms > 0)
2543 if(nAtom < nInternalAtoms)
2554 "INFO: %s - atom index %u (%u) not found, %u atoms stored\n", __FUNCTION__,
2584 #if (!defined(QSORT_R_BSD) && !defined(QSORT_R_GNUC)) || defined(__DOXYGEN__) 2586 struct my_qsort_data
2591 int (*compare)(
void *,
const void *,
const void *);
2595 static void MyQuickSort2(
struct my_qsort_data *pData,
int iLow,
int iHigh);
2601 int (*compar)(
void *,
const void *,
const void *))
2603 struct my_qsort_data sData;
2604 unsigned char buf[32], buf2[32];
2613 sData.cbData = size;
2614 sData.pThunk = thunk;
2615 sData.compare = compar;
2617 if(sData.cbData <=
sizeof(buf))
2624 sData.pBR =
WBAlloc(sData.cbData * 2);
2625 sData.pSW = (
unsigned char *)sData.pBR + sData.cbData;
2628 MyQuickSort2(&sData, 0, nmemb - 1);
2630 if(sData.cbData >
sizeof(buf))
2636 static __inline__
void *ElementFromIndex(
struct my_qsort_data *pData,
int iElement)
2638 return ((
unsigned char *)pData->pData) + pData->cbData * iElement;
2641 static int DoCompareI(
struct my_qsort_data *pData,
int iLeft,
int iRight)
2643 void *p1 = ElementFromIndex(pData, iLeft);
2644 void *p2 = ElementFromIndex(pData, iRight);
2646 return pData->compare(pData->pThunk, p1, p2);
2649 static int DoCompareP(
struct my_qsort_data *pData,
int iLeft,
void *pRight)
2651 void *p1 = ElementFromIndex(pData, iLeft);
2653 return pData->compare(pData->pThunk, p1, pRight);
2656 static void DoSwapData(
struct my_qsort_data *pData,
int iLeft,
int iRight)
2658 void *p1 = ElementFromIndex(pData, iLeft);
2659 void *p2 = ElementFromIndex(pData, iRight);
2662 memcpy(pData->pSW, p1, pData->cbData);
2663 memcpy(p1, p2, pData->cbData);
2664 memcpy(p2, pData->pSW, pData->cbData);
2667 void MyQuickSort2(
struct my_qsort_data *pData,
int iLow,
int iHigh )
2669 int iUp, iDown, iBreak;
2671 unsigned char buf[32], buf2[32];
2676 iBreak = (iLow + iHigh) / 2;
2677 pBreak = ElementFromIndex(pData, iBreak);
2679 if( (iHigh - iLow) > 5 )
2691 if(DoCompareI(pData, iLow, iHigh) <= 0)
2693 if(DoCompareP(pData, iLow, pBreak) < 0)
2695 if(DoCompareP(pData, iHigh, pBreak) < 0)
2697 pBreak = ElementFromIndex(pData, iHigh);
2702 pBreak = ElementFromIndex(pData, iLow);
2707 if(DoCompareP(pData, iHigh, pBreak) < 0)
2709 if(DoCompareP(pData, iLow, pBreak) < 0)
2711 pBreak = ElementFromIndex(pData, iLow);
2716 pBreak = ElementFromIndex(pData, iHigh);
2721 memcpy(pData->pBR, pBreak, pData->cbData);
2722 pBreak = pData->pBR;
2736 if(DoCompareP(pData, iUp, pBreak) < 0)
2748 if(DoCompareP(pData, iDown, pBreak) > 0)
2769 DoSwapData(pData, iUp, iDown);
2776 }
while ( iUp <= iDown );
2782 MyQuickSort2(pData, iLow, iDown );
2786 MyQuickSort2(pData, iUp, iHigh );
2791 #endif // !defined(QSORT_R_BSD) && !defined(QSORT_R_GNUC) 2794 #if !defined(HAVE_XPM) || defined(__DOXYGEN__) 2818 #define MAX_XPM_COLOR_CHAR_SIZE 4 2820 typedef struct _MY_XPM_COLOR_
2822 char c[MAX_XPM_COLOR_CHAR_SIZE];
2827 static int MyXPMColorCompare(
const void *p1,
const void *p2)
2831 return memcmp(p1, p2, MAX_XPM_COLOR_CHAR_SIZE);
2834 static char * MyXPMToData(
const char *pXPM[],
int *piW,
int *piH,
char **ppTransparency)
2836 MY_XPM_COLOR *pClr, *pC;
2837 int i1, i2, i3, iW, iH;
2838 int nColors, nCharsPerColor;
2839 char cNone[MAX_XPM_COLOR_CHAR_SIZE]={0};
2840 const char *pX, *pY, *pZ;
2872 WB_ERROR_PRINT(
"%s - unexpected parameter, pXPM=%p, ppX=%p, pX=%p\n", __FUNCTION__, pXPM, ppX, pX);
2878 #define NEXT_INT(iW,pX,pY,pZ){int iLen; NEXT_WORD(pX,pY,pZ); \ 2879 iLen=pZ - pY > sizeof(tbuf) - 1 ? sizeof(tbuf) - 1 : pZ - pY; \ 2880 if(iLen>0){memcpy(tbuf,pY,iLen);} tbuf[iLen]=0; iW=atoi(tbuf);} 2881 NEXT_INT(iW,pX,pY,pZ);
2882 NEXT_INT(iH,pX,pY,pZ);
2883 NEXT_INT(nColors,pX,pY,pZ);
2884 NEXT_INT(nCharsPerColor,pX,pY,pZ);
2888 if(*pX || !iW || !iH || !nColors || !nCharsPerColor || nCharsPerColor >
sizeof(pClr[0].c))
2890 WB_ERROR_PRINT(
"%s fail, iW=%d iH=%d nColors=%d nCharsPerColor=%d\n",
2891 __FUNCTION__, iW, iH, nColors, nCharsPerColor);
2897 pClr =
WBAlloc(nColors *
sizeof(MY_XPM_COLOR));
2903 for(i1=0; i1 < nColors; i1++)
2911 WB_ERROR_PRINT(
"%s NULL pX unexpected, i1=%d\n", __FUNCTION__, i1);
2915 bzero(pClr[i1].c,
sizeof(pClr[i1].c));
2917 for(i2=0; i2 < nCharsPerColor; i2++)
2919 pClr[i1].c[i2] = *(pX++);
2922 while(*pX && *pX <=
' ')
2928 if(*pX !=
'c' || pX[1] >
' ' || (pX[2] !=
'#' && strncmp(pX + 2,
"None",4)))
2930 WB_ERROR_PRINT(
"%s fail 1, pX=\"%s\" pY=\"%s\" %d %c %d\n", __FUNCTION__, pX, pY, pX[1], pX[2], strncmp(pX + 2,
"None",4));
2938 if(!strncmp(pX,
"None",4))
2940 memcpy(cNone, pClr[i1].c,
sizeof(pClr[i1].c));
2941 bzero(&(pClr[i1].clrColor),
sizeof(XColor));
2947 memcpy(tbuf, pX, 7);
2973 WB_ERROR_PRINT(
"%s fail, not enough memory for pRval, size=%d\n", __FUNCTION__, iH * iW * 4);
2977 if(ppTransparency && cNone[0])
2985 WB_ERROR_PRINT(
"%s fail, not enough memory for pT, size=%d\n", __FUNCTION__, (iH * iW) / 8 + 2);
2989 bzero(pT, iH * i3 + 2);
2996 qsort(pClr, nColors,
sizeof(*pClr), MyXPMColorCompare);
3001 for(i2=0, pR=pRval; i2 < iH; i2++)
3008 WB_ERROR_PRINT(
"%s NULL pX unexpected, i2=%d\n", __FUNCTION__, i2);
3014 for(i1=0; i1 < iW; i1++)
3016 bzero(tbuf,
sizeof(pClr[0].c));
3019 for(i3=0; i3 < nCharsPerColor; i3++)
3024 WB_ERROR_PRINT(
"%s premature end of string, %ld bytes\n", __FUNCTION__, (
long)(pX - pY));
3031 pC = (MY_XPM_COLOR *)bsearch(tbuf, pClr, nColors,
sizeof(*pClr), MyXPMColorCompare);
3033 if(!pC || memcmp(tbuf, pC->c,
sizeof(pC->c)))
3036 WB_ERROR_PRINT(
"%s fail, did not locate color %-4.4s\n", __FUNCTION__, tbuf);
3045 ((
unsigned char *)pR)[0] = pC->clrColor.blue >> 8;
3046 ((
unsigned char *)pR)[1] = pC->clrColor.green >> 8;
3047 ((
unsigned char *)pR)[2] = pC->clrColor.red >> 8;
3048 ((
unsigned char *)pR)[3] = 0;
3054 register unsigned int uiBit;
3055 register unsigned char *pRow;
3069 pRow = pT + i3 * i2;
3071 uiBit = 1 << (i3 & 7);
3073 if(!memcmp(tbuf, cNone,
sizeof(cNone)))
3075 pRow[i3 / 8] &= ~uiBit;
3079 pRow[i3 / 8] |= uiBit;
3090 *ppTransparency = (
char *)pT;
3103 return (
char *)pRval;
3112 char *pTrans = NULL;
3114 Pixmap pxImage, pxMask;
3123 pB = MyXPMToData((
const char **)aData, &iW, &iH, &pTrans);
3143 pxMask = XCreatePixmapFromBitmapData(pDisplay, wID, pTrans, iW, iH,
3161 pxImage = XCreatePixmap(pDisplay, wID, iW, iH, DefaultDepth(pDisplay, DefaultScreen(pDisplay)));
3169 XFreePixmap(pDisplay, pxMask);
3178 XImage *pImage = XCreateImage(pDisplay, DefaultVisual(pDisplay, DefaultScreen(pDisplay)),
3179 DefaultDepth(pDisplay, DefaultScreen(pDisplay)),
3183 iW, iH, 32, iW * 4);
3191 XFreePixmap(pDisplay, pxMask);
3195 XFreePixmap(pDisplay, pxImage);
3205 gcv.foreground = BlackPixel(pDisplay, DefaultScreen(pDisplay));
3206 gcv.background = WhitePixel(pDisplay, DefaultScreen(pDisplay));
3208 gc = XCreateGC(pDisplay, wID, (GCForeground | GCBackground), &gcv);
3216 XFreePixmap(pDisplay, pxMask);
3220 XFreePixmap(pDisplay, pxImage);
3229 XPutImage(pDisplay, pxImage, gc, pImage, 0, 0, 0, 0, iW, iH);
3233 pImage->data = NULL;
3236 XFreeGC(pDisplay, gc);
3240 XDestroyImage(pImage);
3261 pAttr->
depth = DefaultDepth(pDisplay, DefaultScreen(pDisplay));
3305 #endif // !defined(HAVE_XPM) 3328 if(!szFileName || !*szFileName)
3334 #error not yet implemented 3337 if(szFileName[0] ==
'/' && !szFileName[1])
3342 iRval = mkdir(szFileName, flags);
3343 if(iRval && errno == ENOENT)
3351 p2 = p1 + strlen(p1) - 1;
3356 while(p2 > p1 && *p2 !=
'/')
3368 iRval = mkdir(szFileName, flags);
3383 const char *p1, *pCur, *pPath;
3386 if(0 >
WBStat(szFileName, NULL))
3388 if(*szFileName ==
'/')
3391 WB_ERROR_PRINT(
"%s - File does not exist: \"%s\"\n", __FUNCTION__, szFileName);
3397 pRval =
WBAlloc(2 * PATH_MAX + strlen(szFileName));
3401 pPath = getenv(
"PATH");
3411 while(*p1 && *p1 !=
':')
3416 if((p1 - pCur) + 2 < 2 * PATH_MAX)
3419 memcpy(pRval, pCur, p1 - pCur);
3421 if(pRval[(p1 - pCur) - 1] !=
'/')
3423 pRval[(p1 - pCur)] =
'/';
3424 strcpy(pRval + (p1 - pCur) + 1, szFileName);
3428 strcpy(pRval + (p1 - pCur), szFileName);
3448 pPath = pCur = p1 = NULL;
3456 if(*p2 && strlen(p2) < 2 * PATH_MAX)
3458 p1 = strrchr(p2,
'/');
3461 p2[p1 - p2 + 1] = 0;
3481 strcat(pRval, szFileName);
3490 if(!pRval || 0 >
WBStat(pRval, NULL))
3512 const char *szDir = NULL;
3518 unsigned short sA[4];
3520 static const char szH[16]=
"0123456789ABCDEF";
3525 #error windows version not implemented 3532 if(0 >
WBStat(szDir, NULL))
3535 if(0 >
WBStat(szDir, NULL))
3543 for(i1=0; i1 < 256; i1++)
3558 uX.sA[0] ^= uX.sA[1];
3559 uX.sA[0] ^= uX.sA[2];
3560 uX.sA[0] ^= uX.sA[3];
3564 char *pX = pRval + strlen(pRval) - 4;
3566 pX[0] = szH[(uX.sA[0] >> 12) & 0xf];
3567 pX[1] = szH[(uX.sA[0] >> 8) & 0xf];
3568 pX[2] = szH[(uX.sA[0] >> 4) & 0xf];
3569 pX[3] = szH[uX.sA[0] & 0xf];
3587 #error windows code not written yet 3589 h1 = open(pRval, O_CREAT | O_EXCL | O_RDWR, 0644);
3602 if(errno == ENOTDIR || errno == ENOENT || errno == EACCES ||
3603 errno == EPERM || errno == EROFS || errno == EMFILE || errno == ENFILE)
3631 __add_to_temp_file_list(pRval);
3637 static void __add_to_temp_file_list(
const char *szFile)
3639 int i1 = strlen(szFile);
3646 cbTempFileList = PATH_MAX * 256;
3647 pTempFileList =
WBAlloc(cbTempFileList);
3654 pTempFileListEnd = pTempFileList;
3656 else if((pTempFileListEnd - pTempFileList) + i1 + 2 >= cbTempFileList)
3658 pTemp =
WBReAlloc(pTempFileList, cbTempFileList + (128 * PATH_MAX));
3664 cbTempFileList += 128 * PATH_MAX;
3666 if((pTempFileListEnd - pTempFileList) + i1 + 2 >= cbTempFileList)
3672 memcpy(pTempFileListEnd, szFile, i1);
3673 pTempFileListEnd += i1;
3675 *(pTempFileListEnd++) = 0;
3676 *pTempFileListEnd = 0;
3701 WB_PROCESS_ID
WBRunAsyncPipeV(WB_FILE_HANDLE hStdIn, WB_FILE_HANDLE hStdOut, WB_FILE_HANDLE hStdErr,
3702 const char *szAppName, va_list va)
3705 char *pCur, *p1, *pAppName = NULL;
3707 int i1, nItems, cbItems;
3709 WB_PROCESS_ID hRval;
3710 WB_FILE_HANDLE hIn, hOut, hErr;
3716 hIn = hOut = hErr = WB_INVALID_FILE_HANDLE;
3741 if(hStdIn == WB_INVALID_FILE_HANDLE)
3744 hIn = open(
"/dev/null", O_RDONLY, 0);
3746 SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *)
WBAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
3750 InitializeSecurityDescriptor(pSD,SECURITY_DESCRIPTOR_REVISION);
3751 pSD->bInheritHandle = TRUE;
3753 hIn = CreateFile(
"NUL", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
3754 pSD, OPEN_EXISTING, NULL, NULL);
3764 if(!DuplicateHandle(GetCurrentProcess(), hStdIn,
3765 GetCurrentProcess(), &hIn, GENERIC_READ,
3768 hIn = WB_INVALID_FILE_HANDLE;
3773 if(hStdOut == WB_INVALID_FILE_HANDLE)
3776 hOut = open(
"/dev/null", O_WRONLY, 0);
3778 SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *)
WBAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
3782 InitializeSecurityDescriptor(pSD,SECURITY_DESCRIPTOR_REVISION);
3783 pSD->bInheritHandle = TRUE;
3785 hOut = CreateFile(
"NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
3786 pSD, OPEN_EXISTING, NULL, NULL);
3797 hOut = dup(hStdOut);
3799 if(!DuplicateHandle(GetCurrentProcess(), hStdOut,
3800 GetCurrentProcess(), &hOut, GENERIC_WRITE,
3803 hOut = WB_INVALID_FILE_HANDLE;
3808 if(hStdErr == WB_INVALID_FILE_HANDLE)
3811 hErr = open(
"/dev/null", O_WRONLY, 0);
3813 SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *)
WBAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
3817 InitializeSecurityDescriptor(pSD,SECURITY_DESCRIPTOR_REVISION);
3818 pSD->bInheritHandle = TRUE;
3820 hErr = CreateFile(
"NUL", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
3821 pSD, OPEN_EXISTING, NULL, NULL);
3829 hErr = dup(hStdErr);
3831 if(!DuplicateHandle(GetCurrentProcess(), hStdErr,
3832 GetCurrentProcess(), &hErr, GENERIC_WRITE,
3835 hErr = WB_INVALID_FILE_HANDLE;
3842 if(hIn == WB_INVALID_FILE_HANDLE ||
3843 hOut == WB_INVALID_FILE_HANDLE ||
3844 hErr == WB_INVALID_FILE_HANDLE)
3848 if(hIn != WB_INVALID_FILE_HANDLE)
3852 if(hOut != WB_INVALID_FILE_HANDLE)
3856 if(hErr != WB_INVALID_FILE_HANDLE)
3861 if(pAppName != szAppName)
3866 return WB_INVALID_FILE_HANDLE;
3872 cbItems = 2 *
sizeof(
char *) + strlen(szAppName) + 1;
3877 pArg = va_arg(va2,
const char *);
3883 cbItems += strlen(pArg) + 1 +
sizeof(
char *);
3887 argv = (
char **)
WBAlloc(64 + cbItems);
3894 if(pAppName != szAppName)
3900 return WB_INVALID_FILE_HANDLE;
3903 pCur = (
char *)(argv + nItems + 2);
3905 p1 = strrchr(szAppName,
'/');
3908 strcpy(pCur, p1 + 1);
3912 strcpy(pCur, szAppName);
3916 pCur += strlen(pCur) + 1;
3918 for(i1=1; i1 <= nItems; i1++)
3920 pArg = va_arg(va,
const char *);
3924 pCur += strlen(pCur) + 1;
3927 argv[nItems + 1] = NULL;
3941 if(dup2(hIn, 0) != -1 && dup2(hOut, 1) != -1 && dup2(hErr, 2) != -1)
3943 static const char szMsg[]=
"ERROR: 'execve()' failure\n";
3944 extern char **environ;
3948 signal(SIGHUP, SIG_IGN);
3950 signal(SIGHUP, SIG_DFL);
3952 execve(pAppName, argv, environ);
3954 write(2, szMsg,
sizeof(szMsg) - 1);
3964 static const char szMsg[]=
"ERROR: 'dup2()' failure\n";
3965 write(2, szMsg,
sizeof(szMsg) - 1);
3982 #error TODO write the WIN32 code for this using ShellExecuteEx or CreateProcess (example below from Setup Gizmo) 3983 #error and pay SPECIFIC ATTENTION to getting the handle re-direction right for the stdin/stdout/stderr so that piping works 3984 #error and don`t forget the registry entries that ShellExecute uses for the PATH (then again...) 4167 if(pAppName != szAppName)
4179 WB_PROCESS_ID idRval;
4182 va_start(va, szAppName);
4184 idRval =
WBRunAsyncPipeV(WB_INVALID_FILE_HANDLE, WB_INVALID_FILE_HANDLE,
4185 WB_INVALID_FILE_HANDLE, szAppName, va);
4189 if(idRval == WB_INVALID_FILE_HANDLE)
4201 WB_PROCESS_ID
WBRunAsyncPipe(WB_FILE_HANDLE hStdIn, WB_FILE_HANDLE hStdOut, WB_FILE_HANDLE hStdErr,
4202 const char *szAppName, ...)
4204 WB_PROCESS_ID idRval;
4207 va_start(va, szAppName);
4217 #define WBRUNRESULT_BUFFER_MINSIZE 65536 4218 #define WBRUNRESULT_BYTES_TO_READ 256 4220 static char * WBRunResultInternal(WB_FILE_HANDLE hStdIn,
const char *szAppName, va_list va)
4222 WB_PROCESS_ID idRval;
4223 WB_FILE_HANDLE hP[2];
4224 char *p1, *p2, *pRval;
4225 int i1, i2, iStat, iRunning;
4229 cbBuf = WBRUNRESULT_BUFFER_MINSIZE;
4245 hP[0] = hP[1] = WB_INVALID_FILE_HANDLE;
4248 if(!CreatePipe(&(pH[0]), &(pH[1]), NULL, 0))
4249 #else // !WIN32 (everybody else) 4260 WB_INVALID_FILE_HANDLE, szAppName, va);
4262 if(idRval == WB_INVALID_FILE_HANDLE)
4274 fcntl(hP[0], F_SETFL, O_NONBLOCK);
4285 i2 = WBRUNRESULT_BYTES_TO_READ;
4286 if((p1 - pRval) + i2 >= cbBuf)
4288 i2 = cbBuf - (p1 - pRval);
4289 if(i2 < WBRUNRESULT_BYTES_TO_READ / 8)
4291 p2 =
WBReAlloc(pRval, cbBuf + WBRUNRESULT_BUFFER_MINSIZE / 2);
4301 cbBuf += WBRUNRESULT_BUFFER_MINSIZE / 2;
4302 p1 = p2 + (p1 - pRval);
4304 i2 = WBRUNRESULT_BYTES_TO_READ;
4310 i1 = read(hP[0], p1, i2);
4348 if(::WaitForSingleObject(idRval, 5) != WAIT_TIMEOUT)
4350 if(!GetExitCodeProcess(hProcess, &dwExitCode) ||
4351 dwExitCode != STILL_ACTIVE)
4363 #else // !WIN32 (everybody else) 4366 if(waitpid(idRval, &iStat, WNOHANG) &&
4382 kill(idRval, SIGKILL);
4397 if(::WaitForSingleObject(idRval, 5) != WAIT_TIMEOUT)
4399 if(!GetExitCodeProcess(hProcess, &dwExitCode) ||
4400 dwExitCode != STILL_ACTIVE)
4412 #else // !WIN32 (everybody else) 4419 iRval = waitpid(idProcess, &iStat, WNOHANG);
4421 if(iRval > 0 && (iRval == (
int)idProcess || (
int)idProcess == -1 || (
int)idProcess == 0))
4423 if(WIFEXITED(iStat))
4427 *pExitCode = (
WB_INT32)WEXITSTATUS(iStat);
4438 WB_ERROR_PRINT(
"ERROR: %s - waitpid returns %d, but does not match %d\n",
4439 __FUNCTION__, iRval, (
int)idProcess);
4452 va_start(va, szAppName);
4454 pRval = WBRunResultInternal(WB_INVALID_FILE_HANDLE, szAppName, va);
4465 char *pRval, *pTemp = NULL;
4467 WB_FILE_HANDLE hIn = WB_INVALID_FILE_HANDLE;
4470 va_start(va, szAppName);
4472 if(szStdInBuf && *szStdInBuf)
4477 unsigned int nLen = strlen(szStdInBuf);
4490 hIn = CreateFile(pTemp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
4491 NULL, OPEN_EXISTING, NULL, NULL);
4493 if(hIn == WB_INVALID_FILE_HANDLE)
4495 hIn = open(pTemp, O_RDWR, 0);
4515 if(!WriteFile(hIn, szStdInBuf, nLen, &dw1, NULL)
4522 SetFilePointer(hIn, 0, NULL, FILE_BEGIN);
4524 if(write(hIn, szStdInBuf, nLen) != nLen)
4530 lseek(hIn, 0, SEEK_SET);
4536 pRval = WBRunResultInternal(hIn, szAppName, va);
4572 return((
WB_MODULE)LoadLibrary(szModuleName));
4577 FreeLibrary(hModule);
4587 return((
void *)GetProcAddress(hModule, szDataName));
4594 return((
WB_MODULE)dlopen(szModuleName, RTLD_LAZY | RTLD_LOCAL));
4607 #else // other POSIX systems - TODO, check for 'dlfunc' instead of the OS 4609 #endif // 'dlfunc' check 4614 return((
void *)dlsym(hModule, szDataName));
4618 #endif // POSIX, WIN32 4638 if(!pthread_key_create(&keyRval, NULL))
4651 pthread_key_delete(keyVal);
4659 return pthread_getspecific(keyVal);
4667 pthread_setspecific(keyVal, pValue);
4675 return pthread_self();
4694 WB_THREAD_PARM *pNext;
4696 void *(*function)(
void *);
4701 volatile unsigned int dwThreadParmSpinLock = 0;
4703 WB_THREAD_PARM aTP[16] =
4705 { &(aTP[1]), NULL, 0 },
4706 { &(aTP[2]), NULL, 0 },
4707 { &(aTP[3]), NULL, 0 },
4708 { &(aTP[4]), NULL, 0 },
4709 { &(aTP[5]), NULL, 0 },
4710 { &(aTP[6]), NULL, 0 },
4711 { &(aTP[7]), NULL, 0 },
4712 { &(aTP[8]), NULL, 0 },
4713 { &(aTP[9]), NULL, 0 },
4714 { &(aTP[19]), NULL, 0 },
4715 { &(aTP[11]), NULL, 0 },
4716 { &(aTP[12]), NULL, 0 },
4717 { &(aTP[13]), NULL, 0 },
4718 { &(aTP[14]), NULL, 0 },
4719 { &(aTP[15]), NULL, 0 },
4723 WB_THREAD_PARM *pTPHead = &(aTP[0]);
4725 static void *WBInternalThreadProc(
void *pParam)
4728 WB_THREAD_PARM *pParm = (WB_THREAD_PARM *)pParam;
4729 void *(*function2)(
void *);
4738 function2 = pParm->function;
4739 pParam2 = pParm->pParam;
4749 pParm->pNext = pTPHead;
4756 signal(SIGTSTP,SIG_IGN);
4758 pRval = function2(pParam2);
4781 if(!pthread_create(&thrdRval, NULL,
function, pParam))
4796 if(pthread_join(hThread, &pRval))
4809 DWORD dwRval = WaitForSingleObject(hThread, 0);
4810 if(dwRval == WAIT_OBJECT_0)
4814 else if(dwRval == WAIT_TIMEOUT)
4823 int iR = pthread_kill(hThread,0);
4843 pthread_exit(pRval);
4850 CloseHandle(hThread);
4852 pthread_detach(hThread);
4914 if(!pthread_mutex_init(pMtx, NULL))
4952 pthread_mutex_destroy(pMtx);
4966 iRval = pthread_mutex_lock(pMtx);
4968 return iRval ? -1 : 0;
4973 iRval = pthread_mutex_trylock(pMtx);
4979 else if(iRval != EBUSY)
4986 if((ullTemp - ullTime) > nTimeout)
4991 WBDelay(83 + (ullTemp / 13) % 37);
5002 return pthread_mutex_unlock(pMtx);
5046 WB_ERROR_PRINT(
"TEMPORARY: %s - returns -1 (NULL pCond)\n", __FUNCTION__);
5053 struct timespec ts, tsNow;
5055 clock_gettime(CLOCK_REALTIME, &ts);
5057 ts.tv_sec += nTimeout / 1000000;
5058 ts.tv_nsec += (nTimeout % 1000000) * 1000L;
5060 if(ts.tv_nsec > 1000000000L)
5063 ts.tv_nsec -= 1000000000L;
5070 clock_gettime(CLOCK_REALTIME, &tsNow);
5072 if(tsNow.tv_sec > ts.tv_sec ||
5073 (tsNow.tv_sec == ts.tv_sec &&
5074 tsNow.tv_nsec > ts.tv_nsec))
5080 WBDelay(37 + tsNow.tv_nsec % 29);
5106 WB_ERROR_PRINT(
"ERROR: %s - returns -1 (NULL pCond)\n", __FUNCTION__);
5166 return InterlockedDecrement(pValue);
5170 pthread_rwlock_wrlock(&xInterlockedRWLock);
5175 pthread_rwlock_unlock(&xInterlockedRWLock);
5184 return InterlockedIncrement(pValue);
5188 pthread_rwlock_wrlock(&xInterlockedRWLock);
5193 pthread_rwlock_unlock(&xInterlockedRWLock);
5202 return InterlockedExchange(pValue, nNewVal);
5206 pthread_rwlock_wrlock(&xInterlockedRWLock);
5211 pthread_rwlock_unlock(&xInterlockedRWLock);
5223 pthread_rwlock_rdlock(&xInterlockedRWLock);
5227 pthread_rwlock_unlock(&xInterlockedRWLock);
5283 #endif // WIN32,POSIX
const char * GetStartupAppName(void)
returns a pointer to a copy of the application name from argv[0]
void WBPlatformOnExit(void)
Resource 'free-up' on exit (must call)
WB_THREAD_KEY WBThreadAllocLocal(void)
Allocate 'thread local' storage.
'window helper' main header file for the X11workbench Toolkit API
int bQuitFlag
'Quit' Flag - you should check this periodically in your main (message) loop and exit whenever it is ...
#define WB_DEBUG_PRINT(L,...)
Preferred method of implementing conditional debug output.
static __inline__ Colormap WBDefaultColormap(Display *pDisplay)
returns the default colormap for the default screen of the specified display
void WBThreadFreeLocal(WB_THREAD_KEY keyVal)
Free 'thread local' storage allocated by WBThreadAllocLocal()
static __inline__ int WBCheckDebugLevel(WB_UINT64 dwLevel)
Check specified debug level against the value returned by WBGetDebugLevel() and return non-zero for a...
int WBMutexUnlock(WB_MUTEX *pMtx)
Unlock a previously locked mutex.
void * WBThreadGetLocal(WB_THREAD_KEY keyVal)
Get 'thread local' data identified by 'keyVal'.
void WBCatStringN(char **ppDest, const char *pSrc, unsigned int nMaxChars)
A simple utility that concatenates a string onto the end of a 0-byte terminated WBAlloc() string up t...
int WBStringLineCount(const char *pSrc, unsigned int nMaxChars)
Determine how many 'lines' are in a block of text by counting 'linefeed' characters.
char * WBRunResult(const char *szAppName,...)
Run an application synchronously, returning 'stdout' output in a character buffer.
static __inline__ void WBSupressErrorOutput(void)
Supress X11 XErrorEvent output to stderr.
void WBSubAllocTrashMasher(void)
High performance memory sub-allocator 'trash masher' - call periodically to minimize wasted memory.
int MyLoadPixmapFromData(Display *pDisplay, Window wID, char *aData[], Pixmap *pPixmap, Pixmap *pMask, XPM_ATTRIBUTES *pAttr)
Alternate for XpmCreatePixmapFromData() whenever libXpm is not being used.
void WBFreeLibrary(WB_MODULE hModule)
Frees a shared library, DLL, module, or whatever, that was loaded via 'WBLoadLibrary()'.
WB_MODULE WBLoadLibrary(const char *szModuleName)
Loads a shared library, DLL, module, or whatever you call it on your operating system.
char * WBRunResultWithInput(const char *szStdInBuf, const char *szAppName,...)
Run an application synchronously, supplying an input buffer for 'stdin', and returning 'stdout' outpu...
void * WBThreadWait(WB_THREAD hThread)
Wait for a specified threat to exit.
void WBThreadExit(void *pRval)
Exit the current thread immediately, specifying return code.
unsigned int WBInterlockedIncrement(volatile unsigned int *pValue)
Interlocked 'atomic' increment of an unsigned integer.
void WBDebugDump(const char *szTitle, void *pData, int cbData)
conditionally dumps binary data to debug message output
static __inline__ void WBAllowErrorOutput(void)
Restore X11 XErrorEvent output to stderr.
Compatibility structure for use with MyLoadPixmapFromData() whenever libXpm is not in use.
static __inline__ Display * WBGetDefaultDisplay(void)
Returns the default Display.
int WBMain(int argc, char *argv0[], char *envp0[]) __attribute__((weak)) __attribute__((section("text_wbmain")))
Startup function, equivalent to 'main()' - provided for convenience.
WB_PROCESS_ID WBRunAsyncPipe(WB_FILE_HANDLE hStdIn, WB_FILE_HANDLE hStdOut, WB_FILE_HANDLE hStdErr, const char *szAppName,...)
Run an application asynchronously, specifying file handles for STDIN, STDOUT, and STDERR.
unsigned int WBInterlockedExchange(volatile unsigned int *pValue, unsigned int nNewVal)
Interlocked 'atomic' exchange of an unsigned integer with a specified value.
int width
The width of the returned pixmaps.
void * WBReAlloc(void *pBuf, int nNewSize)
High performance memory sub-allocator 're-allocate'.
int WBGetProcessState(WB_PROCESS_ID idProcess, WB_INT32 *pExitCode)
Check on a running process, and return its state, and optionally the exit code.
WB_THREAD WBThreadCreate(void *(*function)(void *), void *pParam)
Create a new thread, returning its WB_THREAD identifier.
int WBStat(const char *szLinkName, unsigned long *pdwModeAttrReturn)
Obtain the 'stat' flags for a file name, resolving links as needed.
void WBDeQuoteString(char *pString)
De-Quote a string 'in place', that is modifying the original string by removing quotes.
void WBToolkitUsage(void)
Displays 'usage' for toolkit options to stderr.
void WBThreadSetLocal(WB_THREAD_KEY keyVal, void *pValue)
Get 'thread local' data identified by 'keyVal'.
void * WBAlloc(int nSize)
High performance memory sub-allocator 'allocate'.
int WBCondSignal(WB_COND *pCond)
Signal a condition (event)
void * WBGetDataAddress(WB_MODULE hModule, const char *szDataName)
Obtains a data pointer for an exported data symbol in a shared library (or DLL)
WB_PROCESS_ID WBRunAsync(const char *szAppName,...)
Run an application asynchronously.
#define WB_ERROR_PRINT(...)
Preferred method of implementing an 'error level' debug message for all subsystems.
char * WBGetPrinterList(void)
Get a list of printer names.
WB_THREAD WBThreadGetCurrent(void)
Get 'current thread' identifier.
void WBFree(void *pBuf)
High performance memory sub-allocator 'free'.
int WBParseStandardArguments(int *pargc, char ***pargv, char ***penvp)
parses standard C arguments as passed to 'main()'
void WBPlatformOnInit(void)
Resource initialization on startup.
unsigned int WBInterlockedDecrement(volatile unsigned int *pValue)
Interlocked 'atomic' decrement of an unsigned integer.
int WBAllocUsableSize(void *pBuf)
High performance memory sub-allocator, similar to 'malloc_usable_size'.
void WBSetDebugLevel(unsigned int iNew)
set debug level
void WBUsage(void)
Optional startup function, sends 'usage' (help) info to stderr - application-defined function.
WB_PROCADDRESS WBGetProcAddress(WB_MODULE hModule, const char *szProcName)
Obtains a function pointer for an exported function symbol in a shared library (or DLL)
int WBMutexCreate(WB_MUTEX *pMtx)
Create a lockable mutex.
int WBMutexLock(WB_MUTEX *pMtx, int nTimeout)
Wait for and lock a mutex, blocking until it is available.
int WBThreadRunning(WB_THREAD hThread)
Determine whether a thread is running (can be suspended)
const char * WBStringNextLine(const char *pSrc, unsigned int *pnMaxChars)
Locate the next line in a block of text, returning its pointer (and updating remaining length)
WB_PROCESS_ID WBRunAsyncPipeV(WB_FILE_HANDLE hStdIn, WB_FILE_HANDLE hStdOut, WB_FILE_HANDLE hStdErr, const char *szAppName, va_list va)
Run an application asynchronously, specifying file handles for STDIN, STDOUT, and STDERR,...
char * WBCopyStringN(const char *pSrc, unsigned int nMaxChars)
A simple utility that returns a WBAlloc() copy of a string up to a maximum length (can also be 0-byte...
int depth
depth of the returned 'image' pixmap. The mask pixmap always has a depth of '1'.
int WBCondWait(WB_COND *pCond, int nTimeout)
Wait for a signal on a condition (event)
void WBMutexFree(WB_MUTEX *pMtx)
Free a lockable mutex.
void WBDebugPrint(const char *pFmt,...) __attribute__((format(printf
conditional debug message output
char * WBCopyString(const char *pSrc)
A simple utility that returns a WBAlloc() copy of a 0-byte terminated string.
int WBCondWaitMutex(WB_COND *pCond, WB_MUTEX *pMtx, int nTimeout)
Wait for a signal on a condition (event)
void WBThreadClose(WB_THREAD hThread)
Close the specified WB_THREAD identifier.
unsigned int WBInterlockedRead(volatile unsigned int *pValue)
Interlocked 'atomic' read of an unsigned integer.
int height
height of the returned pixmaps
#define WB_WARN_PRINT(...)
Preferred method of implementing a 'warning level' debug message for all subsystems.
int WBPrintPostScriptFile(const char *szPrinterName, const char *szFileName)
Send postscript file to a printer (using lpr-cups or lpr on POSIX systems)
int WBCondCreate(WB_COND *pCond)
Create a signallable condition.
void WBNormalizeXMLString(char *pString)
De-Quote and 'normalize' an XML string 'in place', that is modifying the original string by removing ...
static __inline__ WB_UINT64 WBGetDebugLevel(void)
Returns the current debug level assigned by WBSetDebugLevel.
void WBCatString(char **ppDest, const char *pSrc)
A simple utility that concatenates a string onto the end of a 0-byte terminated WBAlloc() string.
void WBCondFree(WB_COND *pCond)
Free a signallable condition.