bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / tomcat-connectors-1.2.32-src / native / common / jk_util.c
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 /***************************************************************************
19  * Description: Utility functions (mainly configuration)                   *
20  * Author:      Gal Shachor <shachor@il.ibm.com>                           *
21  * Author:      Henri Gomez <hgomez@apache.org>                            *
22  * Author:      Rainer Jung <rjung@apache.org>                             *
23  * Version:     $Revision: 1078846 $                                          *
24  ***************************************************************************/
25
26
27 #include "jk_util.h"
28 #include "jk_ajp12_worker.h"
29 #include "jk_ajp13_worker.h"
30 #include "jk_ajp14_worker.h"
31 #include "jk_lb_worker.h"
32 #include "jk_mt.h"
33
34 #define SYSPROPS_OF_WORKER          ("sysprops")
35 #define STDERR_OF_WORKER            ("stderr")
36 #define STDOUT_OF_WORKER            ("stdout")
37 #define SECRET_OF_WORKER            ("secret")
38 #define MX_OF_WORKER                ("mx")
39 #define MS_OF_WORKER                ("ms")
40 #define CP_OF_WORKER                ("class_path")
41 #define BRIDGE_OF_WORKER            ("bridge")
42 #define JVM_OF_WORKER               ("jvm_lib")
43 #define LIBPATH_OF_WORKER           ("ld_path")
44 #define CMD_LINE_OF_WORKER          ("cmd_line")
45 #define NATIVE_LIB_OF_WORKER        ("native_lib")
46 #define REFERENCE_OF_WORKER         ("reference")
47 #define HOST_OF_WORKER              ("host")
48 #define PORT_OF_WORKER              ("port")
49 #define TYPE_OF_WORKER              ("type")
50 #define CACHE_OF_WORKER_DEPRECATED  ("cachesize")
51 #define CACHE_OF_WORKER             ("connection_pool_size")
52 #define CACHE_OF_WORKER_MIN         ("connection_pool_minsize")
53 #define CACHE_TIMEOUT_DEPRECATED    ("cache_timeout")
54 #define CACHE_TIMEOUT_OF_WORKER     ("connection_pool_timeout")
55 #define CACHE_ACQUIRE_OF_WORKER     ("connection_acquire_timeout")
56 #define RECOVERY_OPTS_OF_WORKER     ("recovery_options")
57 #define CONNECT_TIMEOUT_OF_WORKER   ("connect_timeout")
58 #define PREPOST_TIMEOUT_OF_WORKER   ("prepost_timeout")
59 #define REPLY_TIMEOUT_OF_WORKER     ("reply_timeout")
60 #define SOCKET_TIMEOUT_OF_WORKER    ("socket_timeout")
61 #define SOCKET_CONNECT_TIMEOUT_OF_WORKER ("socket_connect_timeout")
62 #define PING_TIMEOUT_OF_WORKER      ("ping_timeout")
63 #define PING_MODE_OF_WORKER         ("ping_mode")
64 #define SOCKET_BUFFER_OF_WORKER     ("socket_buffer")
65 #define SOCKET_KEEPALIVE_OF_WORKER  ("socket_keepalive")
66 #define CONN_PING_INTERVAL_OF_WORKER  ("connection_ping_interval")
67 #define RECYCLE_TIMEOUT_DEPRECATED  ("recycle_timeout")
68 #define LOAD_FACTOR_OF_WORKER       ("lbfactor")
69 #define DISTANCE_OF_WORKER          ("distance")
70 #define BALANCED_WORKERS_DEPRECATED ("balanced_workers")
71 #define BALANCE_WORKERS             ("balance_workers")
72 #define STICKY_SESSION              ("sticky_session")
73 #define STICKY_SESSION_FORCE        ("sticky_session_force")
74 #define SESSION_COOKIE_OF_WORKER    ("session_cookie")
75 #define SESSION_PATH_OF_WORKER      ("session_path")
76
77 #define LOCAL_WORKER_DEPRECATED     ("local_worker")
78 #define LOCAL_WORKER_ONLY_DEPRECATED ("local_worker_only")
79 #define JVM_ROUTE_OF_WORKER_DEPRECATED ("jvm_route")
80 #define ROUTE_OF_WORKER             ("route")
81 #define DOMAIN_OF_WORKER            ("domain")
82 #define REDIRECT_OF_WORKER          ("redirect")
83 #define MOUNT_OF_WORKER             ("mount")
84 #define METHOD_OF_WORKER            ("method")
85 #define LOCK_OF_WORKER              ("lock")
86 #define IS_WORKER_DISABLED_DEPRECATED ("disabled")
87 #define IS_WORKER_STOPPED_DEPRECATED  ("stopped")
88 #define ACTIVATION_OF_WORKER        ("activation")
89 #define WORKER_RECOVER_TIME         ("recover_time")
90 #define WORKER_ERROR_ESCALATION_TIME ("error_escalation_time")
91 #define MAX_REPLY_TIMEOUTS_OF_WORKER ("max_reply_timeouts")
92 #define RETRY_INTERVAL_OF_WORKER    ("retry_interval")
93 #define WORKER_MAX_PACKET_SIZE      ("max_packet_size")
94 #define STYLE_SHEET_OF_WORKER       ("css")
95 #define NAMESPACE_OF_WORKER         ("ns")
96 #define XML_NAMESPACE_OF_WORKER     ("xmlns")
97 #define XML_DOCTYPE_OF_WORKER       ("doctype")
98 #define PROP_PREFIX_OF_WORKER       ("prefix")
99
100 #define READ_ONLY_OF_WORKER         ("read_only")
101 #define USER_OF_WORKER              ("user")
102 #define USER_CASE_OF_WORKER         ("user_case_insensitive")
103 #define GOOD_RATING_OF_WORKER       ("good")
104 #define BAD_RATING_OF_WORKER        ("bad")
105
106 #define DEFAULT_WORKER_TYPE         JK_AJP13_WORKER_NAME
107 #define SECRET_KEY_OF_WORKER        ("secretkey")
108 #define RETRIES_OF_WORKER           ("retries")
109 #define STATUS_FAIL_OF_WORKER       ("fail_on_status")
110
111 #define DEFAULT_WORKER              JK_AJP13_WORKER_NAME
112 #define WORKER_LIST_PROPERTY_NAME     ("worker.list")
113 #define LIST_PROPERTY_NAME            ("list")
114 #define WORKER_MAINTAIN_PROPERTY_NAME ("worker.maintain")
115 #define MAINTAIN_PROPERTY_NAME        ("maintain")
116 #define DEFAULT_MAINTAIN_TIME       (60)
117 #define DEFAULT_LB_FACTOR           (1)
118 #define DEFAULT_DISTANCE            (0)
119
120 #define TOMCAT32_BRIDGE_NAME        ("tomcat32")
121 #define TOMCAT33_BRIDGE_NAME        ("tomcat33")
122 #define TOMCAT40_BRIDGE_NAME        ("tomcat40")
123 #define TOMCAT41_BRIDGE_NAME        ("tomcat41")
124 #define TOMCAT50_BRIDGE_NAME        ("tomcat5")
125
126 #define HUGE_BUFFER_SIZE (8*1024)
127
128 #define MAKE_WORKER_PARAM(P)     \
129         strcpy(buf, "worker.");  \
130         strcat(buf, wname);      \
131         strcat(buf, ".");        \
132         strcat(buf, P)
133
134 /*
135  * define the log format, we're using by default the one from error.log
136  *
137  * [Mon Mar 26 19:44:48.123 2001] [jk_uri_worker_map.c (155)]: Into jk_uri_worker_map_t::uri_worker_map_alloc
138  * log format used by apache in error.log
139  */
140 #define JK_TIME_CONV_MILLI    "%Q"
141 #define JK_TIME_CONV_MICRO    "%q"
142 #define JK_TIME_PATTERN_MILLI "000"
143 #define JK_TIME_PATTERN_MICRO "000000"
144 #define JK_TIME_FORMAT_NONE   "[%a %b %d %H:%M:%S %Y] "
145 #define JK_TIME_FORMAT_MILLI  "[%a %b %d %H:%M:%S." JK_TIME_CONV_MILLI " %Y] "
146 #define JK_TIME_FORMAT_MICRO  "[%a %b %d %H:%M:%S." JK_TIME_CONV_MICRO " %Y] "
147 #define JK_TIME_SUBSEC_NONE   (0)
148 #define JK_TIME_SUBSEC_MILLI  (1)
149 #define JK_TIME_SUBSEC_MICRO  (2)
150
151 /* Visual C++ Toolkit 2003 support */
152 #if defined (_MSC_VER) && (_MSC_VER == 1310)
153     extern long _ftol(double); /* defined by VC6 C libs */
154     extern long _ftol2(double dblSource) { return _ftol(dblSource); }
155 #endif
156
157 static const char *list_properties[] = {
158     BALANCE_WORKERS,
159     MOUNT_OF_WORKER,
160     USER_OF_WORKER,
161     GOOD_RATING_OF_WORKER,
162     BAD_RATING_OF_WORKER,
163     STATUS_FAIL_OF_WORKER,
164     "list",
165     NULL
166 };
167
168 static const char *unique_properties[] = {
169     SECRET_OF_WORKER,
170     REFERENCE_OF_WORKER,
171     HOST_OF_WORKER,
172     PORT_OF_WORKER,
173     TYPE_OF_WORKER,
174     CACHE_OF_WORKER_DEPRECATED,
175     CACHE_OF_WORKER,
176     CACHE_OF_WORKER_MIN,
177     CACHE_TIMEOUT_DEPRECATED,
178     CACHE_TIMEOUT_OF_WORKER,
179     CACHE_ACQUIRE_OF_WORKER,
180     RECOVERY_OPTS_OF_WORKER,
181     CONNECT_TIMEOUT_OF_WORKER,
182     PREPOST_TIMEOUT_OF_WORKER,
183     PING_TIMEOUT_OF_WORKER,
184     PING_MODE_OF_WORKER,
185     REPLY_TIMEOUT_OF_WORKER,
186     SOCKET_TIMEOUT_OF_WORKER,
187     SOCKET_CONNECT_TIMEOUT_OF_WORKER,
188     SOCKET_BUFFER_OF_WORKER,
189     SOCKET_KEEPALIVE_OF_WORKER,
190     CONN_PING_INTERVAL_OF_WORKER,
191     RECYCLE_TIMEOUT_DEPRECATED,
192     LOAD_FACTOR_OF_WORKER,
193     STICKY_SESSION,
194     STICKY_SESSION_FORCE,
195     SESSION_COOKIE_OF_WORKER,
196     SESSION_PATH_OF_WORKER,
197     LOCAL_WORKER_DEPRECATED,
198     LOCAL_WORKER_ONLY_DEPRECATED,
199     JVM_ROUTE_OF_WORKER_DEPRECATED,
200     ROUTE_OF_WORKER,
201     DOMAIN_OF_WORKER,
202     REDIRECT_OF_WORKER,
203     METHOD_OF_WORKER,
204     LOCK_OF_WORKER,
205     IS_WORKER_DISABLED_DEPRECATED,
206     IS_WORKER_STOPPED_DEPRECATED,
207     ACTIVATION_OF_WORKER,
208     WORKER_RECOVER_TIME,
209     WORKER_ERROR_ESCALATION_TIME,
210     MAX_REPLY_TIMEOUTS_OF_WORKER,
211     RETRY_INTERVAL_OF_WORKER,
212     WORKER_MAX_PACKET_SIZE,
213     STYLE_SHEET_OF_WORKER,
214     READ_ONLY_OF_WORKER,
215     RETRIES_OF_WORKER,
216     WORKER_MAINTAIN_PROPERTY_NAME,
217     NAMESPACE_OF_WORKER,
218     XML_NAMESPACE_OF_WORKER,
219     XML_DOCTYPE_OF_WORKER,
220     PROP_PREFIX_OF_WORKER,
221     USER_CASE_OF_WORKER,
222     NULL
223 };
224
225 static const char *deprecated_properties[] = {
226     SYSPROPS_OF_WORKER,
227     STDERR_OF_WORKER,
228     STDOUT_OF_WORKER,
229     MX_OF_WORKER,
230     MS_OF_WORKER,
231     CP_OF_WORKER,
232     BRIDGE_OF_WORKER,
233     JVM_OF_WORKER,
234     LIBPATH_OF_WORKER,
235     CMD_LINE_OF_WORKER,
236     NATIVE_LIB_OF_WORKER,
237     CACHE_OF_WORKER_DEPRECATED,
238     CACHE_TIMEOUT_DEPRECATED,
239     RECYCLE_TIMEOUT_DEPRECATED,
240     BALANCED_WORKERS_DEPRECATED,
241     JVM_ROUTE_OF_WORKER_DEPRECATED,
242     LOCAL_WORKER_DEPRECATED,
243     LOCAL_WORKER_ONLY_DEPRECATED,
244     IS_WORKER_DISABLED_DEPRECATED,
245     IS_WORKER_STOPPED_DEPRECATED,
246     NULL
247 };
248
249 static const char *supported_properties[] = {
250     SYSPROPS_OF_WORKER,
251     STDERR_OF_WORKER,
252     STDOUT_OF_WORKER,
253     SECRET_OF_WORKER,
254     MX_OF_WORKER,
255     MS_OF_WORKER,
256     CP_OF_WORKER,
257     BRIDGE_OF_WORKER,
258     JVM_OF_WORKER,
259     LIBPATH_OF_WORKER,
260     CMD_LINE_OF_WORKER,
261     NATIVE_LIB_OF_WORKER,
262     REFERENCE_OF_WORKER,
263     HOST_OF_WORKER,
264     PORT_OF_WORKER,
265     TYPE_OF_WORKER,
266     CACHE_OF_WORKER_DEPRECATED,
267     CACHE_OF_WORKER,
268     CACHE_OF_WORKER_MIN,
269     CACHE_TIMEOUT_DEPRECATED,
270     CACHE_TIMEOUT_OF_WORKER,
271     CACHE_ACQUIRE_OF_WORKER,
272     RECOVERY_OPTS_OF_WORKER,
273     CONNECT_TIMEOUT_OF_WORKER,
274     PREPOST_TIMEOUT_OF_WORKER,
275     PING_TIMEOUT_OF_WORKER,
276     PING_MODE_OF_WORKER,
277     REPLY_TIMEOUT_OF_WORKER,
278     SOCKET_TIMEOUT_OF_WORKER,
279     SOCKET_CONNECT_TIMEOUT_OF_WORKER,
280     SOCKET_BUFFER_OF_WORKER,
281     SOCKET_KEEPALIVE_OF_WORKER,
282     CONN_PING_INTERVAL_OF_WORKER,
283     RECYCLE_TIMEOUT_DEPRECATED,
284     LOAD_FACTOR_OF_WORKER,
285     DISTANCE_OF_WORKER,
286     BALANCED_WORKERS_DEPRECATED,
287     BALANCE_WORKERS,
288     STICKY_SESSION,
289     STICKY_SESSION_FORCE,
290     SESSION_COOKIE_OF_WORKER,
291     SESSION_PATH_OF_WORKER,
292     LOCAL_WORKER_DEPRECATED,
293     LOCAL_WORKER_ONLY_DEPRECATED,
294     JVM_ROUTE_OF_WORKER_DEPRECATED,
295     ROUTE_OF_WORKER,
296     DOMAIN_OF_WORKER,
297     REDIRECT_OF_WORKER,
298     MOUNT_OF_WORKER,
299     METHOD_OF_WORKER,
300     LOCK_OF_WORKER,
301     IS_WORKER_DISABLED_DEPRECATED,
302     IS_WORKER_STOPPED_DEPRECATED,
303     ACTIVATION_OF_WORKER,
304     WORKER_RECOVER_TIME,
305     WORKER_ERROR_ESCALATION_TIME,
306     MAX_REPLY_TIMEOUTS_OF_WORKER,
307     RETRY_INTERVAL_OF_WORKER,
308     WORKER_MAX_PACKET_SIZE,
309     STYLE_SHEET_OF_WORKER,
310     NAMESPACE_OF_WORKER,
311     XML_NAMESPACE_OF_WORKER,
312     XML_DOCTYPE_OF_WORKER,
313     PROP_PREFIX_OF_WORKER,
314     READ_ONLY_OF_WORKER,
315     USER_OF_WORKER,
316     USER_CASE_OF_WORKER,
317     GOOD_RATING_OF_WORKER,
318     BAD_RATING_OF_WORKER,
319     SECRET_KEY_OF_WORKER,
320     RETRIES_OF_WORKER,
321     STATUS_FAIL_OF_WORKER,
322     LIST_PROPERTY_NAME,
323     MAINTAIN_PROPERTY_NAME,
324     NULL
325 };
326
327 static const char *jk_level_verbs[] = {
328     "[" JK_LOG_TRACE_VERB "] ",
329     "[" JK_LOG_DEBUG_VERB "] ",
330     "[" JK_LOG_INFO_VERB "] ",
331     "[" JK_LOG_WARN_VERB "] ",
332     "[" JK_LOG_ERROR_VERB "] ",
333     "[" JK_LOG_EMERG_VERB "] ",
334     NULL
335 };
336
337 const char *jk_get_bool(int v)
338 {
339     if (v == 0)
340         return "False";
341     else
342         return "True";
343 }
344
345 int jk_get_bool_code(const char *v, int def)
346 {
347     if (!v) {
348         return def;
349     }
350     else if (!strcasecmp(v, "off") ||
351              *v == 'F' || *v == 'f' ||
352              *v == 'N' || *v == 'n' ||
353             (*v == '0' && *(v + 1) == '\0')) {
354         return 0;
355     }
356     else if (!strcasecmp(v, "on") ||
357              *v == 'T' || *v == 't' ||
358              *v == 'Y' || *v == 'y' ||
359             (*v == '1' && *(v + 1) == '\0')) {
360         return 1;
361     }
362     return def;
363 }
364
365 /* Sleep for 100ms */
366 void jk_sleep(int ms)
367 {
368 #ifdef OS2
369     DosSleep(ms);
370 #elif defined(BEOS)
371     snooze(ms * 1000);
372 #elif defined(NETWARE)
373     delay(ms);
374 #elif defined(WIN32)
375     Sleep(ms);
376 #else
377     struct timeval tv;
378     tv.tv_usec = (ms % 1000) * 1000;
379     tv.tv_sec = ms / 1000;
380     select(0, NULL, NULL, NULL, &tv);
381 #endif
382 }
383
384 /* Replace the first occurence of a sub second time format character
385  * by a series of zero digits with the right precision.
386  * We format our timestamp with strftime, but this can not handle
387  * sub second timestamps.
388  * So we first patch the milliseconds or microseconds literally into
389  * the format string, and then pass it on the strftime.
390  * In order to do that efficiently, we prepare a format string, that
391  * already has placeholder digits for the sub second time stamp
392  * and we save the position and time precision of this placeholder.
393  */
394 void jk_set_time_fmt(jk_logger_t *l, const char *jk_log_fmt)
395 {
396     if (l) {
397         char *s;
398
399         if (!jk_log_fmt) {
400 #ifndef NO_GETTIMEOFDAY
401             jk_log_fmt = JK_TIME_FORMAT_MILLI;
402 #else
403             jk_log_fmt = JK_TIME_FORMAT_NONE;
404 #endif
405         }
406         l->log_fmt_type = JK_TIME_SUBSEC_NONE;
407         l->log_fmt_offset = 0;
408         l->log_fmt_size = 0;
409         l->log_fmt = jk_log_fmt;
410
411 /* Look for the first occurence of JK_TIME_CONV_MILLI */
412         if ((s = strstr(jk_log_fmt, JK_TIME_CONV_MILLI))) {
413             size_t offset = s - jk_log_fmt;
414             size_t len = strlen(JK_TIME_PATTERN_MILLI);
415
416 /* If we don't have enough space in our fixed-length char array,
417  * we simply stick to the default format, ignoring JK_TIME_CONV_MILLI.
418  * Otherwise we replace the first occurence of JK_TIME_CONV_MILLI by JK_TIME_PATTERN_MILLI.
419  */
420             if (offset + len < JK_TIME_MAX_SIZE) {
421                 l->log_fmt_type = JK_TIME_SUBSEC_MILLI;
422                 l->log_fmt_offset = offset;
423                 strncpy(l->log_fmt_subsec, jk_log_fmt, offset);
424                 strncpy(l->log_fmt_subsec + offset, JK_TIME_PATTERN_MILLI, len);
425                 strncpy(l->log_fmt_subsec + offset + len,
426                         s + strlen(JK_TIME_CONV_MILLI),
427                         JK_TIME_MAX_SIZE - offset - len - 1);
428 /* Now we put a stop mark into the string to make it's length at most JK_TIME_MAX_SIZE-1
429  * plus terminating '\0'.
430  */
431                 l->log_fmt_subsec[JK_TIME_MAX_SIZE-1] = '\0';
432                 l->log_fmt_size = strlen(l->log_fmt_subsec);
433             }
434 /* Look for the first occurence of JK_TIME_CONV_MICRO */
435         }
436         else if ((s = strstr(jk_log_fmt, JK_TIME_CONV_MICRO))) {
437             size_t offset = s - jk_log_fmt;
438             size_t len = strlen(JK_TIME_PATTERN_MICRO);
439
440 /* If we don't have enough space in our fixed-length char array,
441  * we simply stick to the default format, ignoring JK_TIME_CONV_MICRO.
442  * Otherwise we replace the first occurence of JK_TIME_CONV_MICRO by JK_TIME_PATTERN_MICRO.
443  */
444             if (offset + len < JK_TIME_MAX_SIZE) {
445                 l->log_fmt_type = JK_TIME_SUBSEC_MICRO;
446                 l->log_fmt_offset = offset;
447                 strncpy(l->log_fmt_subsec, jk_log_fmt, offset);
448                 strncpy(l->log_fmt_subsec + offset, JK_TIME_PATTERN_MICRO, len);
449                 strncpy(l->log_fmt_subsec + offset + len,
450                         s + strlen(JK_TIME_CONV_MICRO),
451                         JK_TIME_MAX_SIZE - offset - len - 1);
452 /* Now we put a stop mark into the string to make it's length at most JK_TIME_MAX_SIZE-1
453  * plus terminating '\0'.
454  */
455                 l->log_fmt_subsec[JK_TIME_MAX_SIZE-1] = '\0';
456                 l->log_fmt_size = strlen(l->log_fmt_subsec);
457             }
458         }
459         jk_log(l, JK_LOG_DEBUG, "Pre-processed log time stamp format is '%s'",
460                l->log_fmt_type == JK_TIME_SUBSEC_NONE ? l->log_fmt : l->log_fmt_subsec);
461     }
462 }
463
464 static int set_time_str(char *str, int len, jk_logger_t *l)
465 {
466     time_t t;
467     struct tm *tms;
468 #ifdef _MT_CODE_PTHREAD
469     struct tm res;
470 #endif
471     int done;
472 /* We want to use a fixed maximum size buffer here.
473  * If we would dynamically adjust it to the real format
474  * string length, we could support longer format strings,
475  * but we would have to allocate and free for each log line.
476  */
477     char log_fmt[JK_TIME_MAX_SIZE];
478
479     if (!l || !l->log_fmt) {
480         return 0;
481     }
482
483     log_fmt[0] = '\0';
484
485 #ifndef NO_GETTIMEOFDAY
486     if ( l->log_fmt_type != JK_TIME_SUBSEC_NONE ) {
487         struct timeval tv;
488         int rc = 0;
489
490 #ifdef WIN32
491         gettimeofday(&tv, NULL);
492 #else
493         rc = gettimeofday(&tv, NULL);
494 #endif
495         if (rc == 0) {
496 /* We need this subsec buffer, because we convert
497  * the integer with sprintf(), but we don't
498  * want to write the terminating '\0' into our
499  * final log format string.
500  */
501             char subsec[7];
502             t = tv.tv_sec;
503             strncpy(log_fmt, l->log_fmt_subsec, l->log_fmt_size + 1);
504             if (l->log_fmt_type == JK_TIME_SUBSEC_MILLI) {
505                 sprintf(subsec, "%03d", (int)(tv.tv_usec/1000));
506                 strncpy(log_fmt + l->log_fmt_offset, subsec, 3);
507             }
508             else if (l->log_fmt_type == JK_TIME_SUBSEC_MICRO) {
509                 sprintf(subsec, "%06d", (int)(tv.tv_usec));
510                 strncpy(log_fmt + l->log_fmt_offset, subsec, 6);
511             }
512         }
513         else {
514             t = time(NULL);
515         }
516     }
517     else {
518         t = time(NULL);
519     }
520 #else
521     t = time(NULL);
522 #endif
523 #ifdef _MT_CODE_PTHREAD
524     tms = localtime_r(&t, &res);
525 #else
526     tms = localtime(&t);
527 #endif
528     if (log_fmt[0])
529         done = (int)strftime(str, len, log_fmt, tms);
530     else
531         done = (int)strftime(str, len, l->log_fmt, tms);
532     return done;
533
534 }
535
536 static int JK_METHOD log_to_file(jk_logger_t *l, int level, int used, char *what)
537 {
538     if (l &&
539         (l->level <= level || level == JK_LOG_REQUEST_LEVEL) &&
540         l->logger_private && what) {
541         jk_file_logger_t *p = l->logger_private;
542         if (p->logfile) {
543             what[used++] = '\n';
544             what[used] = '\0';
545 #if defined(JK_LOG_LOCKING)
546 #if defined(WIN32) && defined(_MSC_VER)
547             LockFile((HANDLE)_get_osfhandle(_fileno(p->logfile)),
548                      0, 0, 1, 0);
549 #endif
550 #endif
551             fputs(what, p->logfile);
552             /* [V] Flush the dam' thing! */
553             fflush(p->logfile);
554 #if defined(JK_LOG_LOCKING)
555 #if defined(WIN32) && defined(_MSC_VER)
556             UnlockFile((HANDLE)_get_osfhandle(_fileno(p->logfile)),
557                        0, 0, 1, 0);
558 #endif
559 #endif
560         }
561         return JK_TRUE;
562     }
563     return JK_FALSE;
564 }
565
566 int jk_parse_log_level(const char *level)
567 {
568     if (0 == strcasecmp(level, JK_LOG_TRACE_VERB)) {
569         return JK_LOG_TRACE_LEVEL;
570     }
571
572     if (0 == strcasecmp(level, JK_LOG_DEBUG_VERB)) {
573         return JK_LOG_DEBUG_LEVEL;
574     }
575
576     if (0 == strcasecmp(level, JK_LOG_INFO_VERB)) {
577         return JK_LOG_INFO_LEVEL;
578     }
579
580     if (0 == strcasecmp(level, JK_LOG_WARN_VERB)) {
581         return JK_LOG_WARNING_LEVEL;
582     }
583
584     if (0 == strcasecmp(level, JK_LOG_ERROR_VERB)) {
585         return JK_LOG_ERROR_LEVEL;
586     }
587
588     if (0 == strcasecmp(level, JK_LOG_EMERG_VERB)) {
589         return JK_LOG_EMERG_LEVEL;
590     }
591
592     return JK_LOG_DEF_LEVEL;
593 }
594
595 int jk_open_file_logger(jk_logger_t **l, const char *file, int level)
596 {
597     if (l && file) {
598
599         jk_logger_t *rc = (jk_logger_t *)malloc(sizeof(jk_logger_t));
600         jk_file_logger_t *p = (jk_file_logger_t *) malloc(sizeof(jk_file_logger_t));
601         if (rc && p) {
602             rc->log = log_to_file;
603             rc->level = level;
604             rc->logger_private = p;
605 #if defined(AS400) && !defined(AS400_UTF8)
606             p->logfile = fopen(file, "a+, o_ccsid=0");
607 #elif defined(WIN32) && defined(_MSC_VER)
608             p->logfile = fopen(file, "a+c");
609 #else
610             p->logfile = fopen(file, "a+");
611 #endif
612             if (p->logfile) {
613                 *l = rc;
614                 jk_set_time_fmt(rc, NULL);
615                 return JK_TRUE;
616             }
617         }
618         if (rc) {
619             free(rc);
620         }
621         if (p) {
622             free(p);
623         }
624
625         *l = NULL;
626     }
627     return JK_FALSE;
628 }
629
630 int jk_attach_file_logger(jk_logger_t **l, int fd, int level)
631 {
632     if (l && fd >= 0) {
633
634         jk_logger_t *rc = (jk_logger_t *)malloc(sizeof(jk_logger_t));
635         jk_file_logger_t *p = (jk_file_logger_t *) malloc(sizeof(jk_file_logger_t));
636         if (rc && p) {
637             rc->log = log_to_file;
638             rc->level = level;
639             rc->logger_private = p;
640 #if defined(AS400) && !defined(AS400_UTF8)
641             p->logfile = fdopen(fd, "a+, o_ccsid=0");
642 #elif defined(WIN32) && defined(_MSC_VER)
643             p->logfile = fdopen(fd, "a+c");
644 #else
645             p->logfile = fdopen(fd, "a+");
646 #endif
647             if (p->logfile) {
648                 *l = rc;
649                 jk_set_time_fmt(rc, NULL);
650                 return JK_TRUE;
651             }
652         }
653         if (rc) {
654             free(rc);
655         }
656         if (p) {
657             free(p);
658         }
659
660         *l = NULL;
661     }
662     return JK_FALSE;
663 }
664
665 int jk_close_file_logger(jk_logger_t **l)
666 {
667     if (l && *l) {
668         jk_file_logger_t *p = (*l)->logger_private;
669         if (p) {
670             fflush(p->logfile);
671             fclose(p->logfile);
672             free(p);
673         }
674         free(*l);
675         *l = NULL;
676
677         return JK_TRUE;
678     }
679     return JK_FALSE;
680 }
681
682 int jk_log(jk_logger_t *l,
683            const char *file, int line, const char *funcname, int level,
684            const char *fmt, ...)
685 {
686     int rc = 0;
687     /*
688      * Need to reserve space for terminating zero byte
689      * and platform specific line endings added during the call
690      * to the output routing.
691      */
692     static int usable_size = HUGE_BUFFER_SIZE - 3;
693     if (!l || !file || !fmt) {
694         return -1;
695     }
696
697     if ((l->level <= level) || (level == JK_LOG_REQUEST_LEVEL)) {
698 #ifdef NETWARE
699         /* On NetWare, this can get called on a thread that has a limited stack so */
700         /* we will allocate and free the temporary buffer in this function         */
701         char *buf;
702 #else
703         char buf[HUGE_BUFFER_SIZE];
704 #endif
705         char *f = (char *)(file + strlen(file) - 1);
706         va_list args;
707         int used = 0;
708
709         while (f != file && '\\' != *f && '/' != *f) {
710             f--;
711         }
712         if (f != file) {
713             f++;
714         }
715
716 #ifdef NETWARE
717         buf = (char *)malloc(HUGE_BUFFER_SIZE);
718         if (NULL == buf)
719             return -1;
720 #endif
721         used = set_time_str(buf, usable_size, l);
722
723         if (line) { /* line==0 only used for request log item */
724             /* Log [pid:threadid] for all levels except REQUEST. */
725             /* This information helps to correlate lines from different logs. */
726             /* Performance is no issue, because with production log levels */
727             /* we only call it often, if we have a lot of errors */
728             rc = snprintf(buf + used, usable_size - used,
729                           "[%" JK_PID_T_FMT ":%" JK_PTHREAD_T_FMT "] ", getpid(), jk_gettid());
730             used += rc;
731             if (rc < 0 ) {
732                 return 0;
733             }
734
735             rc = (int)strlen(jk_level_verbs[level]);
736             if (usable_size - used >= rc) {
737                 strncpy(buf + used, jk_level_verbs[level], rc);
738                 used += rc;
739             }
740             else {
741                 return 0;           /* [V] not sure what to return... */
742             }
743
744             if (funcname) {
745                 rc = (int)strlen(funcname);
746                 if (usable_size - used >= rc + 2) {
747                     strncpy(buf + used, funcname, rc);
748                     used += rc;
749                     strncpy(buf + used, "::", 2);
750                     used += 2;
751                 }
752                 else {
753                     return 0;           /* [V] not sure what to return... */
754                 }
755             }
756
757             rc = (int)strlen(f);
758             if (usable_size - used >= rc) {
759                 strncpy(buf + used, f, rc);
760                 used += rc;
761             }
762             else {
763                 return 0;           /* [V] not sure what to return... */
764             }
765
766             rc = snprintf(buf + used, usable_size - used,
767                           " (%d): ", line);
768             used += rc;
769             if (rc < 0 || usable_size - used < 0) {
770                 return 0;           /* [V] not sure what to return... */
771             }
772         }
773
774         va_start(args, fmt);
775         rc = vsnprintf(buf + used, usable_size - used, fmt, args);
776         va_end(args);
777         if ( rc <= usable_size - used ) {
778             used += rc;
779         } else {
780             used = usable_size;
781         }
782         l->log(l, level, used, buf);
783
784 #ifdef NETWARE
785         free(buf);
786 #endif
787     }
788
789     return rc;
790 }
791
792 const char *jk_get_worker_type(jk_map_t *m, const char *wname)
793 {
794     char buf[1024];
795
796     if (!m || !wname) {
797         return NULL;
798     }
799     MAKE_WORKER_PARAM(TYPE_OF_WORKER);
800     return jk_map_get_string(m, buf, DEFAULT_WORKER_TYPE);
801 }
802
803 const char *jk_get_worker_route(jk_map_t *m, const char *wname, const char *def)
804 {
805     char buf[1024];
806     const char *v;
807     if (!m || !wname) {
808         return NULL;
809     }
810     MAKE_WORKER_PARAM(ROUTE_OF_WORKER);
811     v = jk_map_get_string(m, buf, NULL);
812     if (v) {
813         return v;
814     }
815     /* Try old jvm_route directive */
816     MAKE_WORKER_PARAM(JVM_ROUTE_OF_WORKER_DEPRECATED);
817     return jk_map_get_string(m, buf, def);
818 }
819
820 const char *jk_get_worker_domain(jk_map_t *m, const char *wname, const char *def)
821 {
822     char buf[1024];
823     if (!m || !wname) {
824         return NULL;
825     }
826     MAKE_WORKER_PARAM(DOMAIN_OF_WORKER);
827     return jk_map_get_string(m, buf, def);
828 }
829
830 const char *jk_get_worker_redirect(jk_map_t *m, const char *wname, const char *def)
831 {
832     char buf[1024];
833     if (!m || !wname) {
834         return NULL;
835     }
836     MAKE_WORKER_PARAM(REDIRECT_OF_WORKER);
837     return jk_map_get_string(m, buf, def);
838 }
839
840 const char *jk_get_worker_secret(jk_map_t *m, const char *wname)
841 {
842     char buf[1024];
843
844     if (!m || !wname) {
845         return NULL;
846     }
847
848     MAKE_WORKER_PARAM(SECRET_OF_WORKER);
849
850     return jk_map_get_string(m, buf, NULL);
851 }
852
853 /* [V] I suggest that the following general purpose functions be used.       */
854 /*     More should be added (double etc.), but now these were enough for me. */
855 /*     Functions that can be simulated with these should be "deprecated".    */
856
857 int jk_get_worker_str_prop(jk_map_t *m,
858                            const char *wname, const char *pname, const char **prop)
859 {
860     char buf[1024];
861
862     if (m && prop && wname && pname) {
863         MAKE_WORKER_PARAM(pname);
864         *prop = jk_map_get_string(m, buf, NULL);
865         if (*prop) {
866             return JK_TRUE;
867         }
868     }
869     return JK_FALSE;
870 }
871
872 int jk_get_worker_int_prop(jk_map_t *m,
873                            const char *wname, const char *pname, int *prop)
874 {
875     char buf[1024];
876
877     if (m && prop && wname && pname) {
878         int i;
879         MAKE_WORKER_PARAM(pname);
880         i = jk_map_get_int(m, buf, -1);
881         if (-1 != i) {
882             *prop = i;
883             return JK_TRUE;
884         }
885     }
886     return JK_FALSE;
887 }
888
889 const char *jk_get_worker_host(jk_map_t *m, const char *wname, const char *def)
890 {
891     char buf[1024];
892
893     if (!m || !wname) {
894         return NULL;
895     }
896
897     MAKE_WORKER_PARAM(HOST_OF_WORKER);
898
899     return jk_map_get_string(m, buf, def);
900 }
901
902 int jk_get_worker_port(jk_map_t *m, const char *wname, int def)
903 {
904     char buf[1024];
905
906     if (!m || !wname) {
907         return -1;
908     }
909
910     MAKE_WORKER_PARAM(PORT_OF_WORKER);
911
912     return jk_map_get_int(m, buf, def);
913 }
914
915 static int def_cache_size = -1;
916 int jk_get_worker_def_cache_size(int protocol)
917 {
918     if (def_cache_size < 1) {
919         if (protocol == AJP14_PROTO)
920             def_cache_size = AJP14_DEF_CACHE_SZ;
921         else
922             def_cache_size = AJP13_DEF_CACHE_SZ;
923     }
924     return def_cache_size;
925 }
926
927 void jk_set_worker_def_cache_size(int sz)
928 {
929     def_cache_size = sz;
930 }
931
932 int jk_get_worker_cache_size(jk_map_t *m, const char *wname, int def)
933 {
934     char buf[1024];
935     int rv;
936
937     if (!m || !wname) {
938         return -1;
939     }
940
941     MAKE_WORKER_PARAM(CACHE_OF_WORKER);
942     if ((rv = jk_map_get_int(m, buf, -1)) >= 0)
943         return rv;
944     MAKE_WORKER_PARAM(CACHE_OF_WORKER_DEPRECATED);
945     return jk_map_get_int(m, buf, def);
946 }
947
948 int jk_get_worker_cache_size_min(jk_map_t *m, const char *wname, int def)
949 {
950     char buf[1024];
951
952     if (!m || !wname) {
953         return -1;
954     }
955
956     MAKE_WORKER_PARAM(CACHE_OF_WORKER_MIN);
957     return jk_map_get_int(m, buf, def);
958 }
959
960 int jk_get_worker_cache_acquire_timeout(jk_map_t *m, const char *wname, int def)
961 {
962     char buf[1024];
963
964     if (!m || !wname) {
965         return -1;
966     }
967
968     MAKE_WORKER_PARAM(CACHE_ACQUIRE_OF_WORKER);
969     return jk_map_get_int(m, buf, def);
970 }
971
972 int jk_get_worker_socket_timeout(jk_map_t *m, const char *wname, int def)
973 {
974     char buf[1024];
975
976     if (!m || !wname) {
977         return -1;
978     }
979
980     MAKE_WORKER_PARAM(SOCKET_TIMEOUT_OF_WORKER);
981
982     return jk_map_get_int(m, buf, def);
983 }
984
985 int jk_get_worker_socket_connect_timeout(jk_map_t *m, const char *wname, int def)
986 {
987     char buf[1024];
988
989     if (!m || !wname) {
990         return -1;
991     }
992
993     MAKE_WORKER_PARAM(SOCKET_CONNECT_TIMEOUT_OF_WORKER);
994
995     return jk_map_get_int(m, buf, def);
996 }
997
998 int jk_get_worker_recover_timeout(jk_map_t *m, const char *wname, int def)
999 {
1000     char buf[1024];
1001
1002     if (!m || !wname) {
1003         return -1;
1004     }
1005
1006     MAKE_WORKER_PARAM(WORKER_RECOVER_TIME);
1007
1008     return jk_map_get_int(m, buf, def);
1009 }
1010
1011 int jk_get_worker_error_escalation_time(jk_map_t *m, const char *wname, int def)
1012 {
1013     char buf[1024];
1014
1015     if (!m || !wname) {
1016         return -1;
1017     }
1018
1019     MAKE_WORKER_PARAM(WORKER_ERROR_ESCALATION_TIME);
1020
1021     return jk_map_get_int(m, buf, def);
1022 }
1023
1024 int jk_get_worker_max_reply_timeouts(jk_map_t *m, const char *wname, int def)
1025 {
1026     char buf[1024];
1027
1028     if (!m || !wname) {
1029         return -1;
1030     }
1031
1032     MAKE_WORKER_PARAM(MAX_REPLY_TIMEOUTS_OF_WORKER);
1033
1034     return jk_map_get_int(m, buf, def);
1035 }
1036
1037 int jk_get_worker_retry_interval(jk_map_t *m, const char *wname, int def)
1038 {
1039     char buf[1024];
1040
1041     if (!m || !wname) {
1042         return -1;
1043     }
1044
1045     MAKE_WORKER_PARAM(RETRY_INTERVAL_OF_WORKER);
1046
1047     return jk_map_get_int(m, buf, def);
1048 }
1049
1050 int jk_get_worker_socket_buffer(jk_map_t *m, const char *wname, int def)
1051 {
1052     char buf[1024];
1053     int i;
1054     if (!m || !wname) {
1055         return -1;
1056     }
1057
1058     MAKE_WORKER_PARAM(SOCKET_BUFFER_OF_WORKER);
1059
1060     i = jk_map_get_int(m, buf, 0);
1061     if (i > 0 && i < def)
1062         i = def;
1063     return i;
1064 }
1065
1066 int jk_get_worker_socket_keepalive(jk_map_t *m, const char *wname, int def)
1067 {
1068     char buf[1024];
1069
1070     if (!m || !wname) {
1071         return -1;
1072     }
1073
1074     MAKE_WORKER_PARAM(SOCKET_KEEPALIVE_OF_WORKER);
1075
1076     return jk_map_get_bool(m, buf, def);
1077 }
1078
1079 int jk_get_worker_conn_ping_interval(jk_map_t *m, const char *wname, int def)
1080 {
1081     char buf[1024];
1082
1083     if (!m || !wname) {
1084         return -1;
1085     }
1086
1087     MAKE_WORKER_PARAM(CONN_PING_INTERVAL_OF_WORKER);
1088
1089     return jk_map_get_int(m, buf, def);
1090 }
1091
1092 int jk_get_worker_cache_timeout(jk_map_t *m, const char *wname, int def)
1093 {
1094     char buf[1024];
1095     int rv;
1096
1097     if (!m || !wname) {
1098         return -1;
1099     }
1100
1101     MAKE_WORKER_PARAM(CACHE_TIMEOUT_OF_WORKER);
1102     if ((rv = jk_map_get_int(m, buf, -1)) >= 0)
1103         return rv;
1104     MAKE_WORKER_PARAM(CACHE_TIMEOUT_DEPRECATED);
1105
1106     return jk_map_get_int(m, buf, def);
1107 }
1108
1109 int jk_get_worker_connect_timeout(jk_map_t *m, const char *wname, int def)
1110 {
1111     char buf[1024];
1112
1113     if (!m || !wname) {
1114         return -1;
1115     }
1116
1117     MAKE_WORKER_PARAM(CONNECT_TIMEOUT_OF_WORKER);
1118
1119     return jk_map_get_int(m, buf, def);
1120 }
1121
1122 int jk_get_worker_prepost_timeout(jk_map_t *m, const char *wname, int def)
1123 {
1124     char buf[1024];
1125
1126     if (!m || !wname) {
1127         return -1;
1128     }
1129
1130     MAKE_WORKER_PARAM(PREPOST_TIMEOUT_OF_WORKER);
1131
1132     return jk_map_get_int(m, buf, def);
1133 }
1134
1135 int jk_get_worker_ping_timeout(jk_map_t *m, const char *wname, int def)
1136 {
1137     char buf[1024];
1138
1139     if (!m || !wname) {
1140         return -1;
1141     }
1142
1143     MAKE_WORKER_PARAM(PING_TIMEOUT_OF_WORKER);
1144
1145     return jk_map_get_int(m, buf, def);
1146 }
1147
1148 int jk_get_worker_ping_mode(jk_map_t *m, const char *wname, int def)
1149 {
1150     char buf[1024];
1151     const char *v;
1152
1153     if (!m || !wname) {
1154         return def;
1155     }
1156
1157     MAKE_WORKER_PARAM(PING_MODE_OF_WORKER);
1158
1159     v = jk_map_get_string(m, buf, NULL);
1160     return jk_ajp_get_cping_mode(v, def);
1161 }
1162
1163 int jk_get_worker_reply_timeout(jk_map_t *m, const char *wname, int def)
1164 {
1165     char buf[1024];
1166
1167     if (!m || !wname) {
1168         return -1;
1169     }
1170
1171     MAKE_WORKER_PARAM(REPLY_TIMEOUT_OF_WORKER);
1172
1173     return jk_map_get_int(m, buf, def);
1174 }
1175
1176 int jk_get_worker_recycle_timeout(jk_map_t *m, const char *wname, int def)
1177 {
1178     return def;
1179 }
1180
1181 int jk_get_worker_retries(jk_map_t *m, const char *wname, int def)
1182 {
1183     char buf[1024];
1184     int rv;
1185     if (!m || !wname) {
1186         return -1;
1187     }
1188
1189     MAKE_WORKER_PARAM(RETRIES_OF_WORKER);
1190
1191     rv = jk_map_get_int(m, buf, def);
1192     if (rv < 1)
1193         rv = 1;
1194
1195     return rv;
1196 }
1197
1198 int jk_get_worker_recovery_opts(jk_map_t *m, const char *wname, int def)
1199 {
1200     char buf[1024];
1201
1202     if (!m || !wname) {
1203         return -1;
1204     }
1205
1206     MAKE_WORKER_PARAM(RECOVERY_OPTS_OF_WORKER);
1207
1208     return jk_map_get_int(m, buf, def);
1209 }
1210
1211 const char *jk_get_worker_secret_key(jk_map_t *m, const char *wname)
1212 {
1213     char buf[1024];
1214
1215     if (!m || !wname) {
1216         return NULL;
1217     }
1218
1219     MAKE_WORKER_PARAM(SECRET_KEY_OF_WORKER);
1220     return jk_map_get_string(m, buf, NULL);
1221 }
1222
1223 int jk_get_worker_list(jk_map_t *m, char ***list, unsigned *num_of_workers)
1224 {
1225     if (m && list && num_of_workers) {
1226         char **ar = jk_map_get_string_list(m,
1227                                         WORKER_LIST_PROPERTY_NAME,
1228                                         num_of_workers,
1229                                         DEFAULT_WORKER);
1230         if (ar) {
1231             *list = ar;
1232             return JK_TRUE;
1233         }
1234         *list = NULL;
1235         *num_of_workers = 0;
1236     }
1237
1238     return JK_FALSE;
1239 }
1240
1241 int jk_get_is_worker_disabled(jk_map_t *m, const char *wname)
1242 {
1243     int rc = JK_TRUE;
1244     char buf[1024];
1245     if (m && wname) {
1246         int value;
1247         MAKE_WORKER_PARAM(IS_WORKER_DISABLED_DEPRECATED);
1248         value = jk_map_get_bool(m, buf, 0);
1249         if (!value)
1250             rc = JK_FALSE;
1251     }
1252     return rc;
1253 }
1254
1255 int jk_get_is_worker_stopped(jk_map_t *m, const char *wname)
1256 {
1257     int rc = JK_TRUE;
1258     char buf[1024];
1259     if (m && wname) {
1260         int value;
1261         MAKE_WORKER_PARAM(IS_WORKER_STOPPED_DEPRECATED);
1262         value = jk_map_get_bool(m, buf, 0);
1263         if (!value)
1264             rc = JK_FALSE;
1265     }
1266     return rc;
1267 }
1268
1269 int jk_get_worker_activation(jk_map_t *m, const char *wname)
1270 {
1271     char buf[1024];
1272     const char *v;
1273     if (!m || !wname) {
1274         return JK_LB_ACTIVATION_ACTIVE;
1275     }
1276
1277     MAKE_WORKER_PARAM(ACTIVATION_OF_WORKER);
1278     v = jk_map_get_string(m, buf, NULL);
1279     if (v) {
1280         return jk_lb_get_activation_code(v);
1281     }
1282     else if (jk_get_is_worker_stopped(m, wname))
1283         return JK_LB_ACTIVATION_STOPPED;
1284     else if (jk_get_is_worker_disabled(m, wname))
1285         return JK_LB_ACTIVATION_DISABLED;
1286     else
1287         return JK_LB_ACTIVATION_DEF;
1288 }
1289
1290 int jk_get_lb_factor(jk_map_t *m, const char *wname)
1291 {
1292     char buf[1024];
1293
1294     if (!m || !wname) {
1295         return DEFAULT_LB_FACTOR;
1296     }
1297
1298     MAKE_WORKER_PARAM(LOAD_FACTOR_OF_WORKER);
1299
1300     return jk_map_get_int(m, buf, DEFAULT_LB_FACTOR);
1301 }
1302
1303 int jk_get_distance(jk_map_t *m, const char *wname)
1304 {
1305     char buf[1024];
1306
1307     if (!m || !wname) {
1308         return DEFAULT_DISTANCE;
1309     }
1310
1311     MAKE_WORKER_PARAM(DISTANCE_OF_WORKER);
1312
1313     return jk_map_get_int(m, buf, DEFAULT_DISTANCE);
1314 }
1315
1316 int jk_get_is_sticky_session(jk_map_t *m, const char *wname)
1317 {
1318     int rc = JK_TRUE;
1319     char buf[1024];
1320     if (m && wname) {
1321         int value;
1322         MAKE_WORKER_PARAM(STICKY_SESSION);
1323         value = jk_map_get_bool(m, buf, 1);
1324         if (!value)
1325             rc = JK_FALSE;
1326     }
1327     return rc;
1328 }
1329
1330 int jk_get_is_sticky_session_force(jk_map_t *m, const char *wname)
1331 {
1332     int rc = JK_FALSE;
1333     char buf[1024];
1334     if (m && wname) {
1335         int value;
1336         MAKE_WORKER_PARAM(STICKY_SESSION_FORCE);
1337         value = jk_map_get_bool(m, buf, 0);
1338         if (value)
1339             rc = JK_TRUE;
1340     }
1341     return rc;
1342 }
1343
1344 int jk_get_lb_method(jk_map_t *m, const char *wname)
1345 {
1346     char buf[1024];
1347     const char *v;
1348     if (!m || !wname) {
1349         return JK_LB_METHOD_DEF;
1350     }
1351
1352     MAKE_WORKER_PARAM(METHOD_OF_WORKER);
1353     v = jk_map_get_string(m, buf, NULL);
1354     return jk_lb_get_method_code(v);
1355 }
1356
1357 int jk_get_lb_lock(jk_map_t *m, const char *wname)
1358 {
1359     char buf[1024];
1360     const char *v;
1361     if (!m || !wname) {
1362         return JK_LB_LOCK_DEF;
1363     }
1364
1365     MAKE_WORKER_PARAM(LOCK_OF_WORKER);
1366     v = jk_map_get_string(m, buf, NULL);
1367     return jk_lb_get_lock_code(v);
1368 }
1369
1370 int jk_get_max_packet_size(jk_map_t *m, const char *wname)
1371 {
1372     char buf[1024];
1373     int sz;
1374
1375     if (!m || !wname) {
1376         return DEF_BUFFER_SZ;
1377     }
1378
1379     MAKE_WORKER_PARAM(WORKER_MAX_PACKET_SIZE);
1380     sz = jk_map_get_int(m, buf, DEF_BUFFER_SZ);
1381     sz = JK_ALIGN(sz, 1024);
1382     if (sz < DEF_BUFFER_SZ)
1383         sz = DEF_BUFFER_SZ;
1384     else if (sz > 64*1024)
1385         sz = 64*1024;
1386
1387     return sz;
1388 }
1389
1390 int jk_get_worker_fail_on_status(jk_map_t *m, const char *wname,
1391                                  int *list, unsigned int list_size)
1392 {
1393     char buf[1024];
1394     if (!m || !wname || !list) {
1395         return 0;
1396     }
1397     MAKE_WORKER_PARAM(STATUS_FAIL_OF_WORKER);
1398     if (list_size) {
1399         return jk_map_get_int_list(m, buf,
1400                                    list, list_size,
1401                                    NULL);
1402     }
1403
1404     return 0;
1405 }
1406
1407 int jk_get_worker_user_case_insensitive(jk_map_t *m, const char *wname)
1408 {
1409     int rc = JK_FALSE;
1410     char buf[1024];
1411     if (m && wname) {
1412         int value;
1413         MAKE_WORKER_PARAM(USER_CASE_OF_WORKER);
1414         value = jk_map_get_bool(m, buf, 0);
1415         if (value)
1416             rc = JK_TRUE;
1417     }
1418     return rc;
1419
1420 }
1421
1422 const char *jk_get_worker_style_sheet(jk_map_t *m, const char *wname, const char *def)
1423 {
1424     char buf[1024];
1425
1426     if (!m || !wname) {
1427         return NULL;
1428     }
1429
1430     MAKE_WORKER_PARAM(STYLE_SHEET_OF_WORKER);
1431
1432     return jk_map_get_string(m, buf, def);
1433 }
1434
1435 const char *jk_get_worker_name_space(jk_map_t *m, const char *wname, const char *def)
1436 {
1437     const char *rc;
1438     char buf[1024];
1439     if (!m || !wname) {
1440         return NULL;
1441     }
1442     MAKE_WORKER_PARAM(NAMESPACE_OF_WORKER);
1443     rc = jk_map_get_string(m, buf, def);
1444     if (*rc == '-')
1445         return "";
1446     else
1447         return rc;
1448 }
1449
1450 const char *jk_get_worker_xmlns(jk_map_t *m, const char *wname, const char *def)
1451 {
1452     const char *rc;
1453     char buf[1024];
1454     if (!m || !wname) {
1455         return NULL;
1456     }
1457     MAKE_WORKER_PARAM(XML_NAMESPACE_OF_WORKER);
1458     rc = jk_map_get_string(m, buf, def);
1459     if (*rc == '-')
1460         return "";
1461     else
1462         return rc;
1463 }
1464
1465 const char *jk_get_worker_xml_doctype(jk_map_t *m, const char *wname, const char *def)
1466 {
1467     char buf[1024];
1468     if (!m || !wname) {
1469         return NULL;
1470     }
1471     MAKE_WORKER_PARAM(XML_DOCTYPE_OF_WORKER);
1472     return jk_map_get_string(m, buf, def);
1473 }
1474
1475 const char *jk_get_worker_prop_prefix(jk_map_t *m, const char *wname, const char *def)
1476 {
1477     char buf[1024];
1478     if (!m || !wname) {
1479         return NULL;
1480     }
1481     MAKE_WORKER_PARAM(PROP_PREFIX_OF_WORKER);
1482     return jk_map_get_string(m, buf, def);
1483 }
1484
1485 int jk_get_is_read_only(jk_map_t *m, const char *wname)
1486 {
1487     int rc = JK_FALSE;
1488     char buf[1024];
1489     if (m && wname) {
1490         int value;
1491         MAKE_WORKER_PARAM(READ_ONLY_OF_WORKER);
1492         value = jk_map_get_bool(m, buf, 0);
1493         if (value)
1494             rc = JK_TRUE;
1495     }
1496     return rc;
1497 }
1498
1499 int jk_get_worker_user_list(jk_map_t *m,
1500                             const char *wname,
1501                             char ***list, unsigned int *num)
1502 {
1503     char buf[1024];
1504
1505     if (m && list && num && wname) {
1506         char **ar = NULL;
1507
1508         MAKE_WORKER_PARAM(USER_OF_WORKER);
1509         ar = jk_map_get_string_list(m, buf, num, NULL);
1510         if (ar) {
1511             *list = ar;
1512             return JK_TRUE;
1513         }
1514         *list = NULL;
1515         *num = 0;
1516     }
1517
1518     return JK_FALSE;
1519 }
1520
1521 int jk_get_worker_good_rating(jk_map_t *m,
1522                               const char *wname,
1523                               char ***list, unsigned int *num)
1524 {
1525     char buf[1024];
1526
1527     if (m && list && num && wname) {
1528         char **ar = NULL;
1529
1530         MAKE_WORKER_PARAM(GOOD_RATING_OF_WORKER);
1531         ar = jk_map_get_string_list(m, buf, num, NULL);
1532         if (ar) {
1533             *list = ar;
1534             return JK_TRUE;
1535         }
1536         *list = NULL;
1537         *num = 0;
1538     }
1539
1540     return JK_FALSE;
1541 }
1542
1543 int jk_get_worker_bad_rating(jk_map_t *m,
1544                              const char *wname,
1545                              char ***list, unsigned int *num)
1546 {
1547     char buf[1024];
1548
1549     if (m && list && num && wname) {
1550         char **ar = NULL;
1551
1552         MAKE_WORKER_PARAM(BAD_RATING_OF_WORKER);
1553         ar = jk_map_get_string_list(m, buf, num, NULL);
1554         if (ar) {
1555             *list = ar;
1556             return JK_TRUE;
1557         }
1558         *list = NULL;
1559         *num = 0;
1560     }
1561
1562     return JK_FALSE;
1563 }
1564
1565 int jk_get_lb_worker_list(jk_map_t *m,
1566                           const char *wname,
1567                           char ***list, unsigned int *num_of_workers)
1568 {
1569     char buf[1024];
1570
1571     if (m && list && num_of_workers && wname) {
1572         char **ar = NULL;
1573
1574         MAKE_WORKER_PARAM(BALANCE_WORKERS);
1575         ar = jk_map_get_string_list(m, buf, num_of_workers, NULL);
1576         if (ar) {
1577             *list = ar;
1578             return JK_TRUE;
1579         }
1580         /* Try old balanced_workers directive */
1581         MAKE_WORKER_PARAM(BALANCED_WORKERS_DEPRECATED);
1582         ar = jk_map_get_string_list(m, buf, num_of_workers, NULL);
1583         if (ar) {
1584             *list = ar;
1585             return JK_TRUE;
1586         }
1587         *list = NULL;
1588         *num_of_workers = 0;
1589     }
1590
1591     return JK_FALSE;
1592 }
1593
1594 int jk_get_worker_mount_list(jk_map_t *m,
1595                              const char *wname,
1596                              char ***list, unsigned int *num_of_maps)
1597 {
1598     char buf[1024];
1599
1600     if (m && list && num_of_maps && wname) {
1601         char **ar = NULL;
1602
1603         MAKE_WORKER_PARAM(MOUNT_OF_WORKER);
1604         ar = jk_map_get_string_list(m, buf, num_of_maps, NULL);
1605         if (ar) {
1606             *list = ar;
1607             return JK_TRUE;
1608         }
1609         *list = NULL;
1610         *num_of_maps = 0;
1611     }
1612
1613     return JK_FALSE;
1614 }
1615
1616 int jk_get_worker_maintain_time(jk_map_t *m)
1617 {
1618     return jk_map_get_int(m, WORKER_MAINTAIN_PROPERTY_NAME,
1619                           DEFAULT_MAINTAIN_TIME);
1620 }
1621
1622 int jk_get_worker_mx(jk_map_t *m, const char *wname, unsigned *mx)
1623 {
1624     char buf[1024];
1625
1626     if (m && mx && wname) {
1627         int i;
1628         MAKE_WORKER_PARAM(MX_OF_WORKER);
1629
1630         i = jk_map_get_int(m, buf, -1);
1631         if (-1 != i) {
1632             *mx = (unsigned)i;
1633             return JK_TRUE;
1634         }
1635     }
1636
1637     return JK_FALSE;
1638 }
1639
1640 int jk_get_worker_ms(jk_map_t *m, const char *wname, unsigned *ms)
1641 {
1642     char buf[1024];
1643
1644     if (m && ms && wname) {
1645         int i;
1646         MAKE_WORKER_PARAM(MS_OF_WORKER);
1647
1648         i = jk_map_get_int(m, buf, -1);
1649         if (-1 != i) {
1650             *ms = (unsigned)i;
1651             return JK_TRUE;
1652         }
1653     }
1654
1655     return JK_FALSE;
1656 }
1657
1658 int jk_get_worker_classpath(jk_map_t *m, const char *wname, const char **cp)
1659 {
1660     char buf[1024];
1661
1662     if (m && cp && wname) {
1663         MAKE_WORKER_PARAM(CP_OF_WORKER);
1664
1665         *cp = jk_map_get_string(m, buf, NULL);
1666         if (*cp) {
1667             return JK_TRUE;
1668         }
1669     }
1670
1671     return JK_FALSE;
1672 }
1673
1674 int jk_get_worker_bridge_type(jk_map_t *m, const char *wname, unsigned *bt)
1675 {
1676     char buf[1024];
1677     const char *type;
1678
1679     if (m && bt && wname) {
1680         MAKE_WORKER_PARAM(BRIDGE_OF_WORKER);
1681
1682         type = jk_map_get_string(m, buf, NULL);
1683
1684         if (type) {
1685             if (!strcasecmp(type, TOMCAT32_BRIDGE_NAME))
1686                 *bt = TC32_BRIDGE_TYPE;
1687             else if (!strcasecmp(type, TOMCAT33_BRIDGE_NAME))
1688                 *bt = TC33_BRIDGE_TYPE;
1689             else if (!strcasecmp(type, TOMCAT40_BRIDGE_NAME))
1690                 *bt = TC40_BRIDGE_TYPE;
1691             else if (!strcasecmp(type, TOMCAT41_BRIDGE_NAME))
1692                 *bt = TC41_BRIDGE_TYPE;
1693             else if (!strcasecmp(type, TOMCAT50_BRIDGE_NAME))
1694                 *bt = TC50_BRIDGE_TYPE;
1695
1696             return JK_TRUE;
1697         }
1698     }
1699
1700     return JK_FALSE;
1701 }
1702
1703 int jk_get_worker_jvm_path(jk_map_t *m, const char *wname, const char **vm_path)
1704 {
1705     char buf[1024];
1706
1707     if (m && vm_path && wname) {
1708         MAKE_WORKER_PARAM(JVM_OF_WORKER);
1709
1710         *vm_path = jk_map_get_string(m, buf, NULL);
1711         if (*vm_path) {
1712             return JK_TRUE;
1713         }
1714     }
1715
1716     return JK_FALSE;
1717 }
1718
1719 /* [V] This is unused. currently. */
1720 int jk_get_worker_callback_dll(jk_map_t *m, const char *wname, const char **cb_path)
1721 {
1722     char buf[1024];
1723
1724     if (m && cb_path && wname) {
1725         MAKE_WORKER_PARAM(NATIVE_LIB_OF_WORKER);
1726
1727         *cb_path = jk_map_get_string(m, buf, NULL);
1728         if (*cb_path) {
1729             return JK_TRUE;
1730         }
1731     }
1732
1733     return JK_FALSE;
1734 }
1735
1736 int jk_get_worker_cmd_line(jk_map_t *m, const char *wname, const char **cmd_line)
1737 {
1738     char buf[1024];
1739
1740     if (m && cmd_line && wname) {
1741         MAKE_WORKER_PARAM(CMD_LINE_OF_WORKER);
1742
1743         *cmd_line = jk_map_get_string(m, buf, NULL);
1744         if (*cmd_line) {
1745             return JK_TRUE;
1746         }
1747     }
1748
1749     return JK_FALSE;
1750 }
1751
1752
1753 int jk_stat(const char *f, struct stat * statbuf)
1754 {
1755   int rc;
1756 /**
1757  * i5/OS V5R4 expect filename in ASCII for fopen but required them in EBCDIC for stat()
1758  */
1759 #ifdef AS400_UTF8
1760   char *ptr;
1761
1762   ptr = (char *)malloc(strlen(f) + 1);
1763   jk_ascii2ebcdic((char *)f, ptr);
1764   rc = stat(ptr, statbuf);
1765   free(ptr);
1766 #else
1767   rc = stat(f, statbuf);
1768 #endif
1769
1770   return (rc);
1771 }
1772
1773
1774 int jk_file_exists(const char *f)
1775 {
1776     if (f) {
1777         struct stat st;
1778
1779         if ((0 == jk_stat(f, &st)) && (st.st_mode & S_IFREG))
1780       return JK_TRUE;
1781     }
1782
1783     return JK_FALSE;
1784 }
1785
1786 static int jk_is_some_property(const char *prp_name, const char *suffix, const char *sep)
1787 {
1788     char buf[1024];
1789
1790     if (prp_name && suffix) {
1791         size_t prp_name_len;
1792         size_t suffix_len;
1793         strcpy(buf, sep);
1794         strcat(buf, suffix);
1795         prp_name_len = strlen(prp_name);
1796         suffix_len = strlen(buf);
1797         if (prp_name_len >= suffix_len) {
1798             const char *prp_suffix = prp_name + prp_name_len - suffix_len;
1799             if (0 == strcmp(buf, prp_suffix)) {
1800                 return JK_TRUE;
1801             }
1802         }
1803     }
1804
1805     return JK_FALSE;
1806 }
1807
1808 int jk_is_path_property(const char *prp_name)
1809 {
1810     return jk_is_some_property(prp_name, "path", "_");
1811 }
1812
1813 int jk_is_cmd_line_property(const char *prp_name)
1814 {
1815     return jk_is_some_property(prp_name, CMD_LINE_OF_WORKER, ".");
1816 }
1817
1818 int jk_is_list_property(const char *prp_name)
1819 {
1820     const char **props = &list_properties[0];
1821     while (*props) {
1822         if (jk_is_some_property(prp_name, *props, "."))
1823             return JK_TRUE;
1824         props++;
1825     }
1826     return JK_FALSE;
1827 }
1828
1829 int jk_is_unique_property(const char *prp_name)
1830 {
1831     const char **props = &unique_properties[0];
1832     while (*props) {
1833         if (jk_is_some_property(prp_name, *props, "."))
1834             return JK_TRUE;
1835         props++;
1836     }
1837     return JK_FALSE;
1838 }
1839
1840 int jk_is_deprecated_property(const char *prp_name)
1841 {
1842     const char **props = &deprecated_properties[0];
1843     while (*props) {
1844         if (jk_is_some_property(prp_name, *props, "."))
1845             return JK_TRUE;
1846         props++;
1847     }
1848     return JK_FALSE;
1849 }
1850 /*
1851  * Check that property is a valid one (to prevent user typos).
1852  * Only property starting with worker.
1853  */
1854 int jk_is_valid_property(const char *prp_name)
1855 {
1856     const char **props;
1857     if (memcmp(prp_name, "worker.", 7))
1858         return JK_TRUE;
1859
1860     props = &supported_properties[0];
1861     while (*props) {
1862         if (jk_is_some_property(prp_name, *props, "."))
1863             return JK_TRUE;
1864         props++;
1865     }
1866     return JK_FALSE;
1867 }
1868
1869 int jk_get_worker_stdout(jk_map_t *m, const char *wname, const char **stdout_name)
1870 {
1871     char buf[1024];
1872
1873     if (m && stdout_name && wname) {
1874         MAKE_WORKER_PARAM(STDOUT_OF_WORKER);
1875
1876         *stdout_name = jk_map_get_string(m, buf, NULL);
1877         if (*stdout_name) {
1878             return JK_TRUE;
1879         }
1880     }
1881
1882     return JK_FALSE;
1883 }
1884
1885 int jk_get_worker_stderr(jk_map_t *m, const char *wname, const char **stderr_name)
1886 {
1887     char buf[1024];
1888
1889     if (m && stderr_name && wname) {
1890         MAKE_WORKER_PARAM(STDERR_OF_WORKER);
1891
1892         *stderr_name = jk_map_get_string(m, buf, NULL);
1893         if (*stderr_name) {
1894             return JK_TRUE;
1895         }
1896     }
1897
1898     return JK_FALSE;
1899 }
1900
1901 int jk_get_worker_sysprops(jk_map_t *m, const char *wname, const char **sysprops)
1902 {
1903     char buf[1024];
1904
1905     if (m && sysprops && wname) {
1906         MAKE_WORKER_PARAM(SYSPROPS_OF_WORKER);
1907
1908         *sysprops = jk_map_get_string(m, buf, NULL);
1909         if (*sysprops) {
1910             return JK_TRUE;
1911         }
1912     }
1913
1914     return JK_FALSE;
1915 }
1916
1917 int jk_get_worker_libpath(jk_map_t *m, const char *wname, const char **libpath)
1918 {
1919     char buf[1024];
1920
1921     if (m && libpath && wname) {
1922         MAKE_WORKER_PARAM(LIBPATH_OF_WORKER);
1923
1924         *libpath = jk_map_get_string(m, buf, NULL);
1925         if (*libpath) {
1926             return JK_TRUE;
1927         }
1928     }
1929
1930     return JK_FALSE;
1931 }
1932
1933 const char *jk_get_lb_session_cookie(jk_map_t *m, const char *wname, const char *def)
1934 {
1935     char buf[1024];
1936     if (!m || !wname) {
1937         return NULL;
1938     }
1939     MAKE_WORKER_PARAM(SESSION_COOKIE_OF_WORKER);
1940     return jk_map_get_string(m, buf, def);
1941 }
1942
1943 const char *jk_get_lb_session_path(jk_map_t *m, const char *wname, const char *def)
1944 {
1945     char buf[1024];
1946     if (!m || !wname) {
1947         return NULL;
1948     }
1949     MAKE_WORKER_PARAM(SESSION_PATH_OF_WORKER);
1950     return jk_map_get_string(m, buf, def);
1951 }
1952
1953
1954 int is_http_status_fail(unsigned int http_status_fail_num,
1955                         int *http_status_fail, int status)
1956 {
1957     unsigned int i;
1958     int soft_status = -1 * status;
1959     for (i = 0; i < http_status_fail_num; i++) {
1960         if (http_status_fail[i] == status)
1961             return 1;
1962         else if (http_status_fail[i] == soft_status)
1963             return -1;
1964     }
1965     return 0;
1966 }
1967
1968 char **jk_parse_sysprops(jk_pool_t *p, const char *sysprops)
1969 {
1970     char **rc = NULL;
1971 #ifdef _MT_CODE_PTHREAD
1972     char *lasts;
1973 #endif
1974
1975     if (p && sysprops) {
1976         char *prps = jk_pool_strdup(p, sysprops);
1977         if (prps && strlen(prps)) {
1978             unsigned num_of_prps;
1979
1980             for (num_of_prps = 1; *sysprops; sysprops++) {
1981                 if ('*' == *sysprops) {
1982                     num_of_prps++;
1983                 }
1984             }
1985
1986             rc = jk_pool_alloc(p, (num_of_prps + 1) * sizeof(char *));
1987             if (rc) {
1988                 unsigned i = 0;
1989 #ifdef _MT_CODE_PTHREAD
1990                 char *tmp = strtok_r(prps, "*", &lasts);
1991 #else
1992                 char *tmp = strtok(prps, "*");
1993 #endif
1994
1995                 while (tmp && i < num_of_prps) {
1996                     rc[i] = tmp;
1997 #ifdef _MT_CODE_PTHREAD
1998                     tmp = strtok_r(NULL, "*", &lasts);
1999 #else
2000                     tmp = strtok(NULL, "*");
2001 #endif
2002                     i++;
2003                 }
2004                 rc[i] = NULL;
2005             }
2006         }
2007     }
2008
2009     return rc;
2010 }
2011
2012 void jk_append_libpath(jk_pool_t *p, const char *libpath)
2013 {
2014     char *env = NULL;
2015     char *current = getenv(PATH_ENV_VARIABLE);
2016
2017     if (current) {
2018         env = jk_pool_alloc(p, strlen(PATH_ENV_VARIABLE) +
2019                             strlen(current) + strlen(libpath) + 5);
2020         if (env) {
2021             sprintf(env, "%s=%s%c%s",
2022                     PATH_ENV_VARIABLE, libpath, PATH_SEPERATOR, current);
2023         }
2024     }
2025     else {
2026         env = jk_pool_alloc(p, strlen(PATH_ENV_VARIABLE) +
2027                             strlen(libpath) + 5);
2028         if (env) {
2029             sprintf(env, "%s=%s", PATH_ENV_VARIABLE, libpath);
2030         }
2031     }
2032
2033     if (env) {
2034         putenv(env);
2035     }
2036 }
2037
2038 void jk_init_ws_service(jk_ws_service_t *s)
2039 {
2040     s->ws_private = NULL;
2041     s->pool = NULL;
2042     s->method = NULL;
2043     s->protocol = NULL;
2044     s->req_uri = NULL;
2045     s->remote_addr = NULL;
2046     s->remote_port = NULL;
2047     s->remote_host = NULL;
2048     s->remote_user = NULL;
2049     s->auth_type = NULL;
2050     s->query_string = NULL;
2051     s->server_name = NULL;
2052     s->server_port = 80;
2053     s->server_software = NULL;
2054     s->content_length = 0;
2055     s->is_chunked = 0;
2056     s->no_more_chunks = 0;
2057     s->content_read = 0;
2058     s->is_ssl = JK_FALSE;
2059     s->ssl_cert = NULL;
2060     s->ssl_cert_len = 0;
2061     s->ssl_cipher = NULL;
2062     s->ssl_session = NULL;
2063     s->ssl_key_size = -1;
2064     s->headers_names = NULL;
2065     s->headers_values = NULL;
2066     s->num_headers = 0;
2067     s->attributes_names = NULL;
2068     s->attributes_values = NULL;
2069     s->num_attributes = 0;
2070     s->route = NULL;
2071     s->activation = JK_LB_ACTIVATION_ACTIVE;
2072     s->secret = NULL;
2073     s->reco_buf = NULL;
2074     s->reco_status = RECO_NONE;
2075     s->flush_packets = JK_FALSE;
2076     s->flush_header = JK_FALSE;
2077     s->extension.reply_timeout = -1;
2078     s->extension.use_server_error_pages = 0;
2079     s->extension.activation = NULL;
2080     s->extension.fail_on_status_size = 0;
2081     s->extension.fail_on_status = NULL;
2082     s->response_started = JK_FALSE;
2083     s->response_blocked = JK_FALSE;
2084     s->http_response_status = JK_HTTP_OK;
2085     s->uw_map = NULL;
2086     s->start_response = NULL;
2087     s->read = NULL;
2088     s->write = NULL;
2089     s->flush = NULL;
2090     s->done = NULL;
2091     s->disable_reuse = JK_FALSE;
2092     s->add_log_items = NULL;
2093     s->next_vhost = NULL;
2094     s->vhost_to_text = NULL;
2095     s->vhost_to_uw_map = NULL;
2096 }
2097
2098 /* Match = 0, NoMatch = 1, Abort = -1
2099  * Based loosely on sections of wildmat.c by Rich Salz
2100  */
2101 int jk_wildchar_match(const char *str, const char *exp, int icase)
2102 {
2103     int x, y;
2104
2105     for (x = 0, y = 0; exp[y]; ++y, ++x) {
2106         if (!str[x] && exp[y] != '*')
2107             return -1;
2108         if (exp[y] == '*') {
2109             while (exp[++y] == '*');
2110             if (!exp[y])
2111                 return 0;
2112             while (str[x]) {
2113                 int ret;
2114                 if ((ret = jk_wildchar_match(&str[x++], &exp[y], icase)) != 1)
2115                     return ret;
2116             }
2117             return -1;
2118         }
2119         else if (exp[y] != '?') {
2120             if (icase && (tolower(str[x]) != tolower(exp[y])))
2121                 return 1;
2122             else if (!icase && str[x] != exp[y])
2123                 return 1;
2124         }
2125     }
2126     return (str[x] != '\0');
2127 }
2128
2129 #ifdef _MT_CODE_PTHREAD
2130 jk_pthread_t jk_gettid()
2131 {
2132     union {
2133         pthread_t tid;
2134         jk_uint64_t alignme;
2135     } u;
2136 #ifdef AS400
2137     /* OS400 use 64 bits ThreadId */
2138     pthread_id_np_t       tid;
2139 #endif /* AS400 */
2140     u.tid = pthread_self();
2141 #ifdef AS400
2142     /* Get only low 32 bits for now */
2143     pthread_getunique_np(&(u.tid), &tid);
2144     return ((jk_uint32_t)(tid.intId.lo & 0xFFFFFFFF));
2145 #else
2146     return ((jk_pthread_t)u.tid);
2147 #endif /* AS400 */
2148 }
2149 #endif
2150
2151 /***
2152  * ASCII <-> EBCDIC conversions
2153  *
2154  * For now usefull only in i5/OS V5R4 where UTF and EBCDIC mode are mixed
2155  */
2156
2157 #ifdef AS400_UTF8
2158
2159 /* EBCDIC to ASCII translation table */
2160 static u_char ebcdic_to_ascii[256] =
2161 {
2162   0x00,0x01,0x02,0x03,0x20,0x09,0x20,0x7f, /* 00-07 */
2163   0x20,0x20,0x20,0x0b,0x0c,0x0d,0x0e,0x0f, /* 08-0f */
2164   0x10,0x11,0x12,0x13,0x20,0x0a,0x08,0x20, /* 10-17 */
2165   0x18,0x19,0x20,0x20,0x20,0x1d,0x1e,0x1f, /* 18-1f */
2166   0x20,0x20,0x1c,0x20,0x20,0x0a,0x17,0x1b, /* 20-27 */
2167   0x20,0x20,0x20,0x20,0x20,0x05,0x06,0x07, /* 28-2f */
2168   0x20,0x20,0x16,0x20,0x20,0x20,0x20,0x04, /* 30-37 */
2169   0x20,0x20,0x20,0x20,0x14,0x15,0x20,0x1a, /* 38-3f */
2170   0x20,0x20,0x83,0x84,0x85,0xa0,0xc6,0x86, /* 40-47 */
2171   0x87,0xa4,0xbd,0x2e,0x3c,0x28,0x2b,0x7c, /* 48-4f */
2172   0x26,0x82,0x88,0x89,0x8a,0xa1,0x8c,0x8b, /* 50-57 */
2173   0x8d,0xe1,0x21,0x24,0x2a,0x29,0x3b,0xaa, /* 58-5f */
2174   0x2d,0x2f,0xb6,0x8e,0xb7,0xb5,0xc7,0x8f, /* 60-67 */
2175   0x80,0xa5,0xdd,0x2c,0x25,0x5f,0x3e,0x3f, /* 68-6f */
2176   0x9b,0x90,0xd2,0xd3,0xd4,0xd6,0xd7,0xd8, /* 70-77 */
2177   0xde,0x60,0x3a,0x23,0x40,0x27,0x3d,0x22, /* 78-7f */
2178   0x9d,0x61,0x62,0x63,0x64,0x65,0x66,0x67, /* 80-87 */
2179   0x68,0x69,0xae,0xaf,0xd0,0xec,0xe7,0xf1, /* 88-8f */
2180   0xf8,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70, /* 90-97 */
2181   0x71,0x72,0xa6,0xa7,0x91,0xf7,0x92,0xcf, /* 98-9f */
2182   0xe6,0x7e,0x73,0x74,0x75,0x76,0x77,0x78, /* a8-a7 */
2183   0x79,0x7a,0xad,0xa8,0xd1,0xed,0xe8,0xa9, /* a8-af */
2184   0x5e,0x9c,0xbe,0xfa,0xb8,0x15,0x14,0xac, /* b0-b7 */
2185   0xab,0xf3,0x5b,0x5d,0xee,0xf9,0xef,0x9e, /* b8-bf */
2186   0x7b,0x41,0x42,0x43,0x44,0x45,0x46,0x47, /* c0-c7 */
2187   0x48,0x49,0xf0,0x93,0x94,0x95,0xa2,0xe4, /* c8-cf */
2188   0x7d,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50, /* d0-d7 */
2189   0x51,0x52,0xfb,0x96,0x81,0x97,0xa3,0x98, /* d8-df */
2190   0x5c,0xf6,0x53,0x54,0x55,0x56,0x57,0x58, /* e0-e7 */
2191   0x59,0x5a,0xfc,0xe2,0x99,0xe3,0xe0,0xe5, /* e8-ef */
2192   0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, /* f0-f7 */
2193   0x38,0x39,0xfd,0xea,0x9a,0xeb,0xe9,0xff  /* f8-ff */
2194 };
2195
2196 /* ASCII to EBCDIC translation table */
2197 static u_char ascii_to_ebcdic[256] =
2198 {
2199   0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, /* 00-07 */
2200   0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f, /* 08-0f */
2201   0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, /* 10-17 */
2202   0x18,0x19,0x3f,0x27,0x22,0x1d,0x1e,0x1f, /* 18-1f */
2203   0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, /* 20-27 */
2204   0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61, /* 28-2f */
2205   0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, /* 30-37 */
2206   0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f, /* 38-3f */
2207   0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, /* 40-47 */
2208   0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6, /* 48-4f */
2209   0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, /* 50-57 */
2210   0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d, /* 58-5f */
2211   0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, /* 60-67 */
2212   0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96, /* 68-6f */
2213   0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, /* 70-77 */
2214   0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07, /* 78-7f */
2215   0x68,0xdc,0x51,0x42,0x43,0x44,0x47,0x48, /* 80-87 */
2216   0x52,0x53,0x54,0x57,0x56,0x58,0x63,0x67, /* 88-8f */
2217   0x71,0x9c,0x9e,0xcb,0xcc,0xcd,0xdb,0xdd, /* 90-97 */
2218   0xdf,0xec,0xfc,0x70,0xb1,0x80,0xbf,0x40, /* 98-9f */
2219   0x45,0x55,0xee,0xde,0x49,0x69,0x9a,0x9b, /* a8-a7 */
2220   0xab,0xaf,0x5f,0xb8,0xb7,0xaa,0x8a,0x8b, /* a8-af */
2221   0x40,0x40,0x40,0x40,0x40,0x65,0x62,0x64, /* b0-b7 */
2222   0xb4,0x40,0x40,0x40,0x40,0x4a,0xb2,0x40, /* b8-bf */
2223   0x40,0x40,0x40,0x40,0x40,0x40,0x46,0x66, /* c0-c7 */
2224   0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x9f, /* c8-cf */
2225   0x8c,0xac,0x72,0x73,0x74,0x89,0x75,0x76, /* d0-d7 */
2226   0x77,0x40,0x40,0x40,0x40,0x6a,0x78,0x40, /* d8-df */
2227   0xee,0x59,0xeb,0xed,0xcf,0xef,0xa0,0x8e, /* e0-e7 */
2228   0xae,0xfe,0xfb,0xfd,0x8d,0xad,0xbc,0xbe, /* e8-ef */
2229   0xca,0x8f,0x40,0xb9,0xb6,0xb5,0xe1,0x9d, /* f0-f7 */
2230   0x90,0xbd,0xb3,0xda,0xea,0xfa,0x40,0x40  /* f8-ff */
2231 };
2232
2233 void jk_ascii2ebcdic(char *src, char *dst) {
2234     char c;
2235
2236     while ((c = *src++) != 0) {
2237         *dst++ = ascii_to_ebcdic[(unsigned int)c];
2238     }
2239
2240     *dst = 0;
2241 }
2242
2243 void jk_ebcdic2ascii(char *src, char *dst) {
2244     char c;
2245
2246     while ((c = *src++) != 0) {
2247         *dst++ = ebcdic_to_ascii[(unsigned int)c];
2248     }
2249
2250     *dst = 0;
2251 }
2252
2253 #endif