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