~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/threadproc/beos/proc.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * 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
#include "apr_arch_threadproc.h"
 
18
#include "apr_strings.h"
 
19
 
 
20
struct send_pipe {
 
21
        int in;
 
22
        int out;
 
23
        int err;
 
24
};
 
25
 
 
26
APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, apr_pool_t *pool)
 
27
{
 
28
    (*new) = (apr_procattr_t *)apr_palloc(pool, 
 
29
              sizeof(apr_procattr_t));
 
30
 
 
31
    if ((*new) == NULL) {
 
32
        return APR_ENOMEM;
 
33
    }
 
34
    (*new)->pool = pool;
 
35
    (*new)->parent_in = NULL;
 
36
    (*new)->child_in = NULL;
 
37
    (*new)->parent_out = NULL;
 
38
    (*new)->child_out = NULL;
 
39
    (*new)->parent_err = NULL;
 
40
    (*new)->child_err = NULL;
 
41
    (*new)->currdir = NULL; 
 
42
    (*new)->cmdtype = APR_PROGRAM;
 
43
    (*new)->detached = 0;
 
44
    return APR_SUCCESS;
 
45
}
 
46
 
 
47
APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, apr_int32_t in, 
 
48
                                              apr_int32_t out, apr_int32_t err)
 
49
{
 
50
    apr_status_t status;
 
51
    if (in != 0) {
 
52
        if ((status = apr_file_pipe_create(&attr->child_in, &attr->parent_in, 
 
53
                                   attr->pool)) != APR_SUCCESS) {
 
54
            return status;
 
55
        }
 
56
        switch (in) {
 
57
        case APR_FULL_BLOCK:
 
58
            apr_file_pipe_timeout_set(attr->child_in, -1);
 
59
            apr_file_pipe_timeout_set(attr->parent_in, -1);
 
60
            break;
 
61
        case APR_PARENT_BLOCK:
 
62
            apr_file_pipe_timeout_set(attr->child_in, -1);
 
63
            break;
 
64
        case APR_CHILD_BLOCK:
 
65
            apr_file_pipe_timeout_set(attr->parent_in, -1);
 
66
            break;
 
67
        default:
 
68
            break;
 
69
        }
 
70
    } 
 
71
    if (out) {
 
72
        if ((status = apr_file_pipe_create(&attr->parent_out, &attr->child_out, 
 
73
                                   attr->pool)) != APR_SUCCESS) {
 
74
            return status;
 
75
        }
 
76
        switch (out) {
 
77
        case APR_FULL_BLOCK:
 
78
            apr_file_pipe_timeout_set(attr->child_out, -1);
 
79
            apr_file_pipe_timeout_set(attr->parent_out, -1);       
 
80
            break;
 
81
        case APR_PARENT_BLOCK:
 
82
            apr_file_pipe_timeout_set(attr->child_out, -1);
 
83
            break;
 
84
        case APR_CHILD_BLOCK:
 
85
            apr_file_pipe_timeout_set(attr->parent_out, -1);
 
86
            break;
 
87
        default:
 
88
            break;
 
89
        }
 
90
    } 
 
91
    if (err) {
 
92
        if ((status = apr_file_pipe_create(&attr->parent_err, &attr->child_err, 
 
93
                                   attr->pool)) != APR_SUCCESS) {
 
94
            return status;
 
95
        }
 
96
        switch (err) {
 
97
        case APR_FULL_BLOCK:
 
98
            apr_file_pipe_timeout_set(attr->child_err, -1);
 
99
            apr_file_pipe_timeout_set(attr->parent_err, -1);
 
100
            break;
 
101
        case APR_PARENT_BLOCK:
 
102
            apr_file_pipe_timeout_set(attr->child_err, -1);
 
103
            break;
 
104
        case APR_CHILD_BLOCK:
 
105
            apr_file_pipe_timeout_set(attr->parent_err, -1);
 
106
            break;
 
107
        default:
 
108
            break;
 
109
        }
 
110
    } 
 
111
    return APR_SUCCESS;
 
112
}
 
113
 
 
114
APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, 
 
115
                                               const char *dir) 
 
116
{
 
117
    char * cwd;
 
118
    if (dir[0] != '/') {
 
119
        cwd = (char*)malloc(sizeof(char) * PATH_MAX);
 
120
        getcwd(cwd, PATH_MAX);
 
121
        attr->currdir = (char *)apr_pstrcat(attr->pool, cwd, "/", dir, NULL);
 
122
        free(cwd);
 
123
    } else {
 
124
        attr->currdir = (char *)apr_pstrdup(attr->pool, dir);
 
125
    }
 
126
    if (attr->currdir) {
 
127
        return APR_SUCCESS;
 
128
    }
 
129
    return APR_ENOMEM;
 
130
}
 
131
 
 
132
APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
 
133
                                                   apr_cmdtype_e cmd) 
 
134
{
 
135
    attr->cmdtype = cmd;
 
136
    return APR_SUCCESS;
 
137
}
 
138
 
 
139
APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) 
 
140
{
 
141
    attr->detached = detach;
 
142
    return APR_SUCCESS;
 
143
}
 
144
 
 
145
APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
 
146
{
 
147
    int pid;
 
148
    
 
149
    if ((pid = fork()) < 0) {
 
150
        return errno;
 
151
    }
 
152
    else if (pid == 0) {
 
153
                /* This is really ugly...
 
154
                 * The semantics of BeOS's fork() are that areas (used for shared
 
155
                 * memory) get COW'd :-( The only way we can make shared memory
 
156
                 * work across fork() is therefore to find any areas that have
 
157
                 * been created and then clone them into our address space.
 
158
         * Thankfully only COW'd areas have the lock variable set at
 
159
         * anything but 0, so we can use that to find the areas we need to
 
160
         * copy. Of course what makes it even worse is that the loop through
 
161
         * the area's will go into an infinite loop, eating memory and then
 
162
         * eventually segfault unless we know when we reach then end of the
 
163
         * "original" areas and stop. Why? Well, we delete the area and then
 
164
         * add another to the end of the list...
 
165
                 */
 
166
                area_info ai;
 
167
                int32 cookie = 0;
 
168
        area_id highest = 0;
 
169
                
 
170
        while (get_next_area_info(0, &cookie, &ai) == B_OK)
 
171
            if (ai.area > highest)
 
172
                highest = ai.area;
 
173
        cookie = 0;
 
174
        while (get_next_area_info(0, &cookie, &ai) == B_OK) {
 
175
            if (ai.area > highest)
 
176
                break;
 
177
            if (ai.lock > 0) {
 
178
                area_id original = find_area(ai.name);
 
179
                delete_area(ai.area);
 
180
                clone_area(ai.name, &ai.address, B_CLONE_ADDRESS,
 
181
                           ai.protection, original);
 
182
            }
 
183
        }
 
184
                
 
185
        proc->pid = pid;
 
186
        proc->in = NULL; 
 
187
        proc->out = NULL; 
 
188
        proc->err = NULL;
 
189
        return APR_INCHILD;
 
190
    }
 
191
    proc->pid = pid;
 
192
    proc->in = NULL; 
 
193
    proc->out = NULL; 
 
194
    proc->err = NULL; 
 
195
    return APR_INPARENT;
 
196
}
 
197
 
 
198
APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
 
199
                                                       apr_child_errfn_t *errfn)
 
200
{
 
201
    /* won't ever be called on this platform, so don't save the function pointer */
 
202
    return APR_SUCCESS;
 
203
}
 
204
 
 
205
APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
 
206
                                                       apr_int32_t chk)
 
207
{
 
208
    /* won't ever be used on this platform, so don't save the flag */
 
209
    return APR_SUCCESS;
 
210
}
 
211
 
 
212
APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
 
213
                                                       apr_int32_t addrspace)
 
214
{
 
215
    /* won't ever be used on this platform, so don't save the flag */
 
216
    return APR_SUCCESS;
 
217
}
 
218
 
 
219
APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, const char *progname, 
 
220
                                          const char * const *args,
 
221
                                          const char * const *env, 
 
222
                                          apr_procattr_t *attr, 
 
223
                                          apr_pool_t *pool)
 
224
{
 
225
    int i=0,nargs=0;
 
226
    char **newargs = NULL;
 
227
    thread_id newproc, sender;
 
228
    struct send_pipe *sp;        
 
229
    char * dir = NULL;
 
230
            
 
231
    sp = (struct send_pipe *)apr_palloc(pool, sizeof(struct send_pipe));
 
232
 
 
233
    new->in = attr->parent_in;
 
234
    new->err = attr->parent_err;
 
235
    new->out = attr->parent_out;
 
236
        sp->in  = attr->child_in  ? attr->child_in->filedes  : -1;
 
237
        sp->out = attr->child_out ? attr->child_out->filedes : -1;
 
238
        sp->err = attr->child_err ? attr->child_err->filedes : -1;
 
239
 
 
240
    i = 0;
 
241
    while (args && args[i]) {
 
242
        i++;
 
243
    }
 
244
 
 
245
        newargs = (char**)malloc(sizeof(char *) * (i + 4));
 
246
        newargs[0] = strdup("/boot/home/config/bin/apr_proc_stub");
 
247
    if (attr->currdir == NULL) {
 
248
        /* we require the directory , so use a temp. variable */
 
249
        dir = malloc(sizeof(char) * PATH_MAX);
 
250
        getcwd(dir, PATH_MAX);
 
251
        newargs[1] = strdup(dir);
 
252
        free(dir);
 
253
    } else {
 
254
        newargs[1] = strdup(attr->currdir);
 
255
    }
 
256
    newargs[2] = strdup(progname);
 
257
    i=0;nargs = 3;
 
258
 
 
259
    while (args && args[i]) {
 
260
        newargs[nargs] = strdup(args[i]);
 
261
        i++;nargs++;
 
262
    }
 
263
    newargs[nargs] = NULL;
 
264
 
 
265
    /* ### we should be looking at attr->cmdtype in here... */
 
266
 
 
267
    newproc = load_image(nargs, (const char**)newargs, (const char**)env);
 
268
 
 
269
    /* load_image copies the data so now we can free it... */
 
270
    while (--nargs >= 0)
 
271
        free (newargs[nargs]);
 
272
    free(newargs);
 
273
        
 
274
    if (newproc < B_NO_ERROR) {
 
275
        return errno;
 
276
    }
 
277
 
 
278
    resume_thread(newproc);
 
279
 
 
280
    if (attr->child_in) {
 
281
        apr_file_close(attr->child_in);
 
282
    }
 
283
    if (attr->child_out) {
 
284
        apr_file_close(attr->child_out);
 
285
    }
 
286
    if (attr->child_err) {
 
287
        apr_file_close(attr->child_err);
 
288
    }
 
289
 
 
290
    send_data(newproc, 0, (void*)sp, sizeof(struct send_pipe));
 
291
    new->pid = newproc;
 
292
 
 
293
    /* before we go charging on we need the new process to get to a 
 
294
     * certain point.  When it gets there it'll let us know and we
 
295
     * can carry on. */
 
296
    receive_data(&sender, (void*)NULL,0);
 
297
    
 
298
    return APR_SUCCESS;
 
299
}
 
300
 
 
301
APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
 
302
                                                  int *exitcode,
 
303
                                                  apr_exit_why_e *exitwhy,
 
304
                                                  apr_wait_how_e waithow, 
 
305
                                                  apr_pool_t *p)
 
306
{
 
307
    proc->pid = -1;
 
308
    return apr_proc_wait(proc, exitcode, exitwhy, waithow);
 
309
 
310
 
 
311
APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
 
312
                                        int *exitcode, 
 
313
                                        apr_exit_why_e *exitwhy,
 
314
                                        apr_wait_how_e waithow)
 
315
{
 
316
    pid_t pstatus;
 
317
    int waitpid_options = WUNTRACED;
 
318
    int exit_int;
 
319
    int ignore;
 
320
    apr_exit_why_e ignorewhy;
 
321
 
 
322
    if (exitcode == NULL) {
 
323
        exitcode = &ignore;
 
324
    }
 
325
    if (exitwhy == NULL) {
 
326
        exitwhy = &ignorewhy;
 
327
    }
 
328
 
 
329
    if (waithow != APR_WAIT) {
 
330
        waitpid_options |= WNOHANG;
 
331
    }
 
332
 
 
333
    if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) {
 
334
        proc->pid = pstatus;
 
335
        if (WIFEXITED(exit_int)) {
 
336
            *exitwhy = APR_PROC_EXIT;
 
337
            *exitcode = WEXITSTATUS(exit_int);
 
338
        }
 
339
        else if (WIFSIGNALED(exit_int)) {
 
340
            *exitwhy = APR_PROC_SIGNAL;
 
341
            *exitcode = WTERMSIG(exit_int);
 
342
        }
 
343
        else {
 
344
 
 
345
            /* unexpected condition */
 
346
            return APR_EGENERAL;
 
347
        }
 
348
        return APR_CHILD_DONE;
 
349
    }
 
350
    else if (pstatus == 0) {
 
351
        return APR_CHILD_NOTDONE;
 
352
    }
 
353
 
 
354
    return errno;
 
355
 
356
 
 
357
APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in,
 
358
                                   apr_file_t *parent_in)
 
359
{
 
360
    if (attr->child_in == NULL && attr->parent_in == NULL)
 
361
        apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool);
 
362
 
 
363
    if (child_in != NULL)
 
364
        apr_file_dup(&attr->child_in, child_in, attr->pool);
 
365
 
 
366
    if (parent_in != NULL)
 
367
        apr_file_dup(&attr->parent_in, parent_in, attr->pool);
 
368
 
 
369
    return APR_SUCCESS;
 
370
}
 
371
 
 
372
APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out,
 
373
                                                     apr_file_t *parent_out)
 
374
{
 
375
    if (attr->child_out == NULL && attr->parent_out == NULL)
 
376
        apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool);
 
377
 
 
378
    if (child_out != NULL)
 
379
        apr_file_dup(&attr->child_out, child_out, attr->pool);
 
380
 
 
381
    if (parent_out != NULL)
 
382
        apr_file_dup(&attr->parent_out, parent_out, attr->pool);
 
383
 
 
384
    return APR_SUCCESS;
 
385
}
 
386
 
 
387
APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err,
 
388
                                                     apr_file_t *parent_err)
 
389
{
 
390
    if (attr->child_err == NULL && attr->parent_err == NULL)
 
391
        apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool);
 
392
 
 
393
    if (child_err != NULL)
 
394
        apr_file_dup(&attr->child_err, child_err, attr->pool);
 
395
 
 
396
    if (parent_err != NULL)
 
397
        apr_file_dup(&attr->parent_err, parent_err, attr->pool);
 
398
 
 
399
    return APR_SUCCESS;
 
400
}
 
401
 
 
402
APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32_t what, 
 
403
                                                  void *limit)
 
404
{
 
405
    return APR_ENOTIMPL;
 
406
}
 
407
 
 
408
APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, 
 
409
                                                const char *username,
 
410
                                                const char *password)
 
411
{
 
412
    return APR_ENOTIMPL;
 
413
}
 
414
 
 
415
APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
 
416
                                                 const char *groupname)
 
417
{
 
418
    return APR_ENOTIMPL;
 
419
}