feat:replace boost library with C++11 std library
This commit is contained in:
BIN
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
MODULE LIBC.NLM
|
||||
MODULE WS2_32.NLM
|
||||
EXPORT @aprlib.imp
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_portable.h"
|
||||
|
||||
/* static struct utsname sysinfo; */
|
||||
|
||||
/* XXX This needs to be fixed to produce the correct system language */
|
||||
|
||||
APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool)
|
||||
{
|
||||
return apr_pstrdup(pool, "CP1252");
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool)
|
||||
{
|
||||
return apr_os_default_encoding(pool);
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <netware.h>
|
||||
#include <library.h>
|
||||
#include <nks/synch.h>
|
||||
|
||||
#include "apr_pools.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_arch_internal_time.h"
|
||||
|
||||
|
||||
/* library-private data...*/
|
||||
int gLibId = -1;
|
||||
void *gLibHandle = (void *) NULL;
|
||||
NXMutex_t *gLibLock = (NXMutex_t *) NULL;
|
||||
|
||||
/* internal library function prototypes...*/
|
||||
int DisposeLibraryData(void *);
|
||||
|
||||
int _NonAppStart
|
||||
(
|
||||
void *NLMHandle,
|
||||
void *errorScreen,
|
||||
const char *cmdLine,
|
||||
const char *loadDirPath,
|
||||
size_t uninitializedDataLength,
|
||||
void *NLMFileHandle,
|
||||
int (*readRoutineP)( int conn, void *fileHandle, size_t offset,
|
||||
size_t nbytes, size_t *bytesRead, void *buffer ),
|
||||
size_t customDataOffset,
|
||||
size_t customDataSize,
|
||||
int messageCount,
|
||||
const char **messages
|
||||
)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
WSADATA wsaData;
|
||||
#endif
|
||||
apr_status_t status;
|
||||
|
||||
NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0);
|
||||
|
||||
#pragma unused(cmdLine)
|
||||
#pragma unused(loadDirPath)
|
||||
#pragma unused(uninitializedDataLength)
|
||||
#pragma unused(NLMFileHandle)
|
||||
#pragma unused(readRoutineP)
|
||||
#pragma unused(customDataOffset)
|
||||
#pragma unused(customDataSize)
|
||||
#pragma unused(messageCount)
|
||||
#pragma unused(messages)
|
||||
|
||||
gLibId = register_library(DisposeLibraryData);
|
||||
|
||||
if (gLibId < -1)
|
||||
{
|
||||
OutputToScreen(errorScreen, "Unable to register library with kernel.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gLibHandle = NLMHandle;
|
||||
|
||||
gLibLock = NXMutexAlloc(0, 0, &liblock);
|
||||
|
||||
if (!gLibLock)
|
||||
{
|
||||
OutputToScreen(errorScreen, "Unable to allocate library data lock.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
apr_netware_setup_time();
|
||||
|
||||
if ((status = apr_pool_initialize()) != APR_SUCCESS)
|
||||
return status;
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
return WSAStartup((WORD) MAKEWORD(2, 0), &wsaData);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void _NonAppStop( void )
|
||||
{
|
||||
apr_pool_terminate();
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
unregister_library(gLibId);
|
||||
NXMutexFree(gLibLock);
|
||||
}
|
||||
|
||||
int _NonAppCheckUnload( void )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int register_NLM(void *NLMHandle)
|
||||
{
|
||||
APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
|
||||
|
||||
NXLock(gLibLock);
|
||||
if (!app_data) {
|
||||
app_data = (APP_DATA*)library_malloc(gLibHandle, sizeof(APP_DATA));
|
||||
|
||||
if (app_data) {
|
||||
memset (app_data, 0, sizeof(APP_DATA));
|
||||
set_app_data(gLibId, app_data);
|
||||
app_data->gs_nlmhandle = NLMHandle;
|
||||
}
|
||||
}
|
||||
|
||||
if (app_data && (!app_data->initialized)) {
|
||||
app_data->initialized = 1;
|
||||
NXUnlock(gLibLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NXUnlock(gLibLock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int unregister_NLM(void *NLMHandle)
|
||||
{
|
||||
APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
|
||||
|
||||
NXLock(gLibLock);
|
||||
if (app_data) {
|
||||
app_data->initialized = 0;
|
||||
NXUnlock(gLibLock);
|
||||
return 0;
|
||||
}
|
||||
NXUnlock(gLibLock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DisposeLibraryData(void *data)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
library_free(data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setGlobalPool(void *data)
|
||||
{
|
||||
APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
|
||||
|
||||
NXLock(gLibLock);
|
||||
|
||||
if (app_data && !app_data->gPool) {
|
||||
app_data->gPool = data;
|
||||
}
|
||||
|
||||
NXUnlock(gLibLock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* getGlobalPool()
|
||||
{
|
||||
APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId);
|
||||
|
||||
if (app_data) {
|
||||
return app_data->gPool;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define APR_WANT_MEMFUNC
|
||||
#include "apr_want.h"
|
||||
#include "apr_general.h"
|
||||
#include "apr_private.h"
|
||||
|
||||
#if APR_HAS_RANDOM
|
||||
|
||||
#include <nks/plat.h>
|
||||
|
||||
static int NXSeedRandomInternal( size_t width, void *seed )
|
||||
{
|
||||
static int init = 0;
|
||||
int *s = (int *) seed;
|
||||
union { int x; char y[4]; } u;
|
||||
|
||||
if (!init) {
|
||||
srand(NXGetSystemTick());
|
||||
init = 1;
|
||||
}
|
||||
|
||||
if (width > 3)
|
||||
{
|
||||
do
|
||||
{
|
||||
*s++ = rand();
|
||||
}
|
||||
while ((width -= 4) > 3);
|
||||
}
|
||||
|
||||
if (width > 0)
|
||||
{
|
||||
char *p = (char *) s;
|
||||
|
||||
u.x = rand();
|
||||
|
||||
while (width > 0)
|
||||
*p++ = u.y[width--];
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf,
|
||||
apr_size_t length)
|
||||
{
|
||||
if (NXSeedRandom(length, buf) != 0) {
|
||||
return NXSeedRandomInternal (length, buf);
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* APR_HAS_RANDOM */
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_general.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_signal.h"
|
||||
|
||||
#include "apr_arch_misc.h" /* for WSAHighByte / WSALowByte */
|
||||
#include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */
|
||||
#include "apr_arch_internal_time.h"
|
||||
#include "apr_ldap.h" /* for apr_ldap_rebind_init() */
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
/* Prototypes missing from older NDKs */
|
||||
int WSAStartupRTags(WORD wVersionRequested,
|
||||
LPWSADATA lpWSAData,
|
||||
rtag_t WSAStartupRTag,
|
||||
rtag_t WSPSKTRTag,
|
||||
rtag_t lookUpServiceBeginRTag,
|
||||
rtag_t WSAEventRTag,
|
||||
rtag_t WSPCPRTag);
|
||||
|
||||
int WSACleanupRTag(rtag_t rTag);
|
||||
|
||||
/*
|
||||
** Resource tag signatures for using NetWare WinSock 2. These will no longer
|
||||
** be needed by anyone once the new WSAStartupWithNlmHandle() is available
|
||||
** since WinSock will make the calls to AllocateResourceTag().
|
||||
*/
|
||||
#define WS_LOAD_ENTRY_SIGNATURE (*(unsigned long *) "WLDE")
|
||||
#define WS_SKT_SIGNATURE (*(unsigned long *) "WSKT")
|
||||
#define WS_LOOKUP_SERVICE_SIGNATURE (*(unsigned long *) "WLUP")
|
||||
#define WS_WSAEVENT_SIGNATURE (*(unsigned long *) "WEVT")
|
||||
#define WS_CPORT_SIGNATURE (*(unsigned long *) "WCPT")
|
||||
|
||||
|
||||
int (*WSAStartupWithNLMHandle)( WORD version, LPWSADATA data, void *handle ) = NULL;
|
||||
int (*WSACleanupWithNLMHandle)( void *handle ) = NULL;
|
||||
|
||||
static int wsa_startup_with_handle (WORD wVersionRequested, LPWSADATA data, void *handle)
|
||||
{
|
||||
APP_DATA *app_data;
|
||||
|
||||
if (!(app_data = (APP_DATA*) get_app_data(gLibId)))
|
||||
return APR_EGENERAL;
|
||||
|
||||
app_data->gs_startup_rtag = AllocateResourceTag(handle, "WinSock Start-up", WS_LOAD_ENTRY_SIGNATURE);
|
||||
app_data->gs_socket_rtag = AllocateResourceTag(handle, "WinSock socket()", WS_SKT_SIGNATURE);
|
||||
app_data->gs_lookup_rtag = AllocateResourceTag(handle, "WinSock Look-up", WS_LOOKUP_SERVICE_SIGNATURE);
|
||||
app_data->gs_event_rtag = AllocateResourceTag(handle, "WinSock Event", WS_WSAEVENT_SIGNATURE);
|
||||
app_data->gs_pcp_rtag = AllocateResourceTag(handle, "WinSock C-Port", WS_CPORT_SIGNATURE);
|
||||
|
||||
return WSAStartupRTags(wVersionRequested, data,
|
||||
app_data->gs_startup_rtag,
|
||||
app_data->gs_socket_rtag,
|
||||
app_data->gs_lookup_rtag,
|
||||
app_data->gs_event_rtag,
|
||||
app_data->gs_pcp_rtag);
|
||||
}
|
||||
|
||||
static int wsa_cleanup_with_handle (void *handle)
|
||||
{
|
||||
APP_DATA *app_data;
|
||||
|
||||
if (!(app_data = (APP_DATA*) get_app_data(gLibId)))
|
||||
return APR_EGENERAL;
|
||||
|
||||
return WSACleanupRTag(app_data->gs_startup_rtag);
|
||||
}
|
||||
|
||||
static int UnregisterAppWithWinSock (void *nlm_handle)
|
||||
{
|
||||
if (!WSACleanupWithNLMHandle)
|
||||
{
|
||||
if (!(WSACleanupWithNLMHandle = ImportPublicObject(gLibHandle, "WSACleanupWithNLMHandle")))
|
||||
WSACleanupWithNLMHandle = wsa_cleanup_with_handle;
|
||||
}
|
||||
|
||||
return (*WSACleanupWithNLMHandle)(nlm_handle);
|
||||
}
|
||||
|
||||
static int RegisterAppWithWinSock (void *nlm_handle)
|
||||
{
|
||||
int err;
|
||||
WSADATA wsaData;
|
||||
WORD wVersionRequested = MAKEWORD(WSAHighByte, WSALowByte);
|
||||
|
||||
if (!WSAStartupWithNLMHandle)
|
||||
{
|
||||
if (!(WSAStartupWithNLMHandle = ImportPublicObject(gLibHandle, "WSAStartupWithNLMHandle")))
|
||||
WSAStartupWithNLMHandle = wsa_startup_with_handle;
|
||||
}
|
||||
|
||||
err = (*WSAStartupWithNLMHandle)(wVersionRequested, &wsaData, nlm_handle);
|
||||
|
||||
if (LOBYTE(wsaData.wVersion) != WSAHighByte ||
|
||||
HIBYTE(wsaData.wVersion) != WSALowByte) {
|
||||
|
||||
UnregisterAppWithWinSock (nlm_handle);
|
||||
return APR_EEXIST;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_app_initialize(int *argc,
|
||||
const char * const * *argv,
|
||||
const char * const * *env)
|
||||
{
|
||||
/* An absolute noop. At present, only Win32 requires this stub, but it's
|
||||
* required in order to move command arguments passed through the service
|
||||
* control manager into the process, and it's required to fix the char*
|
||||
* data passed in from win32 unicode into utf-8, win32's apr internal fmt.
|
||||
*/
|
||||
return apr_initialize();
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_initialize(void)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
void *nlmhandle = getnlmhandle();
|
||||
|
||||
/* Register the NLM as using APR. If it is already
|
||||
registered then just return. */
|
||||
if (register_NLM(nlmhandle) != 0) {
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* apr_pool_initialize() is being called from the library
|
||||
startup code since all of the memory resources belong
|
||||
to the library rather than the application. */
|
||||
|
||||
if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
|
||||
return APR_ENOPOOL;
|
||||
}
|
||||
|
||||
apr_pool_tag(pool, "apr_initilialize");
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
{
|
||||
int err;
|
||||
if ((err = RegisterAppWithWinSock (nlmhandle))) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
apr_signal_init(pool);
|
||||
#if APR_HAS_LDAP
|
||||
apr_ldap_rebind_init(pool);
|
||||
#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE_NONSTD(void) apr_terminate(void)
|
||||
{
|
||||
APP_DATA *app_data;
|
||||
|
||||
/* Get our instance data for shutting down. */
|
||||
if (!(app_data = (APP_DATA*) get_app_data(gLibId)))
|
||||
return;
|
||||
|
||||
/* Unregister the NLM. If it is not registered
|
||||
then just return. */
|
||||
if (unregister_NLM(app_data->gs_nlmhandle) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* apr_pool_terminate() is being called from the
|
||||
library shutdown code since the memory resources
|
||||
belong to the library rather than the application */
|
||||
|
||||
/* Just clean up the memory for the app that is going
|
||||
away. */
|
||||
netware_pool_proc_cleanup ();
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
UnregisterAppWithWinSock (app_data->gs_nlmhandle);
|
||||
#endif
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_terminate2(void)
|
||||
{
|
||||
apr_terminate();
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_portable.h"
|
||||
|
||||
#ifdef HAVE_LANGINFO_H
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* simple heuristic to determine codepage of source code so that
|
||||
* literal strings (e.g., "GET /\r\n") in source code can be translated
|
||||
* properly
|
||||
*
|
||||
* If appropriate, a symbol can be set at configure time to determine
|
||||
* this. On EBCDIC platforms, it will be important how the code was
|
||||
* unpacked.
|
||||
*/
|
||||
|
||||
APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool)
|
||||
{
|
||||
#ifdef __MVS__
|
||||
# ifdef __CODESET__
|
||||
return __CODESET__;
|
||||
# else
|
||||
return "IBM-1047";
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if ('}' == 0xD0) {
|
||||
return "IBM-1047";
|
||||
}
|
||||
|
||||
if ('{' == 0xFB) {
|
||||
return "EDF04";
|
||||
}
|
||||
|
||||
if ('A' == 0xC1) {
|
||||
return "EBCDIC"; /* not useful */
|
||||
}
|
||||
|
||||
if ('A' == 0x41) {
|
||||
return "ISO-8859-1"; /* not necessarily true */
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool)
|
||||
{
|
||||
#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
|
||||
const char *charset;
|
||||
|
||||
charset = nl_langinfo(CODESET);
|
||||
if (charset && *charset) {
|
||||
#ifdef _OSD_POSIX /* Bug workaround - delete as soon as fixed in OSD_POSIX */
|
||||
/* Some versions of OSD_POSIX return nl_langinfo(CODESET)="^[nN]" */
|
||||
/* Ignore the bogus information and use apr_os_default_encoding() */
|
||||
if (charset[0] != '^')
|
||||
#endif
|
||||
return apr_pstrdup(pool, charset);
|
||||
}
|
||||
#endif
|
||||
|
||||
return apr_os_default_encoding(pool);
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define APR_WANT_STRFUNC
|
||||
#include "apr_want.h"
|
||||
#include "apr.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_env.h"
|
||||
#include "apr_strings.h"
|
||||
|
||||
#if APR_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if APR_HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_get(char **value,
|
||||
const char *envvar,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
#ifdef HAVE_GETENV
|
||||
|
||||
char *val = getenv(envvar);
|
||||
if (!val)
|
||||
return APR_ENOENT;
|
||||
*value = val;
|
||||
return APR_SUCCESS;
|
||||
|
||||
#else
|
||||
return APR_ENOTIMPL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_set(const char *envvar,
|
||||
const char *value,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
#if defined(HAVE_SETENV)
|
||||
|
||||
if (0 > setenv(envvar, value, 1))
|
||||
return APR_ENOMEM;
|
||||
return APR_SUCCESS;
|
||||
|
||||
#elif defined(HAVE_PUTENV)
|
||||
|
||||
if (0 > putenv(apr_pstrcat(pool, envvar, "=", value, NULL)))
|
||||
return APR_ENOMEM;
|
||||
return APR_SUCCESS;
|
||||
|
||||
#else
|
||||
return APR_ENOTIMPL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool)
|
||||
{
|
||||
#ifdef HAVE_UNSETENV
|
||||
|
||||
unsetenv(envvar);
|
||||
return APR_SUCCESS;
|
||||
|
||||
#else
|
||||
/* hint: some platforms allow envvars to be unset via
|
||||
* putenv("varname")... that isn't Single Unix spec,
|
||||
* but if your platform doesn't have unsetenv() it is
|
||||
* worth investigating and potentially adding a
|
||||
* configure check to decide when to use that form of
|
||||
* putenv() here
|
||||
*/
|
||||
return APR_ENOTIMPL;
|
||||
#endif
|
||||
}
|
||||
+443
@@ -0,0 +1,443 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_lib.h"
|
||||
#include "apr_dso.h"
|
||||
|
||||
#if APR_HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* stuffbuffer - like apr_cpystrn() but returns the address of the
|
||||
* dest buffer instead of the address of the terminating '\0'
|
||||
*/
|
||||
static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s)
|
||||
{
|
||||
apr_cpystrn(buf,s,bufsize);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *apr_error_string(apr_status_t statcode)
|
||||
{
|
||||
switch (statcode) {
|
||||
case APR_ENOSTAT:
|
||||
return "Could not perform a stat on the file.";
|
||||
case APR_ENOPOOL:
|
||||
return "A new pool could not be created.";
|
||||
case APR_EBADDATE:
|
||||
return "An invalid date has been provided";
|
||||
case APR_EINVALSOCK:
|
||||
return "An invalid socket was returned";
|
||||
case APR_ENOPROC:
|
||||
return "No process was provided and one was required.";
|
||||
case APR_ENOTIME:
|
||||
return "No time was provided and one was required.";
|
||||
case APR_ENODIR:
|
||||
return "No directory was provided and one was required.";
|
||||
case APR_ENOLOCK:
|
||||
return "No lock was provided and one was required.";
|
||||
case APR_ENOPOLL:
|
||||
return "No poll structure was provided and one was required.";
|
||||
case APR_ENOSOCKET:
|
||||
return "No socket was provided and one was required.";
|
||||
case APR_ENOTHREAD:
|
||||
return "No thread was provided and one was required.";
|
||||
case APR_ENOTHDKEY:
|
||||
return "No thread key structure was provided and one was required.";
|
||||
case APR_ENOSHMAVAIL:
|
||||
return "No shared memory is currently available";
|
||||
case APR_EDSOOPEN:
|
||||
#if APR_HAS_DSO && defined(HAVE_LIBDL)
|
||||
return dlerror();
|
||||
#else
|
||||
return "DSO load failed";
|
||||
#endif /* HAVE_LIBDL */
|
||||
case APR_EBADIP:
|
||||
return "The specified IP address is invalid.";
|
||||
case APR_EBADMASK:
|
||||
return "The specified network mask is invalid.";
|
||||
case APR_ESYMNOTFOUND:
|
||||
return "Could not find the requested symbol.";
|
||||
case APR_ENOTENOUGHENTROPY:
|
||||
return "Not enough entropy to continue.";
|
||||
case APR_INCHILD:
|
||||
return
|
||||
"Your code just forked, and you are currently executing in the "
|
||||
"child process";
|
||||
case APR_INPARENT:
|
||||
return
|
||||
"Your code just forked, and you are currently executing in the "
|
||||
"parent process";
|
||||
case APR_DETACH:
|
||||
return "The specified thread is detached";
|
||||
case APR_NOTDETACH:
|
||||
return "The specified thread is not detached";
|
||||
case APR_CHILD_DONE:
|
||||
return "The specified child process is done executing";
|
||||
case APR_CHILD_NOTDONE:
|
||||
return "The specified child process is not done executing";
|
||||
case APR_TIMEUP:
|
||||
return "The timeout specified has expired";
|
||||
case APR_INCOMPLETE:
|
||||
return "Partial results are valid but processing is incomplete";
|
||||
case APR_BADCH:
|
||||
return "Bad character specified on command line";
|
||||
case APR_BADARG:
|
||||
return "Missing parameter for the specified command line option";
|
||||
case APR_EOF:
|
||||
return "End of file found";
|
||||
case APR_NOTFOUND:
|
||||
return "Could not find specified socket in poll list.";
|
||||
case APR_ANONYMOUS:
|
||||
return "Shared memory is implemented anonymously";
|
||||
case APR_FILEBASED:
|
||||
return "Shared memory is implemented using files";
|
||||
case APR_KEYBASED:
|
||||
return "Shared memory is implemented using a key system";
|
||||
case APR_EINIT:
|
||||
return
|
||||
"There is no error, this value signifies an initialized "
|
||||
"error code";
|
||||
case APR_ENOTIMPL:
|
||||
return "This function has not been implemented on this platform";
|
||||
case APR_EMISMATCH:
|
||||
return "passwords do not match";
|
||||
case APR_EABSOLUTE:
|
||||
return "The given path is absolute";
|
||||
case APR_ERELATIVE:
|
||||
return "The given path is relative";
|
||||
case APR_EINCOMPLETE:
|
||||
return "The given path is incomplete";
|
||||
case APR_EABOVEROOT:
|
||||
return "The given path was above the root path";
|
||||
case APR_EBADPATH:
|
||||
return "The given path is misformatted or contained invalid characters";
|
||||
case APR_EPATHWILD:
|
||||
return "The given path contained wildcard characters";
|
||||
case APR_EBUSY:
|
||||
return "The given lock was busy.";
|
||||
case APR_EPROC_UNKNOWN:
|
||||
return "The process is not recognized.";
|
||||
case APR_EGENERAL:
|
||||
return "Internal error (specific information not available)";
|
||||
default:
|
||||
return "Error string not specified yet";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef OS2
|
||||
#include <ctype.h>
|
||||
|
||||
int apr_canonical_error(apr_status_t err);
|
||||
|
||||
static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
|
||||
{
|
||||
char result[200];
|
||||
unsigned char message[HUGE_STRING_LEN];
|
||||
ULONG len;
|
||||
char *pos;
|
||||
int c;
|
||||
|
||||
if (err >= 10000 && err < 12000) { /* socket error codes */
|
||||
return stuffbuffer(buf, bufsize,
|
||||
strerror(apr_canonical_error(err+APR_OS_START_SYSERR)));
|
||||
}
|
||||
else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err,
|
||||
"OSO001.MSG", &len) == 0) {
|
||||
len--;
|
||||
message[len] = 0;
|
||||
pos = result;
|
||||
|
||||
if (len >= sizeof(result))
|
||||
len = sizeof(result) - 1;
|
||||
|
||||
for (c=0; c<len; c++) {
|
||||
/* skip multiple whitespace */
|
||||
while (apr_isspace(message[c]) && apr_isspace(message[c+1]))
|
||||
c++;
|
||||
*(pos++) = apr_isspace(message[c]) ? ' ' : message[c];
|
||||
}
|
||||
|
||||
*pos = 0;
|
||||
}
|
||||
else {
|
||||
sprintf(result, "OS/2 error %d", err);
|
||||
}
|
||||
|
||||
/* Stuff the string into the caller supplied buffer, then return
|
||||
* a pointer to it.
|
||||
*/
|
||||
return stuffbuffer(buf, bufsize, result);
|
||||
}
|
||||
|
||||
#elif defined(WIN32) || (defined(NETWARE) && defined(USE_WINSOCK))
|
||||
|
||||
static const struct {
|
||||
apr_status_t code;
|
||||
const char *msg;
|
||||
} gaErrorList[] = {
|
||||
{WSAEINTR, "Interrupted system call"},
|
||||
{WSAEBADF, "Bad file number"},
|
||||
{WSAEACCES, "Permission denied"},
|
||||
{WSAEFAULT, "Bad address"},
|
||||
{WSAEINVAL, "Invalid argument"},
|
||||
{WSAEMFILE, "Too many open sockets"},
|
||||
{WSAEWOULDBLOCK, "Operation would block"},
|
||||
{WSAEINPROGRESS, "Operation now in progress"},
|
||||
{WSAEALREADY, "Operation already in progress"},
|
||||
{WSAENOTSOCK, "Socket operation on non-socket"},
|
||||
{WSAEDESTADDRREQ, "Destination address required"},
|
||||
{WSAEMSGSIZE, "Message too long"},
|
||||
{WSAEPROTOTYPE, "Protocol wrong type for socket"},
|
||||
{WSAENOPROTOOPT, "Bad protocol option"},
|
||||
{WSAEPROTONOSUPPORT, "Protocol not supported"},
|
||||
{WSAESOCKTNOSUPPORT, "Socket type not supported"},
|
||||
{WSAEOPNOTSUPP, "Operation not supported on socket"},
|
||||
{WSAEPFNOSUPPORT, "Protocol family not supported"},
|
||||
{WSAEAFNOSUPPORT, "Address family not supported"},
|
||||
{WSAEADDRINUSE, "Address already in use"},
|
||||
{WSAEADDRNOTAVAIL, "Can't assign requested address"},
|
||||
{WSAENETDOWN, "Network is down"},
|
||||
{WSAENETUNREACH, "Network is unreachable"},
|
||||
{WSAENETRESET, "Net connection reset"},
|
||||
{WSAECONNABORTED, "Software caused connection abort"},
|
||||
{WSAECONNRESET, "Connection reset by peer"},
|
||||
{WSAENOBUFS, "No buffer space available"},
|
||||
{WSAEISCONN, "Socket is already connected"},
|
||||
{WSAENOTCONN, "Socket is not connected"},
|
||||
{WSAESHUTDOWN, "Can't send after socket shutdown"},
|
||||
{WSAETOOMANYREFS, "Too many references, can't splice"},
|
||||
{WSAETIMEDOUT, "Connection timed out"},
|
||||
{WSAECONNREFUSED, "Connection refused"},
|
||||
{WSAELOOP, "Too many levels of symbolic links"},
|
||||
{WSAENAMETOOLONG, "File name too long"},
|
||||
{WSAEHOSTDOWN, "Host is down"},
|
||||
{WSAEHOSTUNREACH, "No route to host"},
|
||||
{WSAENOTEMPTY, "Directory not empty"},
|
||||
{WSAEPROCLIM, "Too many processes"},
|
||||
{WSAEUSERS, "Too many users"},
|
||||
{WSAEDQUOT, "Disc quota exceeded"},
|
||||
{WSAESTALE, "Stale NFS file handle"},
|
||||
{WSAEREMOTE, "Too many levels of remote in path"},
|
||||
{WSASYSNOTREADY, "Network system is unavailable"},
|
||||
{WSAVERNOTSUPPORTED, "Winsock version out of range"},
|
||||
{WSANOTINITIALISED, "WSAStartup not yet called"},
|
||||
{WSAEDISCON, "Graceful shutdown in progress"},
|
||||
{WSAHOST_NOT_FOUND, "Host not found"},
|
||||
{WSANO_DATA, "No host data of that type was found"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
|
||||
static char *apr_os_strerror(char *buf, apr_size_t bufsize, apr_status_t errcode)
|
||||
{
|
||||
apr_size_t len=0, i;
|
||||
|
||||
#ifndef NETWARE
|
||||
#ifndef _WIN32_WCE
|
||||
len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
errcode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
buf,
|
||||
(DWORD)bufsize,
|
||||
NULL);
|
||||
#else /* _WIN32_WCE speaks unicode */
|
||||
LPTSTR msg = (LPTSTR) buf;
|
||||
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
errcode,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
msg,
|
||||
(DWORD) (bufsize/sizeof(TCHAR)),
|
||||
NULL);
|
||||
/* in-place convert to US-ASCII, substituting '?' for non ASCII */
|
||||
for(i = 0; i <= len; i++) {
|
||||
if (msg[i] < 0x80 && msg[i] >= 0) {
|
||||
buf[i] = (char) msg[i];
|
||||
} else {
|
||||
buf[i] = '?';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!len) {
|
||||
for (i = 0; gaErrorList[i].msg; ++i) {
|
||||
if (gaErrorList[i].code == errcode) {
|
||||
apr_cpystrn(buf, gaErrorList[i].msg, bufsize);
|
||||
len = strlen(buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len) {
|
||||
/* FormatMessage put the message in the buffer, but it may
|
||||
* have embedded a newline (\r\n), and possible more than one.
|
||||
* Remove the newlines replacing them with a space. This is not
|
||||
* as visually perfect as moving all the remaining message over,
|
||||
* but more efficient.
|
||||
*/
|
||||
i = len;
|
||||
while (i) {
|
||||
i--;
|
||||
if ((buf[i] == '\r') || (buf[i] == '\n'))
|
||||
buf[i] = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Windows didn't provide us with a message. Even stuff like * WSAECONNREFUSED won't get a message.
|
||||
*/
|
||||
apr_snprintf(buf, bufsize, "Unrecognized Win32 error code %d", errcode);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#else
|
||||
/* On Unix, apr_os_strerror() handles error codes from the resolver
|
||||
* (h_errno).
|
||||
*/
|
||||
static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err)
|
||||
{
|
||||
#ifdef HAVE_HSTRERROR
|
||||
return stuffbuffer(buf, bufsize, hstrerror(err));
|
||||
#else /* HAVE_HSTRERROR */
|
||||
const char *msg;
|
||||
|
||||
switch(err) {
|
||||
case HOST_NOT_FOUND:
|
||||
msg = "Unknown host";
|
||||
break;
|
||||
#if defined(NO_DATA)
|
||||
case NO_DATA:
|
||||
#if defined(NO_ADDRESS) && (NO_DATA != NO_ADDRESS)
|
||||
case NO_ADDRESS:
|
||||
#endif
|
||||
msg = "No address for host";
|
||||
break;
|
||||
#elif defined(NO_ADDRESS)
|
||||
case NO_ADDRESS:
|
||||
msg = "No address for host";
|
||||
break;
|
||||
#endif /* NO_DATA */
|
||||
default:
|
||||
msg = "Unrecognized resolver error";
|
||||
}
|
||||
return stuffbuffer(buf, bufsize, msg);
|
||||
#endif /* HAVE_STRERROR */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STRERROR_R) && defined(STRERROR_R_RC_INT) && !defined(BEOS)
|
||||
/* AIX and Tru64 style */
|
||||
static char *native_strerror(apr_status_t statcode, char *buf,
|
||||
apr_size_t bufsize)
|
||||
{
|
||||
if (strerror_r(statcode, buf, bufsize) < 0) {
|
||||
return stuffbuffer(buf, bufsize,
|
||||
"APR does not understand this error code");
|
||||
}
|
||||
else {
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_STRERROR_R)
|
||||
/* glibc style */
|
||||
|
||||
/* BeOS has the function available, but it doesn't provide
|
||||
* the prototype publicly (doh!), so to avoid a build warning
|
||||
* we add a suitable prototype here.
|
||||
*/
|
||||
#if defined(BEOS)
|
||||
const char *strerror_r(apr_status_t, char *, apr_size_t);
|
||||
#endif
|
||||
|
||||
static char *native_strerror(apr_status_t statcode, char *buf,
|
||||
apr_size_t bufsize)
|
||||
{
|
||||
const char *msg;
|
||||
|
||||
buf[0] = '\0';
|
||||
msg = strerror_r(statcode, buf, bufsize);
|
||||
if (buf[0] == '\0') { /* libc didn't use our buffer */
|
||||
return stuffbuffer(buf, bufsize, msg);
|
||||
}
|
||||
else {
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* plain old strerror();
|
||||
* thread-safe on some platforms (e.g., Solaris, OS/390)
|
||||
*/
|
||||
static char *native_strerror(apr_status_t statcode, char *buf,
|
||||
apr_size_t bufsize)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
static char err[32];
|
||||
sprintf(err, "Native Error #%d", statcode);
|
||||
return stuffbuffer(buf, bufsize, err);
|
||||
#else
|
||||
const char *err = strerror(statcode);
|
||||
if (err) {
|
||||
return stuffbuffer(buf, bufsize, err);
|
||||
} else {
|
||||
return stuffbuffer(buf, bufsize,
|
||||
"APR does not understand this error code");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
|
||||
apr_size_t bufsize)
|
||||
{
|
||||
if (statcode < APR_OS_START_ERROR) {
|
||||
return native_strerror(statcode, buf, bufsize);
|
||||
}
|
||||
else if (statcode < APR_OS_START_USERERR) {
|
||||
return stuffbuffer(buf, bufsize, apr_error_string(statcode));
|
||||
}
|
||||
else if (statcode < APR_OS_START_EAIERR) {
|
||||
return stuffbuffer(buf, bufsize, "APR does not understand this error code");
|
||||
}
|
||||
else if (statcode < APR_OS_START_SYSERR) {
|
||||
#if defined(HAVE_GAI_STRERROR)
|
||||
statcode -= APR_OS_START_EAIERR;
|
||||
#if defined(NEGATIVE_EAI)
|
||||
statcode = -statcode;
|
||||
#endif
|
||||
return stuffbuffer(buf, bufsize, gai_strerror(statcode));
|
||||
#else
|
||||
return stuffbuffer(buf, bufsize, "APR does not understand this error code");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
return apr_os_strerror(buf, bufsize, statcode - APR_OS_START_SYSERR);
|
||||
}
|
||||
}
|
||||
|
||||
+309
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_lib.h"
|
||||
|
||||
#define EMSG ""
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_getopt_init(apr_getopt_t **os, apr_pool_t *cont,
|
||||
int argc, const char *const *argv)
|
||||
{
|
||||
void *argv_buff;
|
||||
|
||||
*os = apr_palloc(cont, sizeof(apr_getopt_t));
|
||||
(*os)->cont = cont;
|
||||
(*os)->reset = 0;
|
||||
(*os)->errfn = (apr_getopt_err_fn_t*)(fprintf);
|
||||
(*os)->errarg = (void*)(stderr);
|
||||
|
||||
(*os)->place = EMSG;
|
||||
(*os)->argc = argc;
|
||||
|
||||
/* The argv parameter must be compatible with main()'s argv, since
|
||||
that's the primary purpose of this function. But people might
|
||||
want to use this function with arrays other than the main argv,
|
||||
and we shouldn't touch the caller's data. So we copy. */
|
||||
argv_buff = apr_palloc(cont, (argc + 1) * sizeof(const char *));
|
||||
memcpy(argv_buff, argv, argc * sizeof(const char *));
|
||||
(*os)->argv = argv_buff;
|
||||
(*os)->argv[argc] = NULL;
|
||||
|
||||
(*os)->interleave = 0;
|
||||
(*os)->ind = 1;
|
||||
(*os)->skip_start = 1;
|
||||
(*os)->skip_end = 1;
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_getopt(apr_getopt_t *os, const char *opts,
|
||||
char *optch, const char **optarg)
|
||||
{
|
||||
const char *oli; /* option letter list index */
|
||||
|
||||
if (os->reset || !*os->place) { /* update scanning pointer */
|
||||
os->reset = 0;
|
||||
if (os->ind >= os->argc || *(os->place = os->argv[os->ind]) != '-') {
|
||||
os->place = EMSG;
|
||||
*optch = os->opt;
|
||||
return (APR_EOF);
|
||||
}
|
||||
if (os->place[1] && *++os->place == '-') { /* found "--" */
|
||||
++os->ind;
|
||||
os->place = EMSG;
|
||||
*optch = os->opt;
|
||||
return (APR_EOF);
|
||||
}
|
||||
} /* option letter okay? */
|
||||
if ((os->opt = (int) *os->place++) == (int) ':' ||
|
||||
!(oli = strchr(opts, os->opt))) {
|
||||
/*
|
||||
* if the user didn't specify '-' as an option,
|
||||
* assume it means -1.
|
||||
*/
|
||||
if (os->opt == (int) '-') {
|
||||
*optch = os->opt;
|
||||
return (APR_EOF);
|
||||
}
|
||||
if (!*os->place)
|
||||
++os->ind;
|
||||
if (os->errfn && *opts != ':') {
|
||||
(os->errfn)(os->errarg, "%s: illegal option -- %c\n",
|
||||
apr_filepath_name_get(*os->argv), os->opt);
|
||||
}
|
||||
*optch = os->opt;
|
||||
return (APR_BADCH);
|
||||
}
|
||||
if (*++oli != ':') { /* don't need argument */
|
||||
*optarg = NULL;
|
||||
if (!*os->place)
|
||||
++os->ind;
|
||||
}
|
||||
else { /* need an argument */
|
||||
if (*os->place) /* no white space */
|
||||
*optarg = os->place;
|
||||
else if (os->argc <= ++os->ind) { /* no arg */
|
||||
os->place = EMSG;
|
||||
if (*opts == ':') {
|
||||
*optch = os->opt;
|
||||
return (APR_BADARG);
|
||||
}
|
||||
if (os->errfn) {
|
||||
(os->errfn)(os->errarg,
|
||||
"%s: option requires an argument -- %c\n",
|
||||
apr_filepath_name_get(*os->argv), os->opt);
|
||||
}
|
||||
*optch = os->opt;
|
||||
return (APR_BADCH);
|
||||
}
|
||||
else /* white space */
|
||||
*optarg = os->argv[os->ind];
|
||||
os->place = EMSG;
|
||||
++os->ind;
|
||||
}
|
||||
*optch = os->opt;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Reverse the sequence argv[start..start+len-1]. */
|
||||
static void reverse(const char **argv, int start, int len)
|
||||
{
|
||||
const char *temp;
|
||||
|
||||
for (; len >= 2; start++, len -= 2) {
|
||||
temp = argv[start];
|
||||
argv[start] = argv[start + len - 1];
|
||||
argv[start + len - 1] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Permute os->argv with the goal that non-option arguments will all
|
||||
* appear at the end. os->skip_start is where we started skipping
|
||||
* non-option arguments, os->skip_end is where we stopped, and os->ind
|
||||
* is where we are now.
|
||||
*/
|
||||
static void permute(apr_getopt_t *os)
|
||||
{
|
||||
int len1 = os->skip_end - os->skip_start;
|
||||
int len2 = os->ind - os->skip_end;
|
||||
|
||||
if (os->interleave) {
|
||||
/*
|
||||
* Exchange the sequences argv[os->skip_start..os->skip_end-1] and
|
||||
* argv[os->skip_end..os->ind-1]. The easiest way to do that is
|
||||
* to reverse the entire range and then reverse the two
|
||||
* sub-ranges.
|
||||
*/
|
||||
reverse(os->argv, os->skip_start, len1 + len2);
|
||||
reverse(os->argv, os->skip_start, len2);
|
||||
reverse(os->argv, os->skip_start + len2, len1);
|
||||
}
|
||||
|
||||
/* Reset skip range to the new location of the non-option sequence. */
|
||||
os->skip_start += len2;
|
||||
os->skip_end += len2;
|
||||
}
|
||||
|
||||
/* Helper function to print out an error involving a long option */
|
||||
static apr_status_t serr(apr_getopt_t *os, const char *err, const char *str,
|
||||
apr_status_t status)
|
||||
{
|
||||
if (os->errfn)
|
||||
(os->errfn)(os->errarg, "%s: %s: %s\n",
|
||||
apr_filepath_name_get(*os->argv), err, str);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Helper function to print out an error involving a short option */
|
||||
static apr_status_t cerr(apr_getopt_t *os, const char *err, int ch,
|
||||
apr_status_t status)
|
||||
{
|
||||
if (os->errfn)
|
||||
(os->errfn)(os->errarg, "%s: %s: %c\n",
|
||||
apr_filepath_name_get(*os->argv), err, ch);
|
||||
return status;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_getopt_long(apr_getopt_t *os,
|
||||
const apr_getopt_option_t *opts,
|
||||
int *optch, const char **optarg)
|
||||
{
|
||||
const char *p;
|
||||
int i;
|
||||
|
||||
/* Let the calling program reset option processing. */
|
||||
if (os->reset) {
|
||||
os->place = EMSG;
|
||||
os->ind = 1;
|
||||
os->reset = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can be in one of two states: in the middle of processing a
|
||||
* run of short options, or about to process a new argument.
|
||||
* Since the second case can lead to the first one, handle that
|
||||
* one first. */
|
||||
p = os->place;
|
||||
if (*p == '\0') {
|
||||
/* If we are interleaving, skip non-option arguments. */
|
||||
if (os->interleave) {
|
||||
while (os->ind < os->argc && *os->argv[os->ind] != '-')
|
||||
os->ind++;
|
||||
os->skip_end = os->ind;
|
||||
}
|
||||
if (os->ind >= os->argc || *os->argv[os->ind] != '-') {
|
||||
os->ind = os->skip_start;
|
||||
return APR_EOF;
|
||||
}
|
||||
|
||||
p = os->argv[os->ind++] + 1;
|
||||
if (*p == '-' && p[1] != '\0') { /* Long option */
|
||||
/* Search for the long option name in the caller's table. */
|
||||
apr_size_t len = 0;
|
||||
|
||||
p++;
|
||||
for (i = 0; ; i++) {
|
||||
if (opts[i].optch == 0) /* No match */
|
||||
return serr(os, "invalid option", p - 2, APR_BADCH);
|
||||
|
||||
if (opts[i].name) {
|
||||
len = strlen(opts[i].name);
|
||||
if (strncmp(p, opts[i].name, len) == 0
|
||||
&& (p[len] == '\0' || p[len] == '='))
|
||||
break;
|
||||
}
|
||||
}
|
||||
*optch = opts[i].optch;
|
||||
|
||||
if (opts[i].has_arg) {
|
||||
if (p[len] == '=') /* Argument inline */
|
||||
*optarg = p + len + 1;
|
||||
else {
|
||||
if (os->ind >= os->argc) /* Argument missing */
|
||||
return serr(os, "missing argument", p - 2, APR_BADARG);
|
||||
else /* Argument in next arg */
|
||||
*optarg = os->argv[os->ind++];
|
||||
}
|
||||
} else {
|
||||
*optarg = NULL;
|
||||
if (p[len] == '=')
|
||||
return serr(os, "erroneous argument", p - 2, APR_BADARG);
|
||||
}
|
||||
permute(os);
|
||||
return APR_SUCCESS;
|
||||
} else {
|
||||
if (*p == '-') { /* Bare "--"; we're done */
|
||||
permute(os);
|
||||
os->ind = os->skip_start;
|
||||
return APR_EOF;
|
||||
}
|
||||
else
|
||||
if (*p == '\0') /* Bare "-" is illegal */
|
||||
return serr(os, "invalid option", p, APR_BADCH);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we're in a run of short options, and *p is the next one.
|
||||
* Look for it in the caller's table.
|
||||
*/
|
||||
for (i = 0; ; i++) {
|
||||
if (opts[i].optch == 0) /* No match */
|
||||
return cerr(os, "invalid option character", *p, APR_BADCH);
|
||||
|
||||
if (*p == opts[i].optch)
|
||||
break;
|
||||
}
|
||||
*optch = *p++;
|
||||
|
||||
if (opts[i].has_arg) {
|
||||
if (*p != '\0') /* Argument inline */
|
||||
*optarg = p;
|
||||
else {
|
||||
if (os->ind >= os->argc) /* Argument missing */
|
||||
return cerr(os, "missing argument", *optch, APR_BADARG);
|
||||
else /* Argument in next arg */
|
||||
*optarg = os->argv[os->ind++];
|
||||
}
|
||||
os->place = EMSG;
|
||||
} else {
|
||||
*optarg = NULL;
|
||||
os->place = p;
|
||||
}
|
||||
|
||||
permute(os);
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_arch_threadproc.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
|
||||
#if APR_HAS_OTHER_CHILD
|
||||
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#if APR_HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#ifdef BEOS
|
||||
#include <sys/socket.h> /* for fd_set definition! */
|
||||
#endif
|
||||
|
||||
static apr_other_child_rec_t *other_children = NULL;
|
||||
|
||||
static apr_status_t other_child_cleanup(void *data)
|
||||
{
|
||||
apr_other_child_rec_t **pocr, *nocr;
|
||||
|
||||
for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) {
|
||||
if ((*pocr)->data == data) {
|
||||
nocr = (*pocr)->next;
|
||||
(*(*pocr)->maintenance) (APR_OC_REASON_UNREGISTER, (*pocr)->data, -1);
|
||||
*pocr = nocr;
|
||||
/* XXX: um, well we've just wasted some space in pconf ? */
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc,
|
||||
void (*maintenance) (int reason, void *, int status),
|
||||
void *data, apr_file_t *write_fd, apr_pool_t *p)
|
||||
{
|
||||
apr_other_child_rec_t *ocr;
|
||||
|
||||
ocr = apr_palloc(p, sizeof(*ocr));
|
||||
ocr->p = p;
|
||||
ocr->proc = proc;
|
||||
ocr->maintenance = maintenance;
|
||||
ocr->data = data;
|
||||
if (write_fd == NULL) {
|
||||
ocr->write_fd = (apr_os_file_t) -1;
|
||||
}
|
||||
else {
|
||||
#ifdef WIN32
|
||||
/* This should either go away as part of eliminating apr_proc_probe_writable_fds
|
||||
* or write_fd should point to an apr_file_t
|
||||
*/
|
||||
ocr->write_fd = write_fd->filehand;
|
||||
#else
|
||||
ocr->write_fd = write_fd->filedes;
|
||||
#endif
|
||||
|
||||
}
|
||||
ocr->next = other_children;
|
||||
other_children = ocr;
|
||||
apr_pool_cleanup_register(p, ocr->data, other_child_cleanup,
|
||||
apr_pool_cleanup_null);
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
|
||||
{
|
||||
apr_other_child_rec_t *cur;
|
||||
|
||||
cur = other_children;
|
||||
while (cur) {
|
||||
if (cur->data == data) {
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
/* segfault if this function called with invalid parm */
|
||||
apr_pool_cleanup_kill(cur->p, cur->data, other_child_cleanup);
|
||||
other_child_cleanup(data);
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
|
||||
int reason,
|
||||
int status)
|
||||
{
|
||||
apr_other_child_rec_t *ocr, *nocr;
|
||||
|
||||
for (ocr = other_children; ocr; ocr = nocr) {
|
||||
nocr = ocr->next;
|
||||
if (ocr->proc->pid != proc->pid)
|
||||
continue;
|
||||
|
||||
ocr->proc = NULL;
|
||||
(*ocr->maintenance) (reason, ocr->data, status);
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
return APR_EPROC_UNKNOWN;
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
|
||||
int reason)
|
||||
{
|
||||
/* Todo:
|
||||
* Implement code to detect if pipes are still alive.
|
||||
*/
|
||||
#ifdef WIN32
|
||||
DWORD status;
|
||||
|
||||
if (ocr->proc == NULL)
|
||||
return;
|
||||
|
||||
if (!ocr->proc->hproc) {
|
||||
/* Already mopped up, perhaps we apr_proc_kill'ed it,
|
||||
* they should have already unregistered!
|
||||
*/
|
||||
ocr->proc = NULL;
|
||||
(*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
|
||||
}
|
||||
else if (!GetExitCodeProcess(ocr->proc->hproc, &status)) {
|
||||
CloseHandle(ocr->proc->hproc);
|
||||
ocr->proc->hproc = NULL;
|
||||
ocr->proc = NULL;
|
||||
(*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
|
||||
}
|
||||
else if (status == STILL_ACTIVE) {
|
||||
(*ocr->maintenance) (reason, ocr->data, -1);
|
||||
}
|
||||
else {
|
||||
CloseHandle(ocr->proc->hproc);
|
||||
ocr->proc->hproc = NULL;
|
||||
ocr->proc = NULL;
|
||||
(*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
|
||||
}
|
||||
|
||||
#else /* ndef Win32 */
|
||||
pid_t waitret;
|
||||
int status;
|
||||
|
||||
if (ocr->proc == NULL)
|
||||
return;
|
||||
|
||||
waitret = waitpid(ocr->proc->pid, &status, WNOHANG);
|
||||
if (waitret == ocr->proc->pid) {
|
||||
ocr->proc = NULL;
|
||||
(*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status);
|
||||
}
|
||||
else if (waitret == 0) {
|
||||
(*ocr->maintenance) (reason, ocr->data, -1);
|
||||
}
|
||||
else if (waitret == -1) {
|
||||
/* uh what the heck? they didn't call unregister? */
|
||||
ocr->proc = NULL;
|
||||
(*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
|
||||
{
|
||||
apr_other_child_rec_t *ocr, *next_ocr;
|
||||
|
||||
for (ocr = other_children; ocr; ocr = next_ocr) {
|
||||
next_ocr = ocr->next;
|
||||
apr_proc_other_child_refresh(ocr, reason);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !APR_HAS_OTHER_CHILD */
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc,
|
||||
void (*maintenance) (int reason, void *, int status),
|
||||
void *data, apr_file_t *write_fd, apr_pool_t *p)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_unregister(void *data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc,
|
||||
int reason,
|
||||
int status)
|
||||
{
|
||||
return APR_ENOTIMPL;
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr,
|
||||
int reason)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* APR_HAS_OTHER_CHILD */
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define APR_WANT_MEMFUNC
|
||||
#include "apr_want.h"
|
||||
#include "apr_general.h"
|
||||
|
||||
#include "apr_arch_misc.h"
|
||||
#include <sys/stat.h>
|
||||
#if APR_HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#if APR_HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#if APR_HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#if APR_HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if APR_HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
#if defined(HAVE_UUID_H)
|
||||
#include <uuid.h>
|
||||
#elif defined(HAVE_UUID_UUID_H)
|
||||
#include <uuid/uuid.h>
|
||||
#elif defined(HAVE_SYS_UUID_H)
|
||||
#include <sys/uuid.h>
|
||||
#endif
|
||||
|
||||
#ifndef SHUT_RDWR
|
||||
#define SHUT_RDWR 2
|
||||
#endif
|
||||
|
||||
#if APR_HAS_OS_UUID
|
||||
|
||||
#if defined(HAVE_UUID_CREATE)
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
|
||||
{
|
||||
uint32_t rv;
|
||||
uuid_t g;
|
||||
|
||||
uuid_create(&g, &rv);
|
||||
|
||||
if (rv != uuid_s_ok)
|
||||
return APR_EGENERAL;
|
||||
|
||||
memcpy(uuid_data, &g, sizeof(uuid_t));
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_UUID_GENERATE)
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
|
||||
{
|
||||
uuid_t g;
|
||||
|
||||
uuid_generate(g);
|
||||
|
||||
memcpy(uuid_data, g, sizeof(uuid_t));
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* APR_HAS_OS_UUID */
|
||||
|
||||
#if APR_HAS_RANDOM
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf,
|
||||
apr_size_t length)
|
||||
{
|
||||
#ifdef DEV_RANDOM
|
||||
|
||||
int fd = -1;
|
||||
|
||||
/* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then
|
||||
* gives EOF, so reading 'length' bytes may require opening the
|
||||
* device several times. */
|
||||
do {
|
||||
apr_ssize_t rc;
|
||||
|
||||
if (fd == -1)
|
||||
if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1)
|
||||
return errno;
|
||||
|
||||
do {
|
||||
rc = read(fd, buf, length);
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
|
||||
if (rc < 0) {
|
||||
int errnum = errno;
|
||||
close(fd);
|
||||
return errnum;
|
||||
}
|
||||
else if (rc == 0) {
|
||||
close(fd);
|
||||
fd = -1; /* force open() again */
|
||||
}
|
||||
else {
|
||||
buf += rc;
|
||||
length -= rc;
|
||||
}
|
||||
} while (length > 0);
|
||||
|
||||
close(fd);
|
||||
#elif defined(OS2)
|
||||
static UCHAR randbyte();
|
||||
unsigned int idx;
|
||||
|
||||
for (idx=0; idx<length; idx++)
|
||||
buf[idx] = randbyte();
|
||||
|
||||
#elif defined(HAVE_EGD)
|
||||
/* use EGD-compatible socket daemon (such as EGD or PRNGd).
|
||||
* message format:
|
||||
* 0x00 (get entropy level)
|
||||
* 0xMM (msb) 0xmm 0xll 0xLL (lsb)
|
||||
* 0x01 (read entropy nonblocking) 0xNN (bytes requested)
|
||||
* 0xMM (bytes granted) MM bytes
|
||||
* 0x02 (read entropy blocking) 0xNN (bytes desired)
|
||||
* [block] NN bytes
|
||||
* 0x03 (write entropy) 0xMM 0xLL (bits of entropy) 0xNN (bytes of data)
|
||||
* NN bytes
|
||||
* (no response - write only)
|
||||
* 0x04 (report PID)
|
||||
* 0xMM (length of PID string, not null-terminated) MM chars
|
||||
*/
|
||||
static const char *egd_sockets[] = { EGD_DEFAULT_SOCKET, NULL };
|
||||
const char **egdsockname = NULL;
|
||||
|
||||
int egd_socket, egd_path_len, rv, bad_errno;
|
||||
struct sockaddr_un addr;
|
||||
apr_socklen_t egd_addr_len;
|
||||
apr_size_t resp_expected;
|
||||
unsigned char req[2], resp[255];
|
||||
unsigned char *curbuf = buf;
|
||||
|
||||
for (egdsockname = egd_sockets; *egdsockname && length > 0; egdsockname++) {
|
||||
egd_path_len = strlen(*egdsockname);
|
||||
|
||||
if (egd_path_len > sizeof(addr.sun_path)) {
|
||||
return APR_EINVAL;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||
addr.sun_family = AF_UNIX;
|
||||
memcpy(addr.sun_path, *egdsockname, egd_path_len);
|
||||
egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) +
|
||||
egd_path_len;
|
||||
|
||||
egd_socket = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (egd_socket == -1) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len);
|
||||
|
||||
if (rv == -1) {
|
||||
bad_errno = errno;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* EGD can only return 255 bytes of data at a time. Silly. */
|
||||
while (length > 0) {
|
||||
apr_ssize_t srv;
|
||||
req[0] = 2; /* We'll block for now. */
|
||||
req[1] = length > 255 ? 255: length;
|
||||
|
||||
srv = write(egd_socket, req, 2);
|
||||
if (srv == -1) {
|
||||
bad_errno = errno;
|
||||
shutdown(egd_socket, SHUT_RDWR);
|
||||
close(egd_socket);
|
||||
break;
|
||||
}
|
||||
|
||||
if (srv != 2) {
|
||||
shutdown(egd_socket, SHUT_RDWR);
|
||||
close(egd_socket);
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
||||
resp_expected = req[1];
|
||||
srv = read(egd_socket, resp, resp_expected);
|
||||
if (srv == -1) {
|
||||
bad_errno = errno;
|
||||
shutdown(egd_socket, SHUT_RDWR);
|
||||
close(egd_socket);
|
||||
return bad_errno;
|
||||
}
|
||||
|
||||
memcpy(curbuf, resp, srv);
|
||||
curbuf += srv;
|
||||
length -= srv;
|
||||
}
|
||||
|
||||
shutdown(egd_socket, SHUT_RDWR);
|
||||
close(egd_socket);
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
/* We must have iterated through the list of sockets,
|
||||
* and no go. Return the errno.
|
||||
*/
|
||||
return bad_errno;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_TRUERAND) /* use truerand */
|
||||
|
||||
extern int randbyte(void); /* from the truerand library */
|
||||
unsigned int idx;
|
||||
|
||||
/* this will increase the startup time of the server, unfortunately...
|
||||
* (generating 20 bytes takes about 8 seconds)
|
||||
*/
|
||||
for (idx=0; idx<length; idx++)
|
||||
buf[idx] = (unsigned char) randbyte();
|
||||
|
||||
#endif /* DEV_RANDOM */
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
#undef STR
|
||||
#undef XSTR
|
||||
|
||||
#ifdef OS2
|
||||
#include "randbyte_os2.inc"
|
||||
#endif
|
||||
|
||||
#endif /* APR_HAS_RANDOM */
|
||||
@@ -0,0 +1,123 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* The high resolution timer API provides access to the hardware timer
|
||||
* running at around 1.1MHz. The amount this changes in a time slice is
|
||||
* varies randomly due to system events, hardware interrupts etc
|
||||
*/
|
||||
static UCHAR randbyte_hrtimer()
|
||||
{
|
||||
QWORD t1, t2;
|
||||
UCHAR byte;
|
||||
|
||||
DosTmrQueryTime(&t1);
|
||||
DosSleep(5);
|
||||
DosTmrQueryTime(&t2);
|
||||
|
||||
byte = (t2.ulLo - t1.ulLo) & 0xFF;
|
||||
byte ^= (t2.ulLo - t1.ulLo) >> 8;
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* A bunch of system information like memory & process stats.
|
||||
* Not highly random but every bit helps....
|
||||
*/
|
||||
static UCHAR randbyte_sysinfo()
|
||||
{
|
||||
UCHAR byte = 0;
|
||||
UCHAR SysVars[100];
|
||||
int b;
|
||||
|
||||
DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
|
||||
|
||||
for (b = 0; b < 100; b++) {
|
||||
byte ^= SysVars[b];
|
||||
}
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal
|
||||
* counters which run at the CPU's MHz speed. We get separate
|
||||
* idle / busy / interrupt cycle counts which should provide very good
|
||||
* randomness due to interference of hardware events.
|
||||
* This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions
|
||||
* which is why it's run-time linked.
|
||||
*/
|
||||
|
||||
static APIRET APIENTRY(*DosPerfSysCall) (ULONG ulCommand, ULONG ulParm1,
|
||||
ULONG ulParm2, ULONG ulParm3) = NULL;
|
||||
static HMODULE hDoscalls = 0;
|
||||
#define CMD_KI_RDCNT (0x63)
|
||||
|
||||
typedef struct _CPUUTIL {
|
||||
ULONG ulTimeLow; /* Low 32 bits of time stamp */
|
||||
ULONG ulTimeHigh; /* High 32 bits of time stamp */
|
||||
ULONG ulIdleLow; /* Low 32 bits of idle time */
|
||||
ULONG ulIdleHigh; /* High 32 bits of idle time */
|
||||
ULONG ulBusyLow; /* Low 32 bits of busy time */
|
||||
ULONG ulBusyHigh; /* High 32 bits of busy time */
|
||||
ULONG ulIntrLow; /* Low 32 bits of interrupt time */
|
||||
ULONG ulIntrHigh; /* High 32 bits of interrupt time */
|
||||
} CPUUTIL;
|
||||
|
||||
|
||||
static UCHAR randbyte_perf()
|
||||
{
|
||||
UCHAR byte = 0;
|
||||
CPUUTIL util;
|
||||
int c;
|
||||
|
||||
if (hDoscalls == 0) {
|
||||
char failed_module[20];
|
||||
ULONG rc;
|
||||
|
||||
rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
|
||||
&hDoscalls);
|
||||
|
||||
if (rc == 0) {
|
||||
rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall);
|
||||
|
||||
if (rc) {
|
||||
DosPerfSysCall = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DosPerfSysCall) {
|
||||
if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
|
||||
for (c = 0; c < sizeof(util); c++) {
|
||||
byte ^= ((UCHAR *)&util)[c];
|
||||
}
|
||||
}
|
||||
else {
|
||||
DosPerfSysCall = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static UCHAR randbyte()
|
||||
{
|
||||
return randbyte_hrtimer() ^ randbyte_sysinfo() ^ randbyte_perf();
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_general.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_signal.h"
|
||||
#include "apr_atomic.h"
|
||||
|
||||
#include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */
|
||||
#include "apr_arch_internal_time.h"
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_app_initialize(int *argc,
|
||||
const char * const * *argv,
|
||||
const char * const * *env)
|
||||
{
|
||||
/* An absolute noop. At present, only Win32 requires this stub, but it's
|
||||
* required in order to move command arguments passed through the service
|
||||
* control manager into the process, and it's required to fix the char*
|
||||
* data passed in from win32 unicode into utf-8, win32's apr internal fmt.
|
||||
*/
|
||||
return apr_initialize();
|
||||
}
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_initialize(void)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
apr_status_t status;
|
||||
|
||||
if (initialized++) {
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
#if !defined(BEOS) && !defined(OS2)
|
||||
apr_proc_mutex_unix_setup_lock();
|
||||
apr_unix_setup_time();
|
||||
#endif
|
||||
|
||||
if ((status = apr_pool_initialize()) != APR_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
|
||||
return APR_ENOPOOL;
|
||||
}
|
||||
|
||||
apr_pool_tag(pool, "apr_initialize");
|
||||
|
||||
/* apr_atomic_init() used to be called from here aswell.
|
||||
* Pools rely on mutexes though, which can be backed by
|
||||
* atomics. Due to this circular dependency
|
||||
* apr_pool_initialize() is taking care of calling
|
||||
* apr_atomic_init() at the correct time.
|
||||
*/
|
||||
|
||||
apr_signal_init(pool);
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE_NONSTD(void) apr_terminate(void)
|
||||
{
|
||||
initialized--;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
apr_pool_terminate();
|
||||
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_terminate2(void)
|
||||
{
|
||||
apr_terminate();
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_version.h"
|
||||
#include "apr_general.h" /* for APR_STRINGIFY */
|
||||
|
||||
APR_DECLARE(void) apr_version(apr_version_t *pvsn)
|
||||
{
|
||||
pvsn->major = APR_MAJOR_VERSION;
|
||||
pvsn->minor = APR_MINOR_VERSION;
|
||||
pvsn->patch = APR_PATCH_VERSION;
|
||||
#ifdef APR_IS_DEV_VERSION
|
||||
pvsn->is_dev = 1;
|
||||
#else
|
||||
pvsn->is_dev = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
APR_DECLARE(const char *) apr_version_string(void)
|
||||
{
|
||||
return APR_VERSION_STRING;
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Usage Notes:
|
||||
*
|
||||
* this module, and the misc/win32/utf8.c modules must be
|
||||
* compiled APR_EXPORT_STATIC and linked to an application with
|
||||
* the /entry:wmainCRTStartup flag (which this module kindly
|
||||
* provides to the developer who links to libaprapp-1.lib).
|
||||
* This module becomes the true wmain entry point, and passes
|
||||
* utf-8 reformatted argv and env arrays to the application's
|
||||
* main() function as if nothing happened.
|
||||
*
|
||||
* This module is only compatible with Unicode operating systems.
|
||||
* Mixed (Win9x backwards compatible) binaries should refer instead
|
||||
* to the apr_startup.c module.
|
||||
*
|
||||
* _dbg_malloc/realloc is used in place of the usual API, in order
|
||||
* to convince the MSVCRT that it created these entities. If we
|
||||
* do not create them as _CRT_BLOCK entities, the crt will fault
|
||||
* on an assert. We are not worrying about the crt's locks here,
|
||||
* since we are single threaded [so far].
|
||||
*/
|
||||
|
||||
#include "apr_general.h"
|
||||
#include "ShellAPI.h"
|
||||
#include "wchar.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
#include "assert.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_arch_misc.h"
|
||||
|
||||
#pragma comment(linker,"/ENTRY:wmainCRTStartup")
|
||||
|
||||
extern int main(int argc, const char **argv, const char **env);
|
||||
|
||||
int wmain(int argc, const wchar_t **wargv, const wchar_t **wenv)
|
||||
{
|
||||
char **argv;
|
||||
char **env;
|
||||
int dupenv;
|
||||
|
||||
(void)apr_wastrtoastr(&argv, wargv, argc);
|
||||
|
||||
dupenv = apr_wastrtoastr(&env, wenv, -1);
|
||||
|
||||
_environ = apr_malloc_dbg((dupenv + 1) * sizeof (char *),
|
||||
__FILE__, __LINE__ );
|
||||
memcpy(_environ, env, (dupenv + 1) * sizeof (char *));
|
||||
|
||||
/* MSVCRT will attempt to maintain the wide environment calls
|
||||
* on _putenv(), which is bogus if we've passed a non-ascii
|
||||
* string to _putenv(), since they use MultiByteToWideChar
|
||||
* and breaking the implicit utf-8 assumption we've built.
|
||||
*
|
||||
* Reset _wenviron for good measure.
|
||||
*/
|
||||
if (_wenviron) {
|
||||
wenv = _wenviron;
|
||||
_wenviron = NULL;
|
||||
free((wchar_t **)wenv);
|
||||
}
|
||||
|
||||
apr_app_init_complete = 1;
|
||||
|
||||
return main(argc, argv, env);
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_portable.h"
|
||||
|
||||
|
||||
APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool)
|
||||
{
|
||||
return apr_psprintf(pool, "CP%u", (unsigned) GetACP());
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
int i;
|
||||
#endif
|
||||
#if defined(_WIN32_WCE)
|
||||
LCID locale = GetUserDefaultLCID();
|
||||
#else
|
||||
LCID locale = GetThreadLocale();
|
||||
#endif
|
||||
int len = GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, NULL, 0);
|
||||
char *cp = apr_palloc(pool, (len * sizeof(TCHAR)) + 2);
|
||||
if (0 < GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, (TCHAR*) (cp + 2), len))
|
||||
{
|
||||
/* Fix up the returned number to make a valid codepage name of
|
||||
the form "CPnnnn". */
|
||||
cp[0] = 'C';
|
||||
cp[1] = 'P';
|
||||
#ifdef _UNICODE
|
||||
for(i = 0; i < len; i++) {
|
||||
cp[i + 2] = (char) ((TCHAR*) (cp + 2))[i];
|
||||
}
|
||||
#endif
|
||||
return cp;
|
||||
}
|
||||
|
||||
return apr_os_default_encoding(pool);
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define APR_WANT_STRFUNC
|
||||
#include "apr_want.h"
|
||||
#include "apr.h"
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_arch_utf8.h"
|
||||
#include "apr_env.h"
|
||||
#include "apr_errno.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_strings.h"
|
||||
|
||||
#if APR_HAS_UNICODE_FS && !defined(_WIN32_WCE)
|
||||
static apr_status_t widen_envvar_name (apr_wchar_t *buffer,
|
||||
apr_size_t bufflen,
|
||||
const char *envvar)
|
||||
{
|
||||
apr_size_t inchars;
|
||||
apr_status_t status;
|
||||
|
||||
inchars = strlen(envvar) + 1;
|
||||
status = apr_conv_utf8_to_ucs2(envvar, &inchars, buffer, &bufflen);
|
||||
if (status == APR_INCOMPLETE)
|
||||
status = APR_ENAMETOOLONG;
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_get(char **value,
|
||||
const char *envvar,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
return APR_ENOTIMPL;
|
||||
#else
|
||||
char *val = NULL;
|
||||
DWORD size;
|
||||
|
||||
#if APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t wenvvar[APR_PATH_MAX];
|
||||
apr_size_t inchars, outchars;
|
||||
apr_wchar_t *wvalue, dummy;
|
||||
apr_status_t status;
|
||||
|
||||
status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
SetLastError(0);
|
||||
size = GetEnvironmentVariableW(wenvvar, &dummy, 0);
|
||||
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
|
||||
/* The environment variable doesn't exist. */
|
||||
return APR_ENOENT;
|
||||
|
||||
if (size == 0) {
|
||||
/* The environment value exists, but is zero-length. */
|
||||
*value = apr_pstrdup(pool, "");
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
wvalue = apr_palloc(pool, size * sizeof(*wvalue));
|
||||
size = GetEnvironmentVariableW(wenvvar, wvalue, size);
|
||||
|
||||
inchars = wcslen(wvalue) + 1;
|
||||
outchars = 3 * inchars; /* Enough for any UTF-8 representation */
|
||||
val = apr_palloc(pool, outchars);
|
||||
status = apr_conv_ucs2_to_utf8(wvalue, &inchars, val, &outchars);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
#if APR_HAS_ANSI_FS
|
||||
ELSE_WIN_OS_IS_ANSI
|
||||
{
|
||||
char dummy;
|
||||
|
||||
SetLastError(0);
|
||||
size = GetEnvironmentVariableA(envvar, &dummy, 0);
|
||||
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
|
||||
/* The environment variable doesn't exist. */
|
||||
return APR_ENOENT;
|
||||
|
||||
if (size == 0) {
|
||||
/* The environment value exists, but is zero-length. */
|
||||
*value = apr_pstrdup(pool, "");
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
val = apr_palloc(pool, size);
|
||||
size = GetEnvironmentVariableA(envvar, val, size);
|
||||
if (size == 0)
|
||||
/* Mid-air collision?. Somebody must've changed the env. var. */
|
||||
return APR_INCOMPLETE;
|
||||
}
|
||||
#endif
|
||||
|
||||
*value = val;
|
||||
return APR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_set(const char *envvar,
|
||||
const char *value,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
return APR_ENOTIMPL;
|
||||
#else
|
||||
#if APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t wenvvar[APR_PATH_MAX];
|
||||
apr_wchar_t *wvalue;
|
||||
apr_size_t inchars, outchars;
|
||||
apr_status_t status;
|
||||
|
||||
status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
outchars = inchars = strlen(value) + 1;
|
||||
wvalue = apr_palloc(pool, outchars * sizeof(*wvalue));
|
||||
status = apr_conv_utf8_to_ucs2(value, &inchars, wvalue, &outchars);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (!SetEnvironmentVariableW(wenvvar, wvalue))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
#if APR_HAS_ANSI_FS
|
||||
ELSE_WIN_OS_IS_ANSI
|
||||
{
|
||||
if (!SetEnvironmentVariableA(envvar, value))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
return APR_ENOTIMPL;
|
||||
#else
|
||||
#if APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t wenvvar[APR_PATH_MAX];
|
||||
apr_status_t status;
|
||||
|
||||
status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (!SetEnvironmentVariableW(wenvvar, NULL))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
#if APR_HAS_ANSI_FS
|
||||
ELSE_WIN_OS_IS_ANSI
|
||||
{
|
||||
if (!SetEnvironmentVariableA(envvar, NULL))
|
||||
return apr_get_os_error();
|
||||
}
|
||||
#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_private.h"
|
||||
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
#include <assert.h>
|
||||
|
||||
/* This module is the source of -static- helper functions that are
|
||||
* entirely internal to apr. If the fn is exported - it does not
|
||||
* belong here.
|
||||
*
|
||||
* Namespace decoration is still required to protect us from symbol
|
||||
* clashes in static linkages.
|
||||
*/
|
||||
|
||||
|
||||
/* Shared by apr_app.c and start.c
|
||||
*
|
||||
* An internal apr function to convert an array of strings (either
|
||||
* a counted or NULL terminated list, such as an argv[argc] or env[]
|
||||
* list respectively) from wide Unicode strings to narrow utf-8 strings.
|
||||
* These are allocated from the MSVCRT's _CRT_BLOCK to trick the system
|
||||
* into trusting our store.
|
||||
*/
|
||||
int apr_wastrtoastr(char const * const * *retarr,
|
||||
wchar_t const * const *arr, int args)
|
||||
{
|
||||
apr_size_t elesize = 0;
|
||||
char **newarr;
|
||||
char *elements;
|
||||
char *ele;
|
||||
int arg;
|
||||
|
||||
if (args < 0) {
|
||||
for (args = 0; arr[args]; ++args)
|
||||
;
|
||||
}
|
||||
|
||||
newarr = apr_malloc_dbg((args + 1) * sizeof(char *),
|
||||
__FILE__, __LINE__);
|
||||
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
newarr[arg] = (void*)(wcslen(arr[arg]) + 1);
|
||||
elesize += (apr_size_t)newarr[arg];
|
||||
}
|
||||
|
||||
/* This is a safe max allocation, we will realloc after
|
||||
* processing and return the excess to the free store.
|
||||
* 3 ucs bytes hold any single wchar_t value (16 bits)
|
||||
* 4 ucs bytes will hold a wchar_t pair value (20 bits)
|
||||
*/
|
||||
elesize = elesize * 3 + 1;
|
||||
ele = elements = apr_malloc_dbg(elesize * sizeof(char),
|
||||
__FILE__, __LINE__);
|
||||
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
apr_size_t len = (apr_size_t)newarr[arg];
|
||||
apr_size_t newlen = elesize;
|
||||
|
||||
newarr[arg] = ele;
|
||||
(void)apr_conv_ucs2_to_utf8(arr[arg], &len,
|
||||
newarr[arg], &elesize);
|
||||
|
||||
newlen -= elesize;
|
||||
ele += newlen;
|
||||
assert(elesize && (len == 0));
|
||||
}
|
||||
|
||||
newarr[arg] = NULL;
|
||||
*(ele++) = '\0';
|
||||
|
||||
/* Return to the free store if the heap realloc is the least bit optimized
|
||||
*/
|
||||
ele = apr_realloc_dbg(elements, ele - elements,
|
||||
__FILE__, __LINE__);
|
||||
|
||||
if (ele != elements) {
|
||||
apr_size_t diff = ele - elements;
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
newarr[arg] += diff;
|
||||
}
|
||||
}
|
||||
|
||||
*retarr = (char const * const *)newarr;
|
||||
return args;
|
||||
}
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_private.h"
|
||||
#include "apr_arch_misc.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
#include "assert.h"
|
||||
#include "apr_lib.h"
|
||||
#include "tchar.h"
|
||||
|
||||
APR_DECLARE_DATA apr_oslevel_e apr_os_level = APR_WIN_UNK;
|
||||
|
||||
apr_status_t apr_get_oslevel(apr_oslevel_e *level)
|
||||
{
|
||||
if (apr_os_level == APR_WIN_UNK)
|
||||
{
|
||||
static OSVERSIONINFO oslev;
|
||||
oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&oslev);
|
||||
|
||||
if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
{
|
||||
static unsigned int servpack = 0;
|
||||
TCHAR *pservpack;
|
||||
if ((pservpack = oslev.szCSDVersion)) {
|
||||
while (*pservpack && !apr_isdigit(*pservpack)) {
|
||||
pservpack++;
|
||||
}
|
||||
if (*pservpack)
|
||||
#ifdef _UNICODE
|
||||
servpack = _wtoi(pservpack);
|
||||
#else
|
||||
servpack = atoi(pservpack);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (oslev.dwMajorVersion < 3) {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 3) {
|
||||
if (oslev.dwMajorVersion < 50) {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 50) {
|
||||
apr_os_level = APR_WIN_NT_3_5;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_NT_3_51;
|
||||
}
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 4) {
|
||||
if (servpack < 2)
|
||||
apr_os_level = APR_WIN_NT_4;
|
||||
else if (servpack <= 2)
|
||||
apr_os_level = APR_WIN_NT_4_SP2;
|
||||
else if (servpack <= 3)
|
||||
apr_os_level = APR_WIN_NT_4_SP3;
|
||||
else if (servpack <= 4)
|
||||
apr_os_level = APR_WIN_NT_4_SP4;
|
||||
else if (servpack <= 5)
|
||||
apr_os_level = APR_WIN_NT_4_SP5;
|
||||
else
|
||||
apr_os_level = APR_WIN_NT_4_SP6;
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 5) {
|
||||
if (oslev.dwMinorVersion == 0) {
|
||||
if (servpack == 0)
|
||||
apr_os_level = APR_WIN_2000;
|
||||
else if (servpack == 1)
|
||||
apr_os_level = APR_WIN_2000_SP1;
|
||||
else
|
||||
apr_os_level = APR_WIN_2000_SP2;
|
||||
}
|
||||
else if (oslev.dwMinorVersion == 2) {
|
||||
apr_os_level = APR_WIN_2003;
|
||||
}
|
||||
else {
|
||||
if (servpack < 1)
|
||||
apr_os_level = APR_WIN_XP;
|
||||
else if (servpack == 1)
|
||||
apr_os_level = APR_WIN_XP_SP1;
|
||||
else
|
||||
apr_os_level = APR_WIN_XP_SP2;
|
||||
}
|
||||
}
|
||||
else if (oslev.dwMajorVersion == 6) {
|
||||
if (oslev.dwMinorVersion == 0)
|
||||
apr_os_level = APR_WIN_VISTA;
|
||||
else
|
||||
apr_os_level = APR_WIN_7;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_XP;
|
||||
}
|
||||
}
|
||||
#ifndef WINNT
|
||||
else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
|
||||
TCHAR *prevision;
|
||||
if (prevision = oslev.szCSDVersion) {
|
||||
while (*prevision && !apr_isupper(*prevision)) {
|
||||
prevision++;
|
||||
}
|
||||
}
|
||||
else prevision = _T("");
|
||||
|
||||
if (oslev.dwMinorVersion < 10) {
|
||||
if (*prevision < _T('C'))
|
||||
apr_os_level = APR_WIN_95;
|
||||
else
|
||||
apr_os_level = APR_WIN_95_OSR2;
|
||||
}
|
||||
else if (oslev.dwMinorVersion < 90) {
|
||||
if (*prevision < _T('A'))
|
||||
apr_os_level = APR_WIN_98;
|
||||
else
|
||||
apr_os_level = APR_WIN_98_SE;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_ME;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef _WIN32_WCE
|
||||
else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_CE)
|
||||
{
|
||||
if (oslev.dwMajorVersion < 3) {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
else {
|
||||
apr_os_level = APR_WIN_CE_3;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
apr_os_level = APR_WIN_UNSUP;
|
||||
}
|
||||
}
|
||||
|
||||
*level = apr_os_level;
|
||||
|
||||
if (apr_os_level < APR_WIN_UNSUP) {
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* This is the helper code to resolve late bound entry points
|
||||
* missing from one or more releases of the Win32 API
|
||||
*/
|
||||
|
||||
static const char* const lateDllName[DLL_defined] = {
|
||||
"kernel32", "advapi32", "mswsock", "ws2_32", "shell32", "ntdll.dll" };
|
||||
static HMODULE lateDllHandle[DLL_defined] = {
|
||||
NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
|
||||
FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
|
||||
{
|
||||
if (!lateDllHandle[fnLib]) {
|
||||
lateDllHandle[fnLib] = LoadLibraryA(lateDllName[fnLib]);
|
||||
if (!lateDllHandle[fnLib])
|
||||
return NULL;
|
||||
}
|
||||
#if defined(_WIN32_WCE)
|
||||
if (ordinal)
|
||||
return GetProcAddressA(lateDllHandle[fnLib], (const char *)
|
||||
(apr_ssize_t)ordinal);
|
||||
else
|
||||
return GetProcAddressA(lateDllHandle[fnLib], fnName);
|
||||
#else
|
||||
if (ordinal)
|
||||
return GetProcAddress(lateDllHandle[fnLib], (const char *)
|
||||
(apr_ssize_t)ordinal);
|
||||
else
|
||||
return GetProcAddress(lateDllHandle[fnLib], fnName);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Declared in include/arch/win32/apr_dbg_win32_handles.h
|
||||
*/
|
||||
APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln,
|
||||
int nh, /* HANDLE hv, char *dsc */...)
|
||||
{
|
||||
static DWORD tlsid = 0xFFFFFFFF;
|
||||
static HANDLE fh = NULL;
|
||||
static long ctr = 0;
|
||||
static CRITICAL_SECTION cs;
|
||||
long seq;
|
||||
DWORD wrote;
|
||||
char *sbuf;
|
||||
|
||||
seq = (InterlockedIncrement)(&ctr);
|
||||
|
||||
if (tlsid == 0xFFFFFFFF) {
|
||||
tlsid = (TlsAlloc)();
|
||||
}
|
||||
|
||||
sbuf = (TlsGetValue)(tlsid);
|
||||
if (!fh || !sbuf) {
|
||||
sbuf = (malloc)(1024);
|
||||
(TlsSetValue)(tlsid, sbuf);
|
||||
sbuf[1023] = '\0';
|
||||
if (!fh) {
|
||||
(GetModuleFileNameA)(NULL, sbuf, 250);
|
||||
sprintf(strchr(sbuf, '\0'), ".%u",
|
||||
(unsigned int)(GetCurrentProcessId)());
|
||||
fh = (CreateFileA)(sbuf, GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, 0, NULL);
|
||||
(InitializeCriticalSection)(&cs);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nh) {
|
||||
(sprintf)(sbuf, "%p %08x %08x %s() %s:%d\n",
|
||||
ha, (unsigned int)seq, (unsigned int)GetCurrentThreadId(),
|
||||
fn, fl, ln);
|
||||
(EnterCriticalSection)(&cs);
|
||||
(WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
|
||||
(LeaveCriticalSection)(&cs);
|
||||
}
|
||||
else {
|
||||
va_list a;
|
||||
va_start(a,nh);
|
||||
(EnterCriticalSection)(&cs);
|
||||
do {
|
||||
HANDLE *hv = va_arg(a, HANDLE*);
|
||||
char *dsc = va_arg(a, char*);
|
||||
if (strcmp(dsc, "Signaled") == 0) {
|
||||
if ((apr_ssize_t)ha >= STATUS_WAIT_0
|
||||
&& (apr_ssize_t)ha < STATUS_ABANDONED_WAIT_0) {
|
||||
hv += (apr_ssize_t)ha;
|
||||
}
|
||||
else if ((apr_ssize_t)ha >= STATUS_ABANDONED_WAIT_0
|
||||
&& (apr_ssize_t)ha < STATUS_USER_APC) {
|
||||
hv += (apr_ssize_t)ha - STATUS_ABANDONED_WAIT_0;
|
||||
dsc = "Abandoned";
|
||||
}
|
||||
else if ((apr_ssize_t)ha == WAIT_TIMEOUT) {
|
||||
dsc = "Timed Out";
|
||||
}
|
||||
}
|
||||
(sprintf)(sbuf, "%p %08x %08x %s(%s) %s:%d\n",
|
||||
*hv, (unsigned int)seq,
|
||||
(unsigned int)GetCurrentThreadId(),
|
||||
fn, dsc, fl, ln);
|
||||
(WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL);
|
||||
} while (--nh);
|
||||
(LeaveCriticalSection)(&cs);
|
||||
va_end(a);
|
||||
}
|
||||
return ha;
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include <rpc.h>
|
||||
#include <wincrypt.h>
|
||||
#include "apr_private.h"
|
||||
#include "apr_general.h"
|
||||
#include "apr_portable.h"
|
||||
#include "apr_arch_misc.h"
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf,
|
||||
apr_size_t length)
|
||||
{
|
||||
HCRYPTPROV hProv;
|
||||
apr_status_t res = APR_SUCCESS;
|
||||
|
||||
/* 0x40 bit = CRYPT_SILENT, only introduced in more recent PSDKs
|
||||
* and will only work for Win2K and later.
|
||||
*/
|
||||
DWORD flags = CRYPT_VERIFYCONTEXT
|
||||
| ((apr_os_level >= APR_WIN_2000) ? 0x40 : 0);
|
||||
|
||||
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, flags)) {
|
||||
return apr_get_os_error();
|
||||
}
|
||||
/* XXX: An ugly hack for Win64, randomness is such that noone should
|
||||
* ever expect > 2^31 bytes of data at once without the prng
|
||||
* coming to a complete halt.
|
||||
*/
|
||||
if (!CryptGenRandom(hProv, (DWORD)length, buf)) {
|
||||
res = apr_get_os_error();
|
||||
}
|
||||
CryptReleaseContext(hProv, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data)
|
||||
{
|
||||
/* Note: this call doesn't actually require CoInitialize() first
|
||||
*
|
||||
* XXX: we should scramble the bytes or some such to eliminate the
|
||||
* possible misuse/abuse since uuid is based on the NIC address, and
|
||||
* is therefore not only a uniqifier, but an identity (which might not
|
||||
* be appropriate in all cases.
|
||||
*
|
||||
* Note that Win2000, XP and later no longer suffer from this problem,
|
||||
* a scrambling fix is only needed for (apr_os_level < APR_WIN_2000)
|
||||
*/
|
||||
if (FAILED(UuidCreate((UUID *)uuid_data))) {
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_private.h"
|
||||
#include "apr_general.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_signal.h"
|
||||
#include "shellapi.h"
|
||||
|
||||
#include "apr_arch_misc.h" /* for WSAHighByte / WSALowByte */
|
||||
#include "wchar.h"
|
||||
#include "apr_arch_file_io.h" /* bring in unicode-ness */
|
||||
#include "apr_arch_threadproc.h" /* bring in apr_threadproc_init */
|
||||
#include "assert.h"
|
||||
|
||||
/* This symbol is _private_, although it must be exported.
|
||||
*/
|
||||
int APR_DECLARE_DATA apr_app_init_complete = 0;
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
/* Used by apr_app_initialize to reprocess the environment
|
||||
*
|
||||
* An internal apr function to convert a double-null terminated set
|
||||
* of single-null terminated strings from wide Unicode to narrow utf-8
|
||||
* as a list of strings. These are allocated from the MSVCRT's
|
||||
* _CRT_BLOCK to trick the system into trusting our store.
|
||||
*/
|
||||
static int warrsztoastr(const char * const * *retarr,
|
||||
const wchar_t * arrsz)
|
||||
{
|
||||
const apr_wchar_t *wch;
|
||||
apr_size_t totlen;
|
||||
apr_size_t newlen;
|
||||
apr_size_t wsize;
|
||||
char **env;
|
||||
char *pstrs;
|
||||
char *strs;
|
||||
int arg, args;
|
||||
|
||||
for (args = 1, wch = arrsz; wch[0] || wch[1]; ++wch)
|
||||
if (!*wch)
|
||||
++args;
|
||||
wsize = 1 + wch - arrsz;
|
||||
|
||||
/* This is a safe max allocation, we will alloc each
|
||||
* string exactly after processing and return this
|
||||
* temporary buffer to the free store.
|
||||
* 3 ucs bytes hold any single wchar_t value (16 bits)
|
||||
* 4 ucs bytes will hold a wchar_t pair value (20 bits)
|
||||
*/
|
||||
newlen = totlen = wsize * 3 + 1;
|
||||
pstrs = strs = apr_malloc_dbg(newlen * sizeof(char),
|
||||
__FILE__, __LINE__);
|
||||
|
||||
(void)apr_conv_ucs2_to_utf8(arrsz, &wsize, strs, &newlen);
|
||||
|
||||
assert(newlen && !wsize);
|
||||
|
||||
*retarr = env = apr_malloc_dbg((args + 1) * sizeof(char*),
|
||||
__FILE__, __LINE__);
|
||||
for (arg = 0; arg < args; ++arg) {
|
||||
char* p = pstrs;
|
||||
int len = 0;
|
||||
while (*p++)
|
||||
++len;
|
||||
len += 1;
|
||||
|
||||
*env = apr_malloc_dbg(len * sizeof(char),
|
||||
__FILE__, __LINE__);
|
||||
memcpy(*env, pstrs, len * sizeof(char));
|
||||
|
||||
pstrs += len;
|
||||
++env;
|
||||
}
|
||||
|
||||
*env = NULL;
|
||||
free(strs);
|
||||
|
||||
return args;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reprocess the arguments to main() for a completely apr-ized application
|
||||
*/
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_app_initialize(int *argc,
|
||||
const char * const * *argv,
|
||||
const char * const * *env)
|
||||
{
|
||||
apr_status_t rv = apr_initialize();
|
||||
|
||||
if (rv != APR_SUCCESS) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
apr_app_init_complete = 1;
|
||||
#elif APR_HAS_UNICODE_FS
|
||||
IF_WIN_OS_IS_UNICODE
|
||||
{
|
||||
apr_wchar_t **wstrs;
|
||||
apr_wchar_t *sysstr;
|
||||
int wstrc;
|
||||
int dupenv;
|
||||
|
||||
if (apr_app_init_complete) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
apr_app_init_complete = 1;
|
||||
|
||||
sysstr = GetCommandLineW();
|
||||
if (sysstr) {
|
||||
wstrs = CommandLineToArgvW(sysstr, &wstrc);
|
||||
if (wstrs) {
|
||||
*argc = apr_wastrtoastr(argv, wstrs, wstrc);
|
||||
GlobalFree(wstrs);
|
||||
}
|
||||
}
|
||||
|
||||
sysstr = GetEnvironmentStringsW();
|
||||
dupenv = warrsztoastr(&_environ, sysstr);
|
||||
|
||||
if (env) {
|
||||
*env = apr_malloc_dbg((dupenv + 1) * sizeof (char *),
|
||||
__FILE__, __LINE__ );
|
||||
memcpy((void*)*env, _environ, (dupenv + 1) * sizeof (char *));
|
||||
}
|
||||
else {
|
||||
}
|
||||
|
||||
FreeEnvironmentStringsW(sysstr);
|
||||
|
||||
/* MSVCRT will attempt to maintain the wide environment calls
|
||||
* on _putenv(), which is bogus if we've passed a non-ascii
|
||||
* string to _putenv(), since they use MultiByteToWideChar
|
||||
* and breaking the implicit utf-8 assumption we've built.
|
||||
*
|
||||
* Reset _wenviron for good measure.
|
||||
*/
|
||||
if (_wenviron) {
|
||||
apr_wchar_t **wenv = _wenviron;
|
||||
_wenviron = NULL;
|
||||
free(wenv);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
/* Provide to win32/thread.c */
|
||||
extern DWORD tls_apr_thread;
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_initialize(void)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
apr_status_t status;
|
||||
int iVersionRequested;
|
||||
WSADATA wsaData;
|
||||
int err;
|
||||
apr_oslevel_e osver;
|
||||
|
||||
if (initialized++) {
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Initialize apr_os_level global */
|
||||
if (apr_get_oslevel(&osver) != APR_SUCCESS) {
|
||||
return APR_EEXIST;
|
||||
}
|
||||
|
||||
tls_apr_thread = TlsAlloc();
|
||||
if ((status = apr_pool_initialize()) != APR_SUCCESS)
|
||||
return status;
|
||||
|
||||
if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
|
||||
return APR_ENOPOOL;
|
||||
}
|
||||
|
||||
apr_pool_tag(pool, "apr_initialize");
|
||||
|
||||
iVersionRequested = MAKEWORD(WSAHighByte, WSALowByte);
|
||||
err = WSAStartup((WORD) iVersionRequested, &wsaData);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
if (LOBYTE(wsaData.wVersion) != WSAHighByte ||
|
||||
HIBYTE(wsaData.wVersion) != WSALowByte) {
|
||||
WSACleanup();
|
||||
return APR_EEXIST;
|
||||
}
|
||||
|
||||
apr_signal_init(pool);
|
||||
|
||||
apr_threadproc_init(pool);
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE_NONSTD(void) apr_terminate(void)
|
||||
{
|
||||
initialized--;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
apr_pool_terminate();
|
||||
|
||||
WSACleanup();
|
||||
|
||||
TlsFree(tls_apr_thread);
|
||||
}
|
||||
|
||||
APR_DECLARE(void) apr_terminate2(void)
|
||||
{
|
||||
apr_terminate();
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_errno.h"
|
||||
#include "apr_arch_utf8.h"
|
||||
|
||||
/* Implementation of RFC 3629, "UTF-8, a transformation format of ISO 10646"
|
||||
* with particular attention to canonical translation forms (see section 10
|
||||
* "Security Considerations" of the RFC for more info).
|
||||
*
|
||||
* Since several architectures including Windows support unicode, with UCS2
|
||||
* used as the actual storage conventions by that archicture, these functions
|
||||
* exist to transform or validate UCS2 strings into APR's 'char' type
|
||||
* convention. It is left up to the operating system to determine the
|
||||
* validitity of the string, e.g. normative forms, in the context of
|
||||
* its native language support. Other file systems which support filename
|
||||
* characters of 0x80-0xff but have no explicit requirement for Unicode
|
||||
* will find this function useful only for validating the character sequences
|
||||
* and rejecting poorly encoded UTF8 sequences.
|
||||
*
|
||||
* Len UCS-4 range (hex) UTF-8 octet sequence (binary)
|
||||
* 1:2 00000000-0000007F 0xxxxxxx
|
||||
* 2:2 00000080-000007FF 110XXXXx 10xxxxxx
|
||||
* 3:2 00000800-0000FFFF 1110XXXX 10Xxxxxx 10xxxxxx
|
||||
* 4:4 00010000-001FFFFF 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx
|
||||
* 00200000-03FFFFFF 111110XX 10XXXxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 04000000-7FFFFFFF 1111110X 10XXXXxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*
|
||||
* One of the X bits must be 1 to avoid overlong representation of ucs2 values.
|
||||
*
|
||||
* For conversion into ucs2, the 4th form is limited in range to 0010 FFFF,
|
||||
* and the final two forms are used only by full ucs4, per RFC 3629;
|
||||
*
|
||||
* "Pairs of UCS-2 values between D800 and DFFF (surrogate pairs in
|
||||
* Unicode parlance), being actually UCS-4 characters transformed
|
||||
* through UTF-16, need special treatment: the UTF-16 transformation
|
||||
* must be undone, yielding a UCS-4 character that is then transformed
|
||||
* as above."
|
||||
*
|
||||
* From RFC2781 UTF-16: the compressed ISO 10646 encoding bitmask
|
||||
*
|
||||
* U' = U - 0x10000
|
||||
* U' = 00000000 0000yyyy yyyyyyxx xxxxxxxx
|
||||
* W1 = 110110yy yyyyyyyy
|
||||
* W2 = 110111xx xxxxxxxx
|
||||
* Max U' = 0000 00001111 11111111 11111111
|
||||
* Max U = 0000 00010000 11111111 11111111
|
||||
*
|
||||
* Len is the table above is a mapping of bytes used for utf8:ucs2 values,
|
||||
* which results in these conclusions of maximum allocations;
|
||||
*
|
||||
* apr_conv_utf8_to_ucs2 out bytes:sizeof(in) * 1 <= Req <= sizeof(in) * 2
|
||||
* apr_conv_ucs2_to_utf8 out words:sizeof(in) / 2 <= Req <= sizeof(in) * 3 / 2
|
||||
*/
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_conv_utf8_to_ucs2(const char *in,
|
||||
apr_size_t *inbytes,
|
||||
apr_wchar_t *out,
|
||||
apr_size_t *outwords)
|
||||
{
|
||||
apr_int64_t newch, mask;
|
||||
apr_size_t expect, eating;
|
||||
int ch;
|
||||
|
||||
while (*inbytes && *outwords)
|
||||
{
|
||||
ch = (unsigned char)(*in++);
|
||||
if (!(ch & 0200)) {
|
||||
/* US-ASCII-7 plain text
|
||||
*/
|
||||
--*inbytes;
|
||||
--*outwords;
|
||||
*(out++) = ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ch & 0300) != 0300) {
|
||||
/* Multibyte Continuation is out of place
|
||||
*/
|
||||
return APR_EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Multibyte Sequence Lead Character
|
||||
*
|
||||
* Compute the expected bytes while adjusting
|
||||
* or lead byte and leading zeros mask.
|
||||
*/
|
||||
mask = 0340;
|
||||
expect = 1;
|
||||
while ((ch & mask) == mask) {
|
||||
mask |= mask >> 1;
|
||||
if (++expect > 3) /* (truly 5 for ucs-4) */
|
||||
return APR_EINVAL;
|
||||
}
|
||||
newch = ch & ~mask;
|
||||
eating = expect + 1;
|
||||
if (*inbytes <= expect)
|
||||
return APR_INCOMPLETE;
|
||||
/* Reject values of excessive leading 0 bits
|
||||
* utf-8 _demands_ the shortest possible byte length
|
||||
*/
|
||||
if (expect == 1) {
|
||||
if (!(newch & 0036))
|
||||
return APR_EINVAL;
|
||||
}
|
||||
else {
|
||||
/* Reject values of excessive leading 0 bits
|
||||
*/
|
||||
if (!newch && !((unsigned char)*in & 0077 & (mask << 1)))
|
||||
return APR_EINVAL;
|
||||
if (expect == 2) {
|
||||
/* Reject values D800-DFFF when not utf16 encoded
|
||||
* (may not be an appropriate restriction for ucs-4)
|
||||
*/
|
||||
if (newch == 0015 && ((unsigned char)*in & 0040))
|
||||
return APR_EINVAL;
|
||||
}
|
||||
else if (expect == 3) {
|
||||
/* Short circuit values > 110000
|
||||
*/
|
||||
if (newch > 4)
|
||||
return APR_EINVAL;
|
||||
if (newch == 4 && ((unsigned char)*in & 0060))
|
||||
return APR_EINVAL;
|
||||
}
|
||||
}
|
||||
/* Where the boolean (expect > 2) is true, we will need
|
||||
* an extra word for the output.
|
||||
*/
|
||||
if (*outwords < (apr_size_t)(expect > 2) + 1)
|
||||
break; /* buffer full */
|
||||
while (expect--)
|
||||
{
|
||||
/* Multibyte Continuation must be legal */
|
||||
if (((ch = (unsigned char)*(in++)) & 0300) != 0200)
|
||||
return APR_EINVAL;
|
||||
newch <<= 6;
|
||||
newch |= (ch & 0077);
|
||||
}
|
||||
*inbytes -= eating;
|
||||
/* newch is now a true ucs-4 character
|
||||
*
|
||||
* now we need to fold to ucs-2
|
||||
*/
|
||||
if (newch < 0x10000)
|
||||
{
|
||||
--*outwords;
|
||||
*(out++) = (apr_wchar_t) newch;
|
||||
}
|
||||
else
|
||||
{
|
||||
*outwords -= 2;
|
||||
newch -= 0x10000;
|
||||
*(out++) = (apr_wchar_t) (0xD800 | (newch >> 10));
|
||||
*(out++) = (apr_wchar_t) (0xDC00 | (newch & 0x03FF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Buffer full 'errors' aren't errors, the client must inspect both
|
||||
* the inbytes and outwords values
|
||||
*/
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_conv_ucs2_to_utf8(const apr_wchar_t *in,
|
||||
apr_size_t *inwords,
|
||||
char *out,
|
||||
apr_size_t *outbytes)
|
||||
{
|
||||
apr_int64_t newch, require;
|
||||
apr_size_t need;
|
||||
char *invout;
|
||||
int ch;
|
||||
|
||||
while (*inwords && *outbytes)
|
||||
{
|
||||
ch = (unsigned short)(*in++);
|
||||
if (ch < 0x80)
|
||||
{
|
||||
--*inwords;
|
||||
--*outbytes;
|
||||
*(out++) = (unsigned char) ch;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ch & 0xFC00) == 0xDC00) {
|
||||
/* Invalid Leading ucs-2 Multiword Continuation Character
|
||||
*/
|
||||
return APR_EINVAL;
|
||||
}
|
||||
if ((ch & 0xFC00) == 0xD800) {
|
||||
/* Leading ucs-2 Multiword Character
|
||||
*/
|
||||
if (*inwords < 2) {
|
||||
/* Missing ucs-2 Multiword Continuation Character
|
||||
*/
|
||||
return APR_INCOMPLETE;
|
||||
}
|
||||
if (((unsigned short)(*in) & 0xFC00) != 0xDC00) {
|
||||
/* Invalid ucs-2 Multiword Continuation Character
|
||||
*/
|
||||
return APR_EINVAL;
|
||||
}
|
||||
newch = (ch & 0x03FF) << 10 | ((unsigned short)(*in++) & 0x03FF);
|
||||
newch += 0x10000;
|
||||
}
|
||||
else {
|
||||
/* ucs-2 Single Word Character
|
||||
*/
|
||||
newch = ch;
|
||||
}
|
||||
/* Determine the absolute minimum utf-8 bytes required
|
||||
*/
|
||||
require = newch >> 11;
|
||||
need = 1;
|
||||
while (require)
|
||||
require >>= 5, ++need;
|
||||
if (need >= *outbytes)
|
||||
break; /* Insufficient buffer */
|
||||
*inwords -= (need > 2) + 1;
|
||||
*outbytes -= need + 1;
|
||||
/* Compute the utf-8 characters in last to first order,
|
||||
* calculating the lead character length bits along the way.
|
||||
*/
|
||||
ch = 0200;
|
||||
out += need + 1;
|
||||
invout = out;
|
||||
while (need--) {
|
||||
ch |= ch >> 1;
|
||||
*(--invout) = (unsigned char)(0200 | (newch & 0077));
|
||||
newch >>= 6;
|
||||
}
|
||||
/* Compute the lead utf-8 character and move the dest offset
|
||||
*/
|
||||
*(--invout) = (unsigned char)(ch | newch);
|
||||
}
|
||||
}
|
||||
/* Buffer full 'errors' aren't errors, the client must inspect both
|
||||
* the inwords and outbytes values
|
||||
*/
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user