-
/*
- * $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/
* --------------------------------------------------------
* 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"
#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)
printf("</ADDRESS></BODY></HTML>\n");
}
-
-static void
-print_option(op_t current_opt, op_t opt_nr)
-{
- printf("<OPTION%sVALUE=\"%s\">%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("<HTML><HEAD><TITLE>Cache Manager Interface</TITLE></HEAD>\n");
printf("<BODY><H1>Cache Manager Interface</H1>\n");
printf("<P>This is a WWW interface to the instrumentation interface\n");
printf("SIZE=30 VALUE=\"%s\"><BR>\n", host);
printf("<STRONG>Cache Port:</STRONG><INPUT NAME=\"port\" ");
printf("SIZE=30 VALUE=\"%d\"><BR>\n", port);
- printf("<STRONG>Password :</STRONG><INPUT TYPE=\"password\" ");
- printf("NAME=\"password\" SIZE=30 VALUE=\"%s\"><BR>\n", password);
- printf("<STRONG>URL :</STRONG><INPUT NAME=\"url\" ");
- printf("SIZE=30 VALUE=\"%s\"><BR>\n", url);
- printf("<STRONG>Operation :</STRONG>");
- printf("<SELECT NAME=\"operation\">\n");
- print_option(op, INFO);
- print_option(op, CACHED);
- print_option(op, PARAM);
-#ifdef MENU_SHOW_LOG
- print_option(op, LOG);
-#endif
- print_option(op, STATS_U);
- print_option(op, STATS_IO);
- print_option(op, STATS_HDRS);
- print_option(op, STATS_FDS);
- print_option(op, STATS_NETDB);
- print_option(op, STATS_O);
- print_option(op, STATS_VM);
- print_option(op, SERVER);
- print_option(op, CLIENTS);
- print_option(op, STATS_I);
- print_option(op, STATS_F);
- print_option(op, STATS_D);
- print_option(op, STATS_R);
- print_option(op, SHUTDOWN);
- print_option(op, REFRESH);
- print_option(op, PCONN);
-#ifdef REMOVE_OBJECT
- print_option(op, REMOVE);
-#endif
printf("</SELECT><BR>\n");
- printf("<HR>\n");
- printf("<INPUT TYPE=\"submit\"> <INPUT TYPE=\"reset\">\n");
+ printf("<INPUT TYPE=\"submit\" VALUE=\"Continue...\">\n");
printf("</FORM></PRE>\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("<HTML><HEAD><TITLE>Cache Manager Error</TITLE></HEAD>\n");
+ printf("<BODY><H1>Cache Manager Error</H1>\n");
+ printf("<P>\n%s</P>\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, "<LI><A HREF=\"%s\">%s</A>\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("<H2>Cache Manager menu for %s:</H2>", req->hostname);
+ printf("<UL>\n");
+ } else {
+ printf("<P><A HREF=\"%s\">%s</A>\n<HR>\n",
+ menu_url(req, "menu"), "Cache Manager menu");
+ printf("<PRE>\n");
}
- if (then < 0)
- return "NEVER";
- if (delta < ONE_MINUTE)
- snprintf(buf, 128, "%ds", (int) (delta / ONE_SECOND));
- else if (delta < ONE_HOUR)
- snprintf(buf, 128, "%dm", (int) (delta / ONE_MINUTE));
- else if (delta < ONE_DAY)
- snprintf(buf, 128, "%dh", (int) (delta / ONE_HOUR));
- else if (delta < ONE_WEEK)
- snprintf(buf, 128, "%dD", (int) (delta / ONE_DAY));
- else if (delta < ONE_MONTH)
- snprintf(buf, 128, "%dW", (int) (delta / ONE_WEEK));
- else if (delta < ONE_YEAR)
- snprintf(buf, 128, "%dM", (int) (delta / ONE_MONTH));
+ while (fgets(buf, 1024, fp) != NULL) {
+ if (1 == state)
+ if (parse_menu)
+ fputs(munge_menu_line(buf, req), stdout);
+ else
+ fputs(buf, stdout);
+ if (0 == strcmp(buf, "\r\n"))
+ state++;
+ }
+ if (parse_menu)
+ printf("</UL>\n");
else
- snprintf(buf, 128, "%dY", (int) (delta / ONE_YEAR));
- snprintf(buf2, 128, fmt, buf);
- return buf2;
+ printf("</PRE>\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("<LI><A HREF=\"%s\">%s</A><BR>",
- 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,<BR>", describeTimeSince((time_t) atoi(expires + 3)));
- printf("%d bytes, %d accesses, %d active clients,<BR>",
- atoi(size),
- atoi(refcount),
- atoi(clients));
- printf("%s, %s, %s, %s,<BR>",
- 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("<P><STRONG>Unknown CGI parameter: %s</STRONG></P>\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("<H1>ERROR</H1>\n");
- printf("<P><STRONG>You must provide a hostname!\n</STRONG></P><HR>");
- 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("<HTML><HEAD><TITLE>Cache Manager: %s:%s:%d</TITLE></HEAD>\n",
- operation, hostname, portnum);
- printf("<BODY><FORM METHOD=\"POST\" ACTION=\"%s\">\n", script_name);
- printf("<INPUT TYPE=\"submit\" VALUE=\"Refresh\">\n");
- printf("<SELECT NAME=\"operation\">\n");
- printf("<OPTION VALUE=\"empty\">Empty Form\n");
- print_option(op, INFO);
- print_option(op, CACHED);
- print_option(op, PARAM);
-#ifdef MENU_SHOW_LOG
- print_option(op, LOG);
-#endif
- print_option(op, STATS_U);
- print_option(op, STATS_IO);
- print_option(op, STATS_HDRS);
- print_option(op, STATS_FDS);
- print_option(op, STATS_NETDB);
- print_option(op, STATS_O);
- print_option(op, STATS_VM);
- print_option(op, SERVER);
- print_option(op, CLIENTS);
- print_option(op, STATS_I);
- print_option(op, STATS_F);
- print_option(op, STATS_D);
- print_option(op, STATS_R);
- print_option(op, PCONN);
- printf("</SELECT>\n");
- printf("<INPUT TYPE=\"hidden\" NAME=\"host\" VALUE=\"%s\">\n", hostname);
- printf("<INPUT TYPE=\"hidden\" NAME=\"port\" VALUE=\"%d\">\n", portnum);
- printf("<INPUT TYPE=\"hidden\" NAME=\"password\" VALUE=\"%s\">\n", password);
- printf("<INPUT TYPE=\"hidden\" NAME=\"url\" VALUE=\"%s\">\n", url);
- printf("</FORM>\n");
- printf("<HR>\n");
-
- printf("<H1>%s: %s:%d</H1>\n", operation, hostname, portnum);
- printf("<P>dated %s</P>\n", time_string);
- printf("<PRE>\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</PRE></BODY></HTML>\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("<table border=1><tr><td><STRONG>Parameter</STRONG><td><STRONG>Value</STRONG><td><STRONG>Description</STRONG>\n");
- in_table = 1;
- } else {
- printf("\n Parameter Value Description\n");
- printf("-------------- ------- -------------------------------------\n");
- }
- break;
- case STATS_U:
- if (hasTables) {
- printf("<table border=1><tr><td><STRONG>Protocol</STRONG><td><STRONG>Object Count</STRONG><td><STRONG>Max KB</STRONG><td><STRONG>Current KB</STRONG><td><STRONG>Min KB</STRONG><td><STRONG>Hit Ratio</STRONG><td><STRONG>Transfer KB/sec</STRONG><td><STRONG>Transfer Count</STRONG><td><STRONG>Transfered KB</STRONG></td>\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<P>\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("<tr><td><STRONG>%s</STRONG><td ALIGN=\"right\">%d<td>%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("<tr><td align=\"right\"><STRONG>%s</STRONG>\n", s1);
- else
- printf("%s-Requests\n", s1);
- break;
- }
- if (hasTables)
- printf("<tr><td align=\"right\"><STRONG>%s</STRONG><td align=\"right\">%d<td align=\"right\">%d<td align=\"right\">%d<td align=\"right\">%d<td align=\"right\">%4.2f<td align=\"right\">%d<td align=\"right\">%d<td align=\"right\">%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("<OL>\n");
- }
- parse_object(reserve);
- p_state = 1;
- break;
- default:
- printf("%s\n", "Not currently implemented");
- exit(1);
- }
- }
- }
- }
-
- if (in_list)
- printf("</OL>\n");
-
- if (in_table)
- printf("</table>\n");
-
- printf("\n</PRE>\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;
}