1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58 
59 /*
60  * Resource allocation code... the code here is responsible for making
61  * sure that nothing leaks.
62  *
63  * rst --- 4/95 --- 6/95
64  */
65 
66 #include "httpd.h"
67 #include "http_config.h"
68 #include "http_conf_globals.h"
69 #include "multithread.h"
70 #include "http_log.h"
71 
72 #include <stdarg.h>
73 
74 /* debugging support, define this to enable code which helps detect re-use
75  * of freed memory and other such nonsense.
76  *
77  * The theory is simple.  The FILL_BYTE (0xa5) is written over all malloc'd
78  * memory as we receive it, and is written over everything that we free up
79  * during a clear_pool.  We check that blocks on the free list always
80  * have the FILL_BYTE in them, and we check during palloc() that the bytes
81  * still have FILL_BYTE in them.  If you ever see garbage URLs or whatnot
82  * containing lots of 0xa5s then you know something used data that's been
83  * freed or uninitialized.
84  */
85 /* #define ALLOC_DEBUG */
86 
87 /* debugging support, if defined all allocations will be done with
88  * malloc and free()d appropriately at the end.  This is intended to be
89  * used with something like Electric Fence or Purify to help detect
90  * memory problems.  Note that if you're using efence then you should also
91  * add in ALLOC_DEBUG.  But don't add in ALLOC_DEBUG if you're using Purify
92  * because ALLOC_DEBUG would hide all the uninitialized read errors that
93  * Purify can diagnose.
94  */
95 /* #define ALLOC_USE_MALLOC */
96 
97 /* Pool debugging support.  This is intended to detect cases where the
98  * wrong pool is used when assigning data to an object in another pool.
99  * In particular, it causes the table_{set,add,merge}n routines to check
100  * that their arguments are safe for the table they're being placed in.
101  * It currently only works with the unix multiprocess model, but could
102  * be extended to others.
103  */
104 /* #define POOL_DEBUG */
105 
106 /* Provide diagnostic information about make_table() calls which are
107  * possibly too small.  This requires a recent gcc which supports
108  * __builtin_return_address().  The error_log output will be a
109  * message such as:
110  *    table_push: table created by 0x804d874 hit limit of 10
111  * Use "l *0x804d874" to find the source that corresponds to.  It
112  * indicates that a table allocated by a call at that address has
113  * possibly too small an initial table size guess.
114  */
115 /* #define MAKE_TABLE_PROFILE */
116 
117 #ifdef POOL_DEBUG
118 #ifdef ALLOC_USE_MALLOC
119 # error "sorry, no support for ALLOC_USE_MALLOC and POOL_DEBUG at the same time"
120 #endif
121 #endif
122 
123 #ifdef ALLOC_USE_MALLOC
124 #undef BLOCK_MINFREE
125 #undef BLOCK_MINALLOC
126 #define BLOCK_MINFREE	0
127 #define BLOCK_MINALLOC	0
128 #endif
129 
130 #if defined(EAPI_MM)
131 static AP_MM *mm = NULL;
132 #endif
133 
134 /*****************************************************************
135  *
136  * Managing free storage blocks...
137  */
138 
139 union align {
140     /* Types which are likely to have the longest RELEVANT alignment
141      * restrictions...
142      */
143 
144     char *cp;
145     void (*f) (void);
146     long l;
147     FILE *fp;
148     double d;
149 };
150 
151 #define CLICK_SZ (sizeof(union align))
152 
153 union block_hdr {
154     union align a;
155 
156     /* Actual header... */
157 
158     struct {
159 	char *endp;
160 	union block_hdr *next;
161 	char *first_avail;
162 #if defined(EAPI_MM)
163 	int is_shm;
164 #endif
165 #ifdef POOL_DEBUG
166 	union block_hdr *global_next;
167 	struct pool *owning_pool;
168 #endif
169     } h;
170 };
171 
172 static union block_hdr *block_freelist = NULL;
173 static mutex *alloc_mutex = NULL;
174 static mutex *spawn_mutex = NULL;
175 #ifdef POOL_DEBUG
176 static char *known_stack_point;
177 static int stack_direction;
178 static union block_hdr *global_block_list;
179 #define FREE_POOL	((struct pool *)(-1))
180 #endif
181 
182 #ifdef ALLOC_DEBUG
183 #define FILL_BYTE	((char)(0xa5))
184 
185 #define debug_fill(ptr,size)	((void)memset((ptr), FILL_BYTE, (size)))
186 
debug_verify_filled(const char * ptr,const char * endp,const char * error_msg)187 static ap_inline void debug_verify_filled(const char *ptr,
188     const char *endp, const char *error_msg)
189 {
190     for (; ptr < endp; ++ptr) {
191 	if (*ptr != FILL_BYTE) {
192 	    fputs(error_msg, stderr);
193 	    abort();
194 	    exit(1);
195 	}
196     }
197 }
198 
199 #else
200 #define debug_fill(a,b)
201 #define debug_verify_filled(a,b,c)
202 #endif
203 
204 
205 /* Get a completely new block from the system pool. Note that we rely on
206    malloc() to provide aligned memory. */
207 
208 #if defined(EAPI_MM)
malloc_block(int size,int is_shm)209 static union block_hdr *malloc_block(int size, int is_shm)
210 #else
211 static union block_hdr *malloc_block(int size)
212 #endif
213 {
214     union block_hdr *blok;
215     int request_size;
216 
217 #ifdef ALLOC_DEBUG
218     /* make some room at the end which we'll fill and expect to be
219      * always filled
220      */
221     size += CLICK_SZ;
222 #endif
223     request_size = size + sizeof(union block_hdr);
224 #if defined(EAPI_MM)
225     if (is_shm)
226         blok = (union block_hdr *)ap_mm_malloc(mm, request_size);
227     else
228 #endif
229     blok = (union block_hdr *) malloc(request_size);
230     if (blok == NULL) {
231 	fprintf(stderr, "Ouch!  malloc(%d) failed in malloc_block()\n",
232                 request_size);
233 	exit(1);
234     }
235     debug_fill(blok, size + sizeof(union block_hdr));
236 #if defined(EAPI_MM)
237     blok->h.is_shm = is_shm;
238 #endif
239     blok->h.next = NULL;
240     blok->h.first_avail = (char *) (blok + 1);
241     blok->h.endp = size + blok->h.first_avail;
242 #ifdef ALLOC_DEBUG
243     blok->h.endp -= CLICK_SZ;
244 #endif
245 #ifdef POOL_DEBUG
246     blok->h.global_next = global_block_list;
247     global_block_list = blok;
248     blok->h.owning_pool = NULL;
249 #endif
250 
251     return blok;
252 }
253 
254 
255 
256 #if defined(ALLOC_DEBUG) && !defined(ALLOC_USE_MALLOC)
chk_on_blk_list(union block_hdr * blok,union block_hdr * free_blk)257 static void chk_on_blk_list(union block_hdr *blok, union block_hdr *free_blk)
258 {
259     debug_verify_filled(blok->h.endp, blok->h.endp + CLICK_SZ,
260 	"Ouch!  Someone trounced the padding at the end of a block!\n");
261     while (free_blk) {
262 	if (free_blk == blok) {
263 	    fprintf(stderr, "Ouch!  Freeing free block\n");
264 	    abort();
265 	    exit(1);
266 	}
267 	free_blk = free_blk->h.next;
268     }
269 }
270 #else
271 #define chk_on_blk_list(_x, _y)
272 #endif
273 
274 /* Free a chain of blocks --- must be called with alarms blocked. */
275 
free_blocks(union block_hdr * blok)276 static void free_blocks(union block_hdr *blok)
277 {
278 #ifdef ALLOC_USE_MALLOC
279     union block_hdr *next;
280 
281     for (; blok; blok = next) {
282 	next = blok->h.next;
283 	free(blok);
284     }
285 #else
286     /* First, put new blocks at the head of the free list ---
287      * we'll eventually bash the 'next' pointer of the last block
288      * in the chain to point to the free blocks we already had.
289      */
290 
291     union block_hdr *old_free_list;
292 
293     if (blok == NULL)
294 	return;			/* Sanity check --- freeing empty pool? */
295 
296 #if defined(EAPI_MM)
297     if (blok->h.is_shm)
298         (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
299 #endif
300     (void) ap_acquire_mutex(alloc_mutex);
301     old_free_list = block_freelist;
302     block_freelist = blok;
303 
304     /*
305      * Next, adjust first_avail pointers of each block --- have to do it
306      * sooner or later, and it simplifies the search in new_block to do it
307      * now.
308      */
309 
310     while (blok->h.next != NULL) {
311 	chk_on_blk_list(blok, old_free_list);
312 	blok->h.first_avail = (char *) (blok + 1);
313 	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
314 #ifdef POOL_DEBUG
315 	blok->h.owning_pool = FREE_POOL;
316 #endif
317 	blok = blok->h.next;
318     }
319 
320     chk_on_blk_list(blok, old_free_list);
321     blok->h.first_avail = (char *) (blok + 1);
322     debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
323 #ifdef POOL_DEBUG
324     blok->h.owning_pool = FREE_POOL;
325 #endif
326 
327     /* Finally, reset next pointer to get the old free blocks back */
328 
329     blok->h.next = old_free_list;
330 
331     (void) ap_release_mutex(alloc_mutex);
332 #if defined(EAPI_MM)
333     if (blok->h.is_shm)
334         (void)ap_mm_unlock(mm);
335 #endif
336 #endif
337 }
338 
339 
340 /* Get a new block, from our own free list if possible, from the system
341  * if necessary.  Must be called with alarms blocked.
342  */
343 
344 #if defined(EAPI_MM)
new_block(int min_size,int is_shm)345 static union block_hdr *new_block(int min_size, int is_shm)
346 #else
347 static union block_hdr *new_block(int min_size)
348 #endif
349 {
350     union block_hdr **lastptr = &block_freelist;
351     union block_hdr *blok = block_freelist;
352 
353     /* First, see if we have anything of the required size
354      * on the free list...
355      */
356 
357     while (blok != NULL) {
358 #if defined(EAPI_MM)
359     if (blok->h.is_shm == is_shm &&
360         min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
361 #else
362 	if (min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) {
363 #endif
364 	    *lastptr = blok->h.next;
365 	    blok->h.next = NULL;
366 	    debug_verify_filled(blok->h.first_avail, blok->h.endp,
367 		"Ouch!  Someone trounced a block on the free list!\n");
368 	    return blok;
369 	}
370 	else {
371 	    lastptr = &blok->h.next;
372 	    blok = blok->h.next;
373 	}
374     }
375 
376     /* Nope. */
377 
378     min_size += BLOCK_MINFREE;
379 #if defined(EAPI_MM)
380     blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC, is_shm);
381 #else
382     blok = malloc_block((min_size > BLOCK_MINALLOC) ? min_size : BLOCK_MINALLOC);
383 #endif
384     return blok;
385 }
386 
387 
388 /* Accounting */
389 
390 static long bytes_in_block_list(union block_hdr *blok)
391 {
392     long size = 0;
393 
394     while (blok) {
395 	size += blok->h.endp - (char *) (blok + 1);
396 	blok = blok->h.next;
397     }
398 
399     return size;
400 }
401 
402 
403 /*****************************************************************
404  *
405  * Pool internals and management...
406  * NB that subprocesses are not handled by the generic cleanup code,
407  * basically because we don't want cleanups for multiple subprocesses
408  * to result in multiple three-second pauses.
409  */
410 
411 struct process_chain;
412 struct cleanup;
413 
414 static void run_cleanups(struct cleanup *);
415 static void free_proc_chain(struct process_chain *);
416 
417 struct pool {
418     union block_hdr *first;
419     union block_hdr *last;
420     struct cleanup *cleanups;
421     struct process_chain *subprocesses;
422     struct pool *sub_pools;
423     struct pool *sub_next;
424     struct pool *sub_prev;
425     struct pool *parent;
426     char *free_first_avail;
427 #ifdef ALLOC_USE_MALLOC
428     void *allocation_list;
429 #endif
430 #ifdef POOL_DEBUG
431     struct pool *joined;
432 #endif
433 #if defined(EAPI_MM)
434     int is_shm;
435 #endif
436 };
437 
438 static pool *permanent_pool;
439 
440 /* Each pool structure is allocated in the start of its own first block,
441  * so we need to know how many bytes that is (once properly aligned...).
442  * This also means that when a pool's sub-pool is destroyed, the storage
443  * associated with it is *completely* gone, so we have to make sure it
444  * gets taken off the parent's sub-pool list...
445  */
446 
447 #define POOL_HDR_CLICKS (1 + ((sizeof(struct pool) - 1) / CLICK_SZ))
448 #define POOL_HDR_BYTES (POOL_HDR_CLICKS * CLICK_SZ)
449 
450 #if defined(EAPI_MM)
451 static struct pool *make_sub_pool_internal(struct pool *p, int is_shm)
452 #else
453 API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
454 #endif
455 {
456     union block_hdr *blok;
457     pool *new_pool;
458 
459     ap_block_alarms();
460 
461 #if defined(EAPI_MM)
462     if (is_shm)
463         (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
464 #endif
465     (void) ap_acquire_mutex(alloc_mutex);
466 
467 #if defined(EAPI_MM)
468     blok = new_block(POOL_HDR_BYTES, is_shm);
469 #else
470     blok = new_block(POOL_HDR_BYTES);
471 #endif
472     new_pool = (pool *) blok->h.first_avail;
473     blok->h.first_avail += POOL_HDR_BYTES;
474 #ifdef POOL_DEBUG
475     blok->h.owning_pool = new_pool;
476 #endif
477 
478     memset((char *) new_pool, '\0', sizeof(struct pool));
479     new_pool->free_first_avail = blok->h.first_avail;
480     new_pool->first = new_pool->last = blok;
481 
482     if (p) {
483 	new_pool->parent = p;
484 	new_pool->sub_next = p->sub_pools;
485 	if (new_pool->sub_next)
486 	    new_pool->sub_next->sub_prev = new_pool;
487 	p->sub_pools = new_pool;
488     }
489 
490 #if defined(EAPI_MM)
491     new_pool->is_shm = is_shm;
492 #endif
493 
494     (void) ap_release_mutex(alloc_mutex);
495 #if defined(EAPI_MM)
496     if (is_shm)
497 	(void)ap_mm_unlock(mm);
498 #endif
499     ap_unblock_alarms();
500 
501     return new_pool;
502 }
503 
504 #if defined(EAPI_MM)
505 API_EXPORT(struct pool *) ap_make_sub_pool(struct pool *p)
506 {
507     return make_sub_pool_internal(p, 0);
508 }
509 API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p)
510 {
511     return make_sub_pool_internal(p, 1);
512 }
513 #else
514 API_EXPORT(struct pool *) ap_make_shared_sub_pool(struct pool *p)
515 {
516     return NULL;
517 }
518 #endif
519 
520 #ifdef POOL_DEBUG
521 static void stack_var_init(char *s)
522 {
523     char t;
524 
525     if (s < &t) {
526 	stack_direction = 1; /* stack grows up */
527     }
528     else {
529 	stack_direction = -1; /* stack grows down */
530     }
531 }
532 #endif
533 
534 int ap_shared_pool_possible(void)
535 {
536     return ap_mm_useable();
537 }
538 
539 API_EXPORT(pool *) ap_init_alloc(void)
540 {
541 #ifdef POOL_DEBUG
542     char s;
543 
544     known_stack_point = &s;
545     stack_var_init(&s);
546 #endif
547     alloc_mutex = ap_create_mutex(NULL);
548     spawn_mutex = ap_create_mutex(NULL);
549     permanent_pool = ap_make_sub_pool(NULL);
550     return permanent_pool;
551 }
552 
553 void ap_init_alloc_shared(int early)
554 {
555 #if defined(EAPI_MM)
556     int mm_size;
557     char *mm_path;
558     char *err1, *err2;
559 
560     if (early) {
561         /* process very early on startup */
562         mm_size = ap_mm_maxsize();
563         if (mm_size > EAPI_MM_CORE_MAXSIZE)
564             mm_size = EAPI_MM_CORE_MAXSIZE;
565         mm_path = ap_server_root_relative(permanent_pool,
566                   ap_psprintf(permanent_pool, "%s.%ld",
567                               EAPI_MM_CORE_PATH, (long)getpid()));
568         if ((mm = ap_mm_create(mm_size, mm_path)) == NULL) {
569             fprintf(stderr, "Ouch! ap_mm_create(%d, \"%s\") failed\n", mm_size, mm_path);
570             err1 = ap_mm_error();
571             if (err1 == NULL)
572                 err1 = "-unknown-";
573             err2 = strerror(errno);
574             if (err2 == NULL)
575                 err2 = "-unknown-";
576             fprintf(stderr, "Error: MM: %s: OS: %s\n", err1, err2);
577             exit(1);
578         }
579     }
580     else {
581         /* process a lot later on startup */
582         ap_mm_permission(mm, (S_IRUSR|S_IWUSR), ap_user_id, -1);
583     }
584 #endif /* EAPI_MM */
585     return;
586 }
587 
588 void ap_kill_alloc_shared(void)
589 {
590 #if defined(EAPI_MM)
591     if (mm != NULL) {
592         ap_mm_destroy(mm);
593         mm = NULL;
594     }
595 #endif /* EAPI_MM */
596     return;
597 }
598 
599 void ap_cleanup_alloc(void)
600 {
601     ap_destroy_mutex(alloc_mutex);
602     ap_destroy_mutex(spawn_mutex);
603 }
604 
605 API_EXPORT(void) ap_clear_pool(struct pool *a)
606 {
607     ap_block_alarms();
608 
609 #if defined(EAPI_MM)
610     if (a->is_shm)
611         (void)ap_mm_lock(mm, AP_MM_LOCK_RW);
612 #endif
613     (void) ap_acquire_mutex(alloc_mutex);
614     while (a->sub_pools)
615 	ap_destroy_pool(a->sub_pools);
616     (void) ap_release_mutex(alloc_mutex);
617 #if defined(EAPI_MM)
618     if (a->is_shm)
619 	    (void)ap_mm_unlock(mm);
620 #endif
621     /* Don't hold the mutex during cleanups. */
622     run_cleanups(a->cleanups);
623     a->cleanups = NULL;
624     free_proc_chain(a->subprocesses);
625     a->subprocesses = NULL;
626     free_blocks(a->first->h.next);
627     a->first->h.next = NULL;
628 
629     a->last = a->first;
630     a->first->h.first_avail = a->free_first_avail;
631     debug_fill(a->first->h.first_avail,
632 	a->first->h.endp - a->first->h.first_avail);
633 
634 #ifdef ALLOC_USE_MALLOC
635     {
636 	void *c, *n;
637 
638 	for (c = a->allocation_list; c; c = n) {
639 	    n = *(void **)c;
640 	    free(c);
641 	}
642 	a->allocation_list = NULL;
643     }
644 #endif
645 
646     ap_unblock_alarms();
647 }
648 
649 API_EXPORT(void) ap_destroy_pool(pool *a)
650 {
651     ap_block_alarms();
652     ap_clear_pool(a);
653 
654 #if defined(EAPI_MM)
655     if (a->is_shm)
656 	(void)ap_mm_lock(mm, AP_MM_LOCK_RW);
657 #endif
658     (void) ap_acquire_mutex(alloc_mutex);
659     if (a->parent) {
660 	if (a->parent->sub_pools == a)
661 	    a->parent->sub_pools = a->sub_next;
662 	if (a->sub_prev)
663 	    a->sub_prev->sub_next = a->sub_next;
664 	if (a->sub_next)
665 	    a->sub_next->sub_prev = a->sub_prev;
666     }
667     (void) ap_release_mutex(alloc_mutex);
668 #if defined(EAPI_MM)
669     if (a->is_shm)
670 	(void)ap_mm_unlock(mm);
671 #endif
672 
673     free_blocks(a->first);
674     ap_unblock_alarms();
675 }
676 
677 API_EXPORT(long) ap_bytes_in_pool(pool *p)
678 {
679     return bytes_in_block_list(p->first);
680 }
681 API_EXPORT(long) ap_bytes_in_free_blocks(void)
682 {
683     return bytes_in_block_list(block_freelist);
684 }
685 
686 API_EXPORT(int) ap_acquire_pool(pool *p, ap_pool_lock_mode mode)
687 {
688 #if defined(EAPI_MM)
689     if (!p->is_shm)
690         return 1;
691     return ap_mm_lock(mm, mode == AP_POOL_RD ? AP_MM_LOCK_RD : AP_MM_LOCK_RW);
692 #else
693 	return 1;
694 #endif
695 }
696 
697 API_EXPORT(int) ap_release_pool(pool *p)
698 {
699 #if defined(EAPI_MM)
700     if (!p->is_shm)
701         return 1;
702     return ap_mm_unlock(mm);
703 #else
704 	return 1;
705 #endif
706 }
707 
708 /*****************************************************************
709  * POOL_DEBUG support
710  */
711 #ifdef POOL_DEBUG
712 
713 /* the unix linker defines this symbol as the last byte + 1 of
714  * the executable... so it includes TEXT, BSS, and DATA
715  */
716 extern char _end;
717 
718 /* is ptr in the range [lo,hi) */
719 #define is_ptr_in_range(ptr, lo, hi)	\
720     (((unsigned long)(ptr) - (unsigned long)(lo)) \
721 	< \
722 	(unsigned long)(hi) - (unsigned long)(lo))
723 
724 /* Find the pool that ts belongs to, return NULL if it doesn't
725  * belong to any pool.
726  */
727 API_EXPORT(pool *) ap_find_pool(const void *ts)
728 {
729     const char *s = ts;
730     union block_hdr **pb;
731     union block_hdr *b;
732 
733     /* short-circuit stuff which is in TEXT, BSS, or DATA */
734     if (is_ptr_in_range(s, 0, &_end)) {
735 	return NULL;
736     }
737     /* consider stuff on the stack to also be in the NULL pool...
738      * XXX: there's cases where we don't want to assume this
739      */
740     if ((stack_direction == -1 && is_ptr_in_range(s, &ts, known_stack_point))
741 	|| (stack_direction == 1 && is_ptr_in_range(s, known_stack_point, &ts))) {
742 	abort();
743 	return NULL;
744     }
745     ap_block_alarms();
746     /* search the global_block_list */
747     for (pb = &global_block_list; *pb; pb = &b->h.global_next) {
748 	b = *pb;
749 	if (is_ptr_in_range(s, b, b->h.endp)) {
750 	    if (b->h.owning_pool == FREE_POOL) {
751 		fprintf(stderr,
752 		    "Ouch!  find_pool() called on pointer in a free block\n");
753 		abort();
754 		exit(1);
755 	    }
756 	    if (b != global_block_list) {
757 		/* promote b to front of list, this is a hack to speed
758 		 * up the lookup */
759 		*pb = b->h.global_next;
760 		b->h.global_next = global_block_list;
761 		global_block_list = b;
762 	    }
763 	    ap_unblock_alarms();
764 	    return b->h.owning_pool;
765 	}
766     }
767     ap_unblock_alarms();
768     return NULL;
769 }
770 
771 /* return TRUE iff a is an ancestor of b
772  * NULL is considered an ancestor of all pools
773  */
774 API_EXPORT(int) ap_pool_is_ancestor(pool *a, pool *b)
775 {
776     if (a == NULL) {
777 	return 1;
778     }
779     while (a->joined) {
780 	a = a->joined;
781     }
782     while (b) {
783 	if (a == b) {
784 	    return 1;
785 	}
786 	b = b->parent;
787     }
788     return 0;
789 }
790 
791 /* All blocks belonging to sub will be changed to point to p
792  * instead.  This is a guarantee by the caller that sub will not
793  * be destroyed before p is.
794  */
795 API_EXPORT(void) ap_pool_join(pool *p, pool *sub)
796 {
797     union block_hdr *b;
798 
799     /* We could handle more general cases... but this is it for now. */
800     if (sub->parent != p) {
801 	fprintf(stderr, "pool_join: p is not parent of sub\n");
802 	abort();
803     }
804     ap_block_alarms();
805     while (p->joined) {
806 	p = p->joined;
807     }
808     sub->joined = p;
809     for (b = global_block_list; b; b = b->h.global_next) {
810 	if (b->h.owning_pool == sub) {
811 	    b->h.owning_pool = p;
812 	}
813     }
814     ap_unblock_alarms();
815 }
816 #endif
817 
818 /*****************************************************************
819  *
820  * Allocating stuff...
821  */
822 
823 
824 API_EXPORT(void *) ap_palloc(struct pool *a, int reqsize)
825 {
826 #ifdef ALLOC_USE_MALLOC
827     int size = reqsize + CLICK_SZ;
828     void *ptr;
829 
830     ap_block_alarms();
831     ptr = malloc(size);
832     if (ptr == NULL) {
833 	fputs("Ouch!  Out of memory!\n", stderr);
834 	exit(1);
835     }
836     debug_fill(ptr, size); /* might as well get uninitialized protection */
837     *(void **)ptr = a->allocation_list;
838     a->allocation_list = ptr;
839     ap_unblock_alarms();
840     return (char *)ptr + CLICK_SZ;
841 #else
842 
843     /* Round up requested size to an even number of alignment units (core clicks)
844      */
845 
846     int nclicks = 1 + ((reqsize - 1) / CLICK_SZ);
847     int size = nclicks * CLICK_SZ;
848 
849     /* First, see if we have space in the block most recently
850      * allocated to this pool
851      */
852 
853     union block_hdr *blok = a->last;
854     char *first_avail = blok->h.first_avail;
855     char *new_first_avail;
856 
857     if (reqsize <= 0)
858 	return NULL;
859 
860     new_first_avail = first_avail + size;
861 
862     if (new_first_avail <= blok->h.endp) {
863 	debug_verify_filled(first_avail, blok->h.endp,
864 	    "Ouch!  Someone trounced past the end of their allocation!\n");
865 	blok->h.first_avail = new_first_avail;
866 	return (void *) first_avail;
867     }
868 
869     /* Nope --- get a new one that's guaranteed to be big enough */
870 
871     ap_block_alarms();
872 
873 #if defined(EAPI_MM)
874     if (a->is_shm)
875 	(void)ap_mm_lock(mm, AP_MM_LOCK_RW);
876 #endif
877     (void) ap_acquire_mutex(alloc_mutex);
878 
879 #if defined(EAPI_MM)
880     blok = new_block(size, a->is_shm);
881 #else
882     blok = new_block(size);
883 #endif
884     a->last->h.next = blok;
885     a->last = blok;
886 #ifdef POOL_DEBUG
887     blok->h.owning_pool = a;
888 #endif
889 #if defined(EAPI_MM)
890     blok->h.is_shm = a->is_shm;
891 #endif
892 
893     (void) ap_release_mutex(alloc_mutex);
894 #if defined(EAPI_MM)
895     if (a->is_shm)
896 	(void)ap_mm_unlock(mm);
897 #endif
898 
899     ap_unblock_alarms();
900 
901     first_avail = blok->h.first_avail;
902     blok->h.first_avail += size;
903 
904     return (void *) first_avail;
905 #endif
906 }
907 
908 API_EXPORT(void *) ap_pcalloc(struct pool *a, int size)
909 {
910     void *res = ap_palloc(a, size);
911     memset(res, '\0', size);
912     return res;
913 }
914 
915 API_EXPORT(char *) ap_pstrdup(struct pool *a, const char *s)
916 {
917     char *res;
918     size_t len;
919 
920     if (s == NULL)
921 	return NULL;
922     len = strlen(s) + 1;
923     res = ap_palloc(a, len);
924     memcpy(res, s, len);
925     return res;
926 }
927 
928 API_EXPORT(char *) ap_pstrndup(struct pool *a, const char *s, int n)
929 {
930     char *res;
931 
932     if (s == NULL)
933 	return NULL;
934     res = ap_palloc(a, n + 1);
935     memcpy(res, s, n);
936     res[n] = '\0';
937     return res;
938 }
939 
940 API_EXPORT_NONSTD(char *) ap_pstrcat(pool *a,...)
941 {
942     char *cp, *argp, *res;
943 
944     /* Pass one --- find length of required string */
945 
946     int len = 0;
947     va_list adummy;
948 
949     va_start(adummy, a);
950 
951     while ((cp = va_arg(adummy, char *)) != NULL)
952 	     len += strlen(cp);
953 
954     va_end(adummy);
955 
956     /* Allocate the required string */
957 
958     res = (char *) ap_palloc(a, len + 1);
959     cp = res;
960     *cp = '\0';
961 
962     /* Pass two --- copy the argument strings into the result space */
963 
964     va_start(adummy, a);
965 
966     while ((argp = va_arg(adummy, char *)) != NULL) {
967 	strlcpy(cp, argp, len + 1);
968 	cp += strlen(argp);
969     }
970 
971     va_end(adummy);
972 
973     /* Return the result string */
974 
975     return res;
976 }
977 
978 /* ap_psprintf is implemented by writing directly into the current
979  * block of the pool, starting right at first_avail.  If there's
980  * insufficient room, then a new block is allocated and the earlier
981  * output is copied over.  The new block isn't linked into the pool
982  * until all the output is done.
983  *
984  * Note that this is completely safe because nothing else can
985  * allocate in this pool while ap_psprintf is running.  alarms are
986  * blocked, and the only thing outside of alloc.c that's invoked
987  * is ap_vformatter -- which was purposefully written to be
988  * self-contained with no callouts.
989  */
990 
991 struct psprintf_data {
992     ap_vformatter_buff vbuff;
993 #ifdef ALLOC_USE_MALLOC
994     char *base;
995 #else
996     union block_hdr *blok;
997     int got_a_new_block;
998 #endif
999 };
1000 
1001 #define AP_PSPRINTF_MIN_SIZE 32  /* Minimum size of allowable avail block */
1002 
1003 static int psprintf_flush(ap_vformatter_buff *vbuff)
1004 {
1005     struct psprintf_data *ps = (struct psprintf_data *)vbuff;
1006 #ifdef ALLOC_USE_MALLOC
1007     int cur_len, size;
1008     char *ptr;
1009 
1010     cur_len = (char *)ps->vbuff.curpos - ps->base;
1011     size = cur_len << 1;
1012     if (size < AP_PSPRINTF_MIN_SIZE)
1013         size = AP_PSPRINTF_MIN_SIZE;
1014 #if defined(EAPI_MM)
1015     if (ps->block->h.is_shm)
1016         ptr = ap_mm_realloc(ps->base, size);
1017     else
1018 #endif
1019     ptr = realloc(ps->base, size);
1020     if (ptr == NULL) {
1021 	fputs("Ouch!  Out of memory!\n", stderr);
1022 	exit(1);
1023     }
1024     ps->base = ptr;
1025     ps->vbuff.curpos = ptr + cur_len;
1026     ps->vbuff.endpos = ptr + size - 1;
1027     return 0;
1028 #else
1029     union block_hdr *blok;
1030     union block_hdr *nblok;
1031     size_t cur_len, size;
1032     char *strp;
1033 
1034     blok = ps->blok;
1035     strp = ps->vbuff.curpos;
1036     cur_len = strp - blok->h.first_avail;
1037     size = cur_len << 1;
1038     if (size < AP_PSPRINTF_MIN_SIZE)
1039         size = AP_PSPRINTF_MIN_SIZE;
1040 
1041     /* must try another blok */
1042 #if defined(EAPI_MM)
1043     if (blok->h.is_shm)
1044 	(void)ap_mm_lock(mm, AP_MM_LOCK_RW);
1045 #endif
1046     (void) ap_acquire_mutex(alloc_mutex);
1047 #if defined(EAPI_MM)
1048     nblok = new_block(size, blok->h.is_shm);
1049 #else
1050     nblok = new_block(size);
1051 #endif
1052     (void) ap_release_mutex(alloc_mutex);
1053 #if defined(EAPI_MM)
1054     if (blok->h.is_shm)
1055 	(void)ap_mm_unlock(mm);
1056 #endif
1057     memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);
1058     ps->vbuff.curpos = nblok->h.first_avail + cur_len;
1059     /* save a byte for the NUL terminator */
1060     ps->vbuff.endpos = nblok->h.endp - 1;
1061 
1062     /* did we allocate the current blok? if so free it up */
1063     if (ps->got_a_new_block) {
1064 	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);
1065 #if defined(EAPI_MM)
1066     if (blok->h.is_shm)
1067 	(void)ap_mm_lock(mm, AP_MM_LOCK_RW);
1068 #endif
1069 	(void) ap_acquire_mutex(alloc_mutex);
1070 	blok->h.next = block_freelist;
1071 	block_freelist = blok;
1072 	(void) ap_release_mutex(alloc_mutex);
1073 #if defined(EAPI_MM)
1074     if (blok->h.is_shm)
1075 	(void)ap_mm_unlock(mm);
1076 #endif
1077     }
1078     ps->blok = nblok;
1079     ps->got_a_new_block = 1;
1080     /* note that we've deliberately not linked the new block onto
1081      * the pool yet... because we may need to flush again later, and
1082      * we'd have to spend more effort trying to unlink the block.
1083      */
1084     return 0;
1085 #endif
1086 }
1087 
1088 API_EXPORT(char *) ap_pvsprintf(pool *p, const char *fmt, va_list ap)
1089 {
1090 #ifdef ALLOC_USE_MALLOC
1091     struct psprintf_data ps;
1092     void *ptr;
1093 
1094     ap_block_alarms();
1095 #if defined(EAPI_MM)
1096     if (p->is_shm)
1097         ps.base = ap_mm_malloc(mm, 512);
1098     else
1099 #endif
1100     ps.base = malloc(512);
1101     if (ps.base == NULL) {
1102 	fputs("Ouch!  Out of memory!\n", stderr);
1103 	exit(1);
1104     }
1105     /* need room at beginning for allocation_list */
1106     ps.vbuff.curpos = ps.base + CLICK_SZ;
1107     ps.vbuff.endpos = ps.base + 511;
1108     ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
1109     *ps.vbuff.curpos++ = '\0';
1110     ptr = ps.base;
1111     /* shrink */
1112 #if defined(EAPI_MM)
1113     if (p->is_shm)
1114         ptr = ap_mm_realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
1115     else
1116 #endif
1117     ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);
1118     if (ptr == NULL) {
1119 	fputs("Ouch!  Out of memory!\n", stderr);
1120 	exit(1);
1121     }
1122     *(void **)ptr = p->allocation_list;
1123     p->allocation_list = ptr;
1124     ap_unblock_alarms();
1125     return (char *)ptr + CLICK_SZ;
1126 #else
1127     struct psprintf_data ps;
1128     char *strp;
1129     int size;
1130 
1131     ap_block_alarms();
1132     ps.blok = p->last;
1133     ps.vbuff.curpos = ps.blok->h.first_avail;
1134     ps.vbuff.endpos = ps.blok->h.endp - 1;	/* save one for NUL */
1135     ps.got_a_new_block = 0;
1136 
1137     if (ps.blok->h.first_avail == ps.blok->h.endp)
1138         psprintf_flush(&ps.vbuff);		/* ensure room for NUL */
1139     ap_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);
1140 
1141     strp = ps.vbuff.curpos;
1142     *strp++ = '\0';
1143 
1144     size = strp - ps.blok->h.first_avail;
1145     size = (1 + ((size - 1) / CLICK_SZ)) * CLICK_SZ;
1146     strp = ps.blok->h.first_avail;	/* save away result pointer */
1147     ps.blok->h.first_avail += size;
1148 
1149     /* have to link the block in if it's a new one */
1150     if (ps.got_a_new_block) {
1151 	p->last->h.next = ps.blok;
1152 	p->last = ps.blok;
1153 #ifdef POOL_DEBUG
1154 	ps.blok->h.owning_pool = p;
1155 #endif
1156     }
1157     ap_unblock_alarms();
1158 
1159     return strp;
1160 #endif
1161 }
1162 
1163 API_EXPORT_NONSTD(char *) ap_psprintf(pool *p, const char *fmt, ...)
1164 {
1165     va_list ap;
1166     char *res;
1167 
1168     va_start(ap, fmt);
1169     res = ap_pvsprintf(p, fmt, ap);
1170     va_end(ap);
1171     return res;
1172 }
1173 
1174 /*****************************************************************
1175  *
1176  * The 'array' functions...
1177  */
1178 
1179 static void make_array_core(array_header *res, pool *p, int nelts, int elt_size)
1180 {
1181     if (nelts < 1)
1182 	nelts = 1;		/* Assure sanity if someone asks for
1183 				 * array of zero elts.
1184 				 */
1185 
1186     res->elts = ap_pcalloc(p, nelts * elt_size);
1187 
1188     res->pool = p;
1189     res->elt_size = elt_size;
1190     res->nelts = 0;		/* No active elements yet... */
1191     res->nalloc = nelts;	/* ...but this many allocated */
1192 }
1193 
1194 API_EXPORT(array_header *) ap_make_array(pool *p, int nelts, int elt_size)
1195 {
1196     array_header *res = (array_header *) ap_palloc(p, sizeof(array_header));
1197 
1198     make_array_core(res, p, nelts, elt_size);
1199     return res;
1200 }
1201 
1202 API_EXPORT(void *) ap_push_array(array_header *arr)
1203 {
1204     if (arr->nelts == arr->nalloc) {
1205 	int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2;
1206 	char *new_data;
1207 
1208 	new_data = ap_pcalloc(arr->pool, arr->elt_size * new_size);
1209 
1210 	memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size);
1211 	arr->elts = new_data;
1212 	arr->nalloc = new_size;
1213     }
1214 
1215     ++arr->nelts;
1216     return arr->elts + (arr->elt_size * (arr->nelts - 1));
1217 }
1218 
1219 API_EXPORT(void) ap_array_cat(array_header *dst, const array_header *src)
1220 {
1221     int elt_size = dst->elt_size;
1222 
1223     if (dst->nelts + src->nelts > dst->nalloc) {
1224 	int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2;
1225 	char *new_data;
1226 
1227 	while (dst->nelts + src->nelts > new_size)
1228 	    new_size *= 2;
1229 
1230 	new_data = ap_pcalloc(dst->pool, elt_size * new_size);
1231 	memcpy(new_data, dst->elts, dst->nalloc * elt_size);
1232 
1233 	dst->elts = new_data;
1234 	dst->nalloc = new_size;
1235     }
1236 
1237     memcpy(dst->elts + dst->nelts * elt_size, src->elts, elt_size * src->nelts);
1238     dst->nelts += src->nelts;
1239 }
1240 
1241 API_EXPORT(array_header *) ap_copy_array(pool *p, const array_header *arr)
1242 {
1243     array_header *res = ap_make_array(p, arr->nalloc, arr->elt_size);
1244 
1245     memcpy(res->elts, arr->elts, arr->elt_size * arr->nelts);
1246     res->nelts = arr->nelts;
1247     return res;
1248 }
1249 
1250 /* This cute function copies the array header *only*, but arranges
1251  * for the data section to be copied on the first push or arraycat.
1252  * It's useful when the elements of the array being copied are
1253  * read only, but new stuff *might* get added on the end; we have the
1254  * overhead of the full copy only where it is really needed.
1255  */
1256 
1257 static ap_inline void copy_array_hdr_core(array_header *res,
1258     const array_header *arr)
1259 {
1260     res->elts = arr->elts;
1261     res->elt_size = arr->elt_size;
1262     res->nelts = arr->nelts;
1263     res->nalloc = arr->nelts;	/* Force overflow on push */
1264 }
1265 
1266 API_EXPORT(array_header *) ap_copy_array_hdr(pool *p, const array_header *arr)
1267 {
1268     array_header *res = (array_header *) ap_palloc(p, sizeof(array_header));
1269 
1270     res->pool = p;
1271     copy_array_hdr_core(res, arr);
1272     return res;
1273 }
1274 
1275 /* The above is used here to avoid consing multiple new array bodies... */
1276 
1277 API_EXPORT(array_header *) ap_append_arrays(pool *p,
1278 					 const array_header *first,
1279 					 const array_header *second)
1280 {
1281     array_header *res = ap_copy_array_hdr(p, first);
1282 
1283     ap_array_cat(res, second);
1284     return res;
1285 }
1286 
1287 /* ap_array_pstrcat generates a new string from the pool containing
1288  * the concatenated sequence of substrings referenced as elements within
1289  * the array.  The string will be empty if all substrings are empty or null,
1290  * or if there are no elements in the array.
1291  * If sep is non-NUL, it will be inserted between elements as a separator.
1292  */
1293 API_EXPORT(char *) ap_array_pstrcat(pool *p, const array_header *arr,
1294                                     const char sep)
1295 {
1296     char *cp, *res, **strpp;
1297     int i, len;
1298 
1299     if (arr->nelts <= 0 || arr->elts == NULL)      /* Empty table? */
1300         return (char *) ap_pcalloc(p, 1);
1301 
1302     /* Pass one --- find length of required string */
1303 
1304     len = 0;
1305     for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
1306         if (strpp && *strpp != NULL) {
1307             len += strlen(*strpp);
1308         }
1309         if (++i >= arr->nelts)
1310             break;
1311         if (sep)
1312             ++len;
1313     }
1314 
1315     /* Allocate the required string */
1316 
1317     res = (char *) ap_palloc(p, len + 1);
1318     cp = res;
1319 
1320     /* Pass two --- copy the argument strings into the result space */
1321 
1322     for (i = 0, strpp = (char **) arr->elts; ; ++strpp) {
1323         if (strpp && *strpp != NULL) {
1324             len = strlen(*strpp);
1325             memcpy(cp, *strpp, len);
1326             cp += len;
1327         }
1328         if (++i >= arr->nelts)
1329             break;
1330         if (sep)
1331             *cp++ = sep;
1332     }
1333 
1334     *cp = '\0';
1335 
1336     /* Return the result string */
1337 
1338     return res;
1339 }
1340 
1341 
1342 /*****************************************************************
1343  *
1344  * The "table" functions.
1345  */
1346 
1347 /* XXX: if you tweak this you should look at is_empty_table() and table_elts()
1348  * in ap_alloc.h */
1349 struct table {
1350     /* This has to be first to promote backwards compatibility with
1351      * older modules which cast a table * to an array_header *...
1352      * they should use the table_elts() function for most of the
1353      * cases they do this for.
1354      */
1355     array_header a;
1356 #ifdef MAKE_TABLE_PROFILE
1357     void *creator;
1358 #endif
1359 };
1360 
1361 #ifdef MAKE_TABLE_PROFILE
1362 static table_entry *table_push(table *t)
1363 {
1364     if (t->a.nelts == t->a.nalloc) {
1365 	fprintf(stderr,
1366 	    "table_push: table created by %p hit limit of %u\n",
1367 	    t->creator, t->a.nalloc);
1368     }
1369     return (table_entry *) ap_push_array(&t->a);
1370 }
1371 #else
1372 #define table_push(t)	((table_entry *) ap_push_array(&(t)->a))
1373 #endif
1374 
1375 
1376 API_EXPORT(table *) ap_make_table(pool *p, int nelts)
1377 {
1378     table *t = ap_palloc(p, sizeof(table));
1379 
1380     make_array_core(&t->a, p, nelts, sizeof(table_entry));
1381 #ifdef MAKE_TABLE_PROFILE
1382     t->creator = __builtin_return_address(0);
1383 #endif
1384     return t;
1385 }
1386 
1387 API_EXPORT(table *) ap_copy_table(pool *p, const table *t)
1388 {
1389     table *new = ap_palloc(p, sizeof(table));
1390 
1391 #ifdef POOL_DEBUG
1392     /* we don't copy keys and values, so it's necessary that t->a.pool
1393      * have a life span at least as long as p
1394      */
1395     if (!ap_pool_is_ancestor(t->a.pool, p)) {
1396 	fprintf(stderr, "copy_table: t's pool is not an ancestor of p\n");
1397 	abort();
1398     }
1399 #endif
1400     make_array_core(&new->a, p, t->a.nalloc, sizeof(table_entry));
1401     memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(table_entry));
1402     new->a.nelts = t->a.nelts;
1403     return new;
1404 }
1405 
1406 API_EXPORT(void) ap_clear_table(table *t)
1407 {
1408     t->a.nelts = 0;
1409 }
1410 
1411 API_EXPORT(const char *) ap_table_get(const table *t, const char *key)
1412 {
1413     table_entry *elts = (table_entry *) t->a.elts;
1414     int i;
1415 
1416     if (key == NULL)
1417 	return NULL;
1418 
1419     for (i = 0; i < t->a.nelts; ++i)
1420 	if (!strcasecmp(elts[i].key, key))
1421 	    return elts[i].val;
1422 
1423     return NULL;
1424 }
1425 
1426 API_EXPORT(void) ap_table_set(table *t, const char *key, const char *val)
1427 {
1428     register int i, j, k;
1429     table_entry *elts = (table_entry *) t->a.elts;
1430     int done = 0;
1431 
1432     for (i = 0; i < t->a.nelts; ) {
1433 	if (!strcasecmp(elts[i].key, key)) {
1434 	    if (!done) {
1435 		elts[i].val = ap_pstrdup(t->a.pool, val);
1436 		done = 1;
1437 		++i;
1438 	    }
1439 	    else {		/* delete an extraneous element */
1440 		for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
1441 		    elts[j].key = elts[k].key;
1442 		    elts[j].val = elts[k].val;
1443 		}
1444 		--t->a.nelts;
1445 	    }
1446 	}
1447 	else {
1448 	    ++i;
1449 	}
1450     }
1451 
1452     if (!done) {
1453 	elts = (table_entry *) table_push(t);
1454 	elts->key = ap_pstrdup(t->a.pool, key);
1455 	elts->val = ap_pstrdup(t->a.pool, val);
1456     }
1457 }
1458 
1459 API_EXPORT(void) ap_table_setn(table *t, const char *key, const char *val)
1460 {
1461     register int i, j, k;
1462     table_entry *elts = (table_entry *) t->a.elts;
1463     int done = 0;
1464 
1465 #ifdef POOL_DEBUG
1466     {
1467 	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
1468 	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
1469 	    abort();
1470 	}
1471 	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
1472 	    fprintf(stderr, "table_set: val not in ancestor pool of t\n");
1473 	    abort();
1474 	}
1475     }
1476 #endif
1477 
1478     for (i = 0; i < t->a.nelts; ) {
1479 	if (!strcasecmp(elts[i].key, key)) {
1480 	    if (!done) {
1481 		elts[i].val = (char *)val;
1482 		done = 1;
1483 		++i;
1484 	    }
1485 	    else {		/* delete an extraneous element */
1486 		for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
1487 		    elts[j].key = elts[k].key;
1488 		    elts[j].val = elts[k].val;
1489 		}
1490 		--t->a.nelts;
1491 	    }
1492 	}
1493 	else {
1494 	    ++i;
1495 	}
1496     }
1497 
1498     if (!done) {
1499 	elts = (table_entry *) table_push(t);
1500 	elts->key = (char *)key;
1501 	elts->val = (char *)val;
1502     }
1503 }
1504 
1505 API_EXPORT(void) ap_table_unset(table *t, const char *key)
1506 {
1507     register int i, j, k;
1508     table_entry *elts = (table_entry *) t->a.elts;
1509 
1510     for (i = 0; i < t->a.nelts;) {
1511 	if (!strcasecmp(elts[i].key, key)) {
1512 
1513 	    /* found an element to skip over
1514 	     * there are any number of ways to remove an element from
1515 	     * a contiguous block of memory.  I've chosen one that
1516 	     * doesn't do a memcpy/bcopy/array_delete, *shrug*...
1517 	     */
1518 	    for (j = i, k = i + 1; k < t->a.nelts; ++j, ++k) {
1519 		elts[j].key = elts[k].key;
1520 		elts[j].val = elts[k].val;
1521 	    }
1522 	    --t->a.nelts;
1523 	}
1524 	else {
1525 	    ++i;
1526 	}
1527     }
1528 }
1529 
1530 API_EXPORT(void) ap_table_merge(table *t, const char *key, const char *val)
1531 {
1532     table_entry *elts = (table_entry *) t->a.elts;
1533     int i;
1534 
1535     for (i = 0; i < t->a.nelts; ++i)
1536 	if (!strcasecmp(elts[i].key, key)) {
1537 	    elts[i].val = ap_pstrcat(t->a.pool, elts[i].val, ", ", val, NULL);
1538 	    return;
1539 	}
1540 
1541     elts = (table_entry *) table_push(t);
1542     elts->key = ap_pstrdup(t->a.pool, key);
1543     elts->val = ap_pstrdup(t->a.pool, val);
1544 }
1545 
1546 API_EXPORT(void) ap_table_mergen(table *t, const char *key, const char *val)
1547 {
1548     table_entry *elts = (table_entry *) t->a.elts;
1549     int i;
1550 
1551 #ifdef POOL_DEBUG
1552     {
1553 	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
1554 	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
1555 	    abort();
1556 	}
1557 	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
1558 	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
1559 	    abort();
1560 	}
1561     }
1562 #endif
1563 
1564     for (i = 0; i < t->a.nelts; ++i) {
1565 	if (!strcasecmp(elts[i].key, key)) {
1566 	    elts[i].val = ap_pstrcat(t->a.pool, elts[i].val, ", ", val, NULL);
1567 	    return;
1568 	}
1569     }
1570 
1571     elts = (table_entry *) table_push(t);
1572     elts->key = (char *)key;
1573     elts->val = (char *)val;
1574 }
1575 
1576 API_EXPORT(void) ap_table_add(table *t, const char *key, const char *val)
1577 {
1578     table_entry *elts = (table_entry *) t->a.elts;
1579 
1580     elts = (table_entry *) table_push(t);
1581     elts->key = ap_pstrdup(t->a.pool, key);
1582     elts->val = ap_pstrdup(t->a.pool, val);
1583 }
1584 
1585 API_EXPORT(void) ap_table_addn(table *t, const char *key, const char *val)
1586 {
1587     table_entry *elts = (table_entry *) t->a.elts;
1588 
1589 #ifdef POOL_DEBUG
1590     {
1591 	if (!ap_pool_is_ancestor(ap_find_pool(key), t->a.pool)) {
1592 	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
1593 	    abort();
1594 	}
1595 	if (!ap_pool_is_ancestor(ap_find_pool(val), t->a.pool)) {
1596 	    fprintf(stderr, "table_set: key not in ancestor pool of t\n");
1597 	    abort();
1598 	}
1599     }
1600 #endif
1601 
1602     elts = (table_entry *) table_push(t);
1603     elts->key = (char *)key;
1604     elts->val = (char *)val;
1605 }
1606 
1607 API_EXPORT(table *) ap_overlay_tables(pool *p, const table *overlay, const table *base)
1608 {
1609     table *res;
1610 
1611 #ifdef POOL_DEBUG
1612     /* we don't copy keys and values, so it's necessary that
1613      * overlay->a.pool and base->a.pool have a life span at least
1614      * as long as p
1615      */
1616     if (!ap_pool_is_ancestor(overlay->a.pool, p)) {
1617 	fprintf(stderr, "overlay_tables: overlay's pool is not an ancestor of p\n");
1618 	abort();
1619     }
1620     if (!ap_pool_is_ancestor(base->a.pool, p)) {
1621 	fprintf(stderr, "overlay_tables: base's pool is not an ancestor of p\n");
1622 	abort();
1623     }
1624 #endif
1625 
1626     res = ap_palloc(p, sizeof(table));
1627     /* behave like append_arrays */
1628     res->a.pool = p;
1629     copy_array_hdr_core(&res->a, &overlay->a);
1630     ap_array_cat(&res->a, &base->a);
1631 
1632     return res;
1633 }
1634 
1635 /* And now for something completely abstract ...
1636 
1637  * For each key value given as a vararg:
1638  *   run the function pointed to as
1639  *     int comp(void *r, char *key, char *value);
1640  *   on each valid key-value pair in the table t that matches the vararg key,
1641  *   or once for every valid key-value pair if the vararg list is empty,
1642  *   until the function returns false (0) or we finish the table.
1643  *
1644  * Note that we restart the traversal for each vararg, which means that
1645  * duplicate varargs will result in multiple executions of the function
1646  * for each matching key.  Note also that if the vararg list is empty,
1647  * only one traversal will be made and will cut short if comp returns 0.
1648  *
1649  * Note that the table_get and table_merge functions assume that each key in
1650  * the table is unique (i.e., no multiple entries with the same key).  This
1651  * function does not make that assumption, since it (unfortunately) isn't
1652  * true for some of Apache's tables.
1653  *
1654  * Note that rec is simply passed-on to the comp function, so that the
1655  * caller can pass additional info for the task.
1656  */
1657 API_EXPORT_NONSTD(void) ap_table_do(int (*comp) (void *, const char *, const char *),
1658 	                            void *rec, const table *t,...)
1659 {
1660     va_list vp;
1661     char *argp;
1662     table_entry *elts = (table_entry *) t->a.elts;
1663     int rv, i;
1664 
1665     va_start(vp, t);
1666 
1667     argp = va_arg(vp, char *);
1668 
1669     do {
1670 	for (rv = 1, i = 0; rv && (i < t->a.nelts); ++i) {
1671 	    if (elts[i].key && (!argp || !strcasecmp(elts[i].key, argp))) {
1672 		rv = (*comp) (rec, elts[i].key, elts[i].val);
1673 	    }
1674 	}
1675     } while (argp && ((argp = va_arg(vp, char *)) != NULL));
1676 
1677     va_end(vp);
1678 }
1679 
1680 /* Curse libc and the fact that it doesn't guarantee a stable sort.  We
1681  * have to enforce stability ourselves by using the order field.  If it
1682  * provided a stable sort then we wouldn't even need temporary storage to
1683  * do the work below. -djg
1684  *
1685  * ("stable sort" means that equal keys retain their original relative
1686  * ordering in the output.)
1687  */
1688 typedef struct {
1689     char *key;
1690     char *val;
1691     int order;
1692 } overlap_key;
1693 
1694 static int sort_overlap(const void *va, const void *vb)
1695 {
1696     const overlap_key *a = va;
1697     const overlap_key *b = vb;
1698     int r;
1699 
1700     r = strcasecmp(a->key, b->key);
1701     if (r) {
1702 	return r;
1703     }
1704     return a->order - b->order;
1705 }
1706 
1707 /* prefer to use the stack for temp storage for overlaps smaller than this */
1708 #ifndef AP_OVERLAP_TABLES_ON_STACK
1709 #define AP_OVERLAP_TABLES_ON_STACK	(512)
1710 #endif
1711 
1712 API_EXPORT(void) ap_overlap_tables(table *a, const table *b, unsigned flags)
1713 {
1714     overlap_key cat_keys_buf[AP_OVERLAP_TABLES_ON_STACK];
1715     overlap_key *cat_keys;
1716     int nkeys;
1717     table_entry *e;
1718     table_entry *last_e;
1719     overlap_key *left;
1720     overlap_key *right;
1721     overlap_key *last;
1722 
1723     nkeys = a->a.nelts + b->a.nelts;
1724     if (nkeys < AP_OVERLAP_TABLES_ON_STACK) {
1725 	cat_keys = cat_keys_buf;
1726     }
1727     else {
1728 	/* XXX: could use scratch free space in a or b's pool instead...
1729 	 * which could save an allocation in b's pool.
1730 	 */
1731 	cat_keys = ap_palloc(b->a.pool, sizeof(overlap_key) * nkeys);
1732     }
1733 
1734     nkeys = 0;
1735 
1736     /* Create a list of the entries from a concatenated with the entries
1737      * from b.
1738      */
1739     e = (table_entry *)a->a.elts;
1740     last_e = e + a->a.nelts;
1741     while (e < last_e) {
1742 	cat_keys[nkeys].key = e->key;
1743 	cat_keys[nkeys].val = e->val;
1744 	cat_keys[nkeys].order = nkeys;
1745 	++nkeys;
1746 	++e;
1747     }
1748 
1749     e = (table_entry *)b->a.elts;
1750     last_e = e + b->a.nelts;
1751     while (e < last_e) {
1752 	cat_keys[nkeys].key = e->key;
1753 	cat_keys[nkeys].val = e->val;
1754 	cat_keys[nkeys].order = nkeys;
1755 	++nkeys;
1756 	++e;
1757     }
1758 
1759     qsort(cat_keys, nkeys, sizeof(overlap_key), sort_overlap);
1760 
1761     /* Now iterate over the sorted list and rebuild a.
1762      * Start by making sure it has enough space.
1763      */
1764     a->a.nelts = 0;
1765     if (a->a.nalloc < nkeys) {
1766 	a->a.elts = ap_palloc(a->a.pool, a->a.elt_size * nkeys * 2);
1767 	a->a.nalloc = nkeys * 2;
1768     }
1769 
1770     /*
1771      * In both the merge and set cases we retain the invariant:
1772      *
1773      * left->key, (left+1)->key, (left+2)->key, ..., (right-1)->key
1774      * are all equal keys.  (i.e. strcasecmp returns 0)
1775      *
1776      * We essentially need to find the maximal
1777      * right for each key, then we can do a quick merge or set as
1778      * appropriate.
1779      */
1780 
1781     if (flags & AP_OVERLAP_TABLES_MERGE) {
1782 	left = cat_keys;
1783 	last = left + nkeys;
1784 	while (left < last) {
1785 	    right = left + 1;
1786 	    if (right == last
1787 		|| strcasecmp(left->key, right->key)) {
1788 		ap_table_addn(a, left->key, left->val);
1789 		left = right;
1790 	    }
1791 	    else {
1792 		char *strp;
1793 		char *value;
1794 		size_t len;
1795 
1796 		/* Have to merge some headers.  Let's re-use the order field,
1797 		 * since it's handy... we'll store the length of val there.
1798 		 */
1799 		left->order = strlen(left->val);
1800 		len = left->order;
1801 		do {
1802 		    right->order = strlen(right->val);
1803 		    len += 2 + right->order;
1804 		    ++right;
1805 		} while (right < last
1806 			&& !strcasecmp(left->key, right->key));
1807 		/* right points one past the last header to merge */
1808 		value = ap_palloc(a->a.pool, len + 1);
1809 		strp = value;
1810 		for (;;) {
1811 		    memcpy(strp, left->val, left->order);
1812 		    strp += left->order;
1813 		    ++left;
1814 		    if (left == right) break;
1815 		    *strp++ = ',';
1816 		    *strp++ = ' ';
1817 		}
1818 		*strp = 0;
1819 		ap_table_addn(a, (left-1)->key, value);
1820 	    }
1821 	}
1822     }
1823     else {
1824 	left = cat_keys;
1825 	last = left + nkeys;
1826 	while (left < last) {
1827 	    right = left + 1;
1828 	    while (right < last && !strcasecmp(left->key, right->key)) {
1829 		++right;
1830 	    }
1831 	    ap_table_addn(a, (right-1)->key, (right-1)->val);
1832 	    left = right;
1833 	}
1834     }
1835 }
1836 
1837 /*****************************************************************
1838  *
1839  * Managing generic cleanups.
1840  */
1841 
1842 struct cleanup {
1843     void *data;
1844     void (*plain_cleanup) (void *);
1845     void (*child_cleanup) (void *);
1846     struct cleanup *next;
1847 };
1848 
1849 API_EXPORT(void) ap_register_cleanup_ex(pool *p, void *data,
1850 				      void (*plain_cleanup) (void *),
1851 				      void (*child_cleanup) (void *),
1852 				      int (*magic_cleanup) (void *))
1853 {
1854     struct cleanup *c;
1855     if (p) {
1856 	c = (struct cleanup *) ap_palloc(p, sizeof(struct cleanup));
1857 	c->data = data;
1858 	c->plain_cleanup = plain_cleanup;
1859 	c->child_cleanup = child_cleanup;
1860 	c->next = p->cleanups;
1861 	p->cleanups = c;
1862     }
1863     /* attempt to do magic even if not passed a pool. Allows us
1864      * to perform the magic, therefore, "whenever" we want/need */
1865     if (magic_cleanup) {
1866 	if (!magic_cleanup(data))
1867 	   ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
1868 		 "exec() may not be safe");
1869     }
1870 }
1871 
1872 API_EXPORT(void) ap_register_cleanup(pool *p, void *data,
1873 				     void (*plain_cleanup) (void *),
1874 				     void (*child_cleanup) (void *))
1875 {
1876     ap_register_cleanup_ex(p, data, plain_cleanup, child_cleanup, NULL);
1877 }
1878 
1879 API_EXPORT(void) ap_kill_cleanup(pool *p, void *data, void (*cleanup) (void *))
1880 {
1881     struct cleanup *c = p->cleanups;
1882     struct cleanup **lastp = &p->cleanups;
1883 
1884     while (c) {
1885 	if (c->data == data && c->plain_cleanup == cleanup) {
1886 	    *lastp = c->next;
1887 	    break;
1888 	}
1889 
1890 	lastp = &c->next;
1891 	c = c->next;
1892     }
1893 }
1894 
1895 API_EXPORT(void) ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *))
1896 {
1897     ap_block_alarms();		/* Run cleanup only once! */
1898     (*cleanup) (data);
1899     ap_kill_cleanup(p, data, cleanup);
1900     ap_unblock_alarms();
1901 }
1902 
1903 static void run_cleanups(struct cleanup *c)
1904 {
1905     while (c) {
1906 	(*c->plain_cleanup) (c->data);
1907 	c = c->next;
1908     }
1909 }
1910 
1911 static void run_child_cleanups(struct cleanup *c)
1912 {
1913     while (c) {
1914 	(*c->child_cleanup) (c->data);
1915 	c = c->next;
1916     }
1917 }
1918 
1919 static void cleanup_pool_for_exec(pool *p)
1920 {
1921     run_child_cleanups(p->cleanups);
1922     p->cleanups = NULL;
1923 
1924     for (p = p->sub_pools; p; p = p->sub_next)
1925 	cleanup_pool_for_exec(p);
1926 }
1927 
1928 API_EXPORT(void) ap_cleanup_for_exec(void)
1929 {
1930     /*
1931      * Don't need to do anything on NT, NETWARE or OS/2, because I
1932      * am actually going to spawn the new process - not
1933      * exec it. All handles that are not inheritable, will
1934      * be automajically closed. The only problem is with
1935      * file handles that are open, but there isn't much
1936      * I can do about that (except if the child decides
1937      * to go out and close them
1938      */
1939     ap_block_alarms();
1940     cleanup_pool_for_exec(permanent_pool);
1941     ap_unblock_alarms();
1942 }
1943 
1944 API_EXPORT_NONSTD(void) ap_null_cleanup(void *data)
1945 {
1946     /* do nothing cleanup routine */
1947 }
1948 
1949 /*****************************************************************
1950  *
1951  * Files and file descriptors; these are just an application of the
1952  * generic cleanup interface.
1953  */
1954 
1955 int ap_close_fd_on_exec(int fd)
1956 {
1957     /* Protect the fd so that it will not be inherited by child processes */
1958     if(fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
1959 	ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
1960 		     "fcntl(%d, F_SETFD, FD_CLOEXEC) failed", fd);
1961 	return 0;
1962     }
1963 
1964     return 1;
1965 }
1966 
1967 static void fd_cleanup(void *fdv)
1968 {
1969     close((int) (long) fdv);
1970 }
1971 
1972 static int fd_magic_cleanup(void *fdv)
1973 {
1974     return ap_close_fd_on_exec((int) (long) fdv);
1975 }
1976 
1977 API_EXPORT(void) ap_note_cleanups_for_fd_ex(pool *p, int fd, int domagic)
1978 {
1979     ap_register_cleanup_ex(p, (void *) (long) fd, fd_cleanup, fd_cleanup,
1980                            domagic ? fd_magic_cleanup : NULL);
1981 }
1982 
1983 API_EXPORT(void) ap_note_cleanups_for_fd(pool *p, int fd)
1984 {
1985     ap_note_cleanups_for_fd_ex(p, fd, 0);
1986 }
1987 
1988 API_EXPORT(void) ap_kill_cleanups_for_fd(pool *p, int fd)
1989 {
1990     ap_kill_cleanup(p, (void *) (long) fd, fd_cleanup);
1991 }
1992 
1993 API_EXPORT(int) ap_popenf_ex(pool *a, const char *name, int flg, int mode,
1994                              int domagic)
1995 {
1996     int fd;
1997     int save_errno;
1998 
1999     ap_block_alarms();
2000     fd = open(name, flg, mode);
2001     save_errno = errno;
2002     if (fd >= 0) {
2003 	fd = ap_slack(fd, AP_SLACK_HIGH);
2004 	ap_note_cleanups_for_fd_ex(a, fd, domagic);
2005     }
2006     ap_unblock_alarms();
2007     errno = save_errno;
2008     return fd;
2009 }
2010 
2011 API_EXPORT(int) ap_popenf(pool *a, const char *name, int flg, int mode)
2012 {
2013     return ap_popenf_ex(a, name, flg, mode, 0);
2014 }
2015 
2016 API_EXPORT(int) ap_pclosef(pool *a, int fd)
2017 {
2018     int res;
2019     int save_errno;
2020 
2021     ap_block_alarms();
2022     res = close(fd);
2023     save_errno = errno;
2024     ap_kill_cleanup(a, (void *) (long) fd, fd_cleanup);
2025     ap_unblock_alarms();
2026     errno = save_errno;
2027     return res;
2028 }
2029 
2030 
2031 /* Note that we have separate plain_ and child_ cleanups for FILE *s,
2032  * since fclose() would flush I/O buffers, which is extremely undesirable;
2033  * we just close the descriptor.
2034  */
2035 
2036 static void file_cleanup(void *fpv)
2037 {
2038     fclose((FILE *) fpv);
2039 }
2040 
2041 static void file_child_cleanup(void *fpv)
2042 {
2043     close(fileno((FILE *) fpv));
2044 }
2045 
2046 static int file_magic_cleanup(void *fpv)
2047 {
2048     return ap_close_fd_on_exec(fileno((FILE *) fpv));
2049 }
2050 
2051 API_EXPORT(void) ap_note_cleanups_for_file_ex(pool *p, FILE *fp, int domagic)
2052 {
2053     ap_register_cleanup_ex(p, (void *) fp, file_cleanup, file_child_cleanup,
2054                            domagic ? file_magic_cleanup : NULL);
2055 }
2056 
2057 API_EXPORT(void) ap_note_cleanups_for_file(pool *p, FILE *fp)
2058 {
2059     ap_note_cleanups_for_file_ex(p, fp, 0);
2060 }
2061 
2062 API_EXPORT(FILE *) ap_pfopen(pool *a, const char *name, const char *mode)
2063 {
2064     FILE *fd = NULL;
2065     int baseFlag, desc;
2066     int modeFlags = 0;
2067     int saved_errno;
2068 
2069     modeFlags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
2070 
2071     ap_block_alarms();
2072 
2073     if (*mode == 'a') {
2074 	/* Work around faulty implementations of fopen */
2075 	baseFlag = (*(mode + 1) == '+') ? O_RDWR : O_WRONLY;
2076 	desc = open(name, baseFlag | O_APPEND | O_CREAT,
2077 		    modeFlags);
2078 	if (desc >= 0) {
2079 	    desc = ap_slack(desc, AP_SLACK_LOW);
2080 	    fd = ap_fdopen(desc, mode);
2081 	}
2082     }
2083     else {
2084 	fd = fopen(name, mode);
2085     }
2086     saved_errno = errno;
2087     if (fd != NULL)
2088 	ap_note_cleanups_for_file(a, fd);
2089     ap_unblock_alarms();
2090     errno = saved_errno;
2091     return fd;
2092 }
2093 
2094 API_EXPORT(FILE *) ap_pfdopen(pool *a, int fd, const char *mode)
2095 {
2096     FILE *f;
2097     int saved_errno;
2098 
2099     ap_block_alarms();
2100     f = ap_fdopen(fd, mode);
2101     saved_errno = errno;
2102     if (f != NULL)
2103 	ap_note_cleanups_for_file(a, f);
2104     ap_unblock_alarms();
2105     errno = saved_errno;
2106     return f;
2107 }
2108 
2109 
2110 API_EXPORT(int) ap_pfclose(pool *a, FILE *fd)
2111 {
2112     int res;
2113 
2114     ap_block_alarms();
2115     res = fclose(fd);
2116     ap_kill_cleanup(a, (void *) fd, file_cleanup);
2117     ap_unblock_alarms();
2118     return res;
2119 }
2120 
2121 /*
2122  * DIR * with cleanup
2123  */
2124 
2125 static void dir_cleanup(void *dv)
2126 {
2127     closedir((DIR *) dv);
2128 }
2129 
2130 API_EXPORT(DIR *) ap_popendir(pool *p, const char *name)
2131 {
2132     DIR *d;
2133     int save_errno;
2134 
2135     ap_block_alarms();
2136     d = opendir(name);
2137     if (d == NULL) {
2138 	save_errno = errno;
2139 	ap_unblock_alarms();
2140 	errno = save_errno;
2141 	return NULL;
2142     }
2143     ap_register_cleanup(p, (void *) d, dir_cleanup, dir_cleanup);
2144     ap_unblock_alarms();
2145     return d;
2146 }
2147 
2148 API_EXPORT(void) ap_pclosedir(pool *p, DIR * d)
2149 {
2150     ap_block_alarms();
2151     ap_kill_cleanup(p, (void *) d, dir_cleanup);
2152     closedir(d);
2153     ap_unblock_alarms();
2154 }
2155 
2156 /*****************************************************************
2157  *
2158  * Files and file descriptors; these are just an application of the
2159  * generic cleanup interface.
2160  */
2161 
2162 static void socket_cleanup(void *fdv)
2163 {
2164     closesocket((int) (long) fdv);
2165 }
2166 
2167 static int socket_magic_cleanup(void *fpv)
2168 {
2169     return ap_close_fd_on_exec((int) (long) fpv);
2170 }
2171 
2172 API_EXPORT(void) ap_note_cleanups_for_socket_ex(pool *p, int fd, int domagic)
2173 {
2174     ap_register_cleanup_ex(p, (void *) (long) fd, socket_cleanup,
2175                            socket_cleanup,
2176                            domagic ? socket_magic_cleanup : NULL);
2177 }
2178 
2179 API_EXPORT(void) ap_note_cleanups_for_socket(pool *p, int fd)
2180 {
2181     ap_note_cleanups_for_socket_ex(p, fd, 0);
2182 }
2183 
2184 API_EXPORT(void) ap_kill_cleanups_for_socket(pool *p, int sock)
2185 {
2186     ap_kill_cleanup(p, (void *) (long) sock, socket_cleanup);
2187 }
2188 
2189 API_EXPORT(int) ap_psocket_ex(pool *p, int domain, int type, int protocol,
2190                               int domagic)
2191 {
2192     int fd;
2193 
2194     ap_block_alarms();
2195     fd = socket(domain, type, protocol);
2196     if (fd == -1) {
2197 	int save_errno = errno;
2198 	ap_unblock_alarms();
2199 	errno = save_errno;
2200 	return -1;
2201     }
2202     ap_note_cleanups_for_socket_ex(p, fd, domagic);
2203     ap_unblock_alarms();
2204     return fd;
2205 }
2206 
2207 API_EXPORT(int) ap_psocket(pool *p, int domain, int type, int protocol)
2208 {
2209     return ap_psocket_ex(p, domain, type, protocol, 0);
2210 }
2211 
2212 API_EXPORT(int) ap_pclosesocket(pool *a, int sock)
2213 {
2214     int res;
2215     int save_errno;
2216 
2217     ap_block_alarms();
2218     res = closesocket(sock);
2219     save_errno = errno;
2220     ap_kill_cleanup(a, (void *) (long) sock, socket_cleanup);
2221     ap_unblock_alarms();
2222     errno = save_errno;
2223     return res;
2224 }
2225 
2226 
2227 /*
2228  * Here's a pool-based interface to POSIX regex's regcomp().
2229  * Note that we return regex_t instead of being passed one.
2230  * The reason is that if you use an already-used regex_t structure,
2231  * the memory that you've already allocated gets forgotten, and
2232  * regfree() doesn't clear it. So we don't allow it.
2233  */
2234 
2235 static void regex_cleanup(void *preg)
2236 {
2237     regfree((regex_t *) preg);
2238 }
2239 
2240 API_EXPORT(regex_t *) ap_pregcomp(pool *p, const char *pattern, int cflags)
2241 {
2242     regex_t *preg = ap_palloc(p, sizeof(regex_t));
2243 
2244     if (regcomp(preg, pattern, cflags))
2245 	return NULL;
2246 
2247     ap_register_cleanup(p, (void *) preg, regex_cleanup, regex_cleanup);
2248 
2249     return preg;
2250 }
2251 
2252 
2253 API_EXPORT(void) ap_pregfree(pool *p, regex_t * reg)
2254 {
2255     ap_block_alarms();
2256     regfree(reg);
2257     ap_kill_cleanup(p, (void *) reg, regex_cleanup);
2258     ap_unblock_alarms();
2259 }
2260 
2261 /*****************************************************************
2262  *
2263  * More grotty system stuff... subprocesses.  Frump.  These don't use
2264  * the generic cleanup interface because I don't want multiple
2265  * subprocesses to result in multiple three-second pauses; the
2266  * subprocesses have to be "freed" all at once.  If someone comes
2267  * along with another resource they want to allocate which has the
2268  * same property, we might want to fold support for that into the
2269  * generic interface, but for now, it's a special case
2270  */
2271 
2272 struct process_chain {
2273     pid_t pid;
2274     enum kill_conditions kill_how;
2275     struct process_chain *next;
2276 };
2277 
2278 API_EXPORT(void) ap_note_subprocess(pool *a, pid_t pid, enum kill_conditions
2279 how) {
2280     struct process_chain *new =
2281     (struct process_chain *) ap_palloc(a, sizeof(struct process_chain));
2282 
2283     new->pid = pid;
2284     new->kill_how = how;
2285     new->next = a->subprocesses;
2286     a->subprocesses = new;
2287 }
2288 
2289 #define os_pipe(fds) pipe(fds)
2290 
2291 /* for ap_fdopen, to get binary mode */
2292 #define BINMODE
2293 
2294 static pid_t spawn_child_core(pool *p, int (*func) (void *, child_info *),
2295 			    void *data,enum kill_conditions kill_how,
2296 			    int *pipe_in, int *pipe_out, int *pipe_err)
2297 {
2298     pid_t pid;
2299     int in_fds[2];
2300     int out_fds[2];
2301     int err_fds[2];
2302     int save_errno;
2303 
2304     if (pipe_in && os_pipe(in_fds) < 0) {
2305 	return 0;
2306     }
2307 
2308     if (pipe_out && os_pipe(out_fds) < 0) {
2309 	save_errno = errno;
2310 	if (pipe_in) {
2311 	    close(in_fds[0]);
2312 	    close(in_fds[1]);
2313 	}
2314 	errno = save_errno;
2315 	return 0;
2316     }
2317 
2318     if (pipe_err && os_pipe(err_fds) < 0) {
2319 	save_errno = errno;
2320 	if (pipe_in) {
2321 	    close(in_fds[0]);
2322 	    close(in_fds[1]);
2323 	}
2324 	if (pipe_out) {
2325 	    close(out_fds[0]);
2326 	    close(out_fds[1]);
2327 	}
2328 	errno = save_errno;
2329 	return 0;
2330     }
2331 
2332     if ((pid = fork()) < 0) {
2333 	save_errno = errno;
2334 	if (pipe_in) {
2335 	    close(in_fds[0]);
2336 	    close(in_fds[1]);
2337 	}
2338 	if (pipe_out) {
2339 	    close(out_fds[0]);
2340 	    close(out_fds[1]);
2341 	}
2342 	if (pipe_err) {
2343 	    close(err_fds[0]);
2344 	    close(err_fds[1]);
2345 	}
2346 	errno = save_errno;
2347 	return 0;
2348     }
2349 
2350     if (!pid) {
2351 	/* Child process */
2352 	RAISE_SIGSTOP(SPAWN_CHILD);
2353 
2354 	if (pipe_out) {
2355 	    close(out_fds[0]);
2356 	    dup2(out_fds[1], STDOUT_FILENO);
2357 	    close(out_fds[1]);
2358 	}
2359 
2360 	if (pipe_in) {
2361 	    close(in_fds[1]);
2362 	    dup2(in_fds[0], STDIN_FILENO);
2363 	    close(in_fds[0]);
2364 	}
2365 
2366 	if (pipe_err) {
2367 	    close(err_fds[0]);
2368 	    dup2(err_fds[1], STDERR_FILENO);
2369 	    close(err_fds[1]);
2370 	}
2371 
2372 	/* HP-UX SIGCHLD fix goes here, if someone will remind me what it is... */
2373 	signal(SIGCHLD, SIG_DFL);	/* Was that it? */
2374 
2375 	func(data, NULL);
2376 	exit(1);		/* Should only get here if the exec in func() failed */
2377     }
2378 
2379     /* Parent process */
2380 
2381     ap_note_subprocess(p, pid, kill_how);
2382 
2383     if (pipe_out) {
2384 	close(out_fds[1]);
2385 	*pipe_out = out_fds[0];
2386     }
2387 
2388     if (pipe_in) {
2389 	close(in_fds[0]);
2390 	*pipe_in = in_fds[1];
2391     }
2392 
2393     if (pipe_err) {
2394 	close(err_fds[1]);
2395 	*pipe_err = err_fds[0];
2396     }
2397 
2398     return pid;
2399 }
2400 
2401 
2402 API_EXPORT(int) ap_spawn_child(pool *p, int (*func) (void *, child_info *),
2403 			       void *data, enum kill_conditions kill_how,
2404 			       FILE **pipe_in, FILE **pipe_out,
2405 			       FILE **pipe_err)
2406 {
2407     int fd_in, fd_out, fd_err;
2408     pid_t pid;
2409     int save_errno;
2410 
2411     ap_block_alarms();
2412 
2413     pid = spawn_child_core(p, func, data, kill_how,
2414 			   pipe_in ? &fd_in : NULL,
2415 			   pipe_out ? &fd_out : NULL,
2416 			   pipe_err ? &fd_err : NULL);
2417 
2418     if (pid == 0) {
2419 	save_errno = errno;
2420 	ap_unblock_alarms();
2421 	errno = save_errno;
2422 	return 0;
2423     }
2424 
2425     if (pipe_out) {
2426 	*pipe_out = ap_fdopen(fd_out, "r" BINMODE);
2427 	if (*pipe_out)
2428 	    ap_note_cleanups_for_file(p, *pipe_out);
2429 	else
2430 	    close(fd_out);
2431     }
2432 
2433     if (pipe_in) {
2434 	*pipe_in = ap_fdopen(fd_in, "w" BINMODE);
2435 	if (*pipe_in)
2436 	    ap_note_cleanups_for_file(p, *pipe_in);
2437 	else
2438 	    close(fd_in);
2439     }
2440 
2441     if (pipe_err) {
2442 	*pipe_err = ap_fdopen(fd_err, "r" BINMODE);
2443 	if (*pipe_err)
2444 	    ap_note_cleanups_for_file(p, *pipe_err);
2445 	else
2446 	    close(fd_err);
2447     }
2448 
2449     ap_unblock_alarms();
2450     return pid;
2451 }
2452 
2453 API_EXPORT(int) ap_bspawn_child(pool *p, int (*func) (void *, child_info *), void *data,
2454 				enum kill_conditions kill_how,
2455 				BUFF **pipe_in, BUFF **pipe_out, BUFF **pipe_err)
2456 {
2457     int fd_in, fd_out, fd_err;
2458     pid_t pid;
2459     int save_errno;
2460 
2461     ap_block_alarms();
2462 
2463     pid = spawn_child_core(p, func, data, kill_how,
2464 			   pipe_in ? &fd_in : NULL,
2465 			   pipe_out ? &fd_out : NULL,
2466 			   pipe_err ? &fd_err : NULL);
2467 
2468     if (pid == 0) {
2469 	save_errno = errno;
2470 	ap_unblock_alarms();
2471 	errno = save_errno;
2472 	return 0;
2473     }
2474 
2475     if (pipe_out) {
2476 	*pipe_out = ap_bcreate(p, B_RD);
2477 	ap_note_cleanups_for_fd_ex(p, fd_out, 0);
2478 	ap_bpushfd(*pipe_out, fd_out, fd_out);
2479     }
2480 
2481     if (pipe_in) {
2482 	*pipe_in = ap_bcreate(p, B_WR);
2483 	ap_note_cleanups_for_fd_ex(p, fd_in, 0);
2484 	ap_bpushfd(*pipe_in, fd_in, fd_in);
2485     }
2486 
2487     if (pipe_err) {
2488 	*pipe_err = ap_bcreate(p, B_RD);
2489 	ap_note_cleanups_for_fd_ex(p, fd_err, 0);
2490 	ap_bpushfd(*pipe_err, fd_err, fd_err);
2491     }
2492 
2493     ap_unblock_alarms();
2494     return pid;
2495 }
2496 
2497 
2498 /*
2499  * Timing constants for killing subprocesses
2500  * There is a total 3-second delay between sending a SIGINT
2501  * and sending of the final SIGKILL.
2502  * TIMEOUT_INTERVAL should be set to TIMEOUT_USECS / 64
2503  * for the exponential timeout algorithm.
2504  */
2505 #define TIMEOUT_USECS    3000000
2506 #define TIMEOUT_INTERVAL   46875
2507 
2508 static void free_proc_chain(struct process_chain *procs)
2509 {
2510     /* Dispose of the subprocesses we've spawned off in the course of
2511      * whatever it was we're cleaning up now.  This may involve killing
2512      * some of them off...
2513      */
2514     struct process_chain *p;
2515     int need_timeout = 0;
2516     int status;
2517     int timeout_interval;
2518     struct timeval tv;
2519 
2520     if (procs == NULL)
2521 	return;			/* No work.  Whew! */
2522 
2523     /* First, check to see if we need to do the SIGTERM, sleep, SIGKILL
2524      * dance with any of the processes we're cleaning up.  If we've got
2525      * any kill-on-sight subprocesses, ditch them now as well, so they
2526      * don't waste any more cycles doing whatever it is that they shouldn't
2527      * be doing anymore.
2528      */
2529     /* Pick up all defunct processes */
2530     for (p = procs; p; p = p->next) {
2531 	if (waitpid(p->pid, (int *) 0, WNOHANG) > 0) {
2532 	    p->kill_how = kill_never;
2533 	}
2534     }
2535 
2536     for (p = procs; p; p = p->next) {
2537 	if ((p->kill_how == kill_after_timeout)
2538 	    || (p->kill_how == kill_only_once)) {
2539 	    /*
2540 	     * This is totally bogus, but seems to be the
2541 	     * only portable (as in reliable) way to accomplish
2542 	     * this. Note that this implies an unavoidable
2543 	     * delay.
2544 	     */
2545 	    ap_os_kill(p->pid, SIGTERM);
2546 	    need_timeout = 1;
2547 	}
2548 	else if (p->kill_how == kill_always) {
2549 	    kill(p->pid, SIGKILL);
2550 	}
2551     }
2552 
2553     /* Sleep only if we have to. The sleep algorithm grows
2554      * by a factor of two on each iteration. TIMEOUT_INTERVAL
2555      * is equal to TIMEOUT_USECS / 64.
2556      */
2557     if (need_timeout) {
2558         timeout_interval = TIMEOUT_INTERVAL;
2559         tv.tv_sec = 0;
2560         tv.tv_usec = timeout_interval;
2561         ap_select(0, NULL, NULL, NULL, &tv);
2562 
2563         do {
2564             need_timeout = 0;
2565             for (p = procs; p; p = p->next) {
2566                 if (p->kill_how == kill_after_timeout) {
2567                     if (waitpid(p->pid, (int *) 0, WNOHANG | WUNTRACED) > 0)
2568                         p->kill_how = kill_never;
2569                     else
2570                         need_timeout = 1;
2571                 }
2572             }
2573             if (need_timeout) {
2574                 if (timeout_interval >= TIMEOUT_USECS) {
2575                     break;
2576                 }
2577                 tv.tv_sec = timeout_interval / 1000000;
2578                 tv.tv_usec = timeout_interval % 1000000;
2579                 ap_select(0, NULL, NULL, NULL, &tv);
2580                 timeout_interval *= 2;
2581             }
2582         } while (need_timeout);
2583     }
2584 
2585     /* OK, the scripts we just timed out for have had a chance to clean up
2586      * --- now, just get rid of them, and also clean up the system accounting
2587      * goop...
2588      */
2589 
2590     for (p = procs; p; p = p->next) {
2591 	if (p->kill_how == kill_after_timeout)
2592 	    kill(p->pid, SIGKILL);
2593 
2594 	if (p->kill_how != kill_never)
2595 	    waitpid(p->pid, &status, 0);
2596     }
2597 }
2598