/* ====================================================================
* Copyright (c) 1995-1997 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* 4. The names "Apache Server" and "Apache Group" must not be used to
* endorse or promote products derived from this software without
* prior written permission.
*
* 5. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the Apache Group
* for use in the Apache HTTP server project (http://www.apache.org/)."
*
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
* IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server
* project, please see .
* simple script to monitor the child Apache processes
* Usage:
* httpd_monitor [ -d serverdir | -f conffile ] [ -s sleep_time ]
* -d/-f options specify server dir or config files, as per
* httpd.
* -s specifies how long to pause between screen updates
* If you choose 0, it might chew up lots of CPU time.
*
* Output explanation..
*
* s = sleeping but "ready to go" child (this is '_' in mod_status)
* R = active child - writing to client
* W = active child - reading from client
* K = active child - waiting for additional request on kept-alive connection
* D = active child - doing DNS lookup
* L = active child - logging
* _ = dead child (no longer needed) (this is '.' in mod_status)
* t = just starting (this is 'S' in mod_status)
*
*
* Jim Jagielski
* v1.0 Notes:
* This code is much more ugly and complicated than it
* needs to be.
*
* v1.1:
* Minor fixes
*
* v1.2:
* Handles Apache 1.1.* scoreboard format (W/K/D/L states) -- PCS 09Jul96
*/
#include
#include
#include
#include
#include "../src/httpd.h"
#include "../src/scoreboard.h"
#define DEFAULT_SLEEPTIME 2
#define ASIZE 1024
#define MAX_PROC HARD_SERVER_LIMIT
int
main(argc, argv)
int argc;
char **argv;
{
short_score scoreboard_image;
FILE *afile;
char conf_name[ASIZE];
char pid_name[ASIZE];
char score_name[ASIZE];
char tbuf[ASIZE];
char *ptmp;
static char kid_stat[] = { '_', 's', 'R', 't', 'W', 'K', 'L', 'D' };
int achar;
long thepid;
int score_fd;
int sleep_time = DEFAULT_SLEEPTIME;
int last_len = 0;
int kiddies;
int running, dead, total, loop;
short got_config = 0;
struct stat statbuf;
time_t last_time = 0;
extern char *optarg;
extern int optind, opterr;
void lookfor();
int usage();
/*
* Handle the options. Using getopt() is most probably overkill,
* but let's think about the future!
*/
strcpy(conf_name, HTTPD_ROOT);
while((achar = getopt(argc,argv,"s:d:f:")) != -1) {
switch(achar) {
case 'd':
strcpy(conf_name, optarg);
break;
case 'f':
strcpy(conf_name, optarg);
got_config = 1;
break;
case 's':
sleep_time = atoi(optarg);
break;
case '?':
usage(argv[0]);
}
}
/*
* Now build the name of the httpd.conf file
*/
if (!got_config) {
strcat(conf_name, "/");
strcat(conf_name, SERVER_CONFIG_FILE);
}
/*
* Make sure we have the right file... Barf if not
*/
if (!(afile = fopen(conf_name, "r"))) {
perror("httpd_monitor");
fprintf(stderr, "Can't open config file: %s\n", conf_name);
exit(1);
}
/*
* now scan thru the ConfigFile to look for the items that
* interest us
*/
lookfor(pid_name, score_name, afile);
fclose(afile);
/*
* now open the PidFile and then the ScoreBoardFile
*/
if (!(afile = fopen(pid_name, "r"))) {
perror("httpd_monitor");
fprintf(stderr, "Can't open PIDfile: %s\n", pid_name);
exit(1);
}
fscanf(afile, "%ld", &thepid);
fclose(afile);
/*
* Enough taters, time for the MEAT!
*/
for(;;sleep(sleep_time)) {
if (stat(score_name, &statbuf)) {
perror("httpd_monitor");
fprintf(stderr, "Can't stat scoreboard file: %s\n", score_name);
exit(1);
}
if (last_time == statbuf.st_mtime)
continue; /* tricky ;) */
last_time = statbuf.st_mtime; /* for next time */
if ((score_fd = open(score_name, 0)) == -1 ) {
perror("httpd_monitor");
fprintf(stderr, "Can't open scoreboard file: %s\n", score_name);
exit(1);
}
/*
* all that for _this_
*/
running = dead = total = 0;
ptmp = tbuf;
*ptmp = '\0';
for(kiddies=0;kiddies strlen(tbuf)) {
for(loop=1;loop<=last_len;loop++)
putchar(' ');
for(loop=1;loop<=last_len;loop++)
putchar('\010');
}
printf("%s", tbuf);
fflush(stdout);
last_len = strlen(tbuf);
} /* for */
}
int
usage(arg)
char *arg;
{
printf("httpd_monitor: Usage\n");
printf(" httpd_monitor [ -d config-dir] [ -s sleep-time ]\n");
printf(" Defaults: config-dir = %s\n", HTTPD_ROOT);
printf(" sleep-time = %d seconds\n", DEFAULT_SLEEPTIME);
exit(0);
}
/*
* This function uses some hard-wired knowledge about the
* Apache httpd.conf file setup (basically names of the 3
* parameters we are interested in)
*
* We basically scan thru the file and grab the 3 values we
* need. This could be done better...
*/
void
lookfor(pidname, scorename, thefile)
char *pidname, *scorename;
FILE *thefile;
{
char line[ASIZE], param[ASIZE], value[ASIZE];
char sroot[ASIZE], pidfile[ASIZE], scorefile[ASIZE];
*sroot = *pidfile = *scorefile = '\0';
while (!(feof(thefile))) {
fgets(line, ASIZE-1, thefile);
*value = '\0'; /* protect braindead sscanf() */
sscanf(line, "%1024s %1024s", param, value);
if (strcmp(param, "PidFile")==0 && *value)
strcpy(pidfile, value);
if (strcmp(param, "ScoreBoardFile")==0 && *value)
strcpy(scorefile, value);
if (strcmp(param, "ServerRoot")==0 && *value)
strcpy(sroot, value);
}
/*
* We've reached EOF... we should have encountered the
* ServerRoot line... if not, we bail out
*/
if (!*sroot) {
fprintf(stderr, "Can't find ServerRoot!\n");
exit(1);
}
/*
* Not finding PidFile or ScoreBoardFile is OK, since
* we have defaults for them
*/
if (!*pidfile)
strcpy(pidfile, DEFAULT_PIDLOG);
if (!*scorefile)
strcpy(scorefile, DEFAULT_SCOREBOARD);
/*
* Relative or absolute? Handle both
*/
if (*pidfile == '/')
strcpy(pidname, pidfile);
else {
strcpy(pidname, sroot);
strcat(pidname, "/");
strcat(pidname, pidfile);
}
if (*scorefile == '/')
strcpy(scorename, scorefile);
else {
strcpy(scorename, sroot);
strcat(scorename, "/");
strcat(scorename, scorefile);
}
}