1{ Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 }
16
17{
18 * Resource allocation routines...
19 *
20 * designed so that we don't have to keep track of EVERYTHING so that
21 * it can be explicitly freed later (a fundamentally unsound strategy ---
22 * particularly in the presence of die()).
23 *
24 * Instead, we maintain pools, and allocate items (both memory and I/O
25 * handlers) from the pools --- currently there are two, one for per
26 * transaction info, and one for config info.  When a transaction is over,
27 * we can delete everything in the per-transaction pool without fear, and
28 * without thinking too hard about it either.
29 *
30 * rst
31 }
32
33{ Arenas for configuration info and transaction info
34 * --- actual layout of the pool structure is private to
35 * alloc.c.
36 }
37
38 { Need declaration of DIR on Win32 }
39{.$ifdef Windows}
40  {$include readdir.inc}
41{.$endif}
42
43type
44  pool = record end;
45  Ppool = ^pool;
46  ap_pool = pool;
47  Pap_pool = ^ap_pool;
48
49function ap_init_alloc: PPool;                    { Set up everything }
50 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
51
52//procedure ap_cleanup_alloc;
53// {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
54
55function ap_make_sub_pool(param: PPool): PPool;   { All pools are subpools of permanent_pool }
56 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
57
58procedure ap_destroy_pool(param: PPool);
59 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
60
61{ pools have nested lifetimes -- sub_pools are destroyed when the
62 * parent pool is cleared.  We allow certain liberties with operations
63 * on things such as tables (and on other structures in a more general
64 * sense) where we allow the caller to insert values into a table which
65 * were not allocated from the table's pool.  The table's data will
66 * remain valid as long as all the pools from which its values are
67 * allocated remain valid.
68 *
69 * For example, if B is a sub pool of A, and you build a table T in
70 * pool B, then it's safe to insert data allocated in A or B into T
71 * (because B lives at most as long as A does, and T is destroyed when
72 * B is cleared/destroyed).  On the other hand, if S is a table in
73 * pool A, it is safe to insert data allocated in A into S, but it
74 * is *not safe* to insert data allocated from B into S... because
75 * B can be cleared/destroyed before A is (which would leave dangling
76 * pointers in T's data structures).
77 *
78 * In general we say that it is safe to insert data into a table T
79 * if the data is allocated in any ancestor of T's pool.  This is the
80 * basis on which the POOL_DEBUG code works -- it tests these ancestor
81 * relationships for all data inserted into tables.  POOL_DEBUG also
82 * provides tools (ap_find_pool, and ap_pool_is_ancestor) for other
83 * folks to implement similar restrictions for their own data
84 * structures.
85 *
86 * However, sometimes this ancestor requirement is inconvenient --
87 * sometimes we're forced to create a sub pool (such as through
88 * ap_sub_req_lookup_uri), and the sub pool is guaranteed to have
89 * the same lifetime as the parent pool.  This is a guarantee implemented
90 * by the *caller*, not by the pool code.  That is, the caller guarantees
91 * they won't destroy the sub pool individually prior to destroying the
92 * parent pool.
93 *
94 * In this case the caller must call ap_pool_join() to indicate this
95 * guarantee to the POOL_DEBUG code.  There are a few examples spread
96 * through the standard modules.
97 }
98{$ifndef POOL_DEBUG}
99//#define ap_pool_join(a,b)
100{$else}
101//API_EXPORT(void) ap_pool_join(pool *p, pool *sub);
102//API_EXPORT(pool *) ap_find_pool(const void *ts);
103//API_EXPORT(int) ap_pool_is_ancestor(pool *a, pool *b);
104{$endif}
105
106{ Clearing out EVERYTHING in an pool... destroys any sub-pools }
107
108procedure ap_clear_pool(param1: Ppool);
109 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
110
111{ Preparing for exec() --- close files, etc., but *don't* flush I/O
112 * buffers, *don't* wait for subprocesses, and *don't* free any memory.
113 }
114
115procedure ap_cleanup_for_exec;
116 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
117
118{ routines to allocate memory from an pool... }
119
120function ap_palloc(p: PPool; nbytes: cint): Pointer;
121 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
122
123function ap_pcalloc(p: PPool; nbytes: cint): Pointer;
124 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
125
126function ap_pstrdup(p: PPool; const s: Char): PChar;
127 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
128
129{ make a nul terminated copy of the n characters starting with s }
130
131function ap_pstrndup(p: PPool; const s: PChar; n: cint): PChar;
132 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
133
134//API_EXPORT_NONSTD(char *) ap_pstrcat(struct pool *,...);	{ all '...' must be char* }
135//API_EXPORT_NONSTD(char *) ap_psprintf(struct pool *, const char *fmt, ...)
136//    __attribute__((format(printf,2,3)));
137//API_EXPORT(char *) ap_pvsprintf(struct pool *, const char *fmt, va_list);
138
139{ array and alist management... keeping lists of things.
140 * Common enough to want common support code ...
141 }
142
143type
144  Parray_header = ^array_header;
145
146  array_header = record
147    pool: Pap_pool;
148    elt_size: cint;
149    nelts: cint;
150    nalloc: cint;
151    elts: PChar;
152  end;
153
154//API_EXPORT(array_header *) ap_make_array(pool *p, int nelts, int elt_size);
155//API_EXPORT(void *) ap_push_array(array_header *);
156//API_EXPORT(void) ap_array_cat(array_header *dst, const array_header *src);
157//API_EXPORT(array_header *) ap_append_arrays(pool *, const array_header *,
158//					 const array_header *);
159
160{ ap_array_pstrcat generates a new string from the pool containing
161 * the concatenated sequence of substrings referenced as elements within
162 * the array.  The string will be empty if all substrings are empty or null,
163 * or if there are no elements in the array.
164 * If sep is non-NUL, it will be inserted between elements as a separator.
165 }
166function ap_array_pstrcat(p: PPool; const arr: Parray_header; const sep: Char): PChar;
167 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
168
169{ copy_array copies the *entire* array.  copy_array_hdr just copies
170 * the header, and arranges for the elements to be copied if (and only
171 * if) the code subsequently does a push or arraycat.
172 }
173
174//API_EXPORT(array_header *) ap_copy_array(pool *p, const array_header *src);
175//API_EXPORT(array_header *) ap_copy_array_hdr(pool *p, const array_header *src);
176
177
178{ Tables.  Implemented alist style, for now, though we try to keep
179 * it so that imposing a hash table structure on top in the future
180 * wouldn't be *too* hard...
181 *
182 * Note that key comparisons for these are case-insensitive, largely
183 * because that's what's appropriate and convenient everywhere they're
184 * currently being used...
185 }
186
187type
188  table = record end;
189
190  Ptable = ^table;
191
192  table_entry = record
193    key: PChar;		{ maybe NULL in future;
194			 * check when iterating thru table_elts
195                         }
196    val: PChar;
197  end;
198
199  table_entry_t = table_entry;
200
201function ap_make_table(p: Ppool; nelts: cuint): Ptable;
202 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
203
204function ap_copy_table(p: Ppool; p1: Ptable): Ptable;
205 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
206
207procedure ap_clear_table(p1: Ptable);
208 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
209
210function ap_table_get(const p1: Ptable; const p2: PChar): PChar;
211 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
212
213procedure ap_table_set(p1: Ptable; const name, val: PChar);
214 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
215
216procedure ap_table_setn(p1: Ptable; const name, val: PChar);
217 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
218
219procedure ap_table_merge(p1: Ptable; const name, more_val: PChar);
220 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
221
222procedure ap_table_mergen(p1: Ptable; const name, more_val: PChar);
223 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
224
225procedure ap_table_unset(p1: Ptable; const key: PChar);
226 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
227
228procedure ap_table_add(p1: Ptable; const name, more_val: PChar);
229 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
230
231procedure ap_table_addn(p1: Ptable; const name, more_val: PChar);
232 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
233
234{API_EXPORT_NONSTD(void) ap_table_do(int ( *comp) (void *, const char *, const char *),
235                                    void *rec, const table *t,...);
236
237API_EXPORT(table * ) ap_overlay_tables(pool *p, const table *overlay, const table *base);
238}
239{ Conceptually, ap_overlap_tables does this:
240
241    array_header *barr = ap_table_elts(b);
242    table_entry *belt = (table_entry *)barr->elts;
243    int i;
244
245    for (i = 0; i < barr->nelts; ++i) begin
246	if (flags & AP_OVERLAP_TABLES_MERGE) begin
247	    ap_table_mergen(a, belt[i].key, belt[i].val);
248        end
249	else begin
250	    ap_table_setn(a, belt[i].key, belt[i].val);
251        end;
252    end;
253
254    Except that it is more efficient (less space and cpu-time) especially
255    when b has many elements.
256
257    Notice the assumptions on the keys and values in b -- they must be
258    in an ancestor of a's pool.  In practice b and a are usually from
259    the same pool.
260}
261const
262  AP_OVERLAP_TABLES_SET	= (0);
263  AP_OVERLAP_TABLES_MERGE = (1);
264
265procedure ap_overlap_tables(a: Ptable; const b: Ptable; flags: cuint);
266 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
267
268{ XXX: these know about the definition of struct table in alloc.c.  That
269 * definition is not here because it is supposed to be private, and by not
270 * placing it here we are able to get compile-time diagnostics from modules
271 * written which assume that a table is the same as an array_header. -djg
272 }
273//#define ap_table_elts(t) ((array_header *)(t))
274//#define ap_is_empty_table(t) (((t) == NULL)||(((array_header *)(t))->nelts == 0))
275
276{ routines to remember allocation of other sorts of things...
277 * generic interface first.  Note that we want to have two separate
278 * cleanup functions in the general case, one for exec() preparation,
279 * to keep CGI scripts and the like from inheriting access to things
280 * they shouldn't be able to touch, and one for actually cleaning up,
281 * when the actual server process wants to get rid of the thing,
282 * whatever it is.
283 *
284 * kill_cleanup disarms a cleanup, presumably because the resource in
285 * question has been closed, freed, or whatever, and it's scarce
286 * enough to want to reclaim (e.g., descriptors).  It arranges for the
287 * resource not to be cleaned up a second time (it might have been
288 * reallocated).  run_cleanup does the same, but runs it first.
289 *
290 * Cleanups are identified for purposes of finding & running them off by the
291 * plain_cleanup and data, which should presumably be unique.
292 *
293 * NB any code which invokes register_cleanup or kill_cleanup directly
294 * is a critical section which should be guarded by block_alarms() and
295 * unblock_alarms() below...
296 *
297 * ap_register_cleanup_ex provided to allow for an optional "cleanup"
298 * to be run at call-time for things like setting CLOSEXEC flags
299 * on fd's or whatever else may make sense.
300 }
301
302//API_EXPORT(void) ap_register_cleanup(pool *p, void *data,
303//				     void (*plain_cleanup) (void *),
304//				     void (*child_cleanup) (void *));
305//API_EXPORT(void) ap_register_cleanup_ex(pool *p, void *data,
306//				      void (*plain_cleanup) (void *),
307//				      void (*child_cleanup) (void *),
308//				      int (*magic_cleanup) (void *));
309
310//API_EXPORT(void) ap_kill_cleanup(pool *p, void *data, void (*plain_cleanup) (void *));
311//API_EXPORT(void) ap_run_cleanup(pool *p, void *data, void (*cleanup) (void *));
312
313{ A "do-nothing" cleanup, for register_cleanup; it's faster to do
314 * things this way than to test for NULL. }
315//API_EXPORT_NONSTD(void) ap_null_cleanup(void *data);
316
317{ The time between when a resource is actually allocated, and when it
318 * its cleanup is registered is a critical section, during which the
319 * resource could leak if we got interrupted or timed out.  So, anything
320 * which registers cleanups should bracket resource allocation and the
321 * cleanup registry with these.  (This is done internally by run_cleanup).
322 *
323 * NB they are actually implemented in http_main.c, since they are bound
324 * up with timeout handling in general...
325 }
326
327procedure ap_block_alarms;
328 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
329
330procedure ap_unblock_alarms;
331 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
332
333{ Common cases which want utility support..
334 * the note_cleanups_for_foo routines are for
335 }
336
337{API_EXPORT(FILE *) ap_pfopen(struct pool *, const char *name, const char *fmode);
338API_EXPORT(FILE *) ap_pfdopen(struct pool *, int fd, const char *fmode);}
339
340function ap_popenf(p1: Ppool; const name: PChar; flg, mode: cint): cint;
341 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
342
343function ap_popenf_ex(p1: Ppool; const name: PChar; flg, mode, domagic: cint): cint;
344 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
345
346{API_EXPORT(void) ap_note_cleanups_for_file(pool *, FILE *);
347API_EXPORT(void) ap_note_cleanups_for_file_ex(pool *, FILE *, int);}
348
349procedure ap_note_cleanups_for_fd(p1: Ppool; p2: cint);
350 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
351
352procedure ap_note_cleanups_for_fd_ex(p1: Ppool; p2, p3: cint);
353 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
354
355{$ifdef WIN32}
356//API_EXPORT(void) ap_note_cleanups_for_h(pool *, HANDLE);
357{$endif}
358
359procedure ap_kill_cleanups_for_fd(p: Ppool; fd: cint);
360 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
361
362
363procedure ap_note_cleanups_for_socket(p1: Ppool; p2: cint);
364 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
365
366procedure ap_note_cleanups_for_socket_ex(p1: Ppool; p2, p3: cint);
367 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
368
369procedure ap_kill_cleanups_for_socket(p: Ppool; sock: cint);
370 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
371
372function ap_psocket(p: Ppool; p2, p3, p4: cint): cint;
373 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
374
375function ap_psocket_ex(p: Ppool; p2, p3, p4, p5: cint): cint;
376 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
377
378function ap_pclosesocket(a: Ppool; sock: cint): cint;
379 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
380
381
382function ap_pregcomp(p: Ppool; const pattern: PChar; cflags: cint): Pregex_t;
383 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
384
385procedure ap_pregfree(p: Ppool; reg: Pregex_t);
386 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
387
388{ routines to note closes... file descriptors are constrained enough
389 * on some systems that we want to support this.
390 }
391
392//API_EXPORT(int) ap_pfclose(struct pool *, FILE *);
393
394function ap_pclosef(p1: Ppool; fd: cint): cint;
395 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
396
397{$ifdef WIN32}
398//API_EXPORT(int) ap_pcloseh(struct pool *, HANDLE hDevice);
399{$endif}
400
401{ routines to deal with directories }
402
403function ap_popendir(p: Ppool; const name: PChar): PDIR;
404 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
405
406procedure ap_pclosedir(p: Ppool; d: PDIR);
407 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
408
409{ ... even child processes (which we may want to wait for,
410 * or to kill outright, on unexpected termination).
411 *
412 * ap_spawn_child is a utility routine which handles an awful lot of
413 * the rigamarole associated with spawning a child --- it arranges
414 * for pipes to the child's stdin and stdout, if desired (if not,
415 * set the associated args to NULL).  It takes as args a function
416 * to call in the child, and an argument to be passed to the function.
417 }
418
419type
420  kill_conditions = (
421    kill_never,			{ process is never sent any signals }
422    kill_always,		{ process is sent SIGKILL on pool cleanup }
423    kill_after_timeout,		{ SIGTERM, wait 3 seconds, SIGKILL }
424    just_wait,			{ wait forever for the process to complete }
425    kill_only_once		{ send SIGTERM and then wait }
426  );
427
428procedure ap_note_subprocess(a: Ppool; pid: pid_t; how: kill_conditions);
429 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
430
431{API_EXPORT(int) ap_spawn_child(pool *, int (*)(void *, child_info *),
432				   void *, enum kill_conditions,
433				   FILE **pipe_in, FILE **pipe_out,
434				   FILE **pipe_err);
435int ap_close_fd_on_exec(int fd);}
436
437{ magic numbers --- min free bytes to consider a free pool block useable,
438 * and the min amount to allocate if we have to go to malloc() }
439
440const
441  BLOCK_MINFREE = 4096;
442  BLOCK_MINALLOC = 8192;
443
444{ Finally, some accounting }
445
446function ap_bytes_in_pool(p: PPool): culong;
447 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
448
449function ap_bytes_in_free_blocks: culong;
450 {$IFDEF WINDOWS} stdcall; {$ELSE} cdecl; {$ENDIF} external LibHTTPD;
451
452