feat:replace boost library with C++11 std library
This commit is contained in:
+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;
|
||||
}
|
||||
Reference in New Issue
Block a user