/* ==================================================================== * Copyright (c) 1995-1999 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. For written permission, please contact * apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * 6. 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 * ITS 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 . * */ /* Status Module. Display lots of internal data about how Apache is * performing and the state of all children processes. * * To enable this, add the following lines into any config file: * * * SetHandler server-status * * * You may want to protect this location by password or domain so no one * else can look at it. Then you can access the statistics with a URL like: * * http://your_server_name/server-status * * /server-status - Returns page using tables * /server-status?notable - Returns page for browsers without table support * /server-status?refresh - Returns page with 1 second refresh * /server-status?refresh=6 - Returns page with refresh every 6 seconds * /server-status?auto - Returns page with data for automatic parsing * * Mark Cox, mark@ukweb.com, November 1995 * * 12.11.95 Initial version for www.telescope.org * 13.3.96 Updated to remove rprintf's [Mark] * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie] * 18.3.96 Make extra Scoreboard variables #definable * 25.3.96 Make short report have full precision [Ben Laurie suggested] * 25.3.96 Show uptime better [Mark/Ben Laurie] * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested] * 09.4.96 Added message for non-STATUS compiled version * 18.4.96 Added per child and per slot counters [Jim Jagielski] * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.] * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing * piece in short reports [Ben Laurie] * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if * extended STATUS is enabled) [George Burgyan/Jim J.] * 10.8.98 Allow for extended status info at runtime (no more STATUS) * [Jim J.] */ #define CORE_PRIVATE #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_protocol.h" #include "http_conf_globals.h" /* for ap_extended_status */ #include "http_main.h" #include "util_script.h" #include #include "scoreboard.h" #include "http_log.h" #include #ifdef NEXT #if (NX_CURRENT_COMPILER_RELEASE == 410) #ifdef m68k #define HZ 64 #else #define HZ 100 #endif #else #include #endif #endif /* NEXT */ #define STATUS_MAXLINE 64 #define KBYTE 1024 #define MBYTE 1048576L #define GBYTE 1073741824L #ifndef DEFAULT_TIME_FORMAT #define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z" #endif module MODULE_VAR_EXPORT status_module; /* *command-related code. This is here to prevent use of ExtendedStatus * without status_module included. */ static const char *set_extended_status(cmd_parms *cmd, void *dummy, char *arg) { const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } if (!strcasecmp(arg, "off") || !strcmp(arg, "0")) { ap_extended_status = 0; } else { ap_extended_status = 1; } return NULL; } static const command_rec status_module_cmds[] = { { "ExtendedStatus", set_extended_status, NULL, RSRC_CONF, TAKE1, "\"On\" to enable extended status information, \"Off\" to disable" }, {NULL} }; /* Format the number of bytes nicely */ static void format_byte_out(request_rec *r, unsigned long bytes) { if (bytes < (5 * KBYTE)) ap_rprintf(r, "%d B", (int) bytes); else if (bytes < (MBYTE / 2)) ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE); else if (bytes < (GBYTE / 2)) ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE); else ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE); } static void format_kbyte_out(request_rec *r, unsigned long kbytes) { if (kbytes < KBYTE) ap_rprintf(r, "%d kB", (int) kbytes); else if (kbytes < MBYTE) ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE); else ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE); } static void show_time(request_rec *r, time_t tsecs) { long days, hrs, mins, secs; secs = tsecs % 60; tsecs /= 60; mins = tsecs % 60; tsecs /= 60; hrs = tsecs % 24; days = tsecs / 24; if (days) ap_rprintf(r, " %ld day%s", days, days == 1 ? "" : "s"); if (hrs) ap_rprintf(r, " %ld hour%s", hrs, hrs == 1 ? "" : "s"); if (mins) ap_rprintf(r, " %ld minute%s", mins, mins == 1 ? "" : "s"); if (secs) ap_rprintf(r, " %ld second%s", secs, secs == 1 ? "" : "s"); } /* Main handler for x-httpd-status requests */ /* ID values for command table */ #define STAT_OPT_END -1 #define STAT_OPT_REFRESH 0 #define STAT_OPT_NOTABLE 1 #define STAT_OPT_AUTO 2 struct stat_opt { int id; const char *form_data_str; const char *hdr_out_str; }; static const struct stat_opt status_options[] = /* see #defines above */ { {STAT_OPT_REFRESH, "refresh", "Refresh"}, {STAT_OPT_NOTABLE, "notable", NULL}, {STAT_OPT_AUTO, "auto", NULL}, {STAT_OPT_END, NULL, NULL} }; static char status_flags[SERVER_NUM_STATUS]; static int status_handler(request_rec *r) { char *loc; time_t nowtime = time(NULL); time_t up_time; int i, res; int ready = 0; int busy = 0; unsigned long count = 0; unsigned long lres, bytes; unsigned long my_lres, my_bytes, conn_bytes; unsigned short conn_lres; unsigned long bcount = 0; unsigned long kbcount = 0; unsigned long kbscount = 0; long req_time; /**********************************/ extern float TimeLeft; extern int my_sock; extern struct sockaddr_in to_LBA; /*********************************/ /*float time_left= 0; /* calculated using Bytes_remaining/processing speed */ unsigned long myfileSz ; int StrLen = 0; /*char my_index[] = "index.html";*/ char my_index[] = "/index.html"; /*char my_index[] = "public_html/index.html";*/ char myempty_str[] = "\0"; char * my_new_file; struct stat mystatbuf; unsigned long bytes_remaining_for_this_request; char c_g_i_1[] = ".cgi"; char c_g_i_2[] = ".pi"; char extension[] = "/"; char ext_pub[] = "public_html"; unsigned long bytes_left = 0; unsigned long mybytes_sent = 0 ; float Avg_B_sec = 0; float myreq_B_sec = 0; float Average = 65000.0; /* should #define this value of assumed processing speed */ int count_req = 0 ; long my_time; float speed = 0.0 ; float Average_speed = 0.0; int count_speed = 0; char cgifile[] = "/home/indira/sept_apache/apachenew/htdocs/server-status"; /************************************************* struct sockaddr_in from_my_apache, to_LBA; int my_sock; int length, n; char *buf; extern int sock_flag; register struct hostent *hostptr; struct in_addr *my_addr; /***********************************************/ #ifndef NO_TIMES #ifdef _SC_CLK_TCK float tick = sysconf(_SC_CLK_TCK); #else float tick = HZ; #endif #endif int short_report = 0; int no_table_report = 0; short_score score_record; parent_score ps_record; /*global_score my_global_record;*/ char stat_buffer[HARD_SERVER_LIMIT]; int pid_buffer[HARD_SERVER_LIMIT]; clock_t tu, ts, tcu, tcs; server_rec *vhost; tu = ts = tcu = tcs = 0; if (!ap_exists_scoreboard_image()) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "Server status unavailable in inetd mode"); return HTTP_INTERNAL_SERVER_ERROR; } r->allowed = (1 << M_GET); if (r->method_number != M_GET) return DECLINED; r->content_type = "text/html"; /* * Simple table-driven form data set parser that lets you alter the header */ if (r->args) { i = 0; while (status_options[i].id != STAT_OPT_END) { if ((loc = strstr(r->args, status_options[i].form_data_str)) != NULL) { switch (status_options[i].id) { case STAT_OPT_REFRESH: if (*(loc + strlen(status_options[i].form_data_str)) == '=') ap_table_set(r->headers_out, status_options[i].hdr_out_str, loc + strlen(status_options[i].hdr_out_str) + 1); else ap_table_set(r->headers_out, status_options[i].hdr_out_str, "1"); break; case STAT_OPT_NOTABLE: no_table_report = 1; break; case STAT_OPT_AUTO: r->content_type = "text/plain"; short_report = 1; break; } } i++; } } ap_send_http_header(r); if (r->header_only) return 0; ap_sync_scoreboard_image(); for (i = 0; i < HARD_SERVER_LIMIT; ++i) { score_record = ap_scoreboard_image->servers[i]; ps_record = ap_scoreboard_image->parent[i]; res = score_record.status; stat_buffer[i] = status_flags[res]; pid_buffer[i] = (int) ps_record.pid; if (res == SERVER_READY) ready++; else if (res != SERVER_DEAD) busy++; if (ap_extended_status) { lres = score_record.access_count; bytes = score_record.bytes_served; if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) { #ifndef NO_TIMES tu += score_record.times.tms_utime; ts += score_record.times.tms_stime; tcu += score_record.times.tms_cutime; tcs += score_record.times.tms_cstime; #endif /* NO_TIMES */ count += lres; bcount += bytes; if (bcount >= KBYTE) { kbcount += (bcount >> 10); bcount = bcount & 0x3ff; } } } } up_time = nowtime - ap_restart_time; ap_hard_timeout("send status info", r); if (!short_report) { ap_rputs(DOCTYPE_HTML_3_2 "\nApache Status\n\n", r); ap_rputs("

Apache Extended Server Status for ", r); ap_rvputs(r, ap_get_server_name(r), "

\n\n", NULL); ap_rvputs(r, "Server Version: ", ap_get_server_version(), "
\n", NULL); ap_rvputs(r, "Server Built: ", ap_get_server_built(), "
\n
\n", NULL); ap_rvputs(r, "Current Time: ", ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "
\n", NULL); ap_rvputs(r, "Restart Time: ", ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0), "
\n", NULL); ap_rprintf(r, "Parent Server Generation: %d
\n", (int) ap_my_generation); ap_rputs("Server uptime: ", r); show_time(r, up_time); ap_rputs("
\n", r); } if (ap_extended_status) { if (short_report) { ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %lu\n", count, kbcount); #ifndef NO_TIMES /* Allow for OS/2 not having CPU stats */ if (ts || tu || tcu || tcs) ap_rprintf(r, "CPULoad: %g\n", (tu + ts + tcu + tcs) / tick / up_time * 100.); #endif ap_rprintf(r, "Uptime: %ld\n", (long) (up_time)); if (up_time > 0) ap_rprintf(r, "ReqPerSec: %g\n", (float) count / (float) up_time); if (up_time > 0) ap_rprintf(r, "BytesPerSec: %g\n", KBYTE * (float) kbcount / (float) up_time); if (count > 0) ap_rprintf(r, "BytesPerReq: %g\n", KBYTE * (float) kbcount / (float) count); } else { /* !short_report */ ap_rprintf(r, "Total accesses: %lu - Total Traffic: ", count); format_kbyte_out(r, kbcount); /*ap_rprintf(r, "Time left to process requests= %ld
\n",time_left);*/ #ifndef NO_TIMES /* Allow for OS/2 not having CPU stats */ ap_rputs("
\n", r); ap_rprintf(r, "CPU Usage: u%g s%g cu%g cs%g", tu / tick, ts / tick, tcu / tick, tcs / tick); if (ts || tu || tcu || tcs) ap_rprintf(r, " - %.3g%% CPU load", (tu + ts + tcu + tcs) / tick / up_time * 100.); #endif ap_rputs("
\n", r); if (up_time > 0) ap_rprintf(r, "%.3g requests/sec - ", (float) count / (float) up_time); if (up_time > 0) { Avg_B_sec = KBYTE * ( float) kbcount / (float) up_time ; format_byte_out(r, KBYTE * (float) kbcount / (float) up_time); ap_rputs("/second - ", r); } if (count > 0) { format_byte_out(r, KBYTE * (float) kbcount / (float) count); ap_rputs("/request", r); } ap_rputs("
\n", r); } /* short_report */ } /* ap_extended_status */ if (!short_report) ap_rprintf(r, "\n%d requests currently being processed, %d idle servers\n" ,busy, ready); else ap_rprintf(r, "BusyServers: %d\nIdleServers: %d\n", busy, ready); /* send the scoreboard 'table' out */ if (!short_report) ap_rputs("
", r);
    else
	ap_rputs("Scoreboard: ", r);
/**********************************************************************************/
/* ap_rputs("\n>", r);*/
ap_rputs("", r);
ap_rputs("", r);
ap_rputs(" \
          
", r); bytes_remaining_for_this_request = 0; ap_sync_scoreboard_image(); count_req = 0; for (i = 0; i < HARD_SERVER_LIMIT; ++i) { score_record = ap_scoreboard_image->servers[i]; lres = score_record.access_count; if (lres != 0 || (score_record.status != SERVER_READY && score_record.status != SERVER_DEAD) ) { StrLen = strlen( score_record.my_file); if ( strcmp(score_record.my_file, cgifile) != 0) { /*@@@@@@@@@@@@@ Test for directory @@@@@@@*/ /*if ( strstr(&score_record.my_file[StrLen-1], extension) != NULL )*/ if ( strstr(&score_record.my_file[StrLen-11], ext_pub) != NULL ) { printf("IT HAS A SLASH: filename: %s\n", score_record.my_file ); my_new_file = (char*)malloc(StrLen + strlen(my_index)+1 ); strcpy(my_new_file, myempty_str); /*strncpy(my_new_file, score_record.my_file, StrLen);*/ strcpy(my_new_file, score_record.my_file); strcat(my_new_file, my_index); /*strcpy(score_record.my_file, my_new_file);*/ /*strcat(score_record.my_file, my_index);*/ /*stat( my_new_file, &mystatbuf);*/ /*myfileSz = mystatbuf.st_size;*/ strcpy( score_record.my_file, my_new_file); stat( score_record.my_file, &mystatbuf); score_record.myfilesize = mystatbuf.st_size; score_record.mybytes_sent = mystatbuf.st_size; /*bytes_remaining_for_this_request = myfileSz- score_record.mybytes_sent;*/ /*bytes_remaining_for_this_request = mystatbuf.st_size - score_record.mybytes_sent;*/ /*score_record.mybytes_remaining = bytes_remaining_for_this_request;*/ score_record.mybytes_remaining = 0; /*bytes_remaining_for_this_request = 0;*/ } /*@@@@@@@@@@@@@@@@@@@@*/ else { my_new_file = (char*)malloc(StrLen +1 ); strcpy(my_new_file, myempty_str); strncpy(my_new_file, score_record.my_file, StrLen); if (strstr(&score_record.my_file[StrLen-4], c_g_i_1) != NULL || strstr(&score_record.my_file[StrLen-3], c_g_i_2) != NULL ) { score_record.myfilesize = 0; bytes_remaining_for_this_request = 0 ; score_record.mybytes_remaining = 0; } else /* it is a regular file transfer request */ { myfileSz = score_record.myfilesize; bytes_remaining_for_this_request = myfileSz- score_record.mybytes_sent; score_record.mybytes_remaining = bytes_remaining_for_this_request; } } /*#################################################################*/ #if defined(NO_GETTIMEOFDAY) #ifndef NO_TIMES if (score_record.start_time == (clock_t) 0) #endif /* NO_TIMES */ req_time = 0L; #ifndef NO_TIMES else { req_time = score_record.stop_time - score_record.start_time; req_time = (req_time * 1000) / (int) tick; } #endif /* NO_TIMES */ #else if (score_record.start_time.tv_sec == 0L && score_record.start_time.tv_usec == 0L) req_time = 0L; else req_time = ((score_record.stop_time.tv_sec - score_record.start_time.tv_sec) * 1000) + ((score_record.stop_time.tv_usec - score_record.start_time.tv_usec) / 1000); #endif if (req_time < 0L) req_time = 0L; /*#################################################################*/ /* my_time = nowtime - score_record.start_time; my_time = (my_time * 1000) / (int) tick; */ /* if ( score_record.mybytes_sent != 0 && my_time != 0 ) myreq_B_sec = (float)( ((float)score_record.mybytes_sent)/ ((float)(my_time)) );*/ score_record.time_taken = req_time; if(score_record.time_taken != 0) { speed = (float) score_record.mybytes_sent / ((float)score_record.time_taken / 100.0); Average_speed += speed ; count_speed ++; } else speed = Average; bytes_left += bytes_remaining_for_this_request; score_record.time_to_completion = ((float) bytes_left)/speed ; put_scoreboard_info(i, &score_record); /*ap_rprintf(r, "", my_new_file, myfileSz , score_record.mybytes_sent, req_time, bytes_remaining_for_this_request, speed, score_record.time_to_completion);*/ ap_rprintf(r, "", score_record.my_file, score_record.myfilesize , score_record.mybytes_sent, score_record.time_taken, score_record.mybytes_remaining, speed, score_record.time_to_completion); /*Avg_B_sec += myreq_B_sec ;*/ count_req++; ap_rputs("\n", r); /*strcpy(score_record.my_file, myempty_str);*/ /* bytes_left += bytes_remaining_for_this_request; score_record.time_to_completion = ((float) bytes_left)/speed ; put_scoreboard_info(i, &score_record); */ mybytes_sent = + score_record.mybytes_sent; /*bytes_remaining_for_this_request = 0;*/ myreq_B_sec = 0 ; /*strcpy(my_new_file , myempty_str);*/ free(my_new_file); } /*end strcmp */ } ap_sync_scoreboard_image(); } ap_rputs("", r); ap_rputs("
FILENAME

File Sz

Sent

Time,ms

Bytes Left

Bytes per sec/TL

%s%8ld%lu%lu%lu%f/%f
%s%8ld%lu%lu%lu%f/%f


", r); ap_rprintf(r, "TOTAL BYTES LEFT = %lu bytes

", bytes_left); if ((float)bytes_left > 500.0 ) Average_speed = (float) Average_speed/(float)count_speed ; else Average_speed = Average; TimeLeft = ((float) bytes_left)/Average_speed ; /*my_global_record = ap_scoreboard_image->global;*/ /*my_global_record.time_to_completion = time_left;*/ /*update_scoreboard_global();*/ ap_rputs("Average Processing Speed = ", r ); format_byte_out(r, Average_speed); ap_rputs("/second

", r); ap_rprintf(r, "Time left to process requests = %f seconds
\n\n",TimeLeft); ap_rprintf(r, "Sending to port : = %d
\n", ntohs(to_LBA.sin_port)); ap_rprintf(r, "Sending to address : = %s
\n", inet_ntoa(to_LBA.sin_addr)); if (sendto(my_sock, &TimeLeft, sizeof(float), 0, &to_LBA, sizeof(to_LBA))<0) perror("relay datagram message"); /*ap_rprintf(r, "Time value copied to SB = %f seconds
\n", score_record.time_to_completion);*/ /************************************************************************************* bytes_left = 0; bytes_remaining_for_this_request = 0; ap_sync_scoreboard_image(); for (i = 0; i < HARD_SERVER_LIMIT; ++i) { score_record = ap_scoreboard_image->servers[i]; lres = score_record.access_count; if (lres !=0 ||(score_record.status != SERVER_READY && score_record.status != SERVER_DEAD) ) { if ( strcmp(score_record.my_file, cgifile) != 0) { if (strstr(score_record.my_file, c_g_i_1) != NULL || strstr(score_record.my_file, c_g_i_2) != NULL ) bytes_remaining_for_this_request = 0 ; else { /* start else 1 */ /*@@@@@@@@@@@@@ Test for directory @@@@@@@* StrLen = strlen( score_record.my_file); if ( score_record.my_file[StrLen] == '/' ){ my_new_file = (char*)malloc(StrLen); strncpy(my_new_file, score_record.my_file, StrLen); strcat(my_new_file, my_index); strcpy(score_record.my_file, my_new_file); stat( score_record.my_file, &mystatbuf); free(my_new_file); myfileSz = mystatbuf.st_size; } /*end if */ /*@@@@@@@@@@@@@@@@@@@@* else /*start else 2 * myfileSz = score_record.myfilesize; bytes_remaining_for_this_request = myfileSz - score_record.mybytes_sent; } /*end else 1 * bytes_left += bytes_remaining_for_this_request; } /* end if strcmp * } /* end lres * } /* end for */ /* ap_rprintf(r, "String size = %d
\n", strlen(my_index)); ap_rprintf(r, "String 5th char is: %s
\n", my_index[5] ); ap_rprintf(r, "last char is: %s
\n", my_index[strlen(my_index)] ); */ /*******************************************************************/ /******************************************************************/ for (i = 0; i < HARD_SERVER_LIMIT; ++i) { ap_rputc(stat_buffer[i], r); if ((i % STATUS_MAXLINE == (STATUS_MAXLINE - 1)) && !short_report) ap_rputs("\n", r); } if (short_report) ap_rputs("\n", r); else { ap_rputs("
\n", r); ap_rputs("Scoreboard Key:
\n", r); ap_rputs("\"_\" Waiting for Connection, \n", r); ap_rputs("\"S\" Starting up, \n", r); ap_rputs("\"R\" Reading Request,
\n", r); ap_rputs("\"W\" Sending Reply, \n", r); ap_rputs("\"K\" Keepalive (read), \n", r); ap_rputs("\"D\" DNS Lookup,
\n", r); ap_rputs("\"L\" Logging, \n", r); ap_rputs("\"G\" Gracefully finishing, \n", r); ap_rputs("\".\" Open slot with no current process

\n", r); ap_rputs("

\n", r); /*ap_rputs("Time left
\n",r); ap_rprintf(r,"Time left for req= %ld
\n", time_left);*/ if (!ap_extended_status) { int j = 0; ap_rputs("PID Key:
\n", r); ap_rputs("

\n", r);
	    for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
		if (stat_buffer[i] != '.') {
		    ap_rprintf(r, "   %d in state: %c ", pid_buffer[i],
		     stat_buffer[i]);
		    if (++j >= 3) {
		    	ap_rputs("\n", r);
			j = 0;
		    } else
		    	ap_rputs(",", r);
		}
	    }
	    ap_rputs("\n", r);
	    ap_rputs("
\n", r); } } if (ap_extended_status) { if (!short_report) { if (no_table_report) ap_rputs("


Server Details

\n\n", r); else #ifdef NO_TIMES /* Allow for OS/2 not having CPU stats */ ap_rputs("

\n\n\n\n", r); #else ap_rputs("

\n\n

SrvPIDAccM\nSSReqConnChildSlotClientVHostRequest
\n\n", r); #endif } for (i = 0; i < HARD_SERVER_LIMIT; ++i) { score_record = ap_scoreboard_image->servers[i]; ps_record = ap_scoreboard_image->parent[i]; vhost = score_record.vhostrec; if (ps_record.generation != ap_my_generation) { vhost = NULL; } #if defined(NO_GETTIMEOFDAY) #ifndef NO_TIMES if (score_record.start_time == (clock_t) 0) #endif /* NO_TIMES */ req_time = 0L; #ifndef NO_TIMES else { req_time = score_record.stop_time - score_record.start_time; req_time = (req_time * 1000) / (int) tick; } #endif /* NO_TIMES */ #else if (score_record.start_time.tv_sec == 0L && score_record.start_time.tv_usec == 0L) req_time = 0L; else req_time = ((score_record.stop_time.tv_sec - score_record.start_time.tv_sec) * 1000) + ((score_record.stop_time.tv_usec - score_record.start_time.tv_usec) / 1000); #endif if (req_time < 0L) req_time = 0L; lres = score_record.access_count; my_lres = score_record.my_access_count; conn_lres = score_record.conn_count; bytes = score_record.bytes_served; my_bytes = score_record.my_bytes_served; conn_bytes = score_record.conn_bytes; if (lres != 0 || (score_record.status != SERVER_READY && score_record.status != SERVER_DEAD)) { if (!short_report) { if (no_table_report) { if (score_record.status == SERVER_DEAD) ap_rprintf(r, "Server %d-%d (-): %d|%lu|%lu [", i, (int) ps_record.generation, (int) conn_lres, my_lres, lres); else ap_rprintf(r, "Server %d-%d (%d): %d|%lu|%lu [", i, (int) ps_record.generation, (int) ps_record.pid, (int) conn_lres, my_lres, lres); switch (score_record.status) { case SERVER_READY: ap_rputs("Ready", r); break; case SERVER_STARTING: ap_rputs("Starting", r); break; case SERVER_BUSY_READ: ap_rputs("Read", r); break; case SERVER_BUSY_WRITE: ap_rputs("Write", r); break; case SERVER_BUSY_KEEPALIVE: ap_rputs("Keepalive", r); break; case SERVER_BUSY_LOG: ap_rputs("Logging", r); break; case SERVER_BUSY_DNS: ap_rputs("DNS lookup", r); break; case SERVER_DEAD: ap_rputs("Dead", r); break; case SERVER_GRACEFUL: ap_rputs("Graceful", r); break; default: ap_rputs("?STATE?", r); break; } #ifdef NO_TIMES /* Allow for OS/2 not having CPU stats */ ap_rprintf(r, "]\n %.0f %ld (", #else ap_rprintf(r, "] u%g s%g cu%g cs%g\n %.0f %ld (", score_record.times.tms_utime / tick, score_record.times.tms_stime / tick, score_record.times.tms_cutime / tick, score_record.times.tms_cstime / tick, #endif #ifdef OPTIMIZE_TIMEOUTS difftime(nowtime, ps_record.last_rtime), #else difftime(nowtime, score_record.last_used), #endif (long) req_time); format_byte_out(r, conn_bytes); ap_rputs("|", r); format_byte_out(r, my_bytes); ap_rputs("|", r); format_byte_out(r, bytes); ap_rputs(")\n", r); ap_rprintf(r, " %s {%s}[%s]
\n\n", score_record.client, ap_escape_html(r->pool, score_record.request), vhost ? vhost->server_hostname : "(unavailable)"); } else { /* !no_table_report */ if (score_record.status == SERVER_DEAD) ap_rprintf(r, "\n\n"); else ap_rprintf(r, "\n\n", score_record.client, vhost ? vhost->server_hostname : "(unavailable)", ap_escape_html(r->pool, score_record.request)); } /* no_table_report */ } /* !short_report */ } /* if () */ } /* for () */ if (!(short_report || no_table_report)) { #ifdef NO_TIMES ap_rputs("
SrvPIDAccMCPU\nSSReqConnChildSlotClientVHostRequest
%d-%d-%d/%lu/%lu", i, (int) ps_record.generation, (int) conn_lres, my_lres, lres); else ap_rprintf(r, "
%d-%d%d%d/%lu/%lu", i, (int) ps_record.generation, (int) ps_record.pid, (int) conn_lres, my_lres, lres); switch (score_record.status) { case SERVER_READY: ap_rputs("_", r); break; case SERVER_STARTING: ap_rputs("S", r); break; case SERVER_BUSY_READ: ap_rputs("R", r); break; case SERVER_BUSY_WRITE: ap_rputs("W", r); break; case SERVER_BUSY_KEEPALIVE: ap_rputs("K", r); break; case SERVER_BUSY_LOG: ap_rputs("L", r); break; case SERVER_BUSY_DNS: ap_rputs("D", r); break; case SERVER_DEAD: ap_rputs(".", r); break; case SERVER_GRACEFUL: ap_rputs("G", r); break; default: ap_rputs("?", r); break; } #ifdef NO_TIMES /* Allow for OS/2 not having CPU stats */ ap_rprintf(r, "\n%.0f%ld", #else ap_rprintf(r, "\n%.2f%.0f%ld", (score_record.times.tms_utime + score_record.times.tms_stime + score_record.times.tms_cutime + score_record.times.tms_cstime) / tick, #endif #ifdef OPTIMIZE_TIMEOUTS difftime(nowtime, ps_record.last_rtime), #else difftime(nowtime, score_record.last_used), #endif (long) req_time); ap_rprintf(r, "%-1.1f%-2.2f%-2.2f\n", (float) conn_bytes / KBYTE, (float) my_bytes / MBYTE, (float) bytes / MBYTE); if (score_record.status == SERVER_BUSY_READ) ap_rprintf(r, "??..reading..
%s%s%s
\n \


\ \n \
SrvChild Server number - generation\n \
PIDOS process ID\n \
AccNumber of accesses this connection / this child / this slot\n \
MMode of operation\n \
SSSeconds since beginning of most recent request\n \
ReqMilliseconds required to process most recent request\n \
ConnKilobytes transferred this connection\n \
ChildMegabytes transferred this child\n \
SlotTotal megabytes transferred this slot\n \
\n", r); #else ap_rputs("\n \
\ \n \
SrvChild Server number - generation\n \
PIDOS process ID\n \
AccNumber of accesses this connection / this child / this slot\n \
MMode of operation\n \
CPUCPU usage, number of seconds\n \
SSSeconds since beginning of most recent request\n \
ReqMilliseconds required to process most recent request\n \
ConnKilobytes transferred this connection\n \
ChildMegabytes transferred this child\n \
SlotTotal megabytes transferred this slot\n \
\n", r); #endif } } else { ap_rputs("
To obtain a full report with current status information ", r); ap_rputs("you need to use the ExtendedStatus On directive. \n", r); } /**********************************************************/ /**********************************************************/ if (!short_report) { ap_rputs(ap_psignature("
\n",r), r); ap_rputs("\n", r); } ap_kill_timeout(r); return 0; } static void status_init(server_rec *s, pool *p) { status_flags[SERVER_DEAD] = '.'; /* We don't want to assume these are in */ status_flags[SERVER_READY] = '_'; /* any particular order in scoreboard.h */ status_flags[SERVER_STARTING] = 'S'; status_flags[SERVER_BUSY_READ] = 'R'; status_flags[SERVER_BUSY_WRITE] = 'W'; status_flags[SERVER_BUSY_KEEPALIVE] = 'K'; status_flags[SERVER_BUSY_LOG] = 'L'; status_flags[SERVER_BUSY_DNS] = 'D'; status_flags[SERVER_GRACEFUL] = 'G'; } static const handler_rec status_handlers[] = { {STATUS_MAGIC_TYPE, status_handler}, {"server-status", status_handler}, {NULL} }; module MODULE_VAR_EXPORT status_module = { STANDARD_MODULE_STUFF, status_init, /* initializer */ NULL, /* dir config creater */ NULL, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ status_module_cmds, /* command table */ status_handlers, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL, /* logger */ NULL, /* header parser */ NULL, /* child_init */ NULL, /* child_exit */ NULL /* post read-request */ };