From d23f4e1b36396b975b3de1a630942be944069f3b Mon Sep 17 00:00:00 2001 From: wessels <> Date: Mon, 23 Feb 1998 03:40:24 +0000 Subject: [PATCH] new squid-independent cachemgr.cgi --- src/cachemgr.cc | 1029 ++++++++++------------------------------------- 1 file changed, 207 insertions(+), 822 deletions(-) diff --git a/src/cachemgr.cc b/src/cachemgr.cc index e189eef16c..f37d0f750c 100644 --- a/src/cachemgr.cc +++ b/src/cachemgr.cc @@ -1,9 +1,8 @@ - /* - * $Id: cachemgr.cc,v 1.66 1998/01/07 22:45:25 wessels Exp $ + * $Id: cachemgr.cc,v 1.67 1998/02/22 20:40:24 wessels Exp $ * * DEBUG: section 0 CGI Cache Manager - * AUTHOR: Harvest Derived + * AUTHOR: Duane Wessels * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * -------------------------------------------------------- @@ -17,91 +16,16 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -/* - * Copyright (c) 1994, 1995. All rights reserved. - * - * The Harvest software was developed by the Internet Research Task - * Force Research Group on Resource Discovery (IRTF-RD): - * - * Mic Bowman of Transarc Corporation. - * Peter Danzig of the University of Southern California. - * Darren R. Hardy of the University of Colorado at Boulder. - * Udi Manber of the University of Arizona. - * Michael F. Schwartz of the University of Colorado at Boulder. - * Duane Wessels of the University of Colorado at Boulder. - * - * This copyright notice applies to software in the Harvest - * ``src/'' directory only. Users should consult the individual - * copyright notices in the ``components/'' subdirectories for - * copyright information about other software bundled with the - * Harvest source code distribution. - * - * TERMS OF USE - * - * The Harvest software may be used and re-distributed without - * charge, provided that the software origin and research team are - * cited in any use of the system. Most commonly this is - * accomplished by including a link to the Harvest Home Page - * (http://harvest.cs.colorado.edu/) from the query page of any - * Broker you deploy, as well as in the query result pages. These - * links are generated automatically by the standard Broker - * software distribution. - * - * The Harvest software is provided ``as is'', without express or - * implied warranty, and with no support nor obligation to assist - * in its use, correction, modification or enhancement. We assume - * no liability with respect to the infringement of copyrights, - * trade secrets, or any patents, and are not responsible for - * consequential damages. Proper use of the Harvest software is - * entirely the responsibility of the user. - * - * DERIVATIVE WORKS - * - * Users may make derivative works from the Harvest software, subject - * to the following constraints: - * - * - You must include the above copyright notice and these - * accompanying paragraphs in all forms of derivative works, - * and any documentation and other materials related to such - * distribution and use acknowledge that the software was - * developed at the above institutions. - * - * - You must notify IRTF-RD regarding your distribution of - * the derivative work. - * - * - You must clearly notify users that your are distributing - * a modified version and not the original Harvest software. - * - * - Any derivative product is also subject to these copyright - * and use restrictions. - * - * Note that the Harvest software is NOT in the public domain. We - * retain copyright, as specified above. - * - * HISTORY OF FREE SOFTWARE STATUS - * - * Originally we required sites to license the software in cases - * where they were going to build commercial products/services - * around Harvest. In June 1995 we changed this policy. We now - * allow people to use the core Harvest software (the code found in - * the Harvest ``src/'' directory) for free. We made this change - * in the interest of encouraging the widest possible deployment of - * the technology. The Harvest software is really a reference - * implementation of a set of protocols and formats, some of which - * we intend to standardize. We encourage commercial - * re-implementations of code complying to this set of standards. + * */ #include "config.h" @@ -200,119 +124,32 @@ #include "util.h" #include "snprintf.h" -#define MAX_ENTRIES 10000 - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -#if 0 -#define LF 10 -#define CR 13 -#endif - -typedef enum { - INFO, - CACHED, - SERVER, - CLIENTS, - LOG, - PARAM, - STATS_I, - STATS_F, - STATS_D, - STATS_R, - STATS_O, - STATS_VM, - STATS_U, - STATS_IO, - STATS_HDRS, - STATS_FDS, - STATS_NETDB, - SHUTDOWN, - REFRESH, - PCONN, -#ifdef REMOVE_OBJECT - REMOVE, -#endif - MAXOP -} op_t; - -static const char *const op_cmds[] = -{ - "info", - "squid.conf", - "server_list", - "client_list", - "log", - "config", - "ipcache", - "fqdncache", - "dns", - "redirector", - "objects", - "vm_objects", - "utilization", - "io", - "reply_headers", - "filedescriptors", - "netdb", - "shutdown", - "refresh", - "pconn", -#ifdef REMOVE_OBJECT - "remove", -#endif - "unknown" -}; - -static const char *const op_cmds_descr[] = -{ - "Cache Information", - "Cache Configuration File", - "Cache Server List", - "Cache Client List", - "Cache Log", - "Cache Parameters", - "IP Cache Contents", - "FQDN Cache Contents", - "DNS Server Statistics", - "Redirector Statistics", - "Objects", - "VM Objects", - "Utilization", - "I/O", - "HTTP Reply Headers", - "Filedescriptor Usage", - "Network Probe Database", - "Shutdown Cache", - "Refresh Object (URL required)", - "Persistent Connection Statistics", -#ifdef REMOVE_OBJECT - "Remove Object (URL required)", -#endif - "Unknown Operation" -}; - -static int hasTables = FALSE; +typedef struct { + char *hostname; + int port; + char *action; + char *passwd; +} cachemgr_request; +/* + * static variables + */ static const char *script_name = "/cgi-bin/cachemgr.cgi"; static const char *const w_space = " \t\n\r"; static const char *progname = NULL; static time_t now; static struct in_addr no_addr; -static char x2c(char *); -static int client_comm_connect(int sock, char *dest_host, u_short dest_port); +/* + * Function prototypes + */ static void print_trailer(void); -static void noargs_html(char *, int, char *, char *); -static void unescape_url(char *); -static void plustospace(char *); -static void parse_object(char *); -static char *describeTimeSince(time_t then); +static void noargs_html(char *host, int port); +static void error_html(const char *msg); +static cachemgr_request *read_request(void); +static char *read_get_request(void); +static char *read_post_request(void); + static void print_trailer(void) @@ -324,23 +161,10 @@ print_trailer(void) printf("\n"); } - -static void -print_option(op_t current_opt, op_t opt_nr) -{ - printf("%s\n", - current_opt == opt_nr ? " SELECTED " : " ", - op_cmds[opt_nr], - op_cmds_descr[opt_nr]); -} - - static void -noargs_html(char *host, int port, char *url, char *password) +noargs_html(char *host, int port) { - op_t op = INFO; - - printf("\r\n\r\n"); + printf("Content-type: text/html\r\n\r\n"); printf("Cache Manager Interface\n"); printf("

Cache Manager Interface

\n"); printf("

This is a WWW interface to the instrumentation interface\n"); @@ -352,665 +176,226 @@ noargs_html(char *host, int port, char *url, char *password) printf("SIZE=30 VALUE=\"%s\">
\n", host); printf("Cache Port:
\n", port); - printf("Password :
\n", password); - printf("URL :
\n", url); - printf("Operation :"); - printf("
\n"); - printf("


\n"); - printf(" \n"); + printf("\n"); printf("\n"); print_trailer(); } -#if 0 -/* A utility function from the NCSA httpd cgi-src utils.c */ -char * -makeword(char *line, char stop) +static void +error_html(const char *msg) { - int x = 0, y; - char *word = xmalloc(sizeof(char) * (strlen(line) + 1)); - - for (x = 0; ((line[x]) && (line[x] != stop)); x++) - word[x] = line[x]; - - word[x] = '\0'; - if (line[x]) - ++x; - y = 0; - - while ((line[y++] = line[x++]) != '\0'); - return word; + printf("Content-type: text/html\r\n\r\n"); + printf("Cache Manager Error\n"); + printf("

Cache Manager Error

\n"); + printf("

\n%s

\n", msg); + print_trailer(); } -/* A utility function from the NCSA httpd cgi-src utils.c */ -char * -fmakeword(FILE * f, char stop, int *cl) +static char * +menu_url(cachemgr_request * req, char *action) { - int wsize = 102400; - char *word = NULL; - int ll = 0; - - word = xmalloc(sizeof(char) * (wsize + 1)); - for (;;) { - word[ll] = (char) fgetc(f); - if (ll == wsize) { - word[ll + 1] = '\0'; - wsize += 102400; - word = realloc(word, sizeof(char) * (wsize + 1)); - } - --(*cl); - if ((word[ll] == stop) || (feof(f)) || (!(*cl))) { - if (word[ll] != stop) - ll++; - word[ll] = '\0'; - return word; - } - ++ll; - } - /* NOTREACHED */ + static char url[1024]; + snprintf(url, 1024, "%s?host=%s&port=%d&operation=%s", + script_name, + req->hostname, + req->port, + action); + return url; } -#endif -/* A utility function from the NCSA httpd cgi-src utils.c */ -static char -x2c(char *what) +static const char * +munge_menu_line(const char *buf, cachemgr_request * req) { - char digit; - - digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); - digit *= 16; - digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); - return (digit); + char *x; + char *a; + char *d; + static char html[1024]; + if (strlen(buf) < 1) + return buf; + if (*buf != ' ') + return buf; + x = xstrdup(buf); + if ((a = strtok(x, w_space)) == NULL) + return buf; + if ((d = strtok(NULL, "")) == NULL) + return buf; + snprintf(html, 1024, "
  • %s\n", + menu_url(req, a), d); + return html; } -/* A utility function from the NCSA httpd cgi-src utils.c */ -static void -unescape_url(char *url) +static int +read_reply(int s, cachemgr_request * req) { - int x, y; - - for (x = 0, y = 0; url[y]; ++x, ++y) { - if ((url[x] = url[y]) == '%') { - url[x] = x2c(&url[y + 1]); - y += 2; - } + char buf[1024]; + FILE *fp = fdopen(s, "r"); + int state = 0; + int parse_menu = 0; + if (0 == strlen(req->action)) + parse_menu = 1; + else if (0 == strcasecmp(req->action, "menu")) + parse_menu = 1; + if (fp == NULL) { + perror("fdopen"); + return 1; } - url[x] = '\0'; -} - -/* A utility function from the NCSA httpd cgi-src utils.c */ -static void -plustospace(char *str) -{ - int x; - - for (x = 0; str[x]; x++) - if (str[x] == '+') - str[x] = ' '; -} - -#define ONE_SECOND (1) -#define ONE_MINUTE (ONE_SECOND*60) -#define ONE_HOUR (ONE_MINUTE*60) -#define ONE_DAY (ONE_HOUR*24) -#define ONE_WEEK (ONE_DAY*7) -#define ONE_MONTH (ONE_DAY*30) -#define ONE_YEAR (ONE_DAY*365) - -static char * -describeTimeSince(time_t then) -{ - time_t delta = now - then; - static char buf[128]; - static char buf2[128]; - const char *fmt = "%s ago"; - buf[0] = '\0'; - if (delta < 0) { - delta = (-delta); - fmt = "in %s"; + printf("Content-Type: text/html\r\n\r\n"); + if (parse_menu) { + printf("

    Cache Manager menu for %s:

    ", req->hostname); + printf("\n"); else - snprintf(buf, 128, "%dY", (int) (delta / ONE_YEAR)); - snprintf(buf2, 128, fmt, buf); - return buf2; + printf("\n"); + print_trailer(); + close(s); + return 0; } -static void -parse_object(char *string) +static int +process_request(cachemgr_request * req) { - char *tbuf = NULL; - char *store_status = NULL; - char *mem_status = NULL; - char *swap_status = NULL; - char *ping_status = NULL; - char *lock_count = NULL; - char *flags = NULL; - char *last_verified = NULL; - char *last_use = NULL; - char *last_modified = NULL; - char *expires = NULL; - char *refcount = NULL; - char *clients = NULL; - char *size = NULL; - char *url = NULL; - - tbuf = xstrdup(string); - - if ((store_status = strtok(tbuf, w_space)) == NULL) - goto parse_obj_done; - if ((mem_status = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((swap_status = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((ping_status = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((lock_count = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((flags = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((last_verified = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((last_use = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((last_modified = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((expires = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((refcount = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((clients = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((size = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - if ((url = strtok(NULL, w_space)) == NULL) - goto parse_obj_done; - -#if !ALL_OBJECTS - if (!strncmp(url, "cache_object", 12)) - goto parse_obj_done; - if (!strncmp(url, "POST", 4)) - goto parse_obj_done; -#endif - - printf("
  • %s
    ", - url, url); - printf("Verified %s, ", describeTimeSince((time_t) atoi(last_verified + 3))); - printf("Used %s, ", describeTimeSince((time_t) atoi(last_use + 3))); - printf("Modified %s, ", describeTimeSince((time_t) atoi(last_modified + 3))); - printf("Expires %s,
    ", describeTimeSince((time_t) atoi(expires + 3))); - printf("%d bytes, %d accesses, %d active clients,
    ", - atoi(size), - atoi(refcount), - atoi(clients)); - printf("%s, %s, %s, %s,
    ", - store_status, - mem_status, - swap_status, - ping_status); - printf("%d Locks, Flags: %s\n", - atoi(lock_count), - flags); - - parse_obj_done: - xfree(tbuf); + const struct hostent *hp; + static struct sockaddr_in S; + int s; + int l; + static char buf[1024]; + if (req == NULL) { + noargs_html(CACHEMGR_HOSTNAME, CACHE_HTTP_PORT); + return 1; + } + if (req->hostname == NULL) { + req->hostname = xstrdup(CACHEMGR_HOSTNAME); + } + if (req->port == 0) { + req->port = CACHE_HTTP_PORT; + } + if (req->action == NULL) { + req->action = xstrdup(""); + } + if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + snprintf(buf, 1024, "socket: %s\n", xstrerror()); + error_html(buf); + return 1; + } + memset(&S, '\0', sizeof(struct sockaddr_in)); + S.sin_family = AF_INET; + if ((hp = gethostbyname(req->hostname)) != NULL) + xmemcpy(&S.sin_addr.s_addr, hp->h_addr, hp->h_length); + else if (safe_inet_addr(req->hostname, &S.sin_addr)) + (void) 0; + else { + snprintf(buf, 1024, "Unknown host: %s\n", req->hostname); + error_html(buf); + return 1; + } + S.sin_port = htons(req->port); + if (connect(s, (struct sockaddr *) &S, sizeof(struct sockaddr_in)) < 0) { + snprintf(buf, 1024, "connect: %s\n", xstrerror()); + error_html(buf); + return 1; + } + l = snprintf(buf, 1024, + "GET cache_object://%s/%s HTTP/1.0\r\n" + "Accept: */*\r\n" + "\r\n", + req->hostname, + req->action); + write(s, buf, l); + return read_reply(s, req); } int main(int argc, char *argv[]) { - static char hostname[256] = ""; - static char operation[256] = ""; - static char password[256] = ""; - static char url[4096] = ""; - static char msg[1024]; - static char buf[4096]; - static char reserve[4096]; - static char s1[255]; - static char s2[255]; - char *buffer = NULL; - char *time_string = NULL; - char *agent = NULL; - char *s = NULL; - int conn; - int len; - int bytesWritten; - int portnum = CACHE_HTTP_PORT; - op_t op; - int p_state; - int n_loops; - int cpy_ind; - int indx; - int in_list = 0; - int in_table = 0; - int d1, d2, d3, d4, d5, d6, d7; - int single = TRUE; - float f1; - + char *s; + cachemgr_request *req; safe_inet_addr("255.255.255.255", &no_addr); now = time(NULL); if ((s = strrchr(argv[0], '/'))) progname = xstrdup(s + 1); else progname = xstrdup(argv[0]); - if ((s = getenv("SCRIPT_NAME")) != NULL) { + if ((s = getenv("SCRIPT_NAME")) != NULL) script_name = xstrdup(s); - } - strcpy(hostname, CACHEMGR_HOSTNAME); - - /* a POST request */ - if ((s = getenv("REQUEST_METHOD")) != NULL && !strcasecmp(s, "POST") && - (s = getenv("CONTENT_LENGTH")) != NULL && (len = atoi(s)) > 0) { - buffer = xmalloc(len + 1); - fread(buffer, len, 1, stdin); - buffer[len] = '\0'; - /* a GET request */ - } else if ((s = getenv("QUERY_STRING"))) { - /* convert hostname:portnum to host=hostname&port=portnum */ - if (*s && !strchr(s, '=') && !strchr(s, '&')) { - char *p; - int len_buff = strlen(s) + sizeof "host=&port="; - buffer = xmalloc(len_buff); - if ((p = strchr(s, ':'))) - if (p != s) { - *p = '\0'; - snprintf(buffer, len_buff, "host=%s&port=%s", s, p + 1); - } else { - snprintf(buffer, len_buff, "port=%s", p + 1); - } else - snprintf(buffer, len_buff, "host=%s", s); - } else { - buffer = xstrdup(s); - } - /* no CGI parameters */ - } else { - buffer = xstrdup(""); - } - - printf("Content-type: text/html\r\n\r\n"); - - for (s = strtok(buffer, "&"); s; s = strtok(0, "&")) { - char *v; - - plustospace(s); - unescape_url(s); - if ((v = strchr(s, '=')) != NULL) - *v++ = '\0'; - else - v = s; - - if (!strcmp(s, "host")) { - xstrncpy(hostname, v, sizeof hostname); - } else if (!strcmp(s, "operation")) { - xstrncpy(operation, v, sizeof operation); - } else if (!strcmp(s, "password")) { - xstrncpy(password, v, sizeof password); - } else if (!strcmp(s, "url")) { - xstrncpy(url, v, sizeof url); - } else if (!strcmp(s, "port")) { - portnum = atoi(v); - } else { - printf("

    Unknown CGI parameter: %s

    \n", - s); - noargs_html(hostname, portnum, url, password); - exit(0); - } - } - xfree(buffer); - - if ((agent = getenv("HTTP_USER_AGENT")) != NULL) { - if (!strncasecmp(agent, "Mozilla", 7) || - !strncasecmp(agent, "OmniWeb/2", 9) || - !strncasecmp(agent, "Netscape", 8)) { - hasTables = TRUE; - } - } - /* prints HTML form if no args */ - if (!operation[0] || !strcmp(operation, "empty")) { - noargs_html(hostname, portnum, url, password); - exit(0); - } - if (hostname[0] == '\0') { - printf("

    ERROR

    \n"); - printf("

    You must provide a hostname!\n


    "); - noargs_html(hostname, portnum, url, password); - exit(0); - } - close(0); - - for (op = INFO; op != MAXOP; op = (op_t) (op + 1)) - if (!strcmp(operation, op_cmds[op]) || - !strcmp(operation, op_cmds_descr[op])) - break; - - switch (op) { - case INFO: - case CACHED: - case SERVER: - case CLIENTS: - case LOG: - case PARAM: - case STATS_I: - case STATS_F: - case STATS_D: - case STATS_R: - case STATS_O: - case STATS_VM: - case STATS_U: - case STATS_IO: - case STATS_HDRS: - case STATS_FDS: - case STATS_NETDB: - case PCONN: - case SHUTDOWN: - snprintf(msg, 1024, "GET cache_object://%s/%s@%s HTTP/1.0\r\n\r\n", - hostname, op_cmds[op], password); - break; - case REFRESH: - snprintf(msg, 1024, "GET %s HTTP/1.0\r\nPragma: no-cache\r\nAccept: */*\r\n\r\n", url); - break; -#ifdef REMOVE_OBJECT - case REMOVE: - printf("Remove not yet supported\n"); - exit(0); - /* NOTREACHED */ -#endif - default: - case MAXOP: - printf("Unknown operation: %s\n", operation); - exit(0); - /* NOTREACHED */ - } - - time_string = ctime(&now); - - printf("Cache Manager: %s:%s:%d\n", - operation, hostname, portnum); - printf("
    \n", script_name); - printf("\n"); - printf("\n"); - printf("\n", hostname); - printf("\n", portnum); - printf("\n", password); - printf("\n", url); - printf("
    \n"); - printf("
    \n"); - - printf("

    %s: %s:%d

    \n", operation, hostname, portnum); - printf("

    dated %s

    \n", time_string); - printf("
    \n");
    -
    -    /* Connect to the server */
    -    if ((conn = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
    -	perror("client: socket");
    -	exit(1);
    -    }
    -    if (client_comm_connect(conn, hostname, portnum) < 0) {
    -	printf("Error: connecting to cache mgr: %s:%d\n", hostname, portnum);
    -	printf("%s
    \n", xstrerror()); - exit(1); - } - bytesWritten = write(conn, msg, strlen(msg)); - - if (bytesWritten < 0) { - printf("Error: write failed\n"); - exit(1); - } else if (bytesWritten != (strlen(msg))) { - printf("Error: write short\n"); - exit(1); - } - /* Print header stuff for tables */ - switch (op) { - case INFO: - case CACHED: - case SERVER: - case CLIENTS: - case LOG: - case STATS_I: - case STATS_F: - case STATS_D: - case STATS_R: - case STATS_O: - case STATS_VM: - case STATS_IO: - case STATS_HDRS: - case STATS_FDS: - case STATS_NETDB: - case SHUTDOWN: - case REFRESH: - case PCONN: - break; - case PARAM: - if (hasTables) { - printf("
    ParameterValueDescription\n"); - in_table = 1; - } else { - printf("\n Parameter Value Description\n"); - printf("-------------- ------- -------------------------------------\n"); - } - break; - case STATS_U: - if (hasTables) { - printf("\n"); - in_table = 1; - } else { - printf("Protocol Object Maximum Current Minimum Hit Trans Transfer Transfered\n"); - printf(" Count KB KB KB Rate KB/sec Count KB\n"); - printf("-------- ------- --------- --------- --------- ---- ------ --------- ----------\n"); - } - break; - default: - printf("\n\n

    \nNot currently implemented.\n"); - exit(1); - } - - p_state = 0; - cpy_ind = 0; - n_loops = 0; /* Keep track of passes through loop */ - while ((len = read(conn, buf, sizeof(buf))) > 0) { - n_loops++; - /* Simple state machine for parsing a {{ } { } ...} style list */ - for (indx = 0; indx < len; indx++) { - if (buf[indx] == '{') - p_state++; - else if (buf[indx] == '}') - if (p_state == 2) { /* Have an element of the list */ - single = FALSE; - p_state++; - reserve[cpy_ind] = '\0'; - cpy_ind = 0; - } else if (p_state == 1 && single) /* Check for single element list */ - p_state = 3; - else /* End of list */ - p_state = 0; - else if ((indx == 0) && (n_loops == 1)) { - if (op != REFRESH) - printf("ERROR:%s\n", buf); /* Must be an error message, pass it on */ - else - printf("Refreshed URL: %s\n", url); - } else - reserve[cpy_ind++] = buf[indx]; - - - /* Have an element of the list, so parse reserve[] accordingly */ - if (p_state == 3) { - int sn; - switch (op) { - case CACHED: - p_state = 1; - for (s = reserve; *s; s++) - switch (*s) { - case '<': - printf("<"); - break; - case '&': - printf("&"); - break; - default: - putchar(*s); - break; - } - break; - case INFO: - case SERVER: - case CLIENTS: - case LOG: - case STATS_I: - case STATS_F: - case STATS_D: - case STATS_R: - case STATS_IO: - case STATS_HDRS: - case STATS_FDS: - case STATS_NETDB: - case SHUTDOWN: - case PCONN: - p_state = 1; - printf("%s", reserve); - break; - case REFRESH: - /* throw object away */ - break; - case PARAM: - p_state = 1; - memset(s1, '\0', 255); - memset(s2, '\0', 255); - d1 = 0; - sscanf(reserve, "%s %d \"%[^\"]", s1, &d1, s2); - if (hasTables) - printf("

    ProtocolObject CountMax KBCurrent KBMin KBHit RatioTransfer KB/secTransfer CountTransfered KB
    %s%d%s\n", s1, d1, s2 + 2); - else - printf("%14s %7d %s\n", s1, d1, s2 + 2); - break; - case STATS_U: - p_state = 1; - sn = sscanf(reserve, "%s %d %d %d %d %f %d %d %d", - s1, &d1, &d2, &d3, &d4, &f1, &d5, &d6, &d7); - if (sn == 1) { - if (hasTables) - printf("
    %s\n", s1); - else - printf("%s-Requests\n", s1); - break; - } - if (hasTables) - printf("
    %s%d%d%d%d%4.2f%d%d%d\n", - s1, d1, d2, d3, d4, f1, d5, d6, d7); - else - printf("%8s %7d %9d %9d %9d %4.2f %6d %9d %10d\n", - s1, d1, d2, d3, d4, f1, d5, d6, d7); - break; - case STATS_O: - case STATS_VM: - if (!in_list) { - in_list = 1; - printf("
      \n"); - } - parse_object(reserve); - p_state = 1; - break; - default: - printf("%s\n", "Not currently implemented"); - exit(1); - } - } - } - } - - if (in_list) - printf("
    \n"); - - if (in_table) - printf("
    \n"); - - printf("\n\n"); - print_trailer(); - close(conn); - exit(0); - /* NOTREACHED */ - return 0; + req = read_request(); + return process_request(req); } -static int -client_comm_connect(int sock, char *dest_host, u_short dest_port) +static char * +read_post_request(void) { - const struct hostent *hp; - static struct sockaddr_in to_addr; + char *s; + char *buf; + int len; + if ((s = getenv("REQUEST_METHOD")) == NULL) + return NULL; + if (0 != strcasecmp(s, "POST")) + return NULL; + if ((s = getenv("CONTENT_LENGTH")) == NULL) + return NULL; + if ((len = atoi(s)) <= 0) + return NULL; + buf = xmalloc(len + 1); + fread(buf, len, 1, stdin); + buf[len] = '\0'; + return buf; +} - /* Set up the destination socket address for message to send to. */ - memset(&to_addr, '\0', sizeof(struct sockaddr_in)); - to_addr.sin_family = AF_INET; +static char * +read_get_request(void) +{ + char *s; + if ((s = getenv("QUERY_STRING")) == NULL) + return NULL; + return xstrdup(s); +} - if ((hp = gethostbyname(dest_host)) != NULL) - xmemcpy(&to_addr.sin_addr.s_addr, hp->h_addr, hp->h_length); - else if (safe_inet_addr(dest_host, &to_addr.sin_addr)) +static cachemgr_request * +read_request(void) +{ + char *buf; + cachemgr_request *req; + char *s; + char *t; + char *q; + if ((buf = read_post_request()) != NULL) + (void) 0; + else if ((buf = read_get_request()) != NULL) (void) 0; else - return (-1); - - to_addr.sin_port = htons(dest_port); - return connect(sock, (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)); + return NULL; + if (strlen(buf) == 0) + return NULL; + req = xcalloc(1, sizeof(cachemgr_request)); + for (s = strtok(buf, "&"); s != NULL; s = strtok(NULL, "&")) { + t = xstrdup(s); + if ((q = strchr(t, '=')) == NULL) + continue; + *q++ = '\0'; + if (0 == strcasecmp(t, "host")) + req->hostname = xstrdup(q); + if (0 == strcasecmp(t, "port")) + req->port = atoi(q); + if (0 == strcasecmp(t, "password")) + req->passwd = xstrdup(q); + if (0 == strcasecmp(t, "operation")) + req->action = xstrdup(q); + } + return req; } -- 2.47.3