Here is another pass at it, starting with some of Justin's code but trying to work out a more agreeable place for some of the function. This puts the -k parsing in a rewrite_args hook (one for the Unix MPMs is implemented in mpm_common.c) and puts the actual signalling code in an optional function called from main() (again, one for the Unix MPMs is implemented in mpm_common.c).
This patch concentrates on distributing the work to the right places. It only implements "-k stop", it is only enabled for the prefork MPM (easy to enable for other MPMs), and I didn't sort out the httpd help text (gross). Hopefully this won't break anybody, and it can be quickly filled in with the necessary details. Any comments/concerns? There must be at least ten improvements to this that different people can think of :) Index: include/http_log.h =================================================================== RCS file: /home/cvs/httpd-2.0/include/http_log.h,v retrieving revision 1.36 diff -u -r1.36 http_log.h --- include/http_log.h 17 May 2002 10:48:06 -0000 1.36 +++ include/http_log.h 22 May 2002 17:36:39 -0000 @@ -240,6 +240,14 @@ */ AP_DECLARE(void) ap_log_pid(apr_pool_t *p, const char *fname); +/** + * Retrieve the pid from a pidfile. + * @param p The pool to use for logging + * @param filename The name of the file containing the pid + * @param mypid Pointer to pid_t (valid only if return APR_SUCCESS) + */ +AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename, pid_t +*mypid); + typedef struct piped_log piped_log; /** Index: include/http_main.h =================================================================== RCS file: /home/cvs/httpd-2.0/include/http_main.h,v retrieving revision 1.23 diff -u -r1.23 http_main.h --- include/http_main.h 17 Apr 2002 16:36:27 -0000 1.23 +++ include/http_main.h 22 May 2002 17:36:39 -0000 @@ -59,6 +59,8 @@ #ifndef APACHE_HTTP_MAIN_H #define APACHE_HTTP_MAIN_H +#include "apr_optional.h" + /* AP_SERVER_BASEARGS is the command argument list parsed by http_main.c * in apr_getopt() format. Use this for default'ing args that the MPM * can safely ignore and pass on from its rewrite_args() handler. @@ -88,6 +90,8 @@ /** An array of all -D defines on the command line. This allows people to * effect the server based on command line options */ AP_DECLARE_DATA extern apr_array_header_t *ap_server_config_defines; + +APR_DECLARE_OPTIONAL_FN(int, ap_signal_server, (int *, apr_pool_t *)); #ifdef __cplusplus } Index: include/mpm_common.h =================================================================== RCS file: /home/cvs/httpd-2.0/include/mpm_common.h,v retrieving revision 1.36 diff -u -r1.36 mpm_common.h --- include/mpm_common.h 29 Mar 2002 16:21:48 -0000 1.36 +++ include/mpm_common.h 22 May 2002 17:36:39 -0000 @@ -280,6 +280,11 @@ const char *arg); #endif +#ifdef AP_MPM_WANT_SIGNAL_SERVER +int ap_signal_server(int *, apr_pool_t *); +void ap_mpm_rewrite_args(process_rec *); +#endif + #ifdef __cplusplus } #endif Index: server/log.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/log.c,v retrieving revision 1.120 diff -u -r1.120 log.c --- server/log.c 17 May 2002 11:11:37 -0000 1.120 +++ server/log.c 22 May 2002 17:36:39 -0000 @@ -626,6 +626,55 @@ saved_pid = mypid; } +AP_DECLARE(apr_status_t) ap_read_pid(apr_pool_t *p, const char *filename, + pid_t *mypid) +{ + const int BUFFER_SIZE = sizeof(long) * 3 + 2; /* see apr_ltoa */ + apr_file_t *pid_file = NULL; + apr_status_t rv; + const char *fname; + char *buf, *endptr; + apr_size_t bytes_wanted, bytes_read; + + if (!filename) { + return APR_EGENERAL; + } + + fname = ap_server_root_relative(p, filename); + if (!fname) { + ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, APR_EBADPATH, + NULL, "Invalid PID file path %s, ignoring.", filename); + return APR_EGENERAL; + } + + rv = apr_file_open(&pid_file, fname, APR_READ, APR_OS_DEFAULT, p); + if (rv != APR_SUCCESS) { + return rv; + } + + bytes_wanted = BUFFER_SIZE; + endptr = buf = apr_palloc(p, BUFFER_SIZE); + do { + bytes_read = bytes_wanted; + rv = apr_file_read(pid_file, endptr, &bytes_read); + if (rv != APR_SUCCESS && rv != APR_EOF) { + return rv; + } + bytes_wanted -= bytes_read; + endptr += bytes_read; + } + while (bytes_wanted > 0 && rv != APR_EOF); + + *mypid = strtol(buf, &endptr, 10); + /* We only know for sure that the beginning part is the pid. */ + if (*buf == '\0' || *endptr != '\n') { + return APR_EGENERAL; + } + + apr_file_close(pid_file); + return APR_SUCCESS; +} + AP_DECLARE(void) ap_log_assert(const char *szExp, const char *szFile, int nLine) { Index: server/main.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/main.c,v retrieving revision 1.129 diff -u -r1.129 main.c --- server/main.c 21 May 2002 15:40:51 -0000 1.129 +++ server/main.c 22 May 2002 17:36:39 -0000 @@ -404,8 +404,9 @@ apr_status_t rv; module **mod; const char *optarg; + APR_OPTIONAL_FN_TYPE(ap_signal_server) *signal_server; - AP_MONCONTROL(0); /* turn of profiling of startup */ + AP_MONCONTROL(0); /* turn off profiling of startup */ apr_app_initialize(&argc, &argv, NULL); @@ -563,6 +564,15 @@ if (configtestonly) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Syntax OK"); destroy_and_exit_process(process, 0); + } + + signal_server = APR_RETRIEVE_OPTIONAL_FN(ap_signal_server); + if (signal_server) { + int exit_status; + + if (signal_server(&exit_status, pconf) != 0) { + destroy_and_exit_process(process, exit_status); + } } apr_pool_clear(plog); Index: server/mpm_common.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/mpm_common.c,v retrieving revision 1.94 diff -u -r1.94 mpm_common.c --- server/mpm_common.c 17 May 2002 11:11:37 -0000 1.94 +++ server/mpm_common.c 22 May 2002 17:36:39 -0000 @@ -73,6 +73,8 @@ #include "apr_strings.h" #define APR_WANT_STRFUNC #include "apr_want.h" +#include "apr_getopt.h" +#include "apr_optional.h" #include "httpd.h" #include "http_config.h" @@ -730,3 +732,87 @@ } #endif + +#ifdef AP_MPM_WANT_SIGNAL_SERVER + +static const char *dash_k_arg; + +int ap_signal_server(int *exit_status, apr_pool_t *pconf) +{ + apr_status_t rv; + pid_t otherpid; + + rv = ap_read_pid(pconf, ap_pid_fname, &otherpid); + if (rv != APR_SUCCESS && rv != APR_ENOENT) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, NULL, + "Error retrieving pid file %s", ap_pid_fname); + *exit_status = 1; + return 1; + } + + if (!strcmp(dash_k_arg, "stop")) { + if (rv != APR_SUCCESS) { + printf("httpd (no pid file) not running\n"); + } + else { + kill(otherpid, SIGTERM); + } + *exit_status = 0; + return 1; + } + return 0; +} + +void ap_mpm_rewrite_args(process_rec *process) +{ + apr_array_header_t *mpm_new_argv; + apr_status_t rv; + apr_getopt_t *opt; + char optbuf[3]; + const char *optarg; + int fixed_args; + + mpm_new_argv = apr_array_make(process->pool, process->argc, + sizeof(const char **)); + *(const char **)apr_array_push(mpm_new_argv) = process->argv[0]; + fixed_args = mpm_new_argv->nelts; + apr_getopt_init(&opt, process->pool, process->argc, process->argv); + opt->errfn = NULL; + optbuf[0] = '-'; + while ((rv = apr_getopt(opt, "k:" AP_SERVER_BASEARGS, + optbuf + 1, &optarg)) == APR_SUCCESS) { + switch(optbuf[1]) { + case 'k': + if (!dash_k_arg && !strcmp(optarg, "stop")) { + dash_k_arg = optarg; + break; + } + default: + *(const char **)apr_array_push(mpm_new_argv) = + apr_pstrdup(process->pool, optbuf); + if (optarg) { + *(const char **)apr_array_push(mpm_new_argv) = optarg; + } + } + } + + /* back up to capture the bad argument */ + if (rv == APR_BADCH || rv == APR_BADARG) { + opt->ind--; + } + + while (opt->ind < opt->argc) { + *(const char **)apr_array_push(mpm_new_argv) = + apr_pstrdup(process->pool, opt->argv[opt->ind++]); + } + + process->argc = mpm_new_argv->nelts; + process->argv = (const char * const *)mpm_new_argv->elts; + + if (dash_k_arg) { + APR_REGISTER_OPTIONAL_FN(ap_signal_server); + } +} + +#endif /* AP_MPM_WANT_SIGNAL_SERVER */ + Index: server/mpm/prefork/mpm.h =================================================================== RCS file: /home/cvs/httpd-2.0/server/mpm/prefork/mpm.h,v retrieving revision 1.19 diff -u -r1.19 mpm.h --- server/mpm/prefork/mpm.h 29 Mar 2002 16:15:33 -0000 1.19 +++ server/mpm/prefork/mpm.h 22 May 2002 17:36:39 -0000 @@ -77,6 +77,7 @@ #define AP_MPM_WANT_SET_MAX_REQUESTS #define AP_MPM_WANT_SET_COREDUMPDIR #define AP_MPM_WANT_SET_ACCEPT_LOCK_MECH +#define AP_MPM_WANT_SIGNAL_SERVER #define AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK #define AP_MPM_USES_POD 1 Index: server/mpm/prefork/prefork.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/mpm/prefork/prefork.c,v retrieving revision 1.263 diff -u -r1.263 prefork.c --- server/mpm/prefork/prefork.c 17 May 2002 11:11:39 -0000 1.263 +++ server/mpm/prefork/prefork.c 22 May 2002 17:36:39 -0000 @@ -1388,7 +1388,7 @@ module AP_MODULE_DECLARE_DATA mpm_prefork_module = { MPM20_MODULE_STUFF, - NULL, /* hook to run before apache parses args */ + ap_mpm_rewrite_args, /* hook to run before apache parses args */ NULL, /* create per-directory config structure */ NULL, /* merge per-directory config structures */ NULL, /* create per-server config structure */ -- Jeff Trawick | [EMAIL PROTECTED] Born in Roswell... married an alien...