feat:replace boost library with C++11 std library

This commit is contained in:
Livox-SDK
2020-04-01 20:53:55 +08:00
parent 6d06233944
commit d3258bbd97
1936 changed files with 241862 additions and 60153 deletions
+83
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+123
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}