"Fossies" - the Fresh Open Source Software Archive

Member "mod_fastcgi-2.4.7-0910052141/fcgi_config.c" (10 Apr 2012, 39853 Bytes) of package /linux/www/apache_httpd_modules/old/mod_fastcgi-2.4.7-0910052141.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "fcgi_config.c": 2.4.6_vs_2.4.7-0910052141.

    1 /*
    2  * $Id: fcgi_config.c,v 1.54 2009/09/28 12:33:14 robs Exp $
    3  */
    4 
    5 #define CORE_PRIVATE
    6 #include "fcgi.h"
    7 
    8 #ifdef APACHE2
    9 
   10 #include <limits.h>
   11 #include "mpm_common.h"     /* ap_uname2id, ap_gname2id */
   12 
   13 #ifdef WIN32
   14 #include <direct.h>
   15 #else
   16 #include <unistd.h>
   17 #include "unixd.h"
   18 #endif
   19 
   20 #endif
   21 
   22 #ifdef WIN32
   23 /* warning C4100: unreferenced formal parameter */
   24 /* warning C4706: assignment within conditional expression */ 
   25 #pragma warning( disable : 4100 4706 )
   26 #endif
   27 
   28 /*******************************************************************************
   29  * Get the next configuration directive argument, & return an in_addr and port.
   30  * The arg must be in the form "host:port" where host can be an IP or hostname.
   31  * The pool arg should be persistant storage.
   32  */
   33 static const char *get_host_n_port(pool *p, const char **arg,
   34         const char **host, u_short *port)
   35 {
   36     char *cvptr, *portStr;
   37     long tmp;
   38 
   39     *host = ap_getword_conf(p, arg);
   40     if (**host == '\0')
   41         return "\"\"";
   42 
   43     portStr = strchr(*host, ':');
   44     if (portStr == NULL)
   45         return "missing port specification";
   46 
   47     /* Split the host and port portions */
   48     *portStr++ = '\0';
   49 
   50     /* Convert port number */
   51     tmp = (u_short) strtol(portStr, &cvptr, 10);
   52     if (*cvptr != '\0' || tmp < 1 || tmp > USHRT_MAX)
   53         return ap_pstrcat(p, "bad port number \"", portStr, "\"", NULL);
   54 
   55     *port = (unsigned short) tmp;
   56 
   57     return NULL;
   58 }
   59 
   60 /*******************************************************************************
   61  * Get the next configuration directive argument, & return an u_short.
   62  * The pool arg should be temporary storage.
   63  */
   64 static const char *get_u_short(pool *p, const char **arg,
   65         u_short *num, u_short min)
   66 {
   67     char *ptr;
   68     long tmp;
   69     const char *txt = ap_getword_conf(p, arg);
   70 
   71     if (*txt == '\0') {
   72         return "\"\"";
   73     }
   74 
   75     tmp = strtol(txt, &ptr, 10);
   76 
   77     if (*ptr != '\0') {
   78         return ap_pstrcat(p, "\"", txt, "\" must be a positive integer", NULL);
   79     }
   80     
   81     if (tmp < min || tmp > USHRT_MAX) {
   82         return ap_psprintf(p, "\"%u\" must be >= %u and < %u", *num, min, USHRT_MAX);
   83     }
   84 
   85     *num = (u_short) tmp;
   86 
   87     return NULL;
   88 }
   89 
   90 static const char *get_int(pool *p, const char **arg, int *num, int min)
   91 {
   92     char *cp;
   93     const char *val = ap_getword_conf(p, arg);
   94 
   95     if (*val == '\0')
   96     {
   97         return "\"\"";
   98     }
   99 
  100     *num = (int) strtol(val, &cp, 10);
  101 
  102     if (*cp != '\0')
  103     {
  104         return ap_pstrcat(p, "can't parse ", "\"", val, "\"", NULL);
  105     }
  106     else if (*num < min)
  107     {
  108         return ap_psprintf(p, "\"%d\" must be >= %d", *num, min);
  109     }
  110             
  111     return NULL;
  112 }
  113 
  114 /*******************************************************************************
  115  * Get the next configuration directive argument, & return an u_int.
  116  * The pool arg should be temporary storage.
  117  */
  118 static const char *get_u_int(pool *p, const char **arg,
  119         u_int *num, u_int min)
  120 {
  121     char *ptr;
  122     const char *val = ap_getword_conf(p, arg);
  123 
  124     if (*val == '\0')
  125         return "\"\"";
  126     *num = (u_int)strtol(val, &ptr, 10);
  127 
  128     if (*ptr != '\0')
  129         return ap_pstrcat(p, "\"", val, "\" must be a positive integer", NULL);
  130     else if (*num < min)
  131         return ap_psprintf(p, "\"%u\" must be >= %u", *num, min);
  132     return NULL;
  133 }
  134 
  135 /*******************************************************************************
  136  * Get the next configuration directive argument, & return a float.
  137  * The pool arg should be temporary storage.
  138  */
  139 static const char *get_float(pool *p, const char **arg,
  140         float *num, float min, float max)
  141 {
  142     char *ptr;
  143     const char *val = ap_getword_conf(p, arg);
  144 
  145     if (*val == '\0')
  146         return "\"\"";
  147     *num = (float) strtod(val, &ptr);
  148 
  149     if (*ptr != '\0')
  150         return ap_pstrcat(p, "\"", val, "\" is not a floating point number", NULL);
  151     if (*num < min || *num > max)
  152         return ap_psprintf(p, "\"%f\" is not between %f and %f", *num, min, max);
  153     return NULL;
  154 }
  155 
  156 const char *fcgi_config_set_env_var(pool *p, char **envp, unsigned int *envc, char * var)
  157 {
  158     if (*envc >= MAX_INIT_ENV_VARS) {
  159         return "too many variables, must be <= MAX_INIT_ENV_VARS";
  160     }
  161 
  162     if (strchr(var, '=') == NULL) {
  163         *(envp + *envc) = ap_pstrcat(p, var, "=", getenv(var), NULL);
  164     }
  165     else {
  166         *(envp + *envc) = var;
  167     }
  168 
  169     (*envc)++;
  170 
  171     return NULL;
  172 }
  173 
  174 /*******************************************************************************
  175  * Get the next configuration directive argument, & add it to an env array.
  176  * The pool arg should be permanent storage.
  177  */
  178 static const char *get_env_var(pool *p, const char **arg, char **envp, unsigned int *envc)
  179 {
  180     char * const val = ap_getword_conf(p, arg);
  181 
  182     if (*val == '\0') {
  183         return "\"\"";
  184     }
  185 
  186     return fcgi_config_set_env_var(p, envp, envc, val);
  187 }
  188 
  189 static const char *get_pass_header(pool *p, const char **arg, array_header **array)
  190 {
  191     const char **header;
  192 
  193     if (!*array) {
  194         *array = ap_make_array(p, 10, sizeof(char*));
  195     }
  196 
  197     header = (const char **)ap_push_array(*array);
  198     *header = ap_getword_conf(p, arg);
  199 
  200     return header ? NULL : "\"\"";
  201 }
  202 
  203 /*******************************************************************************
  204  * Return a "standard" message for common configuration errors.
  205  */
  206 static const char *invalid_value(pool *p, const char *cmd, const char *id,
  207         const char *opt, const char *err)
  208 {
  209     return ap_psprintf(p, "%s%s%s: invalid value for %s: %s",
  210                     cmd, id ? " " : "", id ? id : "",  opt, err);
  211 }
  212 
  213 /*******************************************************************************
  214  * Set/Reset the uid/gid that Apache and the PM will run as.  This is ap_user_id
  215  * and ap_group_id if we're started as root, and euid/egid otherwise.  Also try
  216  * to check that the config files don't set the User/Group after a FastCGI
  217  * directive is used that depends on it.
  218  */
  219 /*@@@ To be complete, we should save a handle to the server each AppClass is
  220  * configured in and at init() check that the user/group is still what we
  221  * thought it was.  Also the other directives should only be allowed in the
  222  * parent Apache server.
  223  */
  224 const char *fcgi_config_set_fcgi_uid_n_gid(int set)
  225 {
  226     static int isSet = 0;
  227 
  228 #ifndef WIN32
  229 
  230     uid_t uid = geteuid();
  231     gid_t gid = getegid();
  232 
  233     if (set == 0) {
  234         isSet = 0;
  235         fcgi_user_id = (uid_t)-1;
  236         fcgi_group_id = (gid_t)-1;
  237         return NULL;
  238     }
  239 
  240     if (uid == 0) {
  241         uid = ap_user_id;
  242     }
  243 
  244     if (gid == 0) {
  245         gid = ap_group_id;
  246     }
  247 
  248     if (isSet && (uid != fcgi_user_id || gid != fcgi_group_id)) {
  249         return "User/Group commands must preceed FastCGI server definitions";
  250     }
  251 
  252     isSet = 1;
  253     fcgi_user_id = uid;
  254     fcgi_group_id = gid;
  255 
  256 #endif /* !WIN32 */
  257 
  258     return NULL;
  259 }
  260 
  261 apcb_t fcgi_config_reset_globals(void* dummy)
  262 {
  263     fcgi_config_pool = NULL;
  264     fcgi_servers = NULL;
  265     fcgi_config_set_fcgi_uid_n_gid(0);
  266     fcgi_wrapper = NULL;
  267     fcgi_socket_dir = NULL;
  268     
  269     fcgi_dynamic_total_proc_count = 0;
  270     fcgi_dynamic_epoch = 0;
  271     fcgi_dynamic_last_analyzed = 0;
  272 
  273     dynamicMaxProcs = FCGI_DEFAULT_MAX_PROCS;
  274     dynamicMinProcs = FCGI_DEFAULT_MIN_PROCS;
  275     dynamicMaxClassProcs = FCGI_DEFAULT_MAX_CLASS_PROCS;
  276     dynamicKillInterval = FCGI_DEFAULT_KILL_INTERVAL;
  277     dynamicUpdateInterval = FCGI_DEFAULT_UPDATE_INTERVAL;
  278     dynamicGain = FCGI_DEFAULT_GAIN;
  279     dynamicThreshold1 = FCGI_DEFAULT_THRESHOLD_1;
  280     dynamicThresholdN = FCGI_DEFAULT_THRESHOLD_N;
  281     dynamicPleaseStartDelay = FCGI_DEFAULT_START_PROCESS_DELAY;
  282     dynamicAppConnectTimeout = FCGI_DEFAULT_APP_CONN_TIMEOUT;
  283     dynamicEnvp = &fcgi_empty_env;
  284     dynamicProcessSlack = FCGI_DEFAULT_PROCESS_SLACK;
  285     dynamicAutoRestart = FCGI_DEFAULT_RESTART_DYNAMIC;
  286     dynamicAutoUpdate = FCGI_DEFAULT_AUTOUPDATE;
  287     dynamicListenQueueDepth = FCGI_DEFAULT_LISTEN_Q;
  288     dynamicInitStartDelay = DEFAULT_INIT_START_DELAY;
  289     dynamicRestartDelay = FCGI_DEFAULT_RESTART_DELAY;
  290     dynamicMinServerLife = FCGI_DEFAULT_MIN_SERVER_LIFE;
  291     dynamic_pass_headers = NULL;
  292     dynamic_idle_timeout = FCGI_DEFAULT_IDLE_TIMEOUT;
  293     dynamicFlush = FCGI_FLUSH;
  294 
  295 #ifndef WIN32
  296     /* Close any old pipe (HUP/USR1) */
  297     if (fcgi_pm_pipe[0] != -1) {
  298         close(fcgi_pm_pipe[0]);
  299         fcgi_pm_pipe[0] = -1;
  300     }
  301     if (fcgi_pm_pipe[1] != -1) {
  302         close(fcgi_pm_pipe[1]);
  303         fcgi_pm_pipe[1] = -1;
  304     }
  305 #endif
  306 
  307     return APCB_OK;
  308 }
  309 
  310 /*******************************************************************************
  311  * Create a directory to hold Unix/Domain sockets.
  312  */
  313 const char *fcgi_config_make_dir(pool *tp, char *path)
  314 {
  315     struct stat finfo;
  316     const char *err = NULL;
  317 
  318     /* Is the directory spec'd correctly */
  319     if (*path != '/') {
  320         return "path is not absolute (it must start with a \"/\")";
  321     }
  322     else {
  323         int i = strlen(path) - 1;
  324 
  325         /* Strip trailing "/"s */
  326         while(i > 0 && path[i] == '/') path[i--] = '\0';
  327     }
  328 
  329     /* Does it exist? */
  330     if (stat(path, &finfo) != 0) {
  331         /* No, but maybe we can create it */
  332 #ifdef WIN32
  333         if (mkdir(path) != 0) 
  334 #else
  335         if (mkdir(path, S_IRWXU) != 0)
  336 #endif
  337         {
  338             return ap_psprintf(tp,
  339                 "doesn't exist and can't be created: %s",
  340                 strerror(errno));
  341         }
  342 
  343 #ifndef WIN32
  344         /* If we're root, we're gonna setuid/setgid so we need to chown */
  345         if (geteuid() == 0 && chown(path, ap_user_id, ap_group_id) != 0) {
  346             return ap_psprintf(tp,
  347                 "can't chown() to the server (uid %ld, gid %ld): %s",
  348                 (long)ap_user_id, (long)ap_group_id, strerror(errno));
  349         }
  350 #endif
  351     }
  352     else {
  353         /* Yes, is it a directory? */
  354         if (!S_ISDIR(finfo.st_mode))
  355             return "isn't a directory!";
  356 
  357         /* Can we RWX in there? */
  358 #ifdef WIN32
  359         err = fcgi_util_check_access(tp, NULL, &finfo, _S_IREAD | _S_IWRITE | _S_IEXEC, fcgi_user_id, fcgi_group_id);
  360 #else
  361         err = fcgi_util_check_access(tp, NULL, &finfo, R_OK | W_OK | X_OK,
  362                           fcgi_user_id, fcgi_group_id);
  363 #endif
  364         if (err != NULL) {
  365             return ap_psprintf(tp,
  366                 "access for server (uid %ld, gid %ld) failed: %s",
  367                 (long)fcgi_user_id, (long)fcgi_group_id, err);
  368         }
  369     }
  370     return NULL;
  371 }
  372 
  373 /*******************************************************************************
  374  * Create a "dynamic" subdirectory.  If the directory
  375  * already exists we don't mess with it unless 'wax' is set.
  376  */
  377 #ifndef WIN32
  378 const char *fcgi_config_make_dynamic_dir(pool *p, const int wax)
  379 {
  380     const char *err;
  381     pool *tp;
  382 
  383     fcgi_dynamic_dir = ap_pstrcat(p, fcgi_socket_dir, "/dynamic", NULL);
  384 
  385     if ((err = fcgi_config_make_dir(p, fcgi_dynamic_dir)))
  386         return ap_psprintf(p, "can't create dynamic directory \"%s\": %s", fcgi_dynamic_dir, err);
  387 
  388     /* Don't step on a running server unless its OK. */
  389     if (!wax)
  390         return NULL;
  391 
  392 #ifdef APACHE2
  393     {
  394         apr_dir_t * dir;
  395         apr_finfo_t finfo;
  396 
  397         if (apr_pool_create(&tp, p))
  398             return "apr_pool_create() failed";
  399 
  400         if (apr_dir_open(&dir, fcgi_dynamic_dir, tp))
  401             return "apr_dir_open() failed";
  402 
  403         /* delete the contents */
  404 
  405         while (apr_dir_read(&finfo, APR_FINFO_NAME, dir) == APR_SUCCESS)
  406         {
  407             if (strcmp(finfo.name, ".") == 0 || strcmp(finfo.name, "..") == 0)
  408                 continue;
  409 
  410             apr_file_remove(finfo.name, tp);
  411         }
  412     }
  413 
  414 #else /* !APACHE2 */
  415     {
  416         DIR *dp;
  417         struct dirent *dirp = NULL;
  418 
  419         tp = ap_make_sub_pool(p);
  420 
  421         dp = ap_popendir(tp, fcgi_dynamic_dir);
  422         if (dp == NULL) {
  423             ap_destroy_pool(tp);
  424             return ap_psprintf(p, "can't open dynamic directory \"%s\": %s",
  425                 fcgi_dynamic_dir, strerror(errno));
  426         }
  427 
  428         /* delete the contents */
  429 
  430         while ((dirp = readdir(dp)) != NULL) 
  431         {
  432             if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
  433                 continue;
  434 
  435             unlink(ap_pstrcat(tp, fcgi_dynamic_dir, "/", dirp->d_name, NULL));
  436         }
  437     }
  438 
  439 #endif /* !APACHE2 */
  440 
  441     ap_destroy_pool(tp);
  442 
  443     return NULL;
  444 }
  445 #endif
  446 
  447 /*******************************************************************************
  448  * Change the directory used for the Unix/Domain sockets from the default.
  449  * Create the directory and the "dynamic" subdirectory.
  450  */
  451 const char *fcgi_config_set_socket_dir(cmd_parms *cmd, void *dummy, const char *arg)
  452 {
  453     pool * const tp = cmd->temp_pool;
  454     const char * const name = cmd->cmd->name;
  455     const char *err;
  456     char * arg_nc;
  457 
  458     err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  459     if (err)
  460     {
  461         return err;
  462     }
  463 
  464     if (fcgi_socket_dir) {
  465         return ap_psprintf(tp, "%s %s: already defined as \"%s\"",
  466                         name, arg, fcgi_socket_dir);
  467     }
  468 
  469     err = fcgi_config_set_fcgi_uid_n_gid(1);
  470     if (err != NULL)
  471         return ap_psprintf(tp, "%s %s: %s", name, arg, err);
  472 
  473     if (fcgi_servers != NULL) {
  474         return ap_psprintf(tp,
  475             "The %s command must preceed static FastCGI server definitions",
  476             name);
  477     }
  478 
  479     arg_nc = ap_pstrdup(cmd->pool, arg);
  480 
  481 #ifndef WIN32
  482 
  483 #ifdef APACHE2
  484     if (apr_filepath_merge(&arg_nc, "", arg, 0, cmd->pool))
  485         return ap_psprintf(tp, "%s %s: invalid filepath", name, arg);
  486 #else
  487     arg_nc = ap_os_canonical_filename(cmd->pool, arg_nc);
  488 #endif
  489 
  490     arg_nc = ap_server_root_relative(cmd->pool, arg_nc);
  491 
  492 #else /* WIN32 */
  493 
  494     if (strncmp(arg_nc, "\\\\.\\pipe\\", 9) != 0)
  495         return ap_psprintf(tp, "%s %s is invalid format",name, arg_nc);
  496 
  497 #endif
  498 
  499     fcgi_socket_dir = arg_nc;
  500 
  501 #ifdef WIN32
  502     fcgi_dynamic_dir = ap_pstrcat(cmd->pool, fcgi_socket_dir, "dynamic", NULL);
  503 #else
  504     err = fcgi_config_make_dir(tp, fcgi_socket_dir);
  505     if (err != NULL)
  506         return ap_psprintf(tp, "%s %s: %s", name, arg_nc, err);
  507 
  508     err = fcgi_config_make_dynamic_dir(cmd->pool, 0);
  509     if (err != NULL)
  510         return ap_psprintf(tp, "%s %s: %s", name, arg_nc, err);
  511 #endif
  512 
  513     return NULL;
  514 }
  515 
  516 /*******************************************************************************
  517  * Enable, disable, or specify the path to a wrapper used to invoke all
  518  * FastCGI applications.
  519  */
  520 const char *fcgi_config_set_wrapper(cmd_parms *cmd, void *dummy, const char *arg)
  521 {
  522 #ifdef WIN32
  523     return ap_psprintf(cmd->temp_pool, 
  524         "the %s directive is not supported on WIN", cmd->cmd->name);
  525 #else
  526 
  527     const char *err = NULL;
  528     const char * const name = cmd->cmd->name;
  529     pool * const tp = cmd->temp_pool;
  530     char * wrapper = NULL;
  531 
  532     err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
  533     if (err)
  534     {
  535         return err;
  536     }
  537 
  538     if (fcgi_wrapper)
  539     {
  540         return ap_psprintf(tp, "%s was already set to \"%s\"",
  541                            name, fcgi_wrapper);
  542     }
  543 
  544     err = fcgi_config_set_fcgi_uid_n_gid(1);
  545     if (err != NULL)
  546         return ap_psprintf(tp, "%s %s: %s", name, arg, err);
  547 
  548     if (fcgi_servers != NULL) {
  549         return ap_psprintf(tp,
  550             "The %s command must preceed static FastCGI server definitions", name);
  551     }
  552 
  553     if (strcasecmp(arg, "Off") == 0) {
  554         fcgi_wrapper = NULL;
  555         return NULL;
  556     }
  557 
  558     if (strcasecmp(arg, "On") == 0) 
  559     {
  560         wrapper = SUEXEC_BIN;
  561     }
  562     else
  563     {
  564 #ifdef APACHE2
  565         if (apr_filepath_merge(&wrapper, "", arg, 0, cmd->pool))
  566             return ap_psprintf(tp, "%s %s: invalid filepath", name, arg);
  567 #else
  568         wrapper = ap_os_canonical_filename(cmd->pool, (char *) arg);
  569 #endif
  570 
  571         wrapper = ap_server_root_relative(cmd->pool, wrapper);
  572     }
  573 
  574     err = fcgi_util_check_access(tp, wrapper, NULL, X_OK, fcgi_user_id, fcgi_group_id);
  575     if (err) 
  576     {
  577         return ap_psprintf(tp, "%s: \"%s\" execute access for server "
  578                            "(uid %ld, gid %ld) failed: %s", name, wrapper,
  579                            (long) fcgi_user_id, (long) fcgi_group_id, err);
  580     }
  581 
  582     fcgi_wrapper = wrapper;
  583 
  584     return NULL;
  585 #endif /* !WIN32 */
  586 }
  587 
  588 /*******************************************************************************
  589  * Configure a static FastCGI server.
  590  */
  591 const char *fcgi_config_new_static_server(cmd_parms *cmd, void *dummy, const char *arg)
  592 {
  593     fcgi_server *s;
  594     pool *p = cmd->pool, *tp = cmd->temp_pool;
  595     const char *name = cmd->cmd->name;
  596     char *fs_path = ap_getword_conf(p, &arg);
  597     const char *option, *err;
  598 
  599     /* Allocate temp storage for the array of initial environment variables */
  600     char **envp = ap_pcalloc(tp, sizeof(char *) * (MAX_INIT_ENV_VARS + 3));
  601     unsigned int envc = 0;
  602 
  603 #ifdef WIN32
  604     HANDLE mutex;
  605 #endif
  606 
  607     err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE);
  608     if (err)
  609     {
  610         return err;
  611     }
  612 
  613     if (*fs_path == '\0')
  614         return "AppClass requires a pathname!?";
  615 
  616     if ((err = fcgi_config_set_fcgi_uid_n_gid(1)) != NULL)
  617         return ap_psprintf(tp, "%s %s: %s", name, fs_path, err);
  618 
  619 #ifdef APACHE2
  620     if (apr_filepath_merge(&fs_path, "", fs_path, 0, p))
  621         return ap_psprintf(tp, "%s %s: invalid filepath", name, fs_path);
  622 #else
  623     fs_path = ap_os_canonical_filename(p, fs_path);
  624 #endif
  625     fs_path = ap_server_root_relative(p, fs_path);
  626 
  627     ap_getparents(fs_path);
  628     ap_no2slash(fs_path);
  629 
  630     /* See if we've already got one of these configured */
  631     s = fcgi_util_fs_get_by_id(fs_path, fcgi_util_get_server_uid(cmd->server),
  632                                fcgi_util_get_server_gid(cmd->server));
  633     if (s != NULL) {
  634         if (fcgi_wrapper) {
  635             return ap_psprintf(tp,
  636                 "%s: redefinition of a previously defined FastCGI "
  637                 "server \"%s\" with uid=%ld and gid=%ld",
  638                 name, fs_path, (long) fcgi_util_get_server_uid(cmd->server),
  639                 (long) fcgi_util_get_server_gid(cmd->server));
  640         }
  641         else {
  642             return ap_psprintf(tp,
  643                 "%s: redefinition of a previously defined FastCGI server \"%s\"",
  644                 name, fs_path);
  645         }
  646     }
  647 
  648     err = fcgi_util_fs_is_path_ok(tp, fs_path, NULL);
  649     if (err != NULL) {
  650         return ap_psprintf(tp, "%s: \"%s\" %s", name, fs_path, err);
  651     }
  652 
  653     s = fcgi_util_fs_new(p);
  654     s->fs_path = fs_path;
  655     s->directive = APP_CLASS_STANDARD;
  656     s->restartOnExit = TRUE;
  657     s->numProcesses = 1;
  658 
  659 #ifdef WIN32
  660 
  661     /* TCP FastCGI applications require SystemRoot be present in the environment
  662      * Put it in both for consistency to the application */
  663     fcgi_config_set_env_var(p, envp, &envc, "SystemRoot");
  664 
  665     mutex = CreateMutex(NULL, FALSE, fs_path);
  666     
  667     if (mutex == NULL)
  668     {
  669         ap_log_error(FCGI_LOG_ALERT, fcgi_apache_main_server,
  670             "FastCGI: CreateMutex() failed");
  671         return "failed to create FastCGI application accept mutex";
  672     }
  673     
  674     SetHandleInformation(mutex, HANDLE_FLAG_INHERIT, TRUE);
  675 
  676     s->mutex_env_string = ap_psprintf(p, "_FCGI_MUTEX_=%ld", mutex);
  677 
  678 #endif
  679 
  680     /*  Parse directive arguments */
  681     while (*arg) {
  682         option = ap_getword_conf(tp, &arg);
  683 
  684         if (strcasecmp(option, "-processes") == 0) {
  685             if ((err = get_u_int(tp, &arg, &s->numProcesses, 1)))
  686                 return invalid_value(tp, name, fs_path, option, err);
  687         }
  688         else if (strcasecmp(option, "-restart-delay") == 0) {
  689             if ((err = get_u_int(tp, &arg, &s->restartDelay, 0)))
  690                 return invalid_value(tp, name, fs_path, option, err);
  691         }
  692         else if (strcasecmp(option, "-init-start-delay") == 0) {
  693             if ((err = get_int(tp, &arg, &s->initStartDelay, 0)))
  694                 return invalid_value(tp, name, fs_path, option, err);
  695         }
  696         else if (strcasecmp(option, "-min-server-life") == 0) {
  697             if ((err = get_u_int(tp, &arg, &s->minServerLife, 0)))
  698                 return invalid_value(tp, name, NULL, option, err);
  699         }
  700         else if (strcasecmp(option, "-priority") == 0) {
  701             if ((err = get_u_int(tp, &arg, &s->processPriority, 0)))
  702                 return invalid_value(tp, name, fs_path, option, err);
  703         }
  704         else if (strcasecmp(option, "-listen-queue-depth") == 0) {
  705             if ((err = get_u_int(tp, &arg, &s->listenQueueDepth, 1)))
  706                 return invalid_value(tp, name, fs_path, option, err);
  707         }
  708         else if (strcasecmp(option, "-appConnTimeout") == 0) {
  709             if ((err = get_u_int(tp, &arg, &s->appConnectTimeout, 0)))
  710                 return invalid_value(tp, name, fs_path, option, err);
  711         }
  712         else if (strcasecmp(option, "-idle-timeout") == 0) {
  713             if ((err = get_u_int(tp, &arg, &s->idle_timeout, 1)))
  714                 return invalid_value(tp, name, fs_path, option, err);
  715         }
  716         else if (strcasecmp(option, "-port") == 0) {
  717             if ((err = get_u_short(tp, &arg, &s->port, 1)))
  718                 return invalid_value(tp, name, fs_path, option, err);
  719         }
  720         else if (strcasecmp(option, "-socket") == 0) {
  721             s->socket_path = ap_getword_conf(tp, &arg);
  722             if (*s->socket_path == '\0')
  723                 return invalid_value(tp, name, fs_path, option, "\"\"");
  724         }
  725         else if (strcasecmp(option, "-initial-env") == 0) {
  726             if ((err = get_env_var(p, &arg, envp, &envc)))
  727                 return invalid_value(tp, name, fs_path, option, err);
  728         }
  729         else if (strcasecmp(option, "-pass-header") == 0) {
  730             if ((err = get_pass_header(p, &arg, &s->pass_headers)))
  731                 return invalid_value(tp, name, fs_path, option, err);
  732         }
  733         else if (strcasecmp(option, "-flush") == 0) {
  734             s->flush = 1;
  735         }
  736         else if (strcasecmp(option, "-nph") == 0) {
  737             s->nph = 1;
  738         }
  739         else if (strcasecmp(option, "-user") == 0) {
  740 #ifdef WIN32
  741             return ap_psprintf(tp, 
  742                 "%s %s: the -user option isn't supported on WIN", name, fs_path);
  743 #else
  744             s->user = ap_getword_conf(tp, &arg);
  745             if (*s->user == '\0')
  746                 return invalid_value(tp, name, fs_path, option, "\"\"");
  747 #endif
  748         }
  749         else if (strcasecmp(option, "-group") == 0) {
  750 #ifdef WIN32
  751             return ap_psprintf(tp, 
  752                 "%s %s: the -group option isn't supported on WIN", name, fs_path);
  753 #else
  754             s->group = ap_getword_conf(tp, &arg);
  755             if (*s->group == '\0')
  756                 return invalid_value(tp, name, fs_path, option, "\"\"");
  757 #endif
  758         }
  759         else {
  760             return ap_psprintf(tp, "%s %s: invalid option: %s", name, fs_path, option);
  761         }
  762     } /* while */
  763 
  764 #ifndef WIN32
  765     if (fcgi_wrapper)
  766     {
  767         if (s->group == NULL)
  768         {
  769             s->group = ap_psprintf(tp, "#%ld", (long) fcgi_util_get_server_gid(cmd->server));
  770         }
  771 
  772         if (s->user == NULL)
  773         {
  774             s->user = ap_psprintf(p, "#%ld", (long) fcgi_util_get_server_uid(cmd->server)); 
  775         }
  776 
  777         s->uid = ap_uname2id(s->user);
  778         s->gid = ap_gname2id(s->group);
  779     }
  780     else if (s->user || s->group)
  781     {
  782         ap_log_error(FCGI_LOG_WARN, cmd->server, "FastCGI: there is no "
  783                      "fastcgi wrapper set, user/group options are ignored");
  784     }
  785 
  786     if ((err = fcgi_util_fs_set_uid_n_gid(p, s, s->uid, s->gid)))
  787     {
  788         return ap_psprintf(tp, 
  789             "%s %s: invalid user or group: %s", name, fs_path, err);
  790     }
  791 #endif /* !WIN32 */
  792 
  793     if (s->socket_path != NULL && s->port != 0) {
  794         return ap_psprintf(tp,
  795                 "%s %s: -port and -socket are mutually exclusive options",
  796                 name, fs_path);
  797     }
  798 
  799     /* Move env array to a surviving pool */
  800     s->envp = (char **)ap_pcalloc(p, sizeof(char *) * (envc + 4));
  801     memcpy(s->envp, envp, sizeof(char *) * envc);
  802 
  803     /* Initialize process structs */
  804     s->procs = fcgi_util_fs_create_procs(p, s->numProcesses);
  805 
  806     /* Build the appropriate sockaddr structure */
  807     if (s->port != 0) {
  808         err = fcgi_util_socket_make_inet_addr(p, (struct sockaddr_in **)&s->socket_addr,
  809                                 &s->socket_addr_len, NULL, s->port);
  810         if (err != NULL)
  811             return ap_psprintf(tp, "%s %s: %s", name, fs_path, err);
  812 #ifdef WIN32
  813         err = fcgi_util_socket_make_inet_addr(p, (struct sockaddr_in **)&s->dest_addr,
  814                                           &s->socket_addr_len, "localhost", s->port);
  815         if (err != NULL)
  816             return ap_psprintf(tp, "%s %s: %s", name, fs_path, err);
  817 #endif
  818     } else {
  819         if (s->socket_path == NULL)
  820              s->socket_path = fcgi_util_socket_hash_filename(tp, fs_path, s->user, s->group);
  821 
  822         if (fcgi_socket_dir == NULL)
  823         {
  824 #ifdef WIN32
  825             fcgi_socket_dir = DEFAULT_SOCK_DIR;
  826 #else
  827             fcgi_socket_dir = ap_server_root_relative(p, DEFAULT_SOCK_DIR);
  828 #endif
  829         }
  830 
  831         s->socket_path = fcgi_util_socket_make_path_absolute(p, s->socket_path, 0);
  832 #ifndef WIN32
  833         err = fcgi_util_socket_make_domain_addr(p, (struct sockaddr_un **)&s->socket_addr,
  834                                   &s->socket_addr_len, s->socket_path);
  835         if (err != NULL)
  836             return ap_psprintf(tp, "%s %s: %s", name, fs_path, err);
  837 #endif
  838     }
  839 
  840     /* Add it to the list of FastCGI servers */
  841     fcgi_util_fs_add(s);
  842 
  843     return NULL;
  844 }
  845 
  846 /*******************************************************************************
  847  * Configure a static FastCGI server that is started/managed elsewhere.
  848  */
  849 const char *fcgi_config_new_external_server(cmd_parms *cmd, void *dummy, const char *arg)
  850 {
  851     fcgi_server *s;
  852     pool * const p = cmd->pool, *tp = cmd->temp_pool;
  853     const char * const name = cmd->cmd->name;
  854     char *fs_path = ap_getword_conf(p, &arg);
  855     const char *option, *err;
  856 
  857     err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_DIR_LOC_FILE);
  858     if (err) {
  859         return err;
  860     }
  861 
  862     if (!*fs_path) {
  863         return ap_pstrcat(tp, name, " requires a path and either a -socket or -host option", NULL);
  864     }
  865 
  866 #ifdef APACHE2
  867     if (apr_filepath_merge(&fs_path, "", fs_path, 0, p))
  868         return ap_psprintf(tp, "%s %s: invalid filepath", name, fs_path);
  869 #else
  870     fs_path = ap_os_canonical_filename(p, fs_path);
  871 #endif
  872 
  873     fs_path = ap_server_root_relative(p, fs_path);
  874 
  875     ap_getparents(fs_path);
  876     ap_no2slash(fs_path);
  877 
  878     /* See if we've already got one of these bettys configured */
  879     s = fcgi_util_fs_get_by_id(fs_path, fcgi_util_get_server_uid(cmd->server),
  880                                fcgi_util_get_server_gid(cmd->server));
  881     if (s != NULL) {
  882         if (fcgi_wrapper) {
  883             return ap_psprintf(tp,
  884                 "%s: redefinition of a previously defined class \"%s\" "
  885                 "with uid=%ld and gid=%ld",
  886                 name, fs_path, (long) fcgi_util_get_server_uid(cmd->server),
  887                 (long) fcgi_util_get_server_gid(cmd->server));
  888         }
  889         else 
  890         {
  891             return ap_psprintf(tp,
  892                 "%s: redefinition of previously defined class \"%s\"", name, fs_path);
  893         }
  894     }
  895 
  896     s = fcgi_util_fs_new(p);
  897     s->fs_path = fs_path;
  898     s->directive = APP_CLASS_EXTERNAL;
  899 
  900     /*  Parse directive arguments */
  901     while (*arg != '\0') {
  902         option = ap_getword_conf(tp, &arg);
  903 
  904         if (strcasecmp(option, "-host") == 0) {
  905             if ((err = get_host_n_port(p, &arg, &s->host, &s->port)))
  906                 return invalid_value(tp, name, fs_path, option, err);
  907         }
  908         else if (strcasecmp(option, "-socket") == 0) {
  909             s->socket_path = ap_getword_conf(tp, &arg);
  910             if (*s->socket_path == '\0')
  911                 return invalid_value(tp, name, fs_path, option, "\"\"");
  912         }
  913         else if (strcasecmp(option, "-appConnTimeout") == 0) {
  914             if ((err = get_u_int(tp, &arg, &s->appConnectTimeout, 0)))
  915                 return invalid_value(tp, name, fs_path, option, err);
  916         }
  917         else if (strcasecmp(option, "-idle-timeout") == 0) {
  918             if ((err = get_u_int(tp, &arg, &s->idle_timeout, 1)))
  919                 return invalid_value(tp, name, fs_path, option, err);
  920         }
  921         else if (strcasecmp(option, "-nph") == 0) {
  922             s->nph = 1;
  923         }
  924         else if (strcasecmp(option, "-pass-header") == 0) {
  925             if ((err = get_pass_header(p, &arg, &s->pass_headers)))
  926                 return invalid_value(tp, name, fs_path, option, err);
  927         }
  928         else if (strcasecmp(option, "-flush") == 0) {
  929             s->flush = 1;
  930         }
  931         else if (strcasecmp(option, "-user") == 0) {
  932 #ifdef WIN32
  933             return ap_psprintf(tp, 
  934                 "%s %s: the -user option isn't supported on WIN", name, fs_path);
  935 #else
  936             s->user = ap_getword_conf(tp, &arg);
  937             if (*s->user == '\0')
  938                 return invalid_value(tp, name, fs_path, option, "\"\"");
  939 #endif
  940         }
  941         else if (strcasecmp(option, "-group") == 0) {
  942 #ifdef WIN32
  943             return ap_psprintf(tp, 
  944                 "%s %s: the -group option isn't supported on WIN", name, fs_path);
  945 #else
  946             s->group = ap_getword_conf(tp, &arg);
  947             if (*s->group == '\0')
  948                 return invalid_value(tp, name, fs_path, option, "\"\"");
  949 #endif
  950         }
  951         else {
  952             return ap_psprintf(tp, "%s %s: invalid option: %s", name, fs_path, option);
  953         }
  954     } /* while */
  955 
  956 
  957 #ifndef WIN32
  958     if (fcgi_wrapper)
  959     {
  960         if (s->group == NULL)
  961         {
  962             s->group = ap_psprintf(tp, "#%ld", (long) fcgi_util_get_server_gid(cmd->server));
  963         }
  964 
  965         if (s->user == NULL)
  966         {
  967             s->user = ap_psprintf(p, "#%ld", (long) fcgi_util_get_server_uid(cmd->server));
  968         }
  969 
  970         s->uid = ap_uname2id(s->user);
  971         s->gid = ap_gname2id(s->group);
  972     }
  973     else if (s->user || s->group)
  974     {
  975         ap_log_error(FCGI_LOG_WARN, cmd->server, "FastCGI: there is no "
  976                      "fastcgi wrapper set, user/group options are ignored");
  977     }
  978 
  979     if ((err = fcgi_util_fs_set_uid_n_gid(p, s, s->uid, s->gid)))
  980     {
  981         return ap_psprintf(tp,
  982             "%s %s: invalid user or group: %s", name, fs_path, err);
  983     }
  984 #endif /* !WIN32 */
  985 
  986     /* Require one of -socket or -host, but not both */
  987     if (s->socket_path != NULL && s->port != 0) {
  988         return ap_psprintf(tp,
  989             "%s %s: -host and -socket are mutually exclusive options",
  990             name, fs_path);
  991     }
  992     if (s->socket_path == NULL && s->port == 0) {
  993         return ap_psprintf(tp,
  994             "%s %s: -socket or -host option missing", name, fs_path);
  995     }
  996 
  997     /* Build the appropriate sockaddr structure */
  998     if (s->port != 0) {
  999         err = fcgi_util_socket_make_inet_addr(p, (struct sockaddr_in **)&s->socket_addr,
 1000             &s->socket_addr_len, s->host, s->port);
 1001         if (err != NULL)
 1002             return ap_psprintf(tp, "%s %s: %s", name, fs_path, err);
 1003     } else {
 1004 
 1005         if (fcgi_socket_dir == NULL)
 1006         {
 1007 #ifdef WIN32
 1008             fcgi_socket_dir = DEFAULT_SOCK_DIR;
 1009 #else
 1010             fcgi_socket_dir = ap_server_root_relative(p, DEFAULT_SOCK_DIR);
 1011 #endif
 1012         }
 1013 
 1014         s->socket_path = fcgi_util_socket_make_path_absolute(p, s->socket_path, 0);
 1015 #ifndef WIN32
 1016         err = fcgi_util_socket_make_domain_addr(p, (struct sockaddr_un **)&s->socket_addr,
 1017                                   &s->socket_addr_len, s->socket_path);
 1018         if (err != NULL)
 1019             return ap_psprintf(tp, "%s %s: %s", name, fs_path, err);
 1020 #endif
 1021     }
 1022 
 1023     /* Add it to the list of FastCGI servers */
 1024     fcgi_util_fs_add(s);
 1025 
 1026     return NULL;
 1027 }
 1028 
 1029 /*
 1030  *----------------------------------------------------------------------
 1031  *
 1032  * fcgi_config_set_config --
 1033  *
 1034  *      Implements the FastCGI FCGIConfig configuration directive.
 1035  *      This command adds routines to control the execution of the
 1036  *      dynamic FastCGI processes.
 1037  *
 1038  *
 1039  *----------------------------------------------------------------------
 1040  */
 1041 const char *fcgi_config_set_config(cmd_parms *cmd, void *dummy, const char *arg)
 1042 {
 1043     pool * const p = cmd->pool;
 1044     pool * const tp = cmd->temp_pool;
 1045     const char *err, *option;
 1046     const char * const name = cmd->cmd->name;
 1047 
 1048     /* Allocate temp storage for an initial environment */
 1049     unsigned int envc = 0;
 1050     char **envp = (char **)ap_pcalloc(tp, sizeof(char *) * (MAX_INIT_ENV_VARS + 3));
 1051 
 1052     err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
 1053     if (err)
 1054     {
 1055         return err;
 1056     }
 1057 
 1058     /* Parse the directive arguments */
 1059     while (*arg) {
 1060         option = ap_getword_conf(tp, &arg);
 1061 
 1062         if (strcasecmp(option, "-maxProcesses") == 0) {
 1063             if ((err = get_u_int(tp, &arg, &dynamicMaxProcs, 1)))
 1064                 return invalid_value(tp, name, NULL, option, err);
 1065         }
 1066         else if (strcasecmp(option, "-minProcesses") == 0) {
 1067             if ((err = get_int(tp, &arg, &dynamicMinProcs, 0)))
 1068                 return invalid_value(tp, name, NULL, option, err);
 1069         }
 1070         else if (strcasecmp(option, "-maxClassProcesses") == 0) {
 1071             if ((err = get_int(tp, &arg, &dynamicMaxClassProcs, 1)))
 1072                 return invalid_value(tp, name, NULL, option, err);
 1073         }
 1074         else if (strcasecmp(option, "-killInterval") == 0) {
 1075             if ((err = get_u_int(tp, &arg, &dynamicKillInterval, 1)))
 1076                 return invalid_value(tp, name, NULL, option, err);
 1077         }
 1078         else if (strcasecmp(option, "-updateInterval") == 0) {
 1079             if ((err = get_u_int(tp, &arg, &dynamicUpdateInterval, 1)))
 1080                 return invalid_value(tp, name, NULL, option, err);
 1081         }
 1082         else if (strcasecmp(option, "-gainValue") == 0) {
 1083             if ((err = get_float(tp, &arg, &dynamicGain, 0.0, 1.0)))
 1084                 return invalid_value(tp, name, NULL, option, err);
 1085         }
 1086         else if ((strcasecmp(option, "-singleThreshold") == 0)
 1087             || (strcasecmp(option, "-singleThreshhold") == 0)) 
 1088         {
 1089             if ((err = get_int(tp, &arg, &dynamicThreshold1, 0)))
 1090                 return invalid_value(tp, name, NULL, option, err);
 1091         }
 1092         else if ((strcasecmp(option, "-multiThreshold") == 0)
 1093             || (strcasecmp(option, "-multiThreshhold") == 0)) 
 1094         {
 1095             if ((err = get_int(tp, &arg, &dynamicThresholdN, 0)))
 1096                 return invalid_value(tp, name, NULL, option, err);
 1097         }
 1098         else if (strcasecmp(option, "-startDelay") == 0) {
 1099             if ((err = get_u_int(tp, &arg, &dynamicPleaseStartDelay, 1)))
 1100                 return invalid_value(tp, name, NULL, option, err);
 1101         }
 1102         else if (strcasecmp(option, "-initial-env") == 0) {
 1103             if ((err = get_env_var(p, &arg, envp, &envc)))
 1104                 return invalid_value(tp, name, NULL, option, err);
 1105         }
 1106         else if (strcasecmp(option, "-pass-header") == 0) {
 1107             if ((err = get_pass_header(p, &arg, &dynamic_pass_headers)))
 1108                 return invalid_value(tp, name, NULL, option, err);
 1109         }
 1110         else if (strcasecmp(option, "-appConnTimeout") == 0) {
 1111             if ((err = get_u_int(tp, &arg, &dynamicAppConnectTimeout, 0)))
 1112                 return invalid_value(tp, name, NULL, option, err);
 1113         }
 1114         else if (strcasecmp(option, "-idle-timeout") == 0) {
 1115             if ((err = get_u_int(tp, &arg, &dynamic_idle_timeout, 1)))
 1116                 return invalid_value(tp, name, NULL, option, err);
 1117         }
 1118         else if (strcasecmp(option, "-listen-queue-depth") == 0) {
 1119             if ((err = get_u_int(tp, &arg, &dynamicListenQueueDepth, 1)))
 1120                 return invalid_value(tp, name, NULL, option, err);
 1121         }
 1122         else if (strcasecmp(option, "-min-server-life") == 0) {
 1123             if ((err = get_int(tp, &arg, &dynamicMinServerLife, 0)))
 1124                 return invalid_value(tp, name, NULL, option, err);
 1125         }
 1126         else if (strcasecmp(option, "-restart-delay") == 0) {
 1127             if ((err = get_u_int(tp, &arg, &dynamicRestartDelay, 0)))
 1128                 return invalid_value(tp, name, NULL, option, err);
 1129         }
 1130         else if (strcasecmp(option, "-init-start-delay") == 0) {
 1131             if ((err = get_u_int(tp, &arg, &dynamicInitStartDelay, 0)))
 1132                 return invalid_value(tp, name, NULL, option, err);
 1133         }
 1134         else if (strcasecmp(option, "-processSlack") == 0) {
 1135             if ((err = get_u_int(tp, &arg, &dynamicProcessSlack, 1)))
 1136                 return invalid_value(tp, name, NULL, option, err);
 1137         }
 1138         else if (strcasecmp(option, "-restart") == 0) {
 1139             dynamicAutoRestart = 1;
 1140         }
 1141         else if (strcasecmp(option, "-autoUpdate") == 0) {
 1142             dynamicAutoUpdate = 1;
 1143         }
 1144         else if (strcasecmp(option, "-flush") == 0) {
 1145             dynamicFlush = TRUE;
 1146         }
 1147         else {
 1148             return ap_psprintf(tp, "%s: invalid option: %s", name, option);
 1149         }
 1150     } /* while */
 1151 
 1152     if (dynamicProcessSlack >= dynamicMaxProcs + 1) {
 1153         /* the kill policy would work unexpectedly */
 1154         return ap_psprintf(tp, 
 1155             "%s: processSlack (%u) must be less than maxProcesses (%u) + 1", 
 1156             name, dynamicProcessSlack, dynamicMaxProcs);
 1157     }
 1158 
 1159     /* Move env array to a surviving pool, leave 2 extra slots for 
 1160      * WIN32 _FCGI_MUTEX_ and _FCGI_SHUTDOWN_EVENT_ */
 1161     dynamicEnvp = (char **)ap_pcalloc(p, sizeof(char *) * (envc + 4));
 1162     memcpy(dynamicEnvp, envp, sizeof(char *) * envc);
 1163 
 1164     return NULL;
 1165 }
 1166 
 1167 void *fcgi_config_create_dir_config(pool *p, char *dummy)
 1168 {
 1169     fcgi_dir_config *dir_config = ap_pcalloc(p, sizeof(fcgi_dir_config));
 1170 
 1171     dir_config->authenticator_options = FCGI_AUTHORITATIVE;
 1172     dir_config->authorizer_options = FCGI_AUTHORITATIVE;
 1173     dir_config->access_checker_options = FCGI_AUTHORITATIVE;
 1174 
 1175     return dir_config;
 1176 }
 1177 
 1178 
 1179 const char *fcgi_config_new_auth_server(cmd_parms * cmd,
 1180     void * dircfg, const char *fs_path, const char * compat)
 1181 {
 1182     fcgi_dir_config * dir_config = (fcgi_dir_config *) dircfg;
 1183     pool * const tp = cmd->temp_pool;
 1184     char * auth_server;
 1185 
 1186 #ifdef APACHE2
 1187     if (apr_filepath_merge(&auth_server, "", fs_path, 0, cmd->pool))
 1188         return ap_psprintf(tp, "%s %s: invalid filepath", cmd->cmd->name, fs_path);
 1189 #else
 1190     auth_server = (char *) ap_os_canonical_filename(cmd->pool, fs_path);
 1191 #endif
 1192 
 1193     auth_server = ap_server_root_relative(cmd->pool, auth_server);
 1194 
 1195     /* Make sure its already configured or at least a candidate for dynamic */
 1196     if (fcgi_util_fs_get_by_id(auth_server, fcgi_util_get_server_uid(cmd->server),
 1197                                fcgi_util_get_server_gid(cmd->server)) == NULL) 
 1198     {
 1199         const char *err = fcgi_util_fs_is_path_ok(tp, auth_server, NULL);
 1200         if (err)
 1201             return ap_psprintf(tp, "%s: \"%s\" %s", cmd->cmd->name, auth_server, err);
 1202     }
 1203 
 1204     if (compat && strcasecmp(compat, "-compat"))
 1205         return ap_psprintf(cmd->temp_pool, "%s: unknown option: \"%s\"", cmd->cmd->name, compat);
 1206 
 1207     switch((int)cmd->info) {
 1208         case FCGI_AUTH_TYPE_AUTHENTICATOR:
 1209             dir_config->authenticator = auth_server;
 1210             dir_config->authenticator_options |= (compat) ? FCGI_COMPAT : 0;
 1211             break;
 1212         case FCGI_AUTH_TYPE_AUTHORIZER:
 1213             dir_config->authorizer = auth_server;
 1214             dir_config->authorizer_options |= (compat) ? FCGI_COMPAT : 0;
 1215             break;
 1216         case FCGI_AUTH_TYPE_ACCESS_CHECKER:
 1217             dir_config->access_checker = auth_server;
 1218             dir_config->access_checker_options |= (compat) ? FCGI_COMPAT : 0;
 1219             break;
 1220     }
 1221 
 1222     return NULL;
 1223 }
 1224 
 1225 const char *fcgi_config_set_authoritative_slot(cmd_parms * cmd,
 1226     void * dir_config, int arg)
 1227 {
 1228     int offset = (int)(long)cmd->info;
 1229 
 1230     if (arg)
 1231         *((u_char *)dir_config + offset) |= FCGI_AUTHORITATIVE;
 1232     else
 1233         *((u_char *)dir_config + offset) &= ~FCGI_AUTHORITATIVE;
 1234 
 1235     return NULL;
 1236 }