/* * initialized the shared memory block in the parent process */ int oidc_cache_shm_post_config(server_rec *s) { oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(s->module_config, &auth_openidc_module); if (cfg->cache_cfg != NULL) return APR_SUCCESS; oidc_cache_cfg_shm_t *context = oidc_cache_shm_cfg_create(s->process->pool); cfg->cache_cfg = context; /* create the shared memory segment */ apr_status_t rv = apr_shm_create(&context->shm, sizeof(oidc_cache_shm_entry_t) * cfg->cache_shm_size_max, NULL, s->process->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "oidc_cache_shm_post_config: apr_shm_create failed to create shared memory segment"); return HTTP_INTERNAL_SERVER_ERROR; } /* initialize the whole segment to '/0' */ int i; oidc_cache_shm_entry_t *table = apr_shm_baseaddr_get(context->shm); for (i = 0; i < cfg->cache_shm_size_max; i++) { table[i].key[0] = '\0'; table[i].access = 0; } const char *dir; apr_temp_dir_get(&dir, s->process->pool); /* construct the mutex filename */ context->mutex_filename = apr_psprintf(s->process->pool, "%s/httpd_mutex.%ld.%pp", dir, (long int) getpid(), s); /* create the mutex lock */ rv = apr_global_mutex_create(&context->mutex, (const char *) context->mutex_filename, APR_LOCK_DEFAULT, s->process->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "oidc_cache_shm_post_config: apr_global_mutex_create failed to create mutex on file %s", context->mutex_filename); return HTTP_INTERNAL_SERVER_ERROR; } /* need this on Linux */ #ifdef AP_NEED_SET_MUTEX_PERMS #if MODULE_MAGIC_NUMBER_MAJOR >= 20081201 rv = ap_unixd_set_global_mutex_perms(context->mutex); #else rv = unixd_set_global_mutex_perms(context->mutex); #endif if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "oidc_cache_shm_post_config: unixd_set_global_mutex_perms failed; could not set permissions "); return HTTP_INTERNAL_SERVER_ERROR; } #endif return OK; }
apr_status_t kahanaIOTempDir( apr_pool_t *p, const char **dir ) { apr_status_t rc; // create temp file if( ( rc = apr_temp_dir_get( dir, p ) ) ){ kahanaLogPut( NULL, NULL, "failed to apr_temp_dir_get(): %s", STRERROR_APR( rc ) ); } return rc; }
Path Path::getTempDir() { const char * tempdir = NULL; Pool pool; if (apr_temp_dir_get(&tempdir, pool) != APR_SUCCESS) { tempdir = NULL; } return tempdir; }
apr_status_t kahanaIOTempFile( apr_pool_t *p, apr_file_t **fp, apr_int32_t flags ) { int rc = APR_SUCCESS; const char *tmpdir = NULL; // create temp file if( ( rc = apr_temp_dir_get( &tmpdir, p ) ) ){ kahanaLogPut( NULL, NULL, "failed to apr_temp_dir_get(): %s", STRERROR_APR( rc ) ); } else if( ( rc = apr_file_mktemp( fp, (char*)apr_pstrcat( p, tmpdir, "/XXXXXX", NULL ), flags, p ) ) ){ kahanaLogPut( NULL, NULL, "failed to apr_file_mktemp(): %s", STRERROR_APR( rc ) ); } return rc; }
int lua_apr_temp_dir_get(lua_State *L) { apr_pool_t* memory_pool; const char *filepath; apr_status_t status; memory_pool = to_pool(L); status = apr_temp_dir_get(&filepath, memory_pool); if (status != APR_SUCCESS) { return push_error_status(L, status); } else { lua_pushstring(L, filepath); return 1; } }
static int Ganglia_cfg_include(cfg_t *cfg, cfg_opt_t *opt, int argc, const char **argv) { char *fname = (char*)argv[0]; struct stat statbuf; DIR *dir; struct dirent *entry; if(argc != 1) { cfg_error(cfg, "wrong number of arguments to cfg_include()"); return 1; } if (stat (fname, &statbuf) == 0) { return cfg_include(cfg, opt, argc, argv); } else if (has_wildcard(fname)) { int ret; char *path = calloc(strlen(fname) + 1, sizeof(char)); char *pattern = NULL; char *idx = strrchr(fname, '/'); apr_pool_t *p; apr_file_t *ftemp; char *dirname = NULL; char tn[] = "gmond.tmp.XXXXXX"; if (idx == NULL) { idx = strrchr(fname, '\\'); } if (idx == NULL) { strncpy (path, ".", 1); pattern = fname; } else { strncpy (path, fname, idx - fname); pattern = idx + 1; } apr_pool_create(&p, NULL); if (apr_temp_dir_get((const char**)&dirname, p) != APR_SUCCESS) { #ifndef LINUX cfg_error(cfg, "failed to determine the temp dir"); apr_pool_destroy(p); return 1; #else /* * workaround APR BUG46297 by using the POSIX shared memory * ramdrive that is available since glibc 2.2 */ dirname = apr_psprintf(p, "%s", "/dev/shm"); #endif } dirname = apr_psprintf(p, "%s/%s", dirname, tn); if (apr_file_mktemp(&ftemp, dirname, APR_CREATE | APR_READ | APR_WRITE | APR_DELONCLOSE, p) != APR_SUCCESS) { cfg_error(cfg, "unable to create a temporary file %s", dirname); apr_pool_destroy(p); return 1; } dir = opendir(path); if(dir != NULL){ while((entry = readdir(dir)) != NULL) { ret = fnmatch(pattern, entry->d_name, FNM_PATHNAME|FNM_PERIOD); if (ret == 0) { char *newpath, *line; newpath = apr_psprintf (p, "%s/%s", path, entry->d_name); line = apr_pstrcat(p, "include ('", newpath, "')\n", NULL); apr_file_puts(line, ftemp); } } closedir(dir); free (path); argv[0] = dirname; if (cfg_include(cfg, opt, argc, argv)) cfg_error(cfg, "failed to process include file %s", fname); else debug_msg("processed include file %s\n", fname); } apr_file_close(ftemp); apr_pool_destroy(p); argv[0] = fname; } else { cfg_error(cfg, "invalid include path"); return 1; } return 0; }
/* * Let's do it. We end up doing a lot of file opening and closing, * but what do we care? This application isn't run constantly. */ int main(int argc, const char * const argv[]) { apr_file_t *fpw = NULL; char record[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; char *password = NULL; char *pwfilename = NULL; char *user = NULL; char tn[] = "htpasswd.tmp.XXXXXX"; char *dirname; char *scratch, cp[MAX_STRING_LEN]; int found = 0; int i; int alg = ALG_APMD5; int mask = 0; apr_pool_t *pool; int existing_file = 0; #if APR_CHARSET_EBCDIC apr_status_t rv; apr_xlate_t *to_ascii; #endif apr_app_initialize(&argc, &argv, NULL); atexit(terminate); apr_pool_create(&pool, NULL); apr_file_open_stderr(&errfile, pool); #if APR_CHARSET_EBCDIC rv = apr_xlate_open(&to_ascii, "ISO-8859-1", APR_DEFAULT_CHARSET, pool); if (rv) { apr_file_printf(errfile, "apr_xlate_open(to ASCII)->%d" NL, rv); exit(1); } rv = apr_SHA1InitEBCDIC(to_ascii); if (rv) { apr_file_printf(errfile, "apr_SHA1InitEBCDIC()->%d" NL, rv); exit(1); } rv = apr_MD5InitEBCDIC(to_ascii); if (rv) { apr_file_printf(errfile, "apr_MD5InitEBCDIC()->%d" NL, rv); exit(1); } #endif /*APR_CHARSET_EBCDIC*/ check_args(pool, argc, argv, &alg, &mask, &user, &pwfilename, &password); #if defined(WIN32) || defined(NETWARE) if (alg == ALG_CRYPT) { alg = ALG_APMD5; apr_file_printf(errfile, "Automatically using MD5 format." NL); } #endif #if (!(defined(WIN32) || defined(TPF) || defined(NETWARE))) if (alg == ALG_PLAIN) { apr_file_printf(errfile,"Warning: storing passwords as plain text " "might just not work on this platform." NL); } #endif /* * Only do the file checks if we're supposed to frob it. */ if (!(mask & APHTP_NOFILE)) { existing_file = exists(pwfilename, pool); if (existing_file) { /* * Check that this existing file is readable and writable. */ if (!accessible(pool, pwfilename, APR_READ | APR_APPEND)) { apr_file_printf(errfile, "%s: cannot open file %s for " "read/write access" NL, argv[0], pwfilename); exit(ERR_FILEPERM); } } else { /* * Error out if -c was omitted for this non-existant file. */ if (!(mask & APHTP_NEWFILE)) { apr_file_printf(errfile, "%s: cannot modify file %s; use '-c' to create it" NL, argv[0], pwfilename); exit(ERR_FILEPERM); } /* * As it doesn't exist yet, verify that we can create it. */ if (!accessible(pool, pwfilename, APR_CREATE | APR_WRITE)) { apr_file_printf(errfile, "%s: cannot create file %s" NL, argv[0], pwfilename); exit(ERR_FILEPERM); } } } /* * All the file access checks (if any) have been made. Time to go to work; * try to create the record for the username in question. If that * fails, there's no need to waste any time on file manipulations. * Any error message text is returned in the record buffer, since * the mkrecord() routine doesn't have access to argv[]. */ if (!(mask & APHTP_DELUSER)) { i = mkrecord(user, record, sizeof(record) - 1, password, alg); if (i != 0) { apr_file_printf(errfile, "%s: %s" NL, argv[0], record); exit(i); } if (mask & APHTP_NOFILE) { printf("%s" NL, record); exit(0); } } /* * We can access the files the right way, and we have a record * to add or update. Let's do it.. */ if (apr_temp_dir_get((const char**)&dirname, pool) != APR_SUCCESS) { apr_file_printf(errfile, "%s: could not determine temp dir" NL, argv[0]); exit(ERR_FILEPERM); } dirname = apr_psprintf(pool, "%s/%s", dirname, tn); if (apr_file_mktemp(&ftemp, dirname, 0, pool) != APR_SUCCESS) { apr_file_printf(errfile, "%s: unable to create temporary file %s" NL, argv[0], dirname); exit(ERR_FILEPERM); } /* * If we're not creating a new file, copy records from the existing * one to the temporary file until we find the specified user. */ if (existing_file && !(mask & APHTP_NEWFILE)) { if (apr_file_open(&fpw, pwfilename, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool) != APR_SUCCESS) { apr_file_printf(errfile, "%s: unable to read file %s" NL, argv[0], pwfilename); exit(ERR_FILEPERM); } while (apr_file_gets(line, sizeof(line), fpw) == APR_SUCCESS) { char *colon; strcpy(cp, line); scratch = cp; while (apr_isspace(*scratch)) { ++scratch; } if (!*scratch || (*scratch == '#')) { putline(ftemp, line); continue; } /* * See if this is our user. */ colon = strchr(scratch, ':'); if (colon != NULL) { *colon = '\0'; } else { /* * If we've not got a colon on the line, this could well * not be a valid htpasswd file. * We should bail at this point. */ apr_file_printf(errfile, "%s: The file %s does not appear " "to be a valid htpasswd file." NL, argv[0], pwfilename); apr_file_close(fpw); exit(ERR_INVALID); } if (strcmp(user, scratch) != 0) { putline(ftemp, line); continue; } else { if (!(mask & APHTP_DELUSER)) { /* We found the user we were looking for. * Add him to the file. */ apr_file_printf(errfile, "Updating "); putline(ftemp, record); found++; } else { /* We found the user we were looking for. * Delete them from the file. */ apr_file_printf(errfile, "Deleting "); found++; } } } apr_file_close(fpw); } if (!found && !(mask & APHTP_DELUSER)) { apr_file_printf(errfile, "Adding "); putline(ftemp, record); } else if (!found && (mask & APHTP_DELUSER)) { apr_file_printf(errfile, "User %s not found" NL, user); exit(0); } apr_file_printf(errfile, "password for user %s" NL, user); /* The temporary file has all the data, just copy it to the new location. */ if (apr_file_copy(dirname, pwfilename, APR_FILE_SOURCE_PERMS, pool) != APR_SUCCESS) { apr_file_printf(errfile, "%s: unable to update file %s" NL, argv[0], pwfilename); exit(ERR_FILEPERM); } apr_file_close(ftemp); return 0; }
static int exipc_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { void *data; /* These two help ensure that we only init once. */ const char *userdata_key; apr_status_t rs; exipc_data *base; const char *tempdir; /* * The following checks if this routine has been called before. * This is necessary because the parent process gets initialized * a couple of times as the server starts up, and we don't want * to create any more mutexes and shared memory segments than * we're actually going to use. * * The key needs to be unique for the entire web server, so put * the module name in it. */ userdata_key = "example_ipc_init_module"; apr_pool_userdata_get(&data, userdata_key, s->process->pool); if (!data) { /* * If no data was found for our key, this must be the first * time the module is initialized. Put some data under that * key and return. */ apr_pool_userdata_set((const void *) 1, userdata_key, apr_pool_cleanup_null, s->process->pool); return OK; } /* Kilroy was here */ /* * Both the shared memory and mutex allocation routines take a * file name. Depending on system-specific implementation of these * routines, that file may or may not actually be created. We'd * like to store those files in the operating system's designated * temporary directory, which APR can point us to. */ rs = apr_temp_dir_get(&tempdir, pconf); if (APR_SUCCESS != rs) { ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to find temporary directory"); return HTTP_INTERNAL_SERVER_ERROR; } /* Create the shared memory segment */ /* * Create a unique filename using our pid. This information is * stashed in the global variable so the children inherit it. */ shmfilename = apr_psprintf(pconf, "%s/httpd_shm.%ld", tempdir, (long int)getpid()); /* Now create that segment */ rs = apr_shm_create(&exipc_shm, sizeof(exipc_data), (const char *) shmfilename, pconf); if (APR_SUCCESS != rs) { ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to create shared memory segment on file %s", shmfilename); return HTTP_INTERNAL_SERVER_ERROR; } /* Created it, now let's zero it out */ base = (exipc_data *)apr_shm_baseaddr_get(exipc_shm); base->counter = 0; /* Create global mutex */ /* * Create another unique filename to lock upon. Note that * depending on OS and locking mechanism of choice, the file * may or may not be actually created. */ mutexfilename = apr_psprintf(pconf, "%s/httpd_mutex.%ld", tempdir, (long int) getpid()); rs = apr_global_mutex_create(&exipc_mutex, (const char *) mutexfilename, APR_LOCK_DEFAULT, pconf); if (APR_SUCCESS != rs) { ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to create mutex on file %s", mutexfilename); return HTTP_INTERNAL_SERVER_ERROR; } /* * After the mutex is created, its permissions need to be adjusted * on unix platforms so that the child processe can acquire * it. This call takes care of that. The preprocessor define was * set up early in this source file since Apache doesn't provide * it. */ #ifdef MOD_EXIPC_SET_MUTEX_PERMS rs = unixd_set_global_mutex_perms(exipc_mutex); if (APR_SUCCESS != rs) { ap_log_error(APLOG_MARK, APLOG_CRIT, rs, s, "Parent could not set permissions on Example IPC " "mutex: check User and Group directives"); return HTTP_INTERNAL_SERVER_ERROR; } #endif /* MOD_EXIPC_SET_MUTEX_PERMS */ /* * Destroy the shm segment when the configuration pool gets destroyed. This * happens on server restarts. The parent will then (above) allocate a new * shm segment that the new children will bind to. */ apr_pool_cleanup_register(pconf, NULL, shm_cleanup_wrapper, apr_pool_cleanup_null); return OK; }
/* * fstream_open * * Allocate a new file stream given a path (a url). in case of wildcards, * expand them here. we end up with a final list of files and include them * in our filestream that we return. * * In case of errors we set the proper http response code to send to the client. */ fstream_t* fstream_open(const char *path, const struct fstream_options *options, int *response_code, const char **response_string) { int i; fstream_t* fs; *response_code = 500; *response_string = "Internal Server Error"; if (0 == (fs = gfile_malloc(sizeof *fs))) { gfile_printf_then_putc_newline("fstream out of memory"); return 0; } memset(fs, 0, sizeof *fs); fs->options = *options; fs->buffer = gfile_malloc(options->bufsize); /* * get a list of all files that were requested to be read and include them * in our fstream. This includes any wildcard pattern matching. */ if (glob_path(fs, path)) { fstream_close(fs); return 0; } /* * If the list of files in our filestrem includes a directory name, expand * the directory and add all the files inside of it. */ if (fpath_all_directories(&fs->glob)) { if (expand_directories(fs)) { fstream_close(fs); return 0; } } /* * check if we don't have any matching files */ if (fs->glob.gl_pathc == 0) { gfile_printf_then_putc_newline("fstream bad path: %s", path); fstream_close(fs); *response_code = 404; *response_string = "No matching file(s) found"; return 0; } if (fs->glob.gl_pathc != 1 && options->forwrite) { gfile_printf_then_putc_newline("fstream open for write found more than one file (%d)", fs->glob.gl_pathc); *response_code = 404; *response_string = "More than 1 file found for writing. Unsupported operation."; fstream_close(fs); return 0; } #ifdef GPFXDIST /* * when the subprocess transformation wants to handle iteration over the files * we write the paths to a temporary file and replace the fs->glob items with * just a single entry referencing the path to the temporary file. */ if (options->transform && options->transform->pass_paths) { apr_pool_t* mp = options->transform->mp; apr_file_t* f = NULL; const char* tempdir = NULL; char* tempfilename = NULL; apr_status_t rv; if ((rv = apr_temp_dir_get(&tempdir, mp)) != APR_SUCCESS) { *response_code = 500; *response_string = "failed to get temporary directory for paths file"; gfile_printf_then_putc_newline(*response_string); fstream_close(fs); return 0; } tempfilename = apr_pstrcat(mp, tempdir, "/pathsXXXXXX", NULL); if ((rv = apr_file_mktemp(&f, tempfilename, APR_CREATE|APR_WRITE|APR_EXCL, mp)) != APR_SUCCESS) { *response_code = 500; *response_string = "failed to open temporary paths file"; gfile_printf_then_putc_newline(*response_string); fstream_close(fs); return 0; } options->transform->tempfilename = tempfilename; for (i = 0; i<fs->glob.gl_pathc; i++) { char* filename = fs->glob.gl_pathv[i]; apr_size_t expected = strlen(filename) + 1; if (apr_file_printf(f, "%s\n", filename) < expected) { apr_file_close(f); *response_code = 500; *response_string = "failed to fully write path to temporary paths file"; gfile_printf_then_putc_newline(*response_string); fstream_close(fs); return 0; } } apr_file_close(f); if (glob_adjust(fs, tempfilename, response_code, response_string)) { fstream_close(fs); return 0; } } #endif /* * if writing - check write access rights for the one file. * if reading - check read access right for all files, and * then close them, leaving the first file open. * */ for (i = fs->glob.gl_pathc; --i >= 0;) { /* * CR-2173 - the fstream code allows the upper level logic to treat a * collection of input sources as a single stream. One problem it has * to handle is the possibility that some of the underlying sources may * not be readable. Here we're trying to detect potential problems in * advance by checking that we can open and close each source in our * list in reverse order. * * However in the case of subprocess transformations, we don't want to * start and stop each transformation in this manner. The check that * each transformation's underlying input source can be read is still * useful so we do those until we get to the first source, at which * point we proceed to just setup the tranformation for it. */ struct gpfxdist_t* transform = (i == 0) ? options->transform : NULL; gfile_close(&fs->fd); if (gfile_open(&fs->fd, fs->glob.gl_pathv[i], gfile_open_flags(options->forwrite, options->usesync), response_code, response_string, transform)) { gfile_printf_then_putc_newline("fstream unable to open file %s", fs->glob.gl_pathv[i]); fstream_close(fs); return 0; } fs->compressed_size += gfile_get_compressed_size(&fs->fd); } fs->line_number = 1; fs->skip_header_line = options->header; return fs; }
int main(int argc, const char * const argv[]) { apr_file_t *f; apr_status_t rv; char tn[] = "htdigest.tmp.XXXXXX"; char *dirname; char user[MAX_STRING_LEN]; char realm[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; char l[MAX_STRING_LEN]; char w[MAX_STRING_LEN]; char x[MAX_STRING_LEN]; int found; apr_app_initialize(&argc, &argv, NULL); atexit(terminate); apr_pool_create(&cntxt, NULL); apr_file_open_stderr(&errfile, cntxt); #if APR_CHARSET_EBCDIC rv = apr_xlate_open(&to_ascii, "ISO8859-1", APR_DEFAULT_CHARSET, cntxt); if (rv) { apr_file_printf(errfile, "apr_xlate_open(): %s (%d)\n", apr_strerror(rv, line, sizeof(line)), rv); exit(1); } #endif apr_signal(SIGINT, (void (*)(int)) interrupted); if (argc == 5) { if (strcmp(argv[1], "-c")) usage(); rv = apr_file_open(&f, argv[2], APR_WRITE | APR_CREATE, APR_OS_DEFAULT, cntxt); if (rv != APR_SUCCESS) { char errmsg[120]; apr_file_printf(errfile, "Could not open passwd file %s for writing: %s\n", argv[2], apr_strerror(rv, errmsg, sizeof errmsg)); exit(1); } apr_file_printf(errfile, "Adding password for %s in realm %s.\n", argv[4], argv[3]); add_password(argv[4], argv[3], f); apr_file_close(f); exit(0); } else if (argc != 4) usage(); if (apr_temp_dir_get((const char**)&dirname, cntxt) != APR_SUCCESS) { apr_file_printf(errfile, "%s: could not determine temp dir\n", argv[0]); exit(1); } dirname = apr_psprintf(cntxt, "%s/%s", dirname, tn); if (apr_file_mktemp(&tfp, dirname, 0, cntxt) != APR_SUCCESS) { apr_file_printf(errfile, "Could not open temp file %s.\n", dirname); exit(1); } if (apr_file_open(&f, argv[1], APR_READ, APR_OS_DEFAULT, cntxt) != APR_SUCCESS) { apr_file_printf(errfile, "Could not open passwd file %s for reading.\n", argv[1]); apr_file_printf(errfile, "Use -c option to create new one.\n"); cleanup_tempfile_and_exit(1); } apr_cpystrn(user, argv[3], sizeof(user)); apr_cpystrn(realm, argv[2], sizeof(realm)); found = 0; while (!(get_line(line, MAX_STRING_LEN, f))) { if (found || (line[0] == '#') || (!line[0])) { putline(tfp, line); continue; } strcpy(l, line); getword(w, l, ':'); getword(x, l, ':'); if (strcmp(user, w) || strcmp(realm, x)) { putline(tfp, line); continue; } else { apr_file_printf(errfile, "Changing password for user %s in realm %s\n", user, realm); add_password(user, realm, tfp); found = 1; } } if (!found) { apr_file_printf(errfile, "Adding user %s in realm %s\n", user, realm); add_password(user, realm, tfp); } apr_file_close(f); /* The temporary file has all the data, just copy it to the new location. */ if (apr_file_copy(dirname, argv[1], APR_FILE_SOURCE_PERMS, cntxt) != APR_SUCCESS) { apr_file_printf(errfile, "%s: unable to update file %s\n", argv[0], argv[1]); } apr_file_close(tfp); return 0; }
/* * This routine is called in the parent, so we'll set up the shared * memory segments and mutexs here. */ static int dosblock_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { void *data; /* These two help ensure that we only init once. */ const char *userdata_key; apr_status_t rs; const char *tempdir; dosblockipc_data *base; dosblock_cfg *cfg = (dosblock_cfg *)ap_get_module_config(s->module_config, &mod_dosblock_module); /* * The following checks if this routine has been called before. * This is necessary because the parent process gets initialized * a couple of times as the server starts up, and we don't want * to create any more mutexes and shared memory segments than * we're actually going to use. * * The key needs to be unique for the entire web server, so put * the module name in it. */ userdata_key = "dosblock_ipc_init_module"; apr_pool_userdata_get(&data, userdata_key, s->process->pool); if (!data) { /* * If no data was found for our key, this must be the first * time the module is initialized. Put some data under that * key and return. */ apr_pool_userdata_set((const void *) 1, userdata_key, apr_pool_cleanup_null, s->process->pool); return OK; } /* * The shared memory allocation routines take a file name. * Depending on system-specific implementation of these * routines, that file may or may not actually be created. We'd * like to store those files in the operating system's designated * temporary directory, which APR can point us to. */ rs = apr_temp_dir_get(&tempdir, pconf); if (APR_SUCCESS != rs) { ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to find temporary directory"); return HTTP_INTERNAL_SERVER_ERROR; } /* Create the shared memory segments. We also populate a dosrule to shared * memory mapping table with all the shared memory segments */ const apr_array_header_t *tarr = apr_table_elts(cfg->dosrulemap); const apr_table_entry_t *telts = (const apr_table_entry_t*)tarr->elts; int i; for (i = 0; i < tarr->nelts; ++i) { /* * Create a unique filename using our pid. This information is * stashed in the global variable so the children inherit it. */ shmfilename = apr_psprintf(pconf, "%s/httpd_shm_%s.%ld", tempdir, telts[i].key, (long int)getpid()); mutex_filename = apr_psprintf(pconf, "%s/httpd_mutex_%s.%ld", tempdir, telts[i].key, (long int)getpid()); /* Now create that shm segment. We prefer anonymous shm */ rs = apr_shm_create(&dosblockipc_shm[i], sizeof(dosblockipc_data), NULL, pconf); if (APR_ENOTIMPL == rs) { rs = apr_shm_create(&dosblockipc_shm[i], sizeof(dosblockipc_data), (const char *) shmfilename, pconf); } if (APR_SUCCESS != rs) { ap_log_error(APLOG_MARK, APLOG_ERR, rs, s, "Failed to create shared memory segment on file %s", shmfilename); return HTTP_INTERNAL_SERVER_ERROR; } apr_hash_set(cfg->dosrule_shm_map, telts[i].key, APR_HASH_KEY_STRING, apr_psprintf(pconf, "%d",i)); if (cfg->verbosity) ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Dos Rule configured is %s", telts[i].key); base = (dosblockipc_data *)apr_shm_baseaddr_get(dosblockipc_shm[i]); /* Now initialise the array of structs. Zero it out */ base->ds.t = 0; base->ds.isblocked = 0; base->ds.rate_when_blocked = 0; base->next = 0; int j; for (j=0; j<ARSIZE; j++) { base->dh[j].t = 0; base->dh[j].counter = 0; } /* Create global mutex */ rs = apr_global_mutex_create(&dosblockipc_mutex[i], mutex_filename, APR_LOCK_DEFAULT, pconf); if (APR_SUCCESS != rs) { return HTTP_INTERNAL_SERVER_ERROR; } #ifdef AP_NEED_SET_MUTEX_PERMS rs = unixd_set_global_mutex_perms(dosblockipc_mutex[i]); if (rs != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rs, s, "mod_dosblock: Parent could not set permissions " "on shared memory; check User and Group directives"); return rs; } #endif apr_table_set(cfg->dosrule_mutex_map, telts[i].key, mutex_filename); } /* * Destroy the shm segment when the configuration pool gets destroyed. This *happens on server restarts. The parent will then (above) allocate a new * shm segment that the new children will bind to. */ /* apr_pool_cleanup_register(pconf, NULL, shm_cleanup_wrapper(), apr_pool_cleanup_null); */ return OK; }