cervlet.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C), 2000-2003 by Contributors to the monit codebase. 
00003  * All Rights Reserved.
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License as
00007  * published by the Free Software Foundation; either version 2 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <errno.h>
00025 
00026 #ifdef HAVE_SYS_TYPES_H
00027 #include <sys/types.h>
00028 #endif
00029 
00030 #include <sys/socket.h>
00031 
00032 #ifdef HAVE_STRING_H
00033 #include <string.h>
00034 #endif
00035 
00036 #ifdef HAVE_UNISTD_H
00037 #include <unistd.h>
00038 #endif
00039 
00040 #ifdef HAVE_SYS_STAT_H
00041 #include <sys/stat.h>
00042 #endif
00043 
00044 #include "monitor.h"
00045 #include "cervlet.h" 
00046 #include "engine.h"
00047 #include "processor.h"
00048 #include "base64.h"
00049 #include "alert.h"
00050 #include "monit_process.h"
00051 
00052 #define ACTION(c) !strncasecmp(req->url, c, sizeof(c))
00053 
00054 
00055 /* URL Commands supported */
00056 #define HOME        "/"
00057 #define STOP        "/_stop"
00058 #define TEST        "/_monit"
00059 #define ABOUT       "/_about"
00060 #define PIXEL       "/_pixel"
00061 #define RUN         "/_runtime"
00062 #define VIEWLOG     "/_viewlog"
00063 
00064 /* Private prototypes */
00065 static void printPixel(HttpResponse);
00066 static void doGet(HttpRequest, HttpResponse);
00067 static void doPost(HttpRequest, HttpResponse);
00068 static void do_home(HttpRequest, HttpResponse);
00069 static void do_about(HttpRequest, HttpResponse);
00070 static void not_found(HttpRequest, HttpResponse);
00071 static void do_runtime(HttpRequest, HttpResponse);
00072 static void do_viewlog(HttpRequest, HttpResponse);
00073 static void handle_action(HttpRequest, HttpResponse);
00074 static void print_status(Process_T, HttpResponse res);
00075 static void is_monit_running(HttpRequest, HttpResponse);
00076 static void do_process(HttpRequest, HttpResponse, char *);
00077 
00078 extern ssl_server_connection * mySSLServerConnection;
00079 
00096 /* ------------------------------------------------------------------ Public */
00097 
00098 
00103 void init_service() {
00104   
00105   add_Impl(doGet, doPost);
00106   
00107 }
00108 
00109 
00110 /* ----------------------------------------------------------------- Private */
00111 
00112 
00117 static void doPost(HttpRequest req, HttpResponse res) {
00118 
00119   doGet(req, res);
00120 
00121 }
00122 
00123 
00128 static void doGet(HttpRequest req, HttpResponse res) {
00129 
00130   set_content_type(res, "text/html");
00131 
00132   if ( ACTION(HOME) ) {
00133     
00134     LOCK(Run.mutex)
00135     do_home(req, res);
00136     END_LOCK;
00137     
00138   }
00139   else if ( ACTION(RUN) ) {
00140     
00141     LOCK(Run.mutex)
00142     do_runtime(req, res);
00143     END_LOCK;
00144     
00145   }
00146   else if ( ACTION(TEST) ) {
00147     
00148     is_monit_running(req, res);
00149     
00150   }
00151   else if ( ACTION(VIEWLOG) ) {
00152     
00153     do_viewlog(req, res);
00154     
00155   }
00156   else if ( ACTION(ABOUT) ) {
00157     
00158     do_about(req, res);
00159     
00160   }
00161   else if ( ACTION(STOP) ) {
00162     
00163     send_error(res, SC_SERVICE_UNAVAILABLE, "The monit http server is stopped");
00164     stop_httpd();
00165     
00166   }  
00167   else if ( ACTION(PIXEL) ) {
00168     
00169     printPixel(res);
00170     
00171   } else {
00172     
00173     handle_action(req, res);
00174     
00175   }
00176   
00177    
00178 }
00179 
00180 
00181 /* ----------------------------------------------------------------- Helpers */
00182 
00183 
00184 static void is_monit_running(HttpRequest req, HttpResponse res) {
00185 
00186   int monit= exist_daemon();
00187   int status;
00188   char *msg= NULL;
00189 
00190   if ( monit ) {
00191     
00192     status= SC_OK;
00193     msg= get_status_string(status);
00194     
00195   } else {
00196     
00197     status= SC_GONE;
00198     msg= get_status_string(status);
00199     
00200   }
00201 
00202   set_status(res, status, msg);
00203 
00204   free(msg);
00205   
00206 }
00207     
00208 
00209 static void do_home(HttpRequest req, HttpResponse res) {
00210 
00211   int on= TRUE;
00212   struct myprocess *p;
00213   char *uptime= get_process_uptime(Run.pidfile);
00214  
00215   if ( Run.doprocess ) {
00216   HEAD("", Run.polltime)
00217       out_print(res,
00218 "<table cellspacing=\"0\" cellpadding=\"5\" width=\"100%%\" border=\"0\">"
00219 " <tr bgcolor=\"#BBDDFF\">"
00220 "  <td colspan=2 valign=\"top\" align=\"left\" bgcolor=\"#EFF7FF\" width=\"100%%\">"
00221 "  <br><h2 align=\"center\">Monit Process Manager</h2>"
00222 "  <p align=\"center\">Monit is <a href='/_runtime'>running</a> on %s "
00223 "  with <i>uptime, %s</i> and monitoring:</p><br>"
00224 "  </td>"
00225 " </tr>"
00226 "</table>"
00227 "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%%\" border=\"0\">"
00228 "  <tr valign=\"middle\" bgcolor=\"#6F6F6F\">"
00229 "    <td><img src=\"/_pixel\" width=\"1\" height=\"1\" alt=\"\"></td>"
00230 "  </tr>"
00231 "</table>"
00232 "<br><p>&nbsp;</p>"
00233 "<table cellspacing=0 cellpadding=3 border=0 width=\"70%\">"
00234 "<tr><td><h3><b>Server</b></h3></td>"
00235 "<td align=\"right\"><h3><b>Status</b></h3></td>"
00236 "<td align=\"right\"><h3><b>Uptime</b></h3></td>"
00237 "<td align=\"right\"><h3><b>CPU</b></h3></td>"
00238 "<td align=\"right\"><h3><b>Memory</b></h3></td>"
00239 "</tr>"
00240 "<tr><td>&nbsp;</td><td>&nbsp;</td></tr>", Run.localhostname, uptime);
00241   } else {
00242   HEAD("", Run.polltime)
00243       out_print(res,
00244 "<table cellspacing=\"0\" cellpadding=\"5\" width=\"100%%\" border=\"0\">"
00245 " <tr bgcolor=\"#BBDDFF\">"
00246 "  <td colspan=2 valign=\"top\" align=\"left\" bgcolor=\"#EFF7FF\" width=\"100%%\">"
00247 "  <br><h2 align=\"center\">Monit Process Manager</h2>"
00248 "  <p align=\"center\">Monit is <a href='/_runtime'>running</a> on %s "
00249 "  with <i>uptime, %s</i> and monitoring:</p><br>"
00250 "  </td>"
00251 " </tr>"
00252 "</table>"
00253 "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%%\" border=\"0\">"
00254 "  <tr valign=\"middle\" bgcolor=\"#6F6F6F\">"
00255 "    <td><img src=\"/_pixel\" width=\"1\" height=\"1\" alt=\"\"></td>"
00256 "  </tr>"
00257 "</table>"
00258 "<br><p>&nbsp;</p>"
00259 "<table cellspacing=0 cellpadding=3 border=0 width=\"70%\">"
00260 "<tr><td><h3><b>Server</b></h3></td>"
00261 "<td align=\"right\"><h3><b>Status</b></h3></td></tr>"
00262 "<tr><td>&nbsp;</td><td>&nbsp;</td></tr>", Run.localhostname, uptime);
00263   }
00264 
00265   free(uptime);
00266   
00267   for (p= processlist; p; p= p->next) {
00268     
00269     int isrunning= is_process_running(p);
00270     char *uptime= get_process_uptime(p->pidfile);
00271 
00272     if ( Run.doprocess ) {
00273       ProcInfo_T pi= p->procinfo;
00274       if ( isrunning ) {
00275     out_print(res,"<tr %s><td><a href='/%s'>%s</a></td><td align=\"right\">"
00276           "%s</td><td align=\"right\">%s</td>"
00277           "<td align=\"right\">%.1f%%</td>"
00278           "<td align=\"right\">%.1f%% [%ldkB]</td></tr>",
00279           on?"bgcolor=\"#EFEFEF\"":"",
00280           p->name, p->name,
00281           p->has_checksum_error?
00282           "<font color='#ff0000'>Cheksum Error</font>": 
00283           isrunning?
00284           "<font color=green>running</font>":
00285           "<font color=red>not running</font>",
00286           uptime,
00287           pi->cpu_percent/10.0,
00288           pi->mem_percent/10.0,pi->mem_kbyte
00289           );
00290       } else {
00291     out_print(res,"<tr %s><td><a href='/%s'>%s</a></td>"
00292           "<td align=\"right\">%s</td>"
00293           "<td align=\"right\">-</td>"
00294           "<td align=\"right\">- </td>"
00295           "<td align=\"right\">- [-]</td></tr>",
00296           on?"bgcolor=\"#EFEFEF\"":"",
00297           p->name, p->name,
00298           p->has_checksum_error?
00299           "<font color='#ff0000'>Cheksum Error</font>": 
00300           "<font color=red>not running</font>"
00301           );
00302       }
00303     } else {
00304       out_print(res,"<tr %s><td><a href='/%s'>%s</a></td><td align=\"right\">"
00305         "%s %s</td></tr>",
00306         on?"bgcolor=\"#EFEFEF\"":"",
00307         p->name, p->name,
00308         p->has_checksum_error?
00309         "<font color='#ff0000'>Cheksum Error</font>":   
00310         isrunning?
00311         "<font color=green>running</font>":
00312         "<font color=red>not running</font>",
00313         isrunning?uptime:"");
00314     }
00315 
00316 
00317     on= on?FALSE:TRUE;
00318     free(uptime);
00319     
00320   }
00321   out_print(res, "</table>");
00322   FOOT
00323       
00324 }
00325 
00326 
00327 static void do_about(HttpRequest req, HttpResponse res) {
00328 
00329   out_print(res,
00330     "<html><head><title>about monit</title><body bgcolor=white>"
00331     "<br><br><center><a href='http://www.tildeslash.com/monit/'><font size=+2>"
00332     "monit " VERSION "</font></a></center><br><br>");
00333   out_print(res,
00334     "<ul>"
00335     "<li>Copyright &copy; 2000-2003 by <a "
00336     "href=\"http://www.tildeslash.com/monit/who.html\">Contributors</a> "
00337     "to the monit codebase. All Rights Reserved.<br> </small><p>"
00338     "<li>Portions of this software are copyright &copy; 1995, 1996 "
00339     "<a href='http://www.gnu.org/'>Free Software Foundation, Inc.</a>"
00340     "</ul><p><br><p>");
00341   out_print(res,
00342    "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%%\" border=\"0\">"
00343    " <tr bgcolor=\"#6F6F6F\">"
00344    " <td valign=\"bottom\"><img src=\"/_pixel\" width=\"1\" height=\"1\" "
00345    "alt=\"\"></td></tr></table>");
00346   out_print(res,
00347     "<p>This program is free software; you can redistribute it and/or "
00348     "modify it under the terms of the GNU General Public License "
00349     "as published by the Free Software Foundation; either version 2 of "
00350     "the License, or (at your option) any later version.<p>"
00351     "This program is distributed in the hope that it will be useful, but "
00352     "WITHOUT ANY WARRANTY; without even the implied warranty of "
00353     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
00354     "<a href='http://www.tildeslash.com/gpl.html'>GNU "
00355     "General Public License</a> for more details.");
00356 
00357 }
00358 
00359 
00360 static void do_runtime(HttpRequest req, HttpResponse res) {
00361 
00362   int pid=  exist_daemon();
00363   
00364   HEAD("_runtime", 1000)
00365   out_print(res,
00366         "<center><h3>monit runtime status</h3><center><br>");
00367   out_print(res,"<table cellspacing=0 cellpadding=3 border=1 width=\"90%\">"
00368         "<tr><td width=\"40%\"><b>Parameter</b></td>"
00369         "<td width=\"60%\"><b>Value</b></td></tr>");
00370   out_print(res,
00371         "<tr><td>Host</a></td><td>%s</td></tr>",
00372         Run.localhostname);
00373   out_print(res,
00374         "<tr><td>Process id</a></td><td>%d</td></tr>", pid);
00375   out_print(res,
00376         "<tr><td>Effective user running monit</a></td>"
00377         "<td>%s</td></tr>", Run.Env.user);
00378   out_print(res,
00379         "<tr><td>Controlfile</a></td><td>%s</td></tr>", Run.controlfile);
00380   out_print(res,
00381         "<tr><td>Logfile</a></td><td>%s</td></tr>",
00382         Run.logfile?Run.logfile:"Not defined");
00383   out_print(res,
00384         "<tr><td>Pidfile</a></td><td>%s</td></tr>", Run.pidfile);
00385   out_print(res,
00386         "<tr><td>Debug</a></td><td>%s</td></tr>",
00387         Run.debug?"True":"False");
00388   out_print(res,
00389         "<tr><td>Log</a></td><td>%s</td></tr>", Run.dolog?"True":"False");
00390   out_print(res,
00391         "<tr><td>Use syslog</a></td><td>%s</td></tr>",
00392         Run.use_syslog?"True":"False");
00393   out_print(res,
00394         "<tr><td>Mail server</a></td><td>%s</td></tr>",
00395         Run.mailserver?Run.mailserver:"Not defined");
00396   out_print(res,
00397         "<tr><td>Default mail from</a></td><td>%s</td></tr>",
00398             Run.MailFormat.from?Run.MailFormat.from:"Not defined");
00399   out_print(res,
00400         "<tr><td>Default mail subject</a></td><td>%s</td></tr>",
00401             Run.MailFormat.subject?Run.MailFormat.subject:"Not defined");
00402   out_print(res,
00403         "<tr><td>Default mail message</a></td><td>%s</td></tr>",
00404             Run.MailFormat.message?Run.MailFormat.message:"Not defined");
00405   out_print(res,
00406         "<tr><td>Poll time</a></td><td>%d seconds</td></tr>",
00407         Run.polltime);
00408   out_print(res,
00409         "<tr><td>httpd bind address</a>"
00410         "</td><td>%s</td></tr>", Run.bind_addr?Run.bind_addr:"Any/All");
00411   out_print(res,
00412         "<tr><td>httpd portnumber</a>"
00413         "</td><td>%d</td></tr>", Run.httpdport);
00414   out_print(res,
00415         "<tr><td>Use ssl encryption</a>"
00416         "</td><td>%s</td></tr>", Run.httpdssl?"True":"False");
00417   if (Run.httpdssl) {
00418     out_print(res,
00419           "<tr><td>PEM key/certificate file</a>"
00420           "</td><td>%s</td></tr>", Run.httpsslpem);
00421     
00422     if (Run.httpsslclientpem!=NULL) {
00423       out_print(res,
00424         "<tr><td>Client PEM key/certification</a>"
00425         "</td><td>%s</td></tr>", "Enabled");
00426       out_print(res,
00427         "<tr><td>Client PEM key/certificate file</a>"
00428         "</td><td>%s</td></tr>", Run.httpsslclientpem);
00429     } else {
00430       out_print(res,
00431         "<tr><td>Client PEM key/certification</a>"
00432         "</td><td>%s</td></tr>", "Disabled");
00433     }
00434     out_print(res,
00435           "<tr><td>Allow self certified certificates </a>"
00436           "</td><td>%s</td></tr>", Run.allowselfcert?"True":"False");
00437   }
00438   
00439   out_print(res,
00440         "<tr><td>httpd auth. style</a></td><td>%s</td></tr>",
00441         Run.Auth.defined&&has_hosts_allow()?
00442         "Basic Authentication and Host allow list":
00443         Run.Auth.defined?"Basic Authentication":
00444         has_hosts_allow()?"Host allow list":
00445         "No authentication");
00446   out_print(res,"</table>");
00447   out_print(res, "<table cellspacing=16><tr nowrap><td><font size=+1>"
00448         "<font color='#f0000'>Stop monit http server?</font></font>"
00449         "<td align=right><form method=GET action=%s>"
00450         "<input type=submit value=Go style='font-size: 12pt'></font>"
00451         "</form></td>", STOP);
00452   if ( Run.dolog && !Run.use_syslog ) {
00453     out_print(res, "<td><font size=+1>"
00454           "View monit logfile?</font>"
00455           "<td align=right><form method=GET action=%s>"
00456           "<input type=submit value=Go style='font-size: 12pt'></font>"
00457           "</form></td>", VIEWLOG);
00458   }
00459   out_print(res, "</tr></table>");
00460   
00461   FOOT
00462 
00463 }
00464 
00465 
00466 static void do_viewlog(HttpRequest req, HttpResponse res) {
00467 
00468   HEAD("_viewlog", 100)
00469       
00470   if ( Run.dolog && !Run.use_syslog ) {
00471     
00472     struct stat sb;
00473     
00474     if ( !stat(Run.logfile, &sb) ) {
00475       
00476       FILE *f= fopen(Run.logfile, "r");
00477       if ( f ) {
00478     
00479     int n;
00480     char buf[8192];
00481     
00482     out_print(res, "<br><p><form><textarea cols=80 rows=30>");
00483     
00484     while ( (n= fread(buf, sizeof(char), 8192, f)) > 0 ) {
00485       
00486       buf[n]= 0;
00487       out_print(res, "%s", buf);
00488       
00489     }
00490     
00491         fclose(f);
00492     out_print(res, "</textarea></form>");
00493     
00494       } else {
00495     
00496     out_print(res, "Error opening logfile: %s", STRERROR);
00497     
00498       }
00499       
00500     } else {
00501       
00502       out_print(res, "Error stating logfile: %s", STRERROR);
00503       
00504     }
00505     
00506   } else {
00507     
00508     out_print(res,
00509     "<b>Cannot view logfile:</b><br>");
00510     if ( !Run.dolog ) {
00511       
00512       out_print(res, "monit was started without logging");
00513       
00514     } else {
00515       
00516       out_print(res, "monit uses syslog");
00517       
00518     }
00519     
00520   }
00521   
00522   FOOT
00523   
00524 }
00525 
00526 
00527 static void handle_action(HttpRequest req, HttpResponse res) {
00528 
00529   char *name= req->url;
00530   char *action= get_parameter(req, "action");
00531   
00532   if(exist_process(++name)) {
00533     
00534     if(action) {
00535       
00536       struct myprocess *p= get_process(name);
00537       
00538       if( is(action, "start") ) {
00539 
00540     if(p->start) {
00541 
00542       LOCK(p->mutex)
00543         check_process(name, action);
00544       END_LOCK;
00545 
00546     } else {
00547 
00548           send_error(res, SC_BAD_REQUEST,
00549                  "Start method not defined for the process");
00550       goto quit;
00551 
00552     }
00553     
00554       }
00555       
00556       if( is(action, "stop") ) {
00557 
00558     if(p->stop) {
00559 
00560       LOCK(p->mutex)
00561         check_process(name, action);
00562       END_LOCK;
00563 
00564     } else {
00565 
00566           send_error(res, SC_BAD_REQUEST,
00567                  "Stop method not defined for the process");
00568       goto quit;
00569 
00570     }
00571 
00572       }
00573     
00574       if( is(action, "restart") ) {
00575 
00576     if(p->start && p->stop) {
00577  
00578       LOCK(p->mutex)
00579         check_process(name, action);
00580       END_LOCK;
00581 
00582     } else {
00583 
00584           send_error(res, SC_BAD_REQUEST,
00585         "Start or stop method not defined for the process");
00586       goto quit;
00587 
00588     }
00589 
00590       }
00591     
00592       if(is(action, "status")) {
00593 
00594     print_status(p, res);
00595     goto quit;
00596     
00597       }
00598       
00599     }
00600     
00601     LOCK(Run.mutex)
00602     do_process(req, res, name);
00603     END_LOCK;
00604     
00605   } else {
00606     
00607     not_found(req, res);
00608     
00609   }
00610 
00611   quit:
00612   free(action);
00613   reset_depend();
00614   
00615 }
00616 
00617 
00618 static void do_process(HttpRequest req, HttpResponse res, char *name) {
00619   
00620   struct myprocess *p= get_process(name);
00621   int run= is_process_running(p);
00622 
00623   HEAD(name, 1000)
00624   out_print(res,
00625     "<p><br><h3>Process status</h3><br>");
00626   out_print(res,"<table cellspacing=0 cellpadding=3 border=1 width=\"90%\">"
00627         "<tr><td width=\"30%\"><b>Parameter</b></td><td width=\"70%\"><b>Value</b></td></tr>");
00628   out_print(res,
00629     "<tr><td>Name</a></td><td>%s</td></tr>", p->name);
00630   out_print(res,
00631     "<tr><td>Group</a></td><td><font color='#0000ff'>%s</font></td></tr>",
00632         p->group?p->group:"(not defined)");
00633   out_print(res,
00634     "<tr><td>Process id </a></td><td>%d</td></tr>", run);
00635   out_print(res,
00636     "<tr><td>Process status</a></td><td>%s %s</td></tr>",
00637         run?"<font color='#00ff00'>Running</font>":
00638         "<font color='#ff0000'>Not Running</font>",
00639         p->has_checksum_error?
00640         "<font color='#ff0000'><b>Checksum error!</b></font>":"");
00641   out_print(res,
00642     "<tr><td>Pid file</a></td><td>%s</td></tr>",
00643         p->pidfile);
00644   out_print(res,
00645            "<tr><td>Monitoring mode</a></td><td>%s</td></tr>",
00646            modenames[p->mode]);
00647   out_print(res,
00648            "<tr><td>Monitoring status</a></td><td>%s</td></tr>",
00649            statusnames[p->do_validate]);
00650   out_print(res,
00651     "<tr><td>Start program</a></td><td>%s</td></tr>",
00652         p->start?p->start->arg[0]:"(not defined)");
00653   out_print(res,
00654     "<tr><td>Stop program</a></td><td>%s</td></tr>",
00655         p->stop?p->stop->arg[0]:"(not defined)");
00656   {
00657     struct mychecksum *c;
00658     for(c= p->checksumlist; c; c= c->next)
00659     out_print(res, "<tr><td>Associated checksum</a></td><td>%s %s</td>"
00660           "</tr>", c->md5, c->file);
00661   }
00662   {
00663     Dependant_T d;
00664 
00665     for(d= p->dependantlist; d; d= d->next) {
00666       if(d->dependant != NULL) {
00667     out_print(res,"<tr><td>Depends on Process </a></td>"
00668           "<td> <a href=%s> %s </a></td></tr>",
00669           d->dependant, d->dependant);
00670       }
00671     }
00672   }
00673   if ( Run.doprocess ) {
00674     ProcInfo_T pi= p->procinfo;
00675 
00676     out_print(res,
00677           "<tr><td>CPU usage</a></td><td>%.1f%%</td></tr>",
00678           pi->cpu_percent/10.0);
00679     out_print(res,
00680           "<tr><td>Memory usage</a></td><td>%.1f%% [%ldkB]</td></tr>",
00681           pi->mem_percent/10.0,pi->mem_kbyte);
00682   }
00683   {
00684     Port_T n;
00685     for(n= p->portlist; n; n= n->next) {
00686 
00687       if ( n->family == AF_INET ) {
00688 
00689     if ( n->ssl != NULL ) {
00690 
00691       out_print(res,
00692             "<tr><td>Host:Port</a></td><td>%s:%d%s [%s via SSL]</td></tr>",
00693             n->hostname, n->port, n->request?n->request:"",
00694             n->protocol->name);
00695       
00696       if ( n->certmd5 != NULL ) {
00697 
00698         out_print(res,
00699               "<tr><td>Server certificate md5 sum</a></td><td>%s</td></tr>",
00700               n->certmd5);
00701 
00702       }
00703 
00704 
00705     } else {
00706 
00707       out_print(res,
00708             "<tr><td>Host:Port</a></td><td>%s:%d%s [%s]</td></tr>",
00709             n->hostname, n->port, n->request?n->request:"",
00710             n->protocol->name);
00711 
00712     }
00713 
00714       } else if ( n->family == AF_UNIX ) {
00715 
00716     out_print(res,
00717         "<tr><td>Unix Socket</a></td><td>%s [%s]</td></tr>",
00718         n->pathname, n->protocol->name);
00719 
00720       }
00721     }
00722   }
00723   {
00724     struct mytimestamp *t;
00725     for(t= p->timestamplist; t; t= t->next)
00726     out_print(res,
00727       "<tr><td>Associated timestamp</a></td>"
00728           "<td>If %s %s %d second(s) then %s</td></tr>",
00729       t->pathname, operatornames[t->operator], t->time, actionnames[t->action]);
00730   }
00731   {
00732     Resource_T q;
00733 
00734     for (q= p->resourcelist; q; q= q->next) {
00735       switch (q->resource_id) {
00736 
00737       case RESOURCE_ID_CPU_PERCENT: 
00738 
00739     out_print(res,"<tr><td>CPU usage limit</a></td>"
00740           "<td>If %s %.1f%% for %d cycle(s) then %s</td></tr>", 
00741           operatornames[q->operator],
00742           q->limit/10.0, q->max_cycle, 
00743           actionnames[q->action]);
00744     break;
00745 
00746       case RESOURCE_ID_MEM_PERCENT: 
00747     
00748     out_print(res,"<tr><td>Memory usage limit</a></td>"
00749           "<td>If %s %.1f%% for %d cycle(s) then %s</td></tr>", 
00750           operatornames[q->operator],
00751           q->limit/10.0, q->max_cycle, 
00752           actionnames[q->action]);
00753     break;
00754     
00755       case RESOURCE_ID_MEM_KBYTE: 
00756       
00757     out_print(res,"<tr><td>Memory amount limit</a></td>"
00758           "<td>If %s %ld for %d cycle(s) then %s</td></tr>", 
00759           operatornames[q->operator],
00760           q->limit, q->max_cycle, 
00761           actionnames[q->action]);
00762     break;
00763     
00764       case RESOURCE_ID_LOAD1: 
00765       
00766     out_print(res,"<tr><td>Load average (1min)</a></td>"
00767           "<td>If %s %.1f for %d cycle(s) then %s</td></tr>", 
00768           operatornames[q->operator],
00769           q->limit/10.0, q->max_cycle, 
00770           actionnames[q->action]);
00771     break;
00772     
00773       case RESOURCE_ID_LOAD5: 
00774       
00775     out_print(res,"<tr><td>Load average (5min)</a></td>"
00776           "<td>If %s %.1f for %d cycle(s) then %s</td></tr>", 
00777           operatornames[q->operator],
00778           q->limit/10.0, q->max_cycle, 
00779           actionnames[q->action]);
00780     break;
00781     
00782       case RESOURCE_ID_LOAD15: 
00783     out_print(res,"<tr><td>Load average (15min)</a></td>"
00784           "<td>If %s %.1f for %d cycle(s) then %s</td></tr>", 
00785           operatornames[q->operator],
00786           q->limit/10.0, q->max_cycle, 
00787           actionnames[q->action]);
00788     break;
00789     
00790       }    
00791     }
00792   }
00793   out_print(res,
00794         "<tr><td>Check process</a></td><td>Every %d cycle</td></tr>",
00795         p->every?p->every:1);
00796   out_print(res,
00797     "<tr><td>Timeout</a></td><td>Timeout if %d restart within %d cycles"
00798     "</td></tr>", p->to_start, p->to_cycle);
00799   {
00800     Mail_T r;
00801     for(r= p->maillist; r; r= r->next) {
00802       out_print(res,
00803         "<tr bgcolor=\"#EFEFEF\"><td>Alert mail to</a></td><td>%s</td></tr>",
00804         r->to?r->to:"");
00805       out_print(res,
00806     "<tr><td>Alert from</a></td><td>%s</td></tr>",
00807               r->from?r->from:"(default)");
00808       out_print(res,
00809         "<tr><td>Alert subject</a></td><td>%s</td></tr>",
00810           r->subject?r->subject:"(default)");
00811       out_print(res,
00812     "<tr><td>Alert message</a></td><td>%s</td></tr>",
00813           r->message?r->message:"(default)");
00814       out_print(res,
00815     "<tr><td>Alert on timeout</a></td><td>%s</td></tr>",
00816         r->alert_on_timeout?"yes":"no");
00817       out_print(res,
00818     "<tr><td>Alert on restart</a></td><td>%s</td></tr>",
00819         r->alert_on_restart?"yes":"no");
00820       out_print(res,
00821     "<tr><td>Alert on checksum</a></td><td>%s</td></tr>",
00822         r->alert_on_checksum?"yes":"no");
00823       out_print(res,
00824     "<tr><td>Alert on exceeded resource</a></td><td>%s</td></tr>",
00825         r->alert_on_resource?"yes":"no");
00826       out_print(res,
00827     "<tr><td>Alert on stop</a></td><td>%s</td></tr>",
00828         r->alert_on_stop?"yes":"no");
00829       out_print(res,
00830     "<tr><td>Alert on timestamp</a></td><td>%s</td></tr>",
00831         r->alert_on_timestamp?"yes":"no");
00832     }
00833   }
00834   out_print(res, "</table>");
00835   out_print(res, "<table cellspacing=16><tr nowrap><td><font size=+1>");
00836   /* Start program */
00837   if(p->start)
00838      out_print(res, 
00839        "<td><form method=GET action=/%s>"
00840        "<input type=hidden value='start' name=action>"
00841        "<input type=submit value='Start program' style='font-size: 12pt'></font>"
00842        "</form></td>", name);
00843    /* Stop program */
00844   if(p->stop)
00845     out_print(res, 
00846        "<td><form method=GET action=/%s>"
00847        "<input type=hidden value='stop' name=action>"
00848        "<input type=submit value='Stop program' style='font-size: 12pt'></font>"
00849        "</form></td>", name);
00850   if(p->start && p->stop)
00851     out_print(res, 
00852        "<td><form method=GET action=/%s>"
00853        "<input type=hidden value='restart' name=action>"
00854        "<input type=submit value='Restart program' style='font-size: 12pt'></font>"
00855        "</form></td>", name);
00856   out_print(res, "</tr></table>");
00857 
00858   FOOT
00859 
00860   
00861 }
00862 
00863 
00864 static void print_status(Process_T p, HttpResponse res) {
00865 
00866   pid_t  pid= -1;
00867   FILE *out= res->outputstream;
00868   
00869   res->is_committed= TRUE;
00870   
00871   if((pid= is_process_running(p))) {
00872     
00873     char *uptime= get_process_uptime(p->pidfile);
00874     ProcInfo_T pi= p->procinfo;
00875 
00876     if( Run.httpdssl ) {
00877 
00878       printf_ssl_socket(res->ssl, 
00879     "Process '%s' is running with pid [%d]\n\tUptime: %s "
00880     "CPU: %.1f%% Memory: %.1f%% [%ldkB]\n\tMonitoring status: %s\n",
00881     p->name, (int)pid, uptime, pi->cpu_percent/10.0,
00882     pi->mem_percent/10.0,pi->mem_kbyte, statusnames[p->do_validate]);
00883       
00884     } else {
00885 
00886       fprintf(out, 
00887     "Process '%s' is running with pid [%d]\n\tUptime: %s "
00888     "CPU: %.1f%% Memory: %.1f%% [%ldkB]\n\tMonitoring status: %s\n",
00889     p->name, (int)pid, uptime, pi->cpu_percent/10.0,
00890     pi->mem_percent/10.0,pi->mem_kbyte, statusnames[p->do_validate]);
00891 
00892     }    
00893 
00894     free(uptime);
00895     
00896   } else {
00897     
00898     if( Run.httpdssl ) {
00899 
00900       printf_ssl_socket(res->ssl, "Process '%s' is not running\n",  p->name);
00901 
00902     } else {
00903 
00904       fprintf(out, "Process '%s' is not running\n",  p->name);
00905 
00906     }
00907     
00908   }
00909 
00910 }
00911 
00912 
00913 static void printPixel(HttpResponse res) {
00914 
00915   static int l;
00916   static unsigned char *pixel= NULL;
00917 
00918   if ( ! pixel ) {
00919 
00920     pixel= xcalloc(sizeof(unsigned char), strlen(PIXEL_GIF));
00921     l= decode_base64(pixel, PIXEL_GIF);
00922 
00923   }
00924   if (l) {
00925     
00926     if ( Run.httpdssl ) {
00927 
00928       res->is_committed= TRUE;
00929 
00930       printf_ssl_socket(res->ssl, "HTTP/1.0 200 OK\r\n");
00931       printf_ssl_socket(res->ssl, "Content-length: %d\r\n", l);
00932       printf_ssl_socket(res->ssl, "Content-Type: image/gif\r\n");
00933       printf_ssl_socket(res->ssl, "Connection: close\r\n\r\n");
00934       
00935       send_ssl_socket(res->ssl, pixel, l);
00936 
00937     } else {
00938 
00939       FILE *out= res->outputstream;
00940       
00941       res->is_committed= TRUE;
00942       
00943       fprintf(out, "HTTP/1.0 200 OK\r\n");
00944       fprintf(out, "Content-length: %d\r\n", l);
00945       fprintf(out, "Content-Type: image/gif\r\n");
00946       fprintf(out, "Connection: close\r\n\r\n");
00947       
00948       fwrite(pixel, sizeof(unsigned char), l, out);
00949     
00950     }
00951   
00952   }
00953   
00954 }
00955 
00956 
00957 static void not_found(HttpRequest req, HttpResponse res) {
00958   
00959   send_error(res, SC_NOT_FOUND,
00960          "The requested URL was not found on this server");
00961   
00962 }
00963