/* * $Id: fcgi_config.c,v 1.7 1999/04/22 04:45:17 roberts Exp $ */ #include "fcgi.h" /******************************************************************************* * Get the next configuration directive argument, & return an in_addr and port. * The arg must be in the form "host:port" where host can be an IP or hostname. * The pool arg should be persistant storage. */ static const char *get_host_n_port(pool *p, const char **arg, const char **host, u_int *port) { char *cvptr, *portStr; *host = ap_getword_conf(p, arg); if (**host == '\0') return "\"\""; portStr = strchr(*host, ':'); if (portStr == NULL) return "missing port specification"; /* Split the host and port portions */ *portStr++ = '\0'; /* Convert port number */ *port = (u_int)strtol(portStr, &cvptr, 10); if (*cvptr != '\0' || *port < 1 || *port > 65535) return ap_pstrcat(p, "bad port number \"", portStr, "\"", NULL); return NULL; } /******************************************************************************* * Get the next configuration directive argument, & return an u_int. * The pool arg should be temporary storage. */ static const char *get_u_int(pool *p, const char **arg, u_int *num, u_int min) { char *ptr; const char *val = ap_getword_conf(p, arg); if (*val == '\0') return "\"\""; *num = (u_int)strtol(val, &ptr, 10); if (*ptr != '\0') return ap_pstrcat(p, "\"", val, "\" must be a positive integer", NULL); else if (*num < min) return ap_psprintf(p, "\"%u\" must be >= %u", *num, min); return NULL; } /******************************************************************************* * Get the next configuration directive argument, & return a float. * The pool arg should be temporary storage. */ static const char *get_float(pool *p, const char **arg, float *num, float min, float max) { char *ptr; const char *val = ap_getword_conf(p, arg); if (*val == '\0') return "\"\""; *num = strtod(val, &ptr); if (*ptr != '\0') return ap_pstrcat(p, "\"", val, "\" is not a floating point number", NULL); if (*num < min || *num > max) return ap_psprintf(p, "\"%f\" is not between %f and %f", *num, min, max); return NULL; } /******************************************************************************* * Get the next configuration directive argument, & add it to an env array. * The pool arg should be permanent storage. */ static const char *get_env_var(pool *p, const char **arg, const char **envp, int *envc) { const char * const val = ap_getword_conf(p, arg); if (*val == '\0') return "\"\""; if (*envc >= MAX_INIT_ENV_VARS) return "too many variables, must be <= MAX_INIT_ENV_VARS"; if (strchr(val, '=') == NULL) *(envp + *envc) = ap_pstrcat(p, val, "=", getenv(val), NULL); else *(envp + *envc) = val; (*envc)++; return NULL; } /******************************************************************************* * Return a "standard" message for common configuration errors. */ static const char *invalid_value(pool *p, const char *cmd, const char *id, const char *opt, const char *err) { return ap_psprintf(p, "%s%s%s: invalid value for %s: %s", cmd, id ? " " : "", id ? id : "", opt, err); } /******************************************************************************* * Set/Reset the uid/gid that Apache and the PM will run as. This is ap_user_id * and ap_group_id if we're started as root, and euid/egid otherwise. Also try * to check that the config files don't set the User/Group after a FastCGI * directive is used that depends on it. */ /*@@@ To be complete, we should save a handle to the server each AppClass is * configured in and at init() check that the user/group is still what we * thought it was. Also the other directives should only be allowed in the * parent Apache server. */ const char *fcgi_config_set_fcgi_uid_n_gid(int set) { static int isSet = 0; uid_t uid = geteuid(); gid_t gid = getegid(); if (set == 0) { isSet = 0; fcgi_user_id = (uid_t)-1; fcgi_group_id = (gid_t)-1; return NULL; } uid = uid ? uid : ap_user_id; gid = uid ? gid : ap_group_id; if (isSet && (uid != fcgi_user_id || gid != fcgi_group_id)) { return "User/Group commands must preceed FastCGI server definitions"; } isSet = 1; fcgi_user_id = uid; fcgi_group_id = gid; return NULL; } void fcgi_config_reset_globals(void* dummy) { fcgi_config_pool = NULL; fcgi_servers = NULL; fcgi_config_set_fcgi_uid_n_gid(0); fcgi_suexec = NULL; fcgi_socket_dir = DEFAULT_SOCK_DIR; /* fcgi_dynamic_total_proc_count = 0; */ dynamicMaxProcs = FCGI_DEFAULT_MAX_PROCS; dynamicMinProcs = FCGI_DEFAULT_MIN_PROCS; dynamicMaxClassProcs = FCGI_DEFAULT_MAX_CLASS_PROCS; dynamicKillInterval = FCGI_DEFAULT_KILL_INTERVAL; dynamicUpdateInterval = FCGI_DEFAULT_UPDATE_INTERVAL; dynamicGain = FCGI_DEFAULT_GAIN; dynamicThreshhold1 = FCGI_DEFAULT_THRESHHOLD_1; dynamicThreshholdN = FCGI_DEFAULT_THRESHHOLD_N; dynamicPleaseStartDelay = FCGI_DEFAULT_START_PROCESS_DELAY; dynamicAppConnectTimeout = FCGI_DEFAULT_APP_CONN_TIMEOUT; dynamicEnvp = NULL; dynamicProcessSlack = FCGI_DEFAULT_PROCESS_SLACK; dynamicAutoRestart = FCGI_DEFAULT_RESTART_DYNAMIC; dynamicAutoUpdate = FCGI_DEFAULT_AUTOUPDATE; dynamicListenQueueDepth = FCGI_DEFAULT_LISTEN_Q; dynamicInitStartDelay = DEFAULT_INIT_START_DELAY; dynamicRestartDelay = FCGI_DEFAULT_RESTART_DELAY; } /******************************************************************************* * Create a directory to hold Unix/Domain sockets. */ const char *fcgi_config_make_dir(pool *tp, char *path) { struct stat finfo; const char *err = NULL; /* Is the directory spec'd correctly */ if (*path != '/') { return "path is not absolute (it must start with a \"/\")"; } else { int i = strlen(path) - 1; /* Strip trailing "/"s */ while(i > 0 && path[i] == '/') path[i--] = '\0'; } /* Does it exist? */ if (stat(path, &finfo) != 0) { /* No, but maybe we can create it */ if (mkdir(path, S_IRWXU) != 0) { return ap_psprintf(tp, "doesn't exist and can't be created: %s", strerror(errno)); } /* If we're root, we're gonna setuid/setgid so we need to chown */ if (geteuid() == 0 && chown(path, ap_user_id, ap_group_id) != 0) { return ap_psprintf(tp, "can't chown() to the server (uid %ld, gid %ld): %s", (long)ap_user_id, (long)ap_group_id, strerror(errno)); } } else { /* Yes, is it a directory? */ if (!S_ISDIR(finfo.st_mode)) return "isn't a directory!"; /* Can we RWX in there? */ err = fcgi_util_check_access(tp, NULL, &finfo, R_OK | W_OK | X_OK, fcgi_user_id, fcgi_group_id); if (err != NULL) { return ap_psprintf(tp, "access for server (uid %ld, gid %ld) failed: %s", (long)fcgi_user_id, (long)fcgi_group_id, err); } } return NULL; } /******************************************************************************* * Create a "dynamic" subdirectory and fcgi_dynamic_mbox (used for RH->PM comm) * in the fcgi_socket_dir with appropriate permissions. If the directory * already exists we don't mess with it unless 'wax' is set. */ const char *fcgi_config_make_dynamic_dir_n_mbox(pool *p, const int wax) { DIR *dp = NULL; struct dirent *dirp = NULL; int fd; const char *err; pool *tp; fcgi_dynamic_dir = ap_pstrcat(p, fcgi_socket_dir, "/dynamic", NULL); if ((err = fcgi_config_make_dir(p, fcgi_dynamic_dir))) return ap_psprintf(p, "can't create dynamic directory \"%s\": %s", fcgi_dynamic_dir, err); /* Don't step on a running server unless its OK. */ if (!wax) return NULL; /* Create a subpool for the directory operations */ tp = ap_make_sub_pool(p); dp = ap_popendir(tp, fcgi_dynamic_dir); if (dp == NULL) { ap_destroy_pool(tp); return ap_psprintf(p, "can't open dynamic directory \"%s\": %s", fcgi_dynamic_dir, strerror(errno)); } /* Delete everything in the directory, its all FCGI specific */ while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) { continue; } unlink(ap_pstrcat(tp, fcgi_dynamic_dir, "/", dirp->d_name, NULL)); } ap_destroy_pool(tp); /* Create fcgi_dynamic_mbox */ fcgi_dynamic_mbox = ap_pstrcat(p, fcgi_dynamic_dir, "/fcgi_dynamic_mbox", NULL); /* @@@ This really should be a socket or pipe */ fd = ap_popenf(p, fcgi_dynamic_mbox, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { return ap_psprintf(p, "can't create \"%s\": %s", fcgi_dynamic_mbox, strerror(errno)); } /* If we're root, were gonna setuid/setgid so chown */ if (geteuid() == 0 && fchown(fd, ap_user_id, ap_group_id) != 0) { return ap_psprintf(p, "can't chown() \"%s\" to server (uid %ld, gid %ld): %s", fcgi_dynamic_mbox, (long)ap_user_id, (long)ap_group_id, strerror(errno)); } ap_pclosef(p, fd); return NULL; } /******************************************************************************* * Change the directory used for the Unix/Domain sockets from the default. * Create the directory, the "dynamic" subdirectory, and the fcgi_dynamic_mbox used for * comm between the RH and the PM (we do this here, as well as in * fastcgi_init, so we can prevent Apache from starting if it fails). */ const char *fcgi_config_set_socket_dir(cmd_parms *cmd, void *dummy, char *arg) { pool * const tp = cmd->temp_pool; const char * const name = cmd->cmd->name; const char *err; if (strcmp(fcgi_socket_dir, DEFAULT_SOCK_DIR) != 0) { return ap_psprintf(tp, "%s %s: already defined as \"%s\"", name, arg, fcgi_socket_dir); } err = fcgi_config_set_fcgi_uid_n_gid(1); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, arg, err); if (fcgi_servers != NULL) { return ap_psprintf(tp, "The %s command must preceed static FastCGI server definitions", name); } if (!ap_os_is_path_absolute(arg)) arg = ap_make_full_path(cmd->pool, ap_server_root, arg); fcgi_socket_dir = arg; err = fcgi_config_make_dir(tp, fcgi_socket_dir); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, arg, err); err = fcgi_config_make_dynamic_dir_n_mbox(cmd->pool, 0); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, arg, err); return NULL; } /******************************************************************************* * Enable, disable, or specify the path to the suexec program. */ const char *fcgi_config_set_suexec(cmd_parms *cmd, void *dummy, const char *arg) { const char *err = NULL; const char * const name = cmd->cmd->name; pool * const tp = cmd->temp_pool; if (!ap_suexec_enabled) { if (strcasecmp(arg, "Off") != 0) { fprintf(stderr, "Warning: %s requires SUEXEC wrapper be enabled in Apache\n", name); } return NULL; } err = fcgi_config_set_fcgi_uid_n_gid(1); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, arg, err); if (fcgi_servers != NULL) { return ap_psprintf(tp, "The %s command must preceed static FastCGI server definitions", name); } if (strcasecmp(arg, "On") == 0) { fcgi_suexec = SUEXEC_BIN; } else if (strcasecmp(arg, "Off") == 0) { fcgi_suexec = NULL; } else { if (!ap_os_is_path_absolute(arg)) arg = ap_make_full_path(cmd->pool, ap_server_root, arg); err = fcgi_util_check_access(tp, arg, NULL, X_OK, fcgi_user_id, fcgi_group_id); if (err != NULL) { return ap_psprintf(tp, "%s: \"%s\" access for server (uid %ld, gid %ld) failed: %s", name, arg, (long)fcgi_user_id, (long)fcgi_group_id, err); } fcgi_suexec = arg; } return NULL; } /******************************************************************************* * Configure a static FastCGI server. */ const char *fcgi_config_new_static_server(cmd_parms *cmd, void *dummy, const char *arg) { fcgi_server *s; pool *p = cmd->pool, *tp = cmd->temp_pool; const char *name = cmd->cmd->name; const char *fs_path = ap_getword_conf(p, &arg); const char *option, *err; /* Allocate temp storage for the array of initial environment variables */ const char **envp = ap_pcalloc(tp, sizeof(char *) * (MAX_INIT_ENV_VARS + 1)); int envc = 0; if (*fs_path == '\0') return "AppClass requires a pathname!?"; if ((err = fcgi_config_set_fcgi_uid_n_gid(1)) != NULL) return ap_psprintf(tp, "%s %s: %s", name, fs_path, err); if (!ap_os_is_path_absolute(fs_path)) fs_path = ap_make_full_path(p, ap_server_root, fs_path); /* See if we've already got one of these configured */ s = fcgi_util_fs_get_by_id(fs_path, cmd->server->server_uid, cmd->server->server_gid); if (s != NULL) { if (fcgi_suexec) { return ap_psprintf(tp, "%s: redefinition of a previously defined FastCGI server \"%s\" with uid=%ld and gid=%ld", name, fs_path, (long)cmd->server->server_uid, (long)cmd->server->server_gid); } else { return ap_psprintf(tp, "%s: redefinition of a previously defined FastCGI server \"%s\"", name, fs_path); } } err = fcgi_util_fs_is_path_ok(tp, fs_path, NULL, cmd->server->server_uid, cmd->server->server_gid); if (err != NULL) { return ap_psprintf(tp, "%s: \"%s\" %s", name, fs_path, err); } s = fcgi_util_fs_new(p); s->fs_path = fs_path; s->directive = APP_CLASS_STANDARD; s->restartOnExit = TRUE; s->numProcesses = 1; if (fcgi_suexec) { struct passwd *pw; struct group *gr; s->uid = cmd->server->server_uid; pw = getpwuid(s->uid); if (pw == NULL) { return ap_psprintf(tp, "mod_fastcgi: " "getpwuid() couldn't determine the username for uid '%ld', " "you probably need to modify the User directive: %s", (long)s->uid, strerror(errno)); } s->user = ap_pstrdup(p, pw->pw_name); s->username = s->user; s->gid = cmd->server->server_gid; gr = getgrgid(s->gid); if (gr == NULL) { return ap_psprintf(tp, "mod_fastcgi: " "getgrgid() couldn't determine the group name for gid '%ld', " "you probably need to modify the Group directive: %s\n", (long)s->gid, strerror(errno)); } s->group = ap_pstrdup(p, gr->gr_name); } /* Parse directive arguments */ while (*arg) { option = ap_getword_conf(tp, &arg); if (strcasecmp(option, "-processes") == 0) { err = get_u_int(tp, &arg, &s->numProcesses, 1); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-restart-delay") == 0) { err = get_u_int(tp, &arg, &s->restartDelay, 0); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-init-start-delay") == 0) { err = get_u_int(tp, &arg, &s->initStartDelay, 0); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-priority") == 0) { err = get_u_int(tp, &arg, &s->processPriority, 0); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-listen-queue-depth") == 0) { err = get_u_int(tp, &arg, &s->listenQueueDepth, 1); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-appConnTimeout") == 0) { err = get_u_int(tp, &arg, &s->appConnectTimeout, 0); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-port") == 0) { err = get_u_int(tp, &arg, &s->port, 1); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-socket") == 0) { s->socket_path = ap_getword_conf(tp, &arg); if (*s->socket_path == '\0') return invalid_value(tp, name, fs_path, option, "\"\""); continue; } else if (strcasecmp(option, "-initial-env") == 0) { err = get_env_var(p, &arg, envp, &envc); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-flush") == 0) { s->flush = 1; continue; } else return invalid_value(tp, name, fs_path, option, NULL); } /* while */ if (s->socket_path != NULL && s->port != 0) { return ap_psprintf(tp, "%s %s: -port and -socket are mutually exclusive options", name, fs_path); } /* If -intial-env option was used, move env array to a surviving pool */ if (envc++) { s->envp = (const char **)ap_palloc(p, sizeof(char *) * envc); memcpy(s->envp, envp, sizeof(char *) * envc); } /* Initialize process structs */ s->procs = fcgi_util_fs_create_procs(p, s->numProcesses); /* Build the appropriate sockaddr structure */ if (s->port != 0) { err = fcgi_util_socket_make_inet_addr(p, (struct sockaddr_in **)&s->socket_addr, &s->socket_addr_len, NULL, s->port); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, fs_path, err); } else { if (s->socket_path == NULL) s->socket_path = fcgi_util_socket_hash_filename(tp, fs_path, s->user, s->group); s->socket_path = fcgi_util_socket_make_path_absolute(p, s->socket_path, 0); err = fcgi_util_socket_make_domain_addr(p, (struct sockaddr_un **)&s->socket_addr, &s->socket_addr_len, s->socket_path); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, fs_path, err); } /* Add it to the list of FastCGI servers */ fcgi_util_fs_add(s); return NULL; } /******************************************************************************* * Configure a static FastCGI server that is started/managed elsewhere. */ const char *fcgi_config_new_external_server(cmd_parms *cmd, void *dummy, const char *arg) { fcgi_server *s; pool * const p = cmd->pool, *tp = cmd->temp_pool; const char * const name = cmd->cmd->name; const char *fs_path = ap_getword_conf(p, &arg); const char *option, *err; if (!*fs_path) { return ap_pstrcat(tp, name, " requires a path and either a -socket or -host option", NULL); } if (!ap_os_is_path_absolute(fs_path)) fs_path = ap_make_full_path(p, ap_server_root, fs_path); /* See if we've already got one of these bettys configured */ s = fcgi_util_fs_get_by_id(fs_path, cmd->server->server_uid, cmd->server->server_gid); if (s != NULL) { if (fcgi_suexec != NULL) { return ap_psprintf(tp, "%s: redefinition of a previously defined class \"%s\" with uid=%ld and gid=%ld", name, fs_path, (long)cmd->server->server_uid, (long)cmd->server->server_gid); } else { return ap_psprintf(tp, "%s: redefinition of previously defined class \"%s\"", name, fs_path); } } s = fcgi_util_fs_new(p); s->fs_path = fs_path; s->directive = APP_CLASS_EXTERNAL; err = fcgi_util_fs_set_uid_n_gid(p, s, cmd->server->server_uid, cmd->server->server_gid); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, fs_path, err); /* Parse directive arguments */ while (*arg != '\0') { option = ap_getword_conf(tp, &arg); if (strcasecmp(option, "-host") == 0) { err = get_host_n_port(p, &arg, &s->host, &s->port); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-socket") == 0) { s->socket_path = ap_getword_conf(tp, &arg); if (*s->socket_path == '\0') return invalid_value(tp, name, fs_path, option, "\"\""); continue; } else if (strcasecmp(option, "-appConnTimeout") == 0) { err = get_u_int(tp, &arg, &s->appConnectTimeout, 0); if (err != NULL) return invalid_value(tp, name, fs_path, option, err); continue; } else if (strcasecmp(option, "-flush") == 0) { s->flush = 1; continue; } else { return ap_psprintf(tp, "%s %s: invalid option: %s", name, fs_path, option); } } /* while */ /* Require one of -socket or -host, but not both */ if (s->socket_path != NULL && s->port != 0) { return ap_psprintf(tp, "%s %s: -host and -socket are mutually exclusive options", name, fs_path); } if (s->socket_path == NULL && s->port == 0) { return ap_psprintf(tp, "%s %s: -socket or -host option missing", name, fs_path); } /* Build the appropriate sockaddr structure */ if (s->port != 0) { err = fcgi_util_socket_make_inet_addr(p, (struct sockaddr_in **)&s->socket_addr, &s->socket_addr_len, s->host, s->port); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, fs_path, err); } else { s->socket_path = fcgi_util_socket_make_path_absolute(p, s->socket_path, 0); err = fcgi_util_socket_make_domain_addr(p, (struct sockaddr_un **)&s->socket_addr, &s->socket_addr_len, s->socket_path); if (err != NULL) return ap_psprintf(tp, "%s %s: %s", name, fs_path, err); } /* Add it to the list of FastCGI servers */ fcgi_util_fs_add(s); return NULL; } /* *---------------------------------------------------------------------- * * fcgi_config_set_config -- * * Implements the FastCGI FCGIConfig configuration directive. * This command adds routines to control the execution of the * dynamic FastCGI processes. * * *---------------------------------------------------------------------- */ const char *fcgi_config_set_config(cmd_parms *cmd, void *dummy, const char *arg) { pool * const p = cmd->pool; pool * const tp = cmd->temp_pool; const char *err, *option; const char * const name = cmd->cmd->name; /* Allocate temp storage for an initial environment */ int envc = 0; const char **envp = (const char **)ap_pcalloc(tp, sizeof(char *) * (MAX_INIT_ENV_VARS + 1)); /* Parse the directive arguments */ while (*arg) { option = ap_getword_conf(tp, &arg); if (strcasecmp(option, "-maxProcesses") == 0) { err = get_u_int(tp, &arg, &dynamicMaxProcs, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-minProcesses") == 0) { err = get_u_int(tp, &arg, &dynamicMinProcs, 0); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-maxClassProcesses") == 0) { err = get_u_int(tp, &arg, &dynamicMaxClassProcs, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-killInterval") == 0) { err = get_u_int(tp, &arg, &dynamicKillInterval, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-updateInterval") == 0) { err = get_u_int(tp, &arg, &dynamicUpdateInterval, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-gainValue") == 0) { err = get_float(tp, &arg, &dynamicGain, 0.0, 1.0); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-singleThreshhold") == 0) { err = get_u_int(tp, &arg, &dynamicThreshhold1, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-multiThreshhold") == 0) { err = get_u_int(tp, &arg, &dynamicThreshholdN, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-startDelay") == 0) { err = get_u_int(tp, &arg, &dynamicPleaseStartDelay, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-initial-env") == 0) { err = get_env_var(p, &arg, envp, &envc); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-appConnTimeout") == 0) { err = get_u_int(tp, &arg, &dynamicAppConnectTimeout, 0); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-listen-queue-depth") == 0) { err = get_u_int(tp, &arg, &dynamicListenQueueDepth, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-restart-delay") == 0) { err = get_u_int(tp, &arg, &dynamicRestartDelay, 0); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-init-start-delay") == 0) { err = get_u_int(tp, &arg, &dynamicInitStartDelay, 0); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-processSlack") == 0) { err = get_u_int(tp, &arg, &dynamicProcessSlack, 1); if (err != NULL) return invalid_value(tp, name, NULL, option, err); continue; } else if (strcasecmp(option, "-restart") == 0) { dynamicAutoRestart = 1; continue; } else if (strcasecmp(option, "-autoUpdate") == 0) { dynamicAutoUpdate = 1; continue; } else { return ap_psprintf(tp, "%s: invalid option: %s", name, option); } } /* while */ /* If -intial-env option was used, move env array to a surviving pool */ if (envc++) { dynamicEnvp = (const char **)ap_palloc(p, sizeof(char *) * envc); memcpy(dynamicEnvp, envp, sizeof(char *) * envc); } return NULL; } void *fcgi_config_create_dir_config(pool *p, char *dummy) { fcgi_dir_config *dir_config = ap_pcalloc(p, sizeof(fcgi_dir_config)); dir_config->authenticator_options = FCGI_AUTHORITATIVE; dir_config->authorizer_options = FCGI_AUTHORITATIVE; dir_config->access_checker_options = FCGI_AUTHORITATIVE; return dir_config; } const char *fcgi_config_new_auth_server(cmd_parms * const cmd, fcgi_dir_config *dir_config, const char *fs_path, const char * const compat) { pool * const tp = cmd->temp_pool; const uid_t uid = cmd->server->server_uid; const gid_t gid = cmd->server->server_gid; if (!ap_os_is_path_absolute(fs_path)) fs_path = ap_make_full_path(cmd->pool, ap_server_root, fs_path); /* Make sure its already configured or at least a candidate for dynamic */ if (fcgi_util_fs_get_by_id(fs_path, uid, gid) == NULL) { const char *err = fcgi_util_fs_is_path_ok(tp, fs_path, NULL, uid, gid); if (err) return ap_psprintf(tp, "%s: \"%s\" %s", cmd->cmd->name, fs_path, err); } if (compat && strcasecmp(compat, "-compat")) return ap_psprintf(cmd->temp_pool, "%s: unknown option: \"%s\"", cmd->cmd->name, compat); switch((int)cmd->info) { case FCGI_AUTH_TYPE_AUTHENTICATOR: dir_config->authenticator = fs_path; dir_config->authenticator_options |= (compat) ? FCGI_COMPAT : 0; break; case FCGI_AUTH_TYPE_AUTHORIZER: dir_config->authorizer = fs_path; dir_config->authorizer_options |= (compat) ? FCGI_COMPAT : 0; break; case FCGI_AUTH_TYPE_ACCESS_CHECKER: dir_config->access_checker = fs_path; dir_config->access_checker_options |= (compat) ? FCGI_COMPAT : 0; break; } return NULL; } const char *fcgi_config_set_authoritative_slot(const cmd_parms * const cmd, fcgi_dir_config * const dir_config, int arg) { int offset = (int)(long)cmd->info; if (arg) *(int *)(dir_config + offset) |= FCGI_AUTHORITATIVE; else *(int *)(dir_config + offset) &= ~FCGI_AUTHORITATIVE; return NULL; }