Using Apache Portable Run-Time by Ryan Bloom Listing One static void setup_shared_mem(pool *p) { #ifdef USE_OS2_SCOREBOARD ... m=(caddr_t) create_shared_heap("\\SHAREMEM\\SCOREBOARD", #elif defined(USE_POSIX_SCOREBOARD) ... fd=shm_open(ap_scoreboard_fname, O_RDWR|O_CREAT|S_IRUSR|S_IWUSR); ... #else ... fd=ap_popenf(p, ap_scoreboard_fname, O_CREAT |O_BINARY|O_RDWR, 0644); ... #endif } static void init_scoreboard(pool *p) { if (ap_scoreboard_image == NULL) { setup_shared_mem(p); } ... } static void setup_shared_mem(pool *p) { ... #ifdef APR_HAS_SHMEM if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE, fname, p) != APR_SUCCESS) { ... } #else ... /* use a file for shared memory */ ... #endif } static void init_scoreboard(pool *p) { if (ap_scoreboard_image == NULL) { setup_shared_mem(p); } ... } Listing Two ap_file_t *fd; ap_status_t rv; rv = ap_open_file(&fd, "testfile", APR_WRITE, APR_OS_DEFAULT, pool) if (rv != APR_SUCCESS) { rv = ap_canonical_error(rv); switch (rv) { case APR_EISDIR: /* The file requested is a directory */ case APR_ACCESS: /* The current user doesn't have write access to this file */ case APR_EMFILE: /* The process already has the maximum number of files open */ } } Listing Three void duplicate_stderr(ap_file_t *error_log) { int errfile; ap_get_os_file(&errfile, error_log); dup2(errfile, STDERR_FILENO); } Listing Four int open_the_file(char *fname, int permissions, int access) { int fd; fd = open(fname, access, permissions); if (fd > 0) { return fd; } return errno; } Listing Five void *open_the_file(char *fname, int permissions, int access) { HANDLE fd; int *errval; fd = CreateFile(fname, access, permissions, NULL, createflags, permissions, 0); if (fd != INVALID_HANDLE_VALUE) return fd; } *errval = GetLastError(); return errval; } Listing Six ap_status_t open_the_file(char *fname, int permissions, int access, ap_pool_t *cont, ap_file_t *newfile); { ap_status_t rv; rv = ap_open(&newfile, fname, access, permissions, cont); return rv; } Listing Seven int create_the_process(char &program_name, char *const args[], char **env, int pipein, int pipeout, int pipeerr) { int pid; if (((*new)->pid = fork()) < 0) { return errno; } /* Child process */ dup2(pipein, STDIN_FILENO); dup2(pipeout, STDOUT_FILENO); dup2(pipeerr, STDERR_FILENO); execve(progname, args, env); } /* We forked properly, but there is no way to know if execve worked. */ ap_close(pipein); ap_close(pipeout); ap_close(pipeerr); return 0; } Listing Eight int create_the_process(char *program_name, char *const args[], char **env, HANDLE pipein, HANDLE pipeout, HANDLE pipeerr) { HANDLE pid, hCurrentProcess; STARTUPINFO si; hCurrentProcess = GetCurrentProcess(); si.cb = sizeof(si); si.hStdInput = pipein; si.hStdOutput = pipeout; si.hStdError = pipeerr; if (CreateProcess(NULL, program_name, NULL, NULL, TRUE, 0, env, NULL, &si, &pid)) { return 0; } return GetLastError(); } Listing Nine int create_the_process(char *program_name, char *const args[], char **env, ap_proc_t *proc, ap_pool_t *pool) { ap_proc_attr *attr = NULL; ap_create_procattr(&attr, pool); /* setup pipes to communicate with the child process. The second * argument details how to setup the pipe for child's stdin, the second is for child's * stdout, and the third is for the child's stderr. There are multiple * options for these arguments: * APR_FULL_BLOCK: Both child and parent block on reads and writes. * APR_PARENT_BLOCK: Parent blocks and reads and writes, child does not. * APR_CHILD_BLOCK: Child blocks on reads and writes, parent does not. * APR_NO_PIPE: No pipe between child and parent for this input/output ap_set_procattr_io(attr, APR_FULL_BLOCK, APR_CHILD_BLOCK, APR_NO_PIPE); return ap_create_process(&proc, program_name, args, NULL, attr, pool); } 3