native/common/jk_util.c (2,005 lines of code) (raw):
/*
* 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.
*/
/***************************************************************************
* Description: Utility functions (mainly configuration) *
* Author: Gal Shachor <shachor@il.ibm.com> *
* Author: Henri Gomez <hgomez@apache.org> *
* Author: Rainer Jung <rjung@apache.org> *
***************************************************************************/
#include "jk_util.h"
#include "jk_ajp12_worker.h"
#include "jk_ajp13_worker.h"
#include "jk_ajp14_worker.h"
#include "jk_lb_worker.h"
#include "jk_mt.h"
#define SYSPROPS_OF_WORKER "sysprops"
#define STDERR_OF_WORKER "stderr"
#define STDOUT_OF_WORKER "stdout"
#define SECRET_OF_WORKER "secret"
#define MX_OF_WORKER "mx"
#define MS_OF_WORKER "ms"
#define CP_OF_WORKER "class_path"
#define BRIDGE_OF_WORKER "bridge"
#define JVM_OF_WORKER "jvm_lib"
#define LIBPATH_OF_WORKER "ld_path"
#define CMD_LINE_OF_WORKER "cmd_line"
#define NATIVE_LIB_OF_WORKER "native_lib"
#define REFERENCE_OF_WORKER "reference"
#define HOST_OF_WORKER "host"
#define SOURCE_OF_WORKER "source"
#define PORT_OF_WORKER "port"
#define TYPE_OF_WORKER "type"
#define CACHE_OF_WORKER_DEPRECATED "cachesize"
#define CACHE_OF_WORKER "connection_pool_size"
#define CACHE_OF_WORKER_MIN "connection_pool_minsize"
#define CACHE_TIMEOUT_DEPRECATED "cache_timeout"
#define CACHE_TIMEOUT_OF_WORKER "connection_pool_timeout"
#define CACHE_ACQUIRE_OF_WORKER "connection_acquire_timeout"
#define RECOVERY_OPTS_OF_WORKER "recovery_options"
#define CONNECT_TIMEOUT_OF_WORKER "connect_timeout"
#define PREPOST_TIMEOUT_OF_WORKER "prepost_timeout"
#define REPLY_TIMEOUT_OF_WORKER "reply_timeout"
#define SOCKET_TIMEOUT_OF_WORKER "socket_timeout"
#define SOCKET_CONNECT_TIMEOUT_OF_WORKER "socket_connect_timeout"
#define PING_TIMEOUT_OF_WORKER "ping_timeout"
#define PING_MODE_OF_WORKER "ping_mode"
#define SOCKET_BUFFER_OF_WORKER "socket_buffer"
#define SOCKET_KEEPALIVE_OF_WORKER "socket_keepalive"
#define CONN_PING_INTERVAL_OF_WORKER "connection_ping_interval"
#define RECYCLE_TIMEOUT_DEPRECATED "recycle_timeout"
#define LOAD_FACTOR_OF_WORKER "lbfactor"
#define DISTANCE_OF_WORKER "distance"
#define BALANCED_WORKERS_DEPRECATED "balanced_workers"
#define BALANCE_WORKERS "balance_workers"
#define STICKY_SESSION "sticky_session"
#define STICKY_SESSION_FORCE "sticky_session_force"
#define SESSION_COOKIE_OF_WORKER "session_cookie"
#define SESSION_PATH_OF_WORKER "session_path"
#define SET_SESSION_COOKIE "set_session_cookie"
#define SESSION_COOKIE_PATH_OF_WORKER "session_cookie_path"
#define LOCAL_WORKER_DEPRECATED "local_worker"
#define LOCAL_WORKER_ONLY_DEPRECATED "local_worker_only"
#define JVM_ROUTE_OF_WORKER_DEPRECATED "jvm_route"
#define ROUTE_OF_WORKER "route"
#define DOMAIN_OF_WORKER "domain"
#define REDIRECT_OF_WORKER "redirect"
#define MOUNT_OF_WORKER "mount"
#define METHOD_OF_WORKER "method"
#define LOCK_OF_WORKER "lock"
#define IS_WORKER_DISABLED_DEPRECATED "disabled"
#define IS_WORKER_STOPPED_DEPRECATED "stopped"
#define ACTIVATION_OF_WORKER "activation"
#define WORKER_RECOVER_TIME "recover_time"
#define WORKER_ERROR_ESCALATION_TIME "error_escalation_time"
#define MAX_REPLY_TIMEOUTS_OF_WORKER "max_reply_timeouts"
#define RETRY_INTERVAL_OF_WORKER "retry_interval"
#define BUSY_LIMIT_OF_WORKER "busy_limit"
#define WORKER_MAX_PACKET_SIZE "max_packet_size"
#define STYLE_SHEET_OF_WORKER "css"
#define NAMESPACE_OF_WORKER "ns"
#define XML_NAMESPACE_OF_WORKER "xmlns"
#define XML_DOCTYPE_OF_WORKER "doctype"
#define PROP_PREFIX_OF_WORKER "prefix"
#define READ_ONLY_OF_WORKER "read_only"
#define USER_OF_WORKER "user"
#define USER_CASE_OF_WORKER "user_case_insensitive"
#define GOOD_RATING_OF_WORKER "good"
#define BAD_RATING_OF_WORKER "bad"
#define PREFER_IPV6_ADDRESS "prefer_ipv6"
#define DEFAULT_WORKER_TYPE JK_AJP13_WORKER_NAME
#define SECRET_KEY_OF_WORKER "secretkey"
#define RETRIES_OF_WORKER "retries"
#define LB_RETRIES_OF_WORKER "lb_retries"
#define STATUS_FAIL_OF_WORKER "fail_on_status"
#define DEFAULT_WORKER JK_AJP13_WORKER_NAME
#define WORKER_LIST_PROPERTY_NAME "worker.list"
#define LIST_PROPERTY_NAME "list"
#define WORKER_MAINTAIN_PROPERTY_NAME "worker.maintain"
#define MAINTAIN_PROPERTY_NAME "maintain"
#define DEFAULT_MAINTAIN_TIME 60
#define DEFAULT_LB_FACTOR 1
#define DEFAULT_DISTANCE 0
#define TOMCAT32_BRIDGE_NAME "tomcat32"
#define TOMCAT33_BRIDGE_NAME "tomcat33"
#define TOMCAT40_BRIDGE_NAME "tomcat40"
#define TOMCAT41_BRIDGE_NAME "tomcat41"
#define TOMCAT50_BRIDGE_NAME "tomcat5"
#define LOG_BUFFER_SIZE 1024
/*
* Our longest worker attribute name is below 30 bytes.
* Add space for "worker.", another ".", the
* worker name and the final '\0'.
*/
#define JK_MAX_ATTRIBUTE_NAME_LEN (30)
#define PARAM_BUFFER_SIZE (JK_MAX_NAME_LEN + 8 + JK_MAX_ATTRIBUTE_NAME_LEN + 1)
#define MAKE_WORKER_PARAM(P) \
{ \
size_t remain = PARAM_BUFFER_SIZE; \
strcpy(buf, "worker."); remain -= strlen("worker."); \
strncat(buf, wname, remain); remain -= strlen(wname); \
strncat(buf, ".", remain); remain -= 1; \
strncat(buf, P, remain); \
}
/*
* define the log format, we're using by default the one from error.log
*
* [Mon Mar 26 19:44:48.123 2001] [jk_uri_worker_map.c (155)]: Into jk_uri_worker_map_t::uri_worker_map_alloc
* log format used by apache in error.log
*/
#define JK_TIME_CONV_MILLI "%Q"
#define JK_TIME_CONV_MICRO "%q"
#define JK_TIME_PATTERN_MILLI "000"
#define JK_TIME_PATTERN_MICRO "000000"
#define JK_TIME_FORMAT_NONE "[%a %b %d %H:%M:%S %Y] "
#define JK_TIME_FORMAT_MILLI "[%a %b %d %H:%M:%S." JK_TIME_CONV_MILLI " %Y] "
#define JK_TIME_FORMAT_MICRO "[%a %b %d %H:%M:%S." JK_TIME_CONV_MICRO " %Y] "
#define JK_TIME_SUBSEC_NONE 0
#define JK_TIME_SUBSEC_MILLI 1
#define JK_TIME_SUBSEC_MICRO 2
/* Visual C++ Toolkit 2003 support */
#if defined (_MSC_VER) && (_MSC_VER == 1310)
extern long _ftol(double); /* defined by VC6 C libs */
extern long _ftol2(double dblSource) { return _ftol(dblSource); }
#endif
static const char *list_properties[] = {
BALANCE_WORKERS,
MOUNT_OF_WORKER,
USER_OF_WORKER,
GOOD_RATING_OF_WORKER,
BAD_RATING_OF_WORKER,
STATUS_FAIL_OF_WORKER,
LIST_PROPERTY_NAME,
NULL
};
static const char *unique_properties[] = {
SECRET_OF_WORKER,
REFERENCE_OF_WORKER,
HOST_OF_WORKER,
SOURCE_OF_WORKER,
PORT_OF_WORKER,
TYPE_OF_WORKER,
CACHE_OF_WORKER_DEPRECATED,
CACHE_OF_WORKER,
CACHE_OF_WORKER_MIN,
CACHE_TIMEOUT_DEPRECATED,
CACHE_TIMEOUT_OF_WORKER,
CACHE_ACQUIRE_OF_WORKER,
RECOVERY_OPTS_OF_WORKER,
CONNECT_TIMEOUT_OF_WORKER,
PREPOST_TIMEOUT_OF_WORKER,
PING_TIMEOUT_OF_WORKER,
PING_MODE_OF_WORKER,
REPLY_TIMEOUT_OF_WORKER,
SOCKET_TIMEOUT_OF_WORKER,
SOCKET_CONNECT_TIMEOUT_OF_WORKER,
SOCKET_BUFFER_OF_WORKER,
SOCKET_KEEPALIVE_OF_WORKER,
CONN_PING_INTERVAL_OF_WORKER,
RECYCLE_TIMEOUT_DEPRECATED,
LOAD_FACTOR_OF_WORKER,
STICKY_SESSION,
STICKY_SESSION_FORCE,
SESSION_COOKIE_OF_WORKER,
SESSION_PATH_OF_WORKER,
SET_SESSION_COOKIE,
SESSION_COOKIE_PATH_OF_WORKER,
LOCAL_WORKER_DEPRECATED,
LOCAL_WORKER_ONLY_DEPRECATED,
JVM_ROUTE_OF_WORKER_DEPRECATED,
ROUTE_OF_WORKER,
DOMAIN_OF_WORKER,
REDIRECT_OF_WORKER,
METHOD_OF_WORKER,
LOCK_OF_WORKER,
IS_WORKER_DISABLED_DEPRECATED,
IS_WORKER_STOPPED_DEPRECATED,
ACTIVATION_OF_WORKER,
WORKER_RECOVER_TIME,
WORKER_ERROR_ESCALATION_TIME,
MAX_REPLY_TIMEOUTS_OF_WORKER,
RETRY_INTERVAL_OF_WORKER,
BUSY_LIMIT_OF_WORKER,
WORKER_MAX_PACKET_SIZE,
STYLE_SHEET_OF_WORKER,
READ_ONLY_OF_WORKER,
RETRIES_OF_WORKER,
LB_RETRIES_OF_WORKER,
WORKER_MAINTAIN_PROPERTY_NAME,
NAMESPACE_OF_WORKER,
XML_NAMESPACE_OF_WORKER,
XML_DOCTYPE_OF_WORKER,
PROP_PREFIX_OF_WORKER,
USER_CASE_OF_WORKER,
PREFER_IPV6_ADDRESS,
NULL
};
static const char *deprecated_properties[] = {
SYSPROPS_OF_WORKER,
STDERR_OF_WORKER,
STDOUT_OF_WORKER,
MX_OF_WORKER,
MS_OF_WORKER,
CP_OF_WORKER,
BRIDGE_OF_WORKER,
JVM_OF_WORKER,
LIBPATH_OF_WORKER,
CMD_LINE_OF_WORKER,
NATIVE_LIB_OF_WORKER,
CACHE_OF_WORKER_DEPRECATED,
CACHE_TIMEOUT_DEPRECATED,
RECYCLE_TIMEOUT_DEPRECATED,
BALANCED_WORKERS_DEPRECATED,
JVM_ROUTE_OF_WORKER_DEPRECATED,
LOCAL_WORKER_DEPRECATED,
LOCAL_WORKER_ONLY_DEPRECATED,
IS_WORKER_DISABLED_DEPRECATED,
IS_WORKER_STOPPED_DEPRECATED,
NULL
};
static const char *supported_properties[] = {
SYSPROPS_OF_WORKER,
STDERR_OF_WORKER,
STDOUT_OF_WORKER,
SECRET_OF_WORKER,
MX_OF_WORKER,
MS_OF_WORKER,
CP_OF_WORKER,
BRIDGE_OF_WORKER,
JVM_OF_WORKER,
LIBPATH_OF_WORKER,
CMD_LINE_OF_WORKER,
NATIVE_LIB_OF_WORKER,
REFERENCE_OF_WORKER,
HOST_OF_WORKER,
SOURCE_OF_WORKER,
PORT_OF_WORKER,
TYPE_OF_WORKER,
CACHE_OF_WORKER_DEPRECATED,
CACHE_OF_WORKER,
CACHE_OF_WORKER_MIN,
CACHE_TIMEOUT_DEPRECATED,
CACHE_TIMEOUT_OF_WORKER,
CACHE_ACQUIRE_OF_WORKER,
RECOVERY_OPTS_OF_WORKER,
CONNECT_TIMEOUT_OF_WORKER,
PREPOST_TIMEOUT_OF_WORKER,
PING_TIMEOUT_OF_WORKER,
PING_MODE_OF_WORKER,
REPLY_TIMEOUT_OF_WORKER,
SOCKET_TIMEOUT_OF_WORKER,
SOCKET_CONNECT_TIMEOUT_OF_WORKER,
SOCKET_BUFFER_OF_WORKER,
SOCKET_KEEPALIVE_OF_WORKER,
CONN_PING_INTERVAL_OF_WORKER,
RECYCLE_TIMEOUT_DEPRECATED,
LOAD_FACTOR_OF_WORKER,
DISTANCE_OF_WORKER,
BALANCED_WORKERS_DEPRECATED,
BALANCE_WORKERS,
STICKY_SESSION,
STICKY_SESSION_FORCE,
SESSION_COOKIE_OF_WORKER,
SESSION_PATH_OF_WORKER,
SET_SESSION_COOKIE,
SESSION_COOKIE_PATH_OF_WORKER,
LOCAL_WORKER_DEPRECATED,
LOCAL_WORKER_ONLY_DEPRECATED,
JVM_ROUTE_OF_WORKER_DEPRECATED,
ROUTE_OF_WORKER,
DOMAIN_OF_WORKER,
REDIRECT_OF_WORKER,
MOUNT_OF_WORKER,
METHOD_OF_WORKER,
LOCK_OF_WORKER,
IS_WORKER_DISABLED_DEPRECATED,
IS_WORKER_STOPPED_DEPRECATED,
ACTIVATION_OF_WORKER,
WORKER_RECOVER_TIME,
WORKER_ERROR_ESCALATION_TIME,
MAX_REPLY_TIMEOUTS_OF_WORKER,
RETRY_INTERVAL_OF_WORKER,
BUSY_LIMIT_OF_WORKER,
WORKER_MAX_PACKET_SIZE,
STYLE_SHEET_OF_WORKER,
NAMESPACE_OF_WORKER,
XML_NAMESPACE_OF_WORKER,
XML_DOCTYPE_OF_WORKER,
PROP_PREFIX_OF_WORKER,
READ_ONLY_OF_WORKER,
USER_OF_WORKER,
USER_CASE_OF_WORKER,
GOOD_RATING_OF_WORKER,
BAD_RATING_OF_WORKER,
SECRET_KEY_OF_WORKER,
RETRIES_OF_WORKER,
LB_RETRIES_OF_WORKER,
STATUS_FAIL_OF_WORKER,
LIST_PROPERTY_NAME,
MAINTAIN_PROPERTY_NAME,
PREFER_IPV6_ADDRESS,
NULL
};
static const char *jk_level_verbs[] = {
"[" JK_LOG_TRACE_VERB "] ",
"[" JK_LOG_DEBUG_VERB "] ",
"[" JK_LOG_INFO_VERB "] ",
"[" JK_LOG_WARN_VERB "] ",
"[" JK_LOG_ERROR_VERB "] ",
"[" JK_LOG_EMERG_VERB "] ",
NULL
};
const char *jk_get_bool(int v)
{
if (v == 0)
return "False";
else
return "True";
}
int jk_get_bool_code(const char *v, int def)
{
if (!v) {
return def;
}
if (!strcasecmp(v, "off") ||
*v == 'F' || *v == 'f' ||
*v == 'N' || *v == 'n' ||
(*v == '0' && *(v + 1) == '\0')) {
return JK_FALSE;
}
if (!strcasecmp(v, "on") ||
*v == 'T' || *v == 't' ||
*v == 'Y' || *v == 'y' ||
(*v == '1' && *(v + 1) == '\0')) {
return JK_TRUE;
}
return def;
}
/* Sleep for 100ms */
void jk_sleep(int ms)
{
#ifdef OS2
DosSleep(ms);
#elif defined(BEOS)
snooze(ms * 1000);
#elif defined(WIN32)
Sleep(ms);
#else
struct timeval tv;
tv.tv_usec = (ms % 1000) * 1000;
tv.tv_sec = ms / 1000;
select(0, NULL, NULL, NULL, &tv);
#endif
}
/* Replace the first occurence of a sub second time format character
* by a series of zero digits with the right precision.
* We format our timestamp with strftime, but this can not handle
* sub second timestamps.
* So we first patch the milliseconds or microseconds literally into
* the format string, and then pass it on the strftime.
* In order to do that efficiently, we prepare a format string, that
* already has placeholder digits for the sub second time stamp
* and we save the position and time precision of this placeholder.
*/
void jk_set_time_fmt(jk_logger_t *l, const char *jk_log_fmt)
{
if (l) {
char *s;
if (!jk_log_fmt) {
#ifndef NO_GETTIMEOFDAY
jk_log_fmt = JK_TIME_FORMAT_MILLI;
#else
jk_log_fmt = JK_TIME_FORMAT_NONE;
#endif
}
l->log_fmt_type = JK_TIME_SUBSEC_NONE;
l->log_fmt_offset = 0;
l->log_fmt_size = 0;
l->log_fmt = jk_log_fmt;
/* Look for the first occurence of JK_TIME_CONV_MILLI */
if ((s = strstr(jk_log_fmt, JK_TIME_CONV_MILLI))) {
size_t offset = s - jk_log_fmt;
size_t len = strlen(JK_TIME_PATTERN_MILLI);
/* If we don't have enough space in our fixed-length char array,
* we simply stick to the default format, ignoring JK_TIME_CONV_MILLI.
* Otherwise we replace the first occurence of
* JK_TIME_CONV_MILLI by JK_TIME_PATTERN_MILLI.
*/
if (offset + len < JK_TIME_MAX_SIZE) {
l->log_fmt_type = JK_TIME_SUBSEC_MILLI;
l->log_fmt_offset = offset;
memcpy(l->log_fmt_subsec, jk_log_fmt, offset);
memcpy(l->log_fmt_subsec + offset, JK_TIME_PATTERN_MILLI, len);
memcpy(l->log_fmt_subsec + offset + len,
s + strlen(JK_TIME_CONV_MILLI),
JK_TIME_MAX_SIZE - offset - len - 1);
/* Now we put a stop mark into the string to make it's length
* at most JK_TIME_MAX_SIZE-1 plus terminating '\0'.
*/
l->log_fmt_subsec[JK_TIME_MAX_SIZE - 1] = '\0';
l->log_fmt_size = strlen(l->log_fmt_subsec);
}
}
/* Look for the first occurence of JK_TIME_CONV_MICRO */
else if ((s = strstr(jk_log_fmt, JK_TIME_CONV_MICRO))) {
size_t offset = s - jk_log_fmt;
size_t len = strlen(JK_TIME_PATTERN_MICRO);
/* If we don't have enough space in our fixed-length char array,
* we simply stick to the default format, ignoring JK_TIME_CONV_MICRO.
* Otherwise we replace the first occurence of JK_TIME_CONV_MICRO
* by JK_TIME_PATTERN_MICRO.
*/
if (offset + len < JK_TIME_MAX_SIZE) {
l->log_fmt_type = JK_TIME_SUBSEC_MICRO;
l->log_fmt_offset = offset;
memcpy(l->log_fmt_subsec, jk_log_fmt, offset);
memcpy(l->log_fmt_subsec + offset, JK_TIME_PATTERN_MICRO, len);
memcpy(l->log_fmt_subsec + offset + len,
s + strlen(JK_TIME_CONV_MICRO),
JK_TIME_MAX_SIZE - offset - len - 1);
/* Now we put a stop mark into the string to make it's length
* at most JK_TIME_MAX_SIZE-1 plus terminating '\0'.
*/
l->log_fmt_subsec[JK_TIME_MAX_SIZE - 1] = '\0';
l->log_fmt_size = strlen(l->log_fmt_subsec);
}
}
}
}
static int set_time_str(char *str, int len, jk_logger_t *l)
{
time_t t;
struct tm *tms;
#ifdef _MT_CODE_PTHREAD
struct tm res;
#endif
int done;
/* We want to use a fixed maximum size buffer here.
* If we would dynamically adjust it to the real format
* string length, we could support longer format strings,
* but we would have to allocate and free for each log line.
*/
char log_fmt[JK_TIME_MAX_SIZE];
if (!l || !l->log_fmt) {
return 0;
}
log_fmt[0] = '\0';
#ifndef NO_GETTIMEOFDAY
if (l->log_fmt_type != JK_TIME_SUBSEC_NONE) {
struct timeval tv;
int rc = 0;
#ifdef WIN32
gettimeofday(&tv, NULL);
#else
rc = gettimeofday(&tv, NULL);
#endif
if (rc == 0) {
/* We need this subsec buffer, because we convert
* the integer with sprintf(), but we don't
* want to write the terminating '\0' into our
* final log format string.
*/
char subsec[7];
t = tv.tv_sec;
strncpy(log_fmt, l->log_fmt_subsec, l->log_fmt_size + 1);
if (l->log_fmt_type == JK_TIME_SUBSEC_MILLI) {
sprintf(subsec, "%03d", (int)(tv.tv_usec/1000));
strncpy(log_fmt + l->log_fmt_offset, subsec, 3);
}
else if (l->log_fmt_type == JK_TIME_SUBSEC_MICRO) {
sprintf(subsec, "%06d", (int)(tv.tv_usec));
strncpy(log_fmt + l->log_fmt_offset, subsec, 6);
}
}
else {
t = time(NULL);
}
}
else {
t = time(NULL);
}
#else
t = time(NULL);
#endif
#ifdef _MT_CODE_PTHREAD
tms = localtime_r(&t, &res);
#else
tms = localtime(&t);
#endif
if (log_fmt[0])
done = (int)strftime(str, len, log_fmt, tms);
else
done = (int)strftime(str, len, l->log_fmt, tms);
return done;
}
static int JK_METHOD log_to_file(jk_logger_t *l, int level, int used, char *what)
{
if (l &&
(l->level <= level || level == JK_LOG_REQUEST_LEVEL) &&
l->logger_private && what) {
jk_file_logger_t *p = l->logger_private;
if (p->logfile) {
what[used++] = '\n';
what[used] = '\0';
#if defined(JK_LOG_LOCKING)
#if defined(WIN32) && defined(_MSC_VER)
LockFile((HANDLE)_get_osfhandle(_fileno(p->logfile)),
0, 0, 1, 0);
#endif
#endif
fputs(what, p->logfile);
/* [V] Flush the dam' thing! */
fflush(p->logfile);
#if defined(JK_LOG_LOCKING)
#if defined(WIN32) && defined(_MSC_VER)
UnlockFile((HANDLE)_get_osfhandle(_fileno(p->logfile)),
0, 0, 1, 0);
#endif
#endif
}
return JK_TRUE;
}
return JK_FALSE;
}
int jk_parse_log_level(const char *level)
{
if (!strcasecmp(level, JK_LOG_TRACE_VERB))
return JK_LOG_TRACE_LEVEL;
if (!strcasecmp(level, JK_LOG_DEBUG_VERB))
return JK_LOG_DEBUG_LEVEL;
if (!strcasecmp(level, JK_LOG_INFO_VERB))
return JK_LOG_INFO_LEVEL;
if (!strcasecmp(level, JK_LOG_WARN_VERB))
return JK_LOG_WARNING_LEVEL;
if (!strcasecmp(level, JK_LOG_ERROR_VERB))
return JK_LOG_ERROR_LEVEL;
if (!strcasecmp(level, JK_LOG_EMERG_VERB))
return JK_LOG_EMERG_LEVEL;
return JK_LOG_DEF_LEVEL;
}
int jk_open_file_logger(jk_logger_t **l, const char *file, int level)
{
if (l && file) {
jk_logger_t *rc = (jk_logger_t *)malloc(sizeof(jk_logger_t));
jk_file_logger_t *p = (jk_file_logger_t *) malloc(sizeof(jk_file_logger_t));
if (rc && p) {
rc->log = log_to_file;
rc->level = level;
rc->logger_private = p;
#if defined(AS400) && !defined(AS400_UTF8)
p->logfile = fopen(file, "a+, o_ccsid=0");
#elif defined(WIN32) && defined(_MSC_VER)
p->logfile = fopen(file, "a+c");
#else
p->logfile = fopen(file, "a+");
#endif
if (p->logfile) {
*l = rc;
jk_set_time_fmt(rc, NULL);
return JK_TRUE;
}
}
if (rc) {
free(rc);
}
if (p) {
free(p);
}
*l = NULL;
}
return JK_FALSE;
}
int jk_attach_file_logger(jk_logger_t **l, int fd, int level)
{
if (l && fd >= 0) {
jk_logger_t *rc = (jk_logger_t *)malloc(sizeof(jk_logger_t));
jk_file_logger_t *p = (jk_file_logger_t *) malloc(sizeof(jk_file_logger_t));
if (rc && p) {
rc->log = log_to_file;
rc->level = level;
rc->logger_private = p;
#if defined(AS400) && !defined(AS400_UTF8)
p->logfile = fdopen(fd, "a+, o_ccsid=0");
#elif defined(WIN32) && defined(_MSC_VER)
p->logfile = fdopen(fd, "a+c");
#else
p->logfile = fdopen(fd, "a+");
#endif
if (p->logfile) {
*l = rc;
jk_set_time_fmt(rc, NULL);
return JK_TRUE;
}
}
if (rc) {
free(rc);
}
if (p) {
free(p);
}
*l = NULL;
}
return JK_FALSE;
}
int jk_close_file_logger(jk_logger_t **l)
{
if (l && *l) {
jk_file_logger_t *p = (*l)->logger_private;
if (p) {
fflush(p->logfile);
fclose(p->logfile);
free(p);
}
free(*l);
*l = NULL;
return JK_TRUE;
}
return JK_FALSE;
}
int jk_log(jk_log_context_t *log_ctx,
const char *file, int line, const char *funcname, int level,
const char *fmt, ...)
{
int rc = 0;
jk_logger_t *l;
/*
* Need to reserve space for terminating zero byte
* and platform specific line endings added during the call
* to the output routing.
*/
static int usable_size = LOG_BUFFER_SIZE - 3;
if (!log_ctx || !(l = log_ctx->logger) || !file || !fmt) {
return -1;
}
if ((l->level <= level) || (level == JK_LOG_REQUEST_LEVEL)) {
char buf[LOG_BUFFER_SIZE];
char *f = (char *)(file + strlen(file) - 1);
va_list args;
int used = 0;
while (f != file && '\\' != *f && '/' != *f) {
f--;
}
if (f != file) {
f++;
}
used = set_time_str(buf, usable_size, l);
if (line) { /* line==0 only used for request log item */
/* Log [requestid] for all levels except REQUEST.
*/
const char *context_id;
if (log_ctx == NULL) {
context_id = "-";
rc = 1;
} else if (log_ctx->id == NULL) {
context_id = "NO-ID";
rc = 5;
}
else {
context_id = log_ctx->id;
rc = (int)strlen(context_id);
}
if (usable_size - used >= rc + 3) {
strncpy(buf + used, "[", 1);
used += 1;
strncpy(buf + used, context_id, rc);
used += rc;
strncpy(buf + used, "] ", 2);
used += 2;
}
else {
strcpy(buf, "Logging failed in context_id formatting");
l->log(l, level, (int)strlen(buf), buf);
return 0;
}
/* Log [pid:threadid] for all levels except REQUEST.
* This information helps to correlate lines from different logs.
* Performance is no issue, because with production log levels
* we only call it often, if we have a lot of errors
*/
rc = snprintf(buf + used, usable_size - used,
"[%" JK_PID_T_FMT ":%" JK_PTHREAD_T_FMT "] ", getpid(), jk_gettid());
used += rc;
if (rc < 0) {
strcpy(buf, "Logging failed in pid/tid formatting");
l->log(l, level, (int)strlen(buf), buf);
return 0;
}
rc = (int)strlen(jk_level_verbs[level]);
if (usable_size - used >= rc) {
strncpy(buf + used, jk_level_verbs[level], rc);
used += rc;
}
else {
strcpy(buf, "Logging failed in log level formatting");
l->log(l, level, (int)strlen(buf), buf);
return 0; /* [V] not sure what to return... */
}
if (funcname) {
rc = (int)strlen(funcname);
if (usable_size - used >= rc + 2) {
strncpy(buf + used, funcname, rc);
used += rc;
strncpy(buf + used, "::", 2);
used += 2;
}
else {
strcpy(buf, "Logging failed in function name formatting");
l->log(l, level, (int)strlen(buf), buf);
return 0; /* [V] not sure what to return... */
}
}
rc = (int)strlen(f);
if (usable_size - used >= rc) {
strncpy(buf + used, f, rc);
used += rc;
}
else {
strcpy(buf, "Logging failed in source file name formatting");
l->log(l, level, (int)strlen(buf), buf);
return 0; /* [V] not sure what to return... */
}
rc = snprintf(buf + used, usable_size - used,
" (%d): ", line);
used += rc;
if (rc < 0 || usable_size - used < 0) {
strcpy(buf, "Logging failed in line number formatting");
l->log(l, level, (int)strlen(buf), buf);
return 0; /* [V] not sure what to return... */
}
}
va_start(args, fmt);
rc = vsnprintf(buf + used, usable_size - used, fmt, args);
va_end(args);
/* Depending on the snprintf implementation used,
* "rc == usable_size - used" can indicate not enough space in buffer */
if (rc < usable_size - used) {
used += rc;
}
else {
used = usable_size;
buf[used - 1] = '.';
buf[used - 2] = '.';
buf[used - 3] = '.';
}
l->log(l, level, used, buf);
}
return rc;
}
const char *jk_get_worker_type(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(TYPE_OF_WORKER);
return jk_map_get_string(m, buf, DEFAULT_WORKER_TYPE);
}
const char *jk_get_worker_route(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
const char *v;
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(ROUTE_OF_WORKER);
v = jk_map_get_string(m, buf, def);
if (v) {
return v;
}
/* Try old jvm_route directive */
MAKE_WORKER_PARAM(JVM_ROUTE_OF_WORKER_DEPRECATED);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_domain(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(DOMAIN_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_redirect(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(REDIRECT_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_secret(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(SECRET_OF_WORKER);
return jk_map_get_string(m, buf, NULL);
}
const char *jk_get_worker_host(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(HOST_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_source(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(SOURCE_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
int jk_get_worker_port(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(PORT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_prefer_ipv6(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(PREFER_IPV6_ADDRESS);
return jk_map_get_bool(m, buf, def);
}
static int def_cache_size = -1;
int jk_get_worker_def_cache_size(int protocol)
{
if (def_cache_size < 1) {
if (protocol == AJP14_PROTO)
def_cache_size = AJP14_DEF_CACHE_SZ;
else
def_cache_size = AJP13_DEF_CACHE_SZ;
}
return def_cache_size;
}
void jk_set_worker_def_cache_size(int sz)
{
def_cache_size = sz;
}
int jk_get_worker_cache_size(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
int rv;
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(CACHE_OF_WORKER);
if ((rv = jk_map_get_int(m, buf, -1)) >= 0)
return rv;
MAKE_WORKER_PARAM(CACHE_OF_WORKER_DEPRECATED);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_cache_size_min(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(CACHE_OF_WORKER_MIN);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_cache_acquire_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(CACHE_ACQUIRE_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_socket_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(SOCKET_TIMEOUT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_socket_connect_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(SOCKET_CONNECT_TIMEOUT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_recover_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(WORKER_RECOVER_TIME);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_error_escalation_time(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(WORKER_ERROR_ESCALATION_TIME);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_max_reply_timeouts(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(MAX_REPLY_TIMEOUTS_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_retry_interval(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(RETRY_INTERVAL_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_busy_limit(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(BUSY_LIMIT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_socket_buffer(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
int i;
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(SOCKET_BUFFER_OF_WORKER);
i = jk_map_get_int(m, buf, 0);
if (i > 0 && i < def)
i = def;
return i;
}
int jk_get_worker_socket_keepalive(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(SOCKET_KEEPALIVE_OF_WORKER);
return jk_map_get_bool(m, buf, def);
}
int jk_get_worker_conn_ping_interval(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(CONN_PING_INTERVAL_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_cache_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
int rv;
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(CACHE_TIMEOUT_OF_WORKER);
if ((rv = jk_map_get_int(m, buf, -1)) >= 0)
return rv;
MAKE_WORKER_PARAM(CACHE_TIMEOUT_DEPRECATED);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_connect_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(CONNECT_TIMEOUT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_prepost_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(PREPOST_TIMEOUT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_ping_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(PING_TIMEOUT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_ping_mode(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
char mode[100];
const char *v;
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(PING_MODE_OF_WORKER);
jk_ajp_get_cping_text(def, mode);
v = jk_map_get_string(m, buf, mode);
return jk_ajp_get_cping_mode(v, def);
}
int jk_get_worker_reply_timeout(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(REPLY_TIMEOUT_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
int jk_get_worker_recycle_timeout(jk_map_t *m, const char *wname, int def)
{
return def;
}
int jk_get_worker_retries(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
int rv;
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(RETRIES_OF_WORKER);
rv = jk_map_get_int(m, buf, def);
if (rv < 1)
rv = 1;
return rv;
}
int jk_get_worker_lb_retries(jk_map_t *m, const char *wname, int def)
{
char buf[1024];
int rv;
if (!m || !wname) {
return -1;
}
MAKE_WORKER_PARAM(LB_RETRIES_OF_WORKER);
rv = jk_map_get_int(m, buf, def);
if (rv < 1)
rv = 1;
return rv;
}
int jk_get_worker_recovery_opts(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(RECOVERY_OPTS_OF_WORKER);
return jk_map_get_int(m, buf, def);
}
const char *jk_get_worker_secret_key(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(SECRET_KEY_OF_WORKER);
return jk_map_get_string(m, buf, NULL);
}
int jk_get_worker_list(jk_map_t *m, char ***list, unsigned *num_of_workers)
{
if (m && list && num_of_workers) {
char **ar = jk_map_get_string_list(m,
WORKER_LIST_PROPERTY_NAME,
num_of_workers,
DEFAULT_WORKER);
if (ar) {
*list = ar;
return JK_TRUE;
}
*list = NULL;
*num_of_workers = 0;
}
return JK_FALSE;
}
int jk_get_is_worker_disabled(jk_map_t *m, const char *wname)
{
int def = JK_FALSE;
char buf[PARAM_BUFFER_SIZE];
if (m && wname) {
MAKE_WORKER_PARAM(IS_WORKER_DISABLED_DEPRECATED);
return jk_map_get_bool(m, buf, def);
}
return JK_TRUE;
}
int jk_get_is_worker_stopped(jk_map_t *m, const char *wname)
{
int def = JK_FALSE;
char buf[PARAM_BUFFER_SIZE];
if (m && wname) {
MAKE_WORKER_PARAM(IS_WORKER_STOPPED_DEPRECATED);
return jk_map_get_bool(m, buf, def);
}
return JK_TRUE;
}
int jk_get_worker_activation(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
const char *v;
if (!m || !wname) {
return JK_LB_ACTIVATION_ACTIVE;
}
MAKE_WORKER_PARAM(ACTIVATION_OF_WORKER);
v = jk_map_get_string(m, buf, NULL);
if (v)
return jk_lb_get_activation_code(v);
if (jk_get_is_worker_stopped(m, wname))
return JK_LB_ACTIVATION_STOPPED;
if (jk_get_is_worker_disabled(m, wname))
return JK_LB_ACTIVATION_DISABLED;
return JK_LB_ACTIVATION_DEF;
}
int jk_get_lb_factor(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return DEFAULT_LB_FACTOR;
}
MAKE_WORKER_PARAM(LOAD_FACTOR_OF_WORKER);
return jk_map_get_int(m, buf, DEFAULT_LB_FACTOR);
}
int jk_get_distance(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return DEFAULT_DISTANCE;
}
MAKE_WORKER_PARAM(DISTANCE_OF_WORKER);
return jk_map_get_int(m, buf, DEFAULT_DISTANCE);
}
int jk_get_is_sticky_session(jk_map_t *m, const char *wname)
{
int def = JK_TRUE;
char buf[PARAM_BUFFER_SIZE];
if (m && wname) {
MAKE_WORKER_PARAM(STICKY_SESSION);
return jk_map_get_bool(m, buf, def);
}
return def;
}
int jk_get_is_sticky_session_force(jk_map_t *m, const char *wname)
{
int def = JK_FALSE;
char buf[PARAM_BUFFER_SIZE];
if (m && wname) {
MAKE_WORKER_PARAM(STICKY_SESSION_FORCE);
return jk_map_get_bool(m, buf, def);
}
return def;
}
int jk_get_lb_method(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
const char *v;
if (!m || !wname) {
return JK_LB_METHOD_DEF;
}
MAKE_WORKER_PARAM(METHOD_OF_WORKER);
v = jk_map_get_string(m, buf, JK_LB_METHOD_DEF);
return jk_lb_get_method_code(v);
}
int jk_get_lb_lock(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
const char *v;
if (!m || !wname) {
return JK_LB_LOCK_DEF;
}
MAKE_WORKER_PARAM(LOCK_OF_WORKER);
v = jk_map_get_string(m, buf, JK_LB_LOCK_DEF);
return jk_lb_get_lock_code(v);
}
int jk_get_max_packet_size(jk_map_t *m, const char *wname)
{
char buf[PARAM_BUFFER_SIZE];
int sz;
if (!m || !wname) {
return AJP13_DEF_PACKET_SIZE;
}
MAKE_WORKER_PARAM(WORKER_MAX_PACKET_SIZE);
sz = jk_map_get_int(m, buf, AJP13_DEF_PACKET_SIZE);
sz = JK_ALIGN(sz, AJP13_PACKET_SIZE_ALIGN);
if (sz < AJP13_DEF_PACKET_SIZE)
sz = AJP13_DEF_PACKET_SIZE;
else if (sz > AJP13_MAX_PACKET_SIZE)
sz = AJP13_MAX_PACKET_SIZE;
return sz;
}
int jk_get_worker_fail_on_status(jk_map_t *m, const char *wname,
int **list, unsigned int *list_size)
{
char buf[PARAM_BUFFER_SIZE];
int *ar;
if (!m || !wname || !list || !list_size) {
return 0;
}
MAKE_WORKER_PARAM(STATUS_FAIL_OF_WORKER);
ar = jk_map_get_int_list(m,
buf,
list_size,
NULL);
if (ar) {
*list = ar;
return JK_TRUE;
}
*list = NULL;
*list_size = 0;
return JK_FALSE;
}
int jk_get_worker_user_case_insensitive(jk_map_t *m, const char *wname)
{
int def = JK_FALSE;
char buf[PARAM_BUFFER_SIZE];
if (m && wname) {
MAKE_WORKER_PARAM(USER_CASE_OF_WORKER);
return jk_map_get_bool(m, buf, def);
}
return def;
}
const char *jk_get_worker_style_sheet(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(STYLE_SHEET_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_name_space(jk_map_t *m, const char *wname, const char *def)
{
const char *rc;
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(NAMESPACE_OF_WORKER);
rc = jk_map_get_string(m, buf, def);
if (*rc == '-')
return "";
else
return rc;
}
const char *jk_get_worker_xmlns(jk_map_t *m, const char *wname, const char *def)
{
const char *rc;
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(XML_NAMESPACE_OF_WORKER);
rc = jk_map_get_string(m, buf, def);
if (*rc == '-')
return "";
else
return rc;
}
const char *jk_get_worker_xml_doctype(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(XML_DOCTYPE_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_prop_prefix(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return def;
}
MAKE_WORKER_PARAM(PROP_PREFIX_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
int jk_get_is_read_only(jk_map_t *m, const char *wname)
{
int def = JK_FALSE;
char buf[PARAM_BUFFER_SIZE];
if (m && wname) {
MAKE_WORKER_PARAM(READ_ONLY_OF_WORKER);
return jk_map_get_bool(m, buf, def);
}
return def;
}
int jk_get_worker_user_list(jk_map_t *m,
const char *wname,
char ***list, unsigned int *num)
{
char buf[PARAM_BUFFER_SIZE];
if (m && list && num && wname) {
char **ar = NULL;
MAKE_WORKER_PARAM(USER_OF_WORKER);
ar = jk_map_get_string_list(m, buf, num, NULL);
if (ar) {
*list = ar;
return JK_TRUE;
}
*list = NULL;
*num = 0;
}
return JK_FALSE;
}
int jk_get_worker_good_rating(jk_map_t *m,
const char *wname,
char ***list, unsigned int *num)
{
char buf[PARAM_BUFFER_SIZE];
if (m && list && num && wname) {
char **ar = NULL;
MAKE_WORKER_PARAM(GOOD_RATING_OF_WORKER);
ar = jk_map_get_string_list(m, buf, num, NULL);
if (ar) {
*list = ar;
return JK_TRUE;
}
*list = NULL;
*num = 0;
}
return JK_FALSE;
}
int jk_get_worker_bad_rating(jk_map_t *m,
const char *wname,
char ***list, unsigned int *num)
{
char buf[PARAM_BUFFER_SIZE];
if (m && list && num && wname) {
char **ar = NULL;
MAKE_WORKER_PARAM(BAD_RATING_OF_WORKER);
ar = jk_map_get_string_list(m, buf, num, NULL);
if (ar) {
*list = ar;
return JK_TRUE;
}
*list = NULL;
*num = 0;
}
return JK_FALSE;
}
int jk_get_lb_worker_list(jk_map_t *m,
const char *wname,
char ***list, unsigned int *num_of_workers)
{
char buf[PARAM_BUFFER_SIZE];
if (m && list && num_of_workers && wname) {
char **ar = NULL;
MAKE_WORKER_PARAM(BALANCE_WORKERS);
ar = jk_map_get_string_list(m, buf, num_of_workers, NULL);
if (ar) {
*list = ar;
return JK_TRUE;
}
/* Try old balanced_workers directive */
MAKE_WORKER_PARAM(BALANCED_WORKERS_DEPRECATED);
ar = jk_map_get_string_list(m, buf, num_of_workers, NULL);
if (ar) {
*list = ar;
return JK_TRUE;
}
*list = NULL;
*num_of_workers = 0;
}
return JK_FALSE;
}
int jk_get_worker_mount_list(jk_map_t *m,
const char *wname,
char ***list, unsigned int *num_of_maps)
{
char buf[PARAM_BUFFER_SIZE];
if (m && list && num_of_maps && wname) {
char **ar = NULL;
MAKE_WORKER_PARAM(MOUNT_OF_WORKER);
ar = jk_map_get_string_list(m, buf, num_of_maps, NULL);
if (ar) {
*list = ar;
return JK_TRUE;
}
*list = NULL;
*num_of_maps = 0;
}
return JK_FALSE;
}
int jk_get_worker_maintain_time(jk_map_t *m)
{
return jk_map_get_int(m, WORKER_MAINTAIN_PROPERTY_NAME,
DEFAULT_MAINTAIN_TIME);
}
int jk_get_worker_mx(jk_map_t *m, const char *wname, unsigned *mx)
{
char buf[PARAM_BUFFER_SIZE];
if (m && mx && wname) {
int i;
MAKE_WORKER_PARAM(MX_OF_WORKER);
i = jk_map_get_int(m, buf, -1);
if (-1 != i) {
*mx = (unsigned)i;
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_ms(jk_map_t *m, const char *wname, unsigned *ms)
{
char buf[PARAM_BUFFER_SIZE];
if (m && ms && wname) {
int i;
MAKE_WORKER_PARAM(MS_OF_WORKER);
i = jk_map_get_int(m, buf, -1);
if (-1 != i) {
*ms = (unsigned)i;
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_classpath(jk_map_t *m, const char *wname, const char **cp)
{
char buf[PARAM_BUFFER_SIZE];
if (m && cp && wname) {
MAKE_WORKER_PARAM(CP_OF_WORKER);
*cp = jk_map_get_string(m, buf, NULL);
if (*cp) {
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_bridge_type(jk_map_t *m, const char *wname, unsigned *bt)
{
char buf[PARAM_BUFFER_SIZE];
const char *type;
if (m && bt && wname) {
MAKE_WORKER_PARAM(BRIDGE_OF_WORKER);
type = jk_map_get_string(m, buf, NULL);
if (type) {
if (!strcasecmp(type, TOMCAT32_BRIDGE_NAME))
*bt = TC32_BRIDGE_TYPE;
else if (!strcasecmp(type, TOMCAT33_BRIDGE_NAME))
*bt = TC33_BRIDGE_TYPE;
else if (!strcasecmp(type, TOMCAT40_BRIDGE_NAME))
*bt = TC40_BRIDGE_TYPE;
else if (!strcasecmp(type, TOMCAT41_BRIDGE_NAME))
*bt = TC41_BRIDGE_TYPE;
else if (!strcasecmp(type, TOMCAT50_BRIDGE_NAME))
*bt = TC50_BRIDGE_TYPE;
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_jvm_path(jk_map_t *m, const char *wname, const char **vm_path)
{
char buf[PARAM_BUFFER_SIZE];
if (m && vm_path && wname) {
MAKE_WORKER_PARAM(JVM_OF_WORKER);
*vm_path = jk_map_get_string(m, buf, NULL);
if (*vm_path) {
return JK_TRUE;
}
}
return JK_FALSE;
}
/* [V] This is unused. currently. */
int jk_get_worker_callback_dll(jk_map_t *m, const char *wname, const char **cb_path)
{
char buf[PARAM_BUFFER_SIZE];
if (m && cb_path && wname) {
MAKE_WORKER_PARAM(NATIVE_LIB_OF_WORKER);
*cb_path = jk_map_get_string(m, buf, NULL);
if (*cb_path) {
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_cmd_line(jk_map_t *m, const char *wname, const char **cmd_line)
{
char buf[PARAM_BUFFER_SIZE];
if (m && cmd_line && wname) {
MAKE_WORKER_PARAM(CMD_LINE_OF_WORKER);
*cmd_line = jk_map_get_string(m, buf, NULL);
if (*cmd_line) {
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_stat(const char *f, struct stat * statbuf)
{
int rc;
/**
* i5/OS V5R4 expect filename in ASCII for fopen but required them in EBCDIC for stat()
*/
#ifdef AS400_UTF8
char *ptr;
ptr = (char *)malloc(strlen(f) + 1);
jk_ascii2ebcdic((char *)f, ptr);
rc = stat(ptr, statbuf);
free(ptr);
#else
rc = stat(f, statbuf);
#endif
return (rc);
}
int jk_file_exists(const char *f)
{
if (f) {
struct stat st;
if ((0 == jk_stat(f, &st)) && (st.st_mode & S_IFREG))
return JK_TRUE;
}
return JK_FALSE;
}
static int jk_is_some_property(const char *prp_name, const char *suffix, const char *sep)
{
if (prp_name && suffix && sep) {
size_t prp_name_len = strlen(prp_name);
size_t suffix_len = strlen(suffix);
size_t sep_len = strlen(sep);
size_t sep_off = sep_len + suffix_len;
if (prp_name_len >= sep_off) {
if (!strncmp(prp_name + prp_name_len - sep_off, sep, sep_len) &&
!strncmp(prp_name + prp_name_len - suffix_len, suffix, suffix_len)) {
return JK_TRUE;
}
}
}
return JK_FALSE;
}
int jk_is_path_property(const char *prp_name)
{
return jk_is_some_property(prp_name, "path", "_");
}
int jk_is_cmd_line_property(const char *prp_name)
{
return jk_is_some_property(prp_name, CMD_LINE_OF_WORKER, ".");
}
int jk_is_list_property(const char *prp_name)
{
const char **props = &list_properties[0];
while (*props) {
if (jk_is_some_property(prp_name, *props, "."))
return JK_TRUE;
props++;
}
return JK_FALSE;
}
int jk_is_unique_property(const char *prp_name)
{
const char **props = &unique_properties[0];
while (*props) {
if (jk_is_some_property(prp_name, *props, "."))
return JK_TRUE;
props++;
}
return JK_FALSE;
}
int jk_is_deprecated_property(const char *prp_name)
{
const char **props = &deprecated_properties[0];
while (*props) {
if (jk_is_some_property(prp_name, *props, "."))
return JK_TRUE;
props++;
}
return JK_FALSE;
}
int jk_check_buffer_size()
{
const char **props;
size_t len = 0;
size_t max_len = 0;
props = &supported_properties[0];
while (*props) {
len = strlen(*props);
if (len > max_len)
max_len = len;
props++;
}
return JK_MAX_ATTRIBUTE_NAME_LEN - (int)max_len;
}
/*
* Check that property is a valid one (to prevent user typos).
* Only property starting with worker.
*/
int jk_is_valid_property(const char *prp_name)
{
const char **props;
/* Any property not starting with "worker." is "valid".
* It is interpreted as the definition of a custom variable.
*/
if (memcmp(prp_name, "worker.", 7))
return JK_TRUE;
props = &supported_properties[0];
while (*props) {
if (jk_is_some_property(prp_name, *props, "."))
return JK_TRUE;
props++;
}
return JK_FALSE;
}
int jk_get_worker_stdout(jk_map_t *m, const char *wname, const char **stdout_name)
{
char buf[PARAM_BUFFER_SIZE];
if (m && stdout_name && wname) {
MAKE_WORKER_PARAM(STDOUT_OF_WORKER);
*stdout_name = jk_map_get_string(m, buf, NULL);
if (*stdout_name) {
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_stderr(jk_map_t *m, const char *wname, const char **stderr_name)
{
char buf[PARAM_BUFFER_SIZE];
if (m && stderr_name && wname) {
MAKE_WORKER_PARAM(STDERR_OF_WORKER);
*stderr_name = jk_map_get_string(m, buf, NULL);
if (*stderr_name) {
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_sysprops(jk_map_t *m, const char *wname, const char **sysprops)
{
char buf[PARAM_BUFFER_SIZE];
if (m && sysprops && wname) {
MAKE_WORKER_PARAM(SYSPROPS_OF_WORKER);
*sysprops = jk_map_get_string(m, buf, NULL);
if (*sysprops) {
return JK_TRUE;
}
}
return JK_FALSE;
}
int jk_get_worker_libpath(jk_map_t *m, const char *wname, const char **libpath)
{
char buf[PARAM_BUFFER_SIZE];
if (m && libpath && wname) {
MAKE_WORKER_PARAM(LIBPATH_OF_WORKER);
*libpath = jk_map_get_string(m, buf, NULL);
if (*libpath) {
return JK_TRUE;
}
}
return JK_FALSE;
}
const char *jk_get_lb_session_cookie(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(SESSION_COOKIE_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_lb_session_path(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(SESSION_PATH_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
int jk_get_lb_set_session_cookie(jk_map_t *m, const char *wname, int def)
{
char buf[PARAM_BUFFER_SIZE];
if (m && wname) {
MAKE_WORKER_PARAM(SET_SESSION_COOKIE);
return jk_map_get_bool(m, buf, def);
}
return def;
}
const char *jk_get_lb_session_cookie_path(jk_map_t *m, const char *wname, const char *def)
{
char buf[PARAM_BUFFER_SIZE];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(SESSION_COOKIE_PATH_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
int is_http_status_fail(unsigned int http_status_fail_num,
int *http_status_fail, int status)
{
unsigned int i;
int soft_status = -1 * status;
for (i = 0; i < http_status_fail_num; i++) {
if (http_status_fail[i] == status)
return 1;
if (http_status_fail[i] == soft_status)
return -1;
}
return 0;
}
char **jk_parse_sysprops(jk_pool_t *p, const char *sysprops)
{
char **rc = NULL;
#ifdef _MT_CODE_PTHREAD
char *lasts;
#endif
if (p && sysprops) {
char *prps = jk_pool_strdup(p, sysprops);
if (prps && strlen(prps)) {
unsigned num_of_prps;
for (num_of_prps = 1; *sysprops; sysprops++) {
if ('*' == *sysprops) {
num_of_prps++;
}
}
rc = jk_pool_alloc(p, (num_of_prps + 1) * sizeof(char *));
if (rc) {
unsigned i = 0;
#ifdef _MT_CODE_PTHREAD
char *tmp = strtok_r(prps, "*", &lasts);
#else
char *tmp = strtok(prps, "*");
#endif
while (tmp && i < num_of_prps) {
rc[i] = tmp;
#ifdef _MT_CODE_PTHREAD
tmp = strtok_r(NULL, "*", &lasts);
#else
tmp = strtok(NULL, "*");
#endif
i++;
}
rc[i] = NULL;
}
}
}
return rc;
}
void jk_append_libpath(jk_pool_t *p, const char *libpath)
{
char *env = NULL;
char *current = getenv(PATH_ENV_VARIABLE);
if (current) {
env = jk_pool_alloc(p, strlen(PATH_ENV_VARIABLE) +
strlen(current) + strlen(libpath) + 5);
if (env) {
sprintf(env, "%s=%s%c%s",
PATH_ENV_VARIABLE, libpath, PATH_SEPERATOR, current);
}
}
else {
env = jk_pool_alloc(p, strlen(PATH_ENV_VARIABLE) +
strlen(libpath) + 5);
if (env) {
sprintf(env, "%s=%s", PATH_ENV_VARIABLE, libpath);
}
}
if (env) {
putenv(env);
}
}
void jk_init_ws_service(jk_ws_service_t *s)
{
memset(s, 0, sizeof(jk_ws_service_t));
s->server_port = 80;
s->ssl_key_size = -1;
s->activation = JK_LB_ACTIVATION_TEXT_ACTIVE;
s->reco_status = RECO_NONE;
s->extension.reply_timeout = -1;
s->http_response_status = JK_HTTP_OK;
}
/* Match = 0, NoMatch = 1, Abort = -1
* Based loosely on sections of wildmat.c by Rich Salz
*/
int jk_wildchar_match(const char *str, const char *exp, int icase)
{
int x, y;
for (x = 0, y = 0; exp[y]; ++y, ++x) {
if (!str[x] && exp[y] != '*')
return -1;
if (exp[y] == '*') {
while (exp[++y] == '*');
if (!exp[y])
return 0;
while (str[x]) {
int ret;
if ((ret = jk_wildchar_match(&str[x++], &exp[y], icase)) != 1)
return ret;
}
return -1;
}
else if (exp[y] != '?') {
if (icase && (tolower(str[x]) != tolower(exp[y])))
return 1;
else if (!icase && str[x] != exp[y])
return 1;
}
}
return (str[x] != '\0');
}
int jk_servlet_normalize(char *path, jk_log_context_t *log_ctx)
{
int l, w;
if (JK_IS_DEBUG_LEVEL(log_ctx)) {
jk_log(log_ctx, JK_LOG_DEBUG, "URI on entering jk_servlet_normalize: [%s]", path);
}
// This test allows the loops below to start at index 1 rather than 0.
if (path[0] != '/') {
if (path[0] == '*' && path[1] == '\0') {
/* Most likely an "OPTIONS *" request */
return 0;
}
jk_log(log_ctx, JK_LOG_WARNING, "Uri [%s] does not start with '/'.", path);
return JK_NORMALIZE_BAD_PATH;
}
/* First pass.
* Remove path parameters ;foo=bar/ from any path segment
*/
for (l = 1, w = 1; path[l] != '\0';) {
if (path[l] == ';') {
l++;
while (path[l] != '/' && path[l] != '\0') {
l++;
}
}
else
path[w++] = path[l++];
}
path[w] = '\0';
/*
* Second pass.
* Collapse ///// sequences to /
*/
for (l = 1, w = 1; path[l] != '\0';) {
if (path[w - 1] == '/' && (path[l] == '/')) {
l++;
}
else
path[w++] = path[l++];
}
path[w] = '\0';
/* Third pass.
* Remove /./ segments
* Both leading and trailing segments will be removed.
*/
for (l = 1, w = 1; path[l] != '\0';) {
if (path[l] == '.' &&
(path[l + 1] == '/' || path[l + 1] == '\0') &&
(l == 0 || path[l - 1] == '/')) {
l++;
if (path[l] == '/') {
l++;
}
}
else
path[w++] = path[l++];
}
path[w] = '\0';
/* Fourth pass.
* Remove /xx/../ segments
* Trailing segments will be removed but leading /../ segments are an error
* condition.
*/
for (l = 1, w = 1; path[l] != '\0';) {
if (path[l] == '.' && path[l + 1] == '.' &&
(path[l + 2] == '/' || path[l + 2] == '\0') &&
(l == 0 || path[l - 1] == '/')) {
// Wind w back to remove the previous segment
if (w == 1) {
jk_log(log_ctx,
JK_LOG_EMERG,
"[%s] contains a '/../' sequence that tries to escape above the root.",
path);
return JK_NORMALIZE_TRAVERSAL;
}
do {
w--;
} while (w != 0 && path[w - 1] != '/');
// Move l forward to the next segment
l += 2;
if (path[l] == '/') {
l++;
}
}
else
path[w++] = path[l++];
}
path[w] = '\0';
if (JK_IS_DEBUG_LEVEL(log_ctx)) {
jk_log(log_ctx, JK_LOG_DEBUG, "URI on exiting jk_servlet_normalize: [%s]", path);
}
return 0;
}
int jk_strip_session_id(char* path, char* session_name, jk_log_context_t *log_ctx) {
char *jsessionid;
jsessionid = strstr(path, session_name);
if (jsessionid) {
int i;
int j;
if (JK_IS_DEBUG_LEVEL(log_ctx)) {
jk_log(log_ctx, JK_LOG_DEBUG,
"removing session identifier for non servlet uri [%s]", path);
}
// Found a session path parameter.
// Need to skip at least as many characters as there are in
// strip_session_name
i = (int) strlen(session_name);
j = 0;
// Increment i until the first character after the parameter
while (jsessionid[i] != '\0' && jsessionid[i] != ';' && jsessionid[i] != '/') {
i++;
}
// Copy until the end
while (jsessionid[i] != '\0') {
jsessionid[j++] = jsessionid[i++];
}
// Terminate
jsessionid[j] = '\0';
if (JK_IS_DEBUG_LEVEL(log_ctx)) {
jk_log(log_ctx, JK_LOG_DEBUG,
"result of removing session identifier for non servlet uri is [%s]", path);
}
return 1;
}
return 0;
}
#ifdef _MT_CODE_PTHREAD
jk_pthread_t jk_gettid()
{
union {
pthread_t tid;
jk_uint64_t alignme;
} u;
#ifdef AS400
/* OS400 use 64 bits ThreadId */
pthread_id_np_t tid;
#endif /* AS400 */
u.tid = pthread_self();
#ifdef AS400
/* Get only low 32 bits for now */
pthread_getunique_np(&(u.tid), &tid);
return ((jk_uint32_t)(tid.intId.lo & 0xFFFFFFFF));
#else
return ((jk_pthread_t)u.tid);
#endif /* AS400 */
}
#endif
/***
* ASCII <-> EBCDIC conversions
*
* For now usefull only in i5/OS V5R4 where UTF and EBCDIC mode are mixed
*/
#ifdef AS400_UTF8
/* EBCDIC to ASCII translation table */
static u_char ebcdic_to_ascii[256] =
{
0x00,0x01,0x02,0x03,0x20,0x09,0x20,0x7f, /* 00-07 */
0x20,0x20,0x20,0x0b,0x0c,0x0d,0x0e,0x0f, /* 08-0f */
0x10,0x11,0x12,0x13,0x20,0x0a,0x08,0x20, /* 10-17 */
0x18,0x19,0x20,0x20,0x20,0x1d,0x1e,0x1f, /* 18-1f */
0x20,0x20,0x1c,0x20,0x20,0x0a,0x17,0x1b, /* 20-27 */
0x20,0x20,0x20,0x20,0x20,0x05,0x06,0x07, /* 28-2f */
0x20,0x20,0x16,0x20,0x20,0x20,0x20,0x04, /* 30-37 */
0x20,0x20,0x20,0x20,0x14,0x15,0x20,0x1a, /* 38-3f */
0x20,0x20,0x83,0x84,0x85,0xa0,0xc6,0x86, /* 40-47 */
0x87,0xa4,0xbd,0x2e,0x3c,0x28,0x2b,0x7c, /* 48-4f */
0x26,0x82,0x88,0x89,0x8a,0xa1,0x8c,0x8b, /* 50-57 */
0x8d,0xe1,0x21,0x24,0x2a,0x29,0x3b,0xaa, /* 58-5f */
0x2d,0x2f,0xb6,0x8e,0xb7,0xb5,0xc7,0x8f, /* 60-67 */
0x80,0xa5,0xdd,0x2c,0x25,0x5f,0x3e,0x3f, /* 68-6f */
0x9b,0x90,0xd2,0xd3,0xd4,0xd6,0xd7,0xd8, /* 70-77 */
0xde,0x60,0x3a,0x23,0x40,0x27,0x3d,0x22, /* 78-7f */
0x9d,0x61,0x62,0x63,0x64,0x65,0x66,0x67, /* 80-87 */
0x68,0x69,0xae,0xaf,0xd0,0xec,0xe7,0xf1, /* 88-8f */
0xf8,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70, /* 90-97 */
0x71,0x72,0xa6,0xa7,0x91,0xf7,0x92,0xcf, /* 98-9f */
0xe6,0x7e,0x73,0x74,0x75,0x76,0x77,0x78, /* a8-a7 */
0x79,0x7a,0xad,0xa8,0xd1,0xed,0xe8,0xa9, /* a8-af */
0x5e,0x9c,0xbe,0xfa,0xb8,0x15,0x14,0xac, /* b0-b7 */
0xab,0xf3,0x5b,0x5d,0xee,0xf9,0xef,0x9e, /* b8-bf */
0x7b,0x41,0x42,0x43,0x44,0x45,0x46,0x47, /* c0-c7 */
0x48,0x49,0xf0,0x93,0x94,0x95,0xa2,0xe4, /* c8-cf */
0x7d,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50, /* d0-d7 */
0x51,0x52,0xfb,0x96,0x81,0x97,0xa3,0x98, /* d8-df */
0x5c,0xf6,0x53,0x54,0x55,0x56,0x57,0x58, /* e0-e7 */
0x59,0x5a,0xfc,0xe2,0x99,0xe3,0xe0,0xe5, /* e8-ef */
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, /* f0-f7 */
0x38,0x39,0xfd,0xea,0x9a,0xeb,0xe9,0xff /* f8-ff */
};
/* ASCII to EBCDIC translation table */
static u_char ascii_to_ebcdic[256] =
{
0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, /* 00-07 */
0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, /* 08-0f */
0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, /* 10-17 */
0x18,0x19,0x3f,0x27,0x22,0x1d,0x1e,0x1f, /* 18-1f */
0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, /* 20-27 */
0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, /* 28-2f */
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, /* 30-37 */
0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, /* 38-3f */
0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, /* 40-47 */
0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, /* 48-4f */
0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, /* 50-57 */
0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, /* 58-5f */
0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, /* 60-67 */
0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, /* 68-6f */
0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, /* 70-77 */
0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, /* 78-7f */
0x68,0xdc,0x51,0x42,0x43,0x44,0x47,0x48, /* 80-87 */
0x52,0x53,0x54,0x57,0x56,0x58,0x63,0x67, /* 88-8f */
0x71,0x9c,0x9e,0xcb,0xcc,0xcd,0xdb,0xdd, /* 90-97 */
0xdf,0xec,0xfc,0x70,0xb1,0x80,0xbf,0x40, /* 98-9f */
0x45,0x55,0xee,0xde,0x49,0x69,0x9a,0x9b, /* a8-a7 */
0xab,0xaf,0x5f,0xb8,0xb7,0xaa,0x8a,0x8b, /* a8-af */
0x40,0x40,0x40,0x40,0x40,0x65,0x62,0x64, /* b0-b7 */
0xb4,0x40,0x40,0x40,0x40,0x4a,0xb2,0x40, /* b8-bf */
0x40,0x40,0x40,0x40,0x40,0x40,0x46,0x66, /* c0-c7 */
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x9f, /* c8-cf */
0x8c,0xac,0x72,0x73,0x74,0x89,0x75,0x76, /* d0-d7 */
0x77,0x40,0x40,0x40,0x40,0x6a,0x78,0x40, /* d8-df */
0xee,0x59,0xeb,0xed,0xcf,0xef,0xa0,0x8e, /* e0-e7 */
0xae,0xfe,0xfb,0xfd,0x8d,0xad,0xbc,0xbe, /* e8-ef */
0xca,0x8f,0x40,0xb9,0xb6,0xb5,0xe1,0x9d, /* f0-f7 */
0x90,0xbd,0xb3,0xda,0xea,0xfa,0x40,0x40 /* f8-ff */
};
void jk_ascii2ebcdic(char *src, char *dst) {
char c;
while ((c = *src++) != 0) {
*dst++ = ascii_to_ebcdic[(unsigned int)c];
}
*dst = 0;
}
void jk_ebcdic2ascii(char *src, char *dst) {
char c;
while ((c = *src++) != 0) {
*dst++ = ebcdic_to_ascii[(unsigned int)c];
}
*dst = 0;
}
#endif
#if defined (WIN32)
static PSECURITY_ATTRIBUTES pNullSA;
static SECURITY_ATTRIBUTES stEmptySA;
/* To share the objects with other processes, we need a 0 ACL
* Code from MS KB Q106387
*/
PSECURITY_ATTRIBUTES jk_get_sa_with_null_dacl()
{
DWORD rc = 0;
PSECURITY_DESCRIPTOR pSD;
if (pNullSA != NULL) {
return pNullSA;
}
else {
stEmptySA.nLength = (DWORD)sizeof(SECURITY_ATTRIBUTES);
stEmptySA.lpSecurityDescriptor = 0;
}
if (!(pNullSA = LocalAlloc(LPTR, sizeof(SECURITY_ATTRIBUTES)))) {
rc = GetLastError();
goto cleanup;
}
pNullSA->nLength = (DWORD)sizeof(SECURITY_ATTRIBUTES);
pSD = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (pSD == 0) {
rc = GetLastError();
goto cleanup;
}
pNullSA->lpSecurityDescriptor = pSD;
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
rc = GetLastError();
goto cleanup;
}
if (!SetSecurityDescriptorDacl(pSD, TRUE, (PACL)0, FALSE)) {
rc = GetLastError();
goto cleanup;
}
pNullSA->lpSecurityDescriptor = pSD;
pNullSA->bInheritHandle = FALSE;
SetLastError(0);
return pNullSA;
cleanup:
if (pSD)
LocalFree(pSD);
if (pNullSA)
LocalFree(pNullSA);
pNullSA = &stEmptySA;
pNullSA->bInheritHandle = FALSE;
SetLastError(rc);
return pNullSA;
}
#endif