cervlet.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C), 2000-2002 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-2002 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       check_process(name, action, TRUE);
00543 
00544     else {
00545 
00546           send_error(res, SC_BAD_REQUEST,
00547                  "Start method not defined for the process");
00548       goto quit;
00549 
00550     }
00551     
00552       }
00553       
00554       if( is(action, "stop") ) {
00555 
00556     if(p->stop)
00557 
00558       check_process(name, action, TRUE);
00559 
00560     else {
00561 
00562           send_error(res, SC_BAD_REQUEST,
00563                  "Stop method not defined for the process");
00564       goto quit;
00565 
00566     }
00567 
00568       }
00569     
00570       if(is(action, "status")) {
00571 
00572     print_status(p, res);
00573     goto quit;
00574     
00575       }
00576       
00577       sleep(2);
00578       
00579     }
00580     
00581     LOCK(Run.mutex)
00582     do_process(req, res, name);
00583     END_LOCK;
00584     
00585   } else {
00586     
00587     not_found(req, res);
00588     
00589   }
00590 
00591   quit:
00592   free(action);
00593   reset_depend();
00594   
00595 }
00596 
00597 
00598 static void do_process(HttpRequest req, HttpResponse res, char *name) {
00599   
00600   struct myprocess *p= get_process(name);
00601   int run= is_process_running(p);
00602 
00603   HEAD(name, 1000)
00604   out_print(res,
00605     "<p><br><h3>Process status</h3><br>");
00606   out_print(res,"<table cellspacing=0 cellpadding=3 border=1 width=\"90%\">"
00607         "<tr><td width=\"30%\"><b>Parameter</b></td><td width=\"70%\"><b>Value</b></td></tr>");
00608   out_print(res,
00609     "<tr><td>Name</a></td><td>%s</td></tr>", p->name);
00610   out_print(res,
00611     "<tr><td>Group</a></td><td><font color='#0000ff'>%s</font></td></tr>",
00612         p->group?p->group:"(not defined)");
00613   out_print(res,
00614     "<tr><td>Process id </a></td><td>%d</td></tr>", run);
00615   out_print(res,
00616     "<tr><td>Process status</a></td><td>%s %s</td></tr>",
00617         run?"<font color='#00ff00'>Running</font>":
00618         "<font color='#ff0000'>Not Running</font>",
00619         p->has_checksum_error?
00620         "<font color='#ff0000'><b>Checksum error!</b></font>":"");
00621   out_print(res,
00622     "<tr><td>Pid file</a></td><td>%s</td></tr>",
00623         p->pidfile);
00624   out_print(res,
00625            "<tr><td>Monitoring mode</a></td><td>%s</td></tr>",
00626            modenames[p->mode]);
00627   out_print(res,
00628     "<tr><td>Start program</a></td><td>%s</td></tr>",
00629         p->start?p->start->arg[0]:"(not defined)");
00630   out_print(res,
00631     "<tr><td>Stop program</a></td><td>%s</td></tr>",
00632         p->stop?p->stop->arg[0]:"(not defined)");
00633   {
00634     struct mychecksum *c;
00635     for(c= p->checksumlist; c; c= c->next)
00636     out_print(res, "<tr><td>Associated checksum</a></td><td>%s %s</td>"
00637           "</tr>", c->md5, c->file);
00638   }
00639   {
00640     Dependant_T d;
00641 
00642     for(d= p->dependantlist; d; d= d->next) {
00643       if(d->dependant != NULL) {
00644     out_print(res,"<tr><td>Depends on Process </a></td>"
00645           "<td> <a href=%s> %s </a></td></tr>",
00646           d->dependant, d->dependant);
00647       }
00648     }
00649   }
00650   if ( Run.doprocess ) {
00651     ProcInfo_T pi= p->procinfo;
00652 
00653     out_print(res,
00654           "<tr><td>CPU usage</a></td><td>%.1f%%</td></tr>",
00655           pi->cpu_percent/10.0);
00656     out_print(res,
00657           "<tr><td>Memory usage</a></td><td>%.1f%% [%ldkB]</td></tr>",
00658           pi->mem_percent/10.0,pi->mem_kbyte);
00659   }
00660   {
00661     Port_T n;
00662     for(n= p->portlist; n; n= n->next) {
00663 
00664       if ( n->family == AF_INET ) {
00665 
00666     if ( n->ssl != NULL ) {
00667 
00668       out_print(res,
00669             "<tr><td>Host:Port</a></td><td>%s:%d%s [%s via SSL]</td></tr>",
00670             n->hostname, n->port, n->request?n->request:"",
00671             n->protocol->name);
00672       
00673       if ( n->certmd5 != NULL ) {
00674 
00675         out_print(res,
00676               "<tr><td>Server certificate md5 sum</a></td><td>%s</td></tr>",
00677               n->certmd5);
00678 
00679       }
00680 
00681 
00682     } else {
00683 
00684       out_print(res,
00685             "<tr><td>Host:Port</a></td><td>%s:%d%s [%s]</td></tr>",
00686             n->hostname, n->port, n->request?n->request:"",
00687             n->protocol->name);
00688 
00689     }
00690 
00691       } else if ( n->family == AF_UNIX ) {
00692 
00693     out_print(res,
00694         "<tr><td>Unix Socket</a></td><td>%s [%s]</td></tr>",
00695         n->pathname, n->protocol->name);
00696 
00697       }
00698     }
00699   }
00700   {
00701     struct mytimestamp *t;
00702     for(t= p->timestamplist; t; t= t->next)
00703     out_print(res,
00704       "<tr><td>Associated timestamp</a></td>"
00705           "<td>If %s %s %d second(s) then %s</td></tr>",
00706       t->pathname, operatornames[t->operator], t->time, actionnames[t->action]);
00707   }
00708   {
00709     Resource_T q;
00710 
00711     for (q= p->resourcelist; q; q= q->next) {
00712       switch (q->resource_id) {
00713 
00714       case RESOURCE_ID_CPU_PERCENT: 
00715 
00716     out_print(res,"<tr><td>CPU usage limit</a></td>"
00717           "<td>If %s %.1f%% for %d cycle(s) then %s</td></tr>", 
00718           operatornames[q->operator],
00719           q->limit/10.0, q->max_cycle, 
00720           actionnames[q->action]);
00721     break;
00722 
00723       case RESOURCE_ID_MEM_PERCENT: 
00724     
00725     out_print(res,"<tr><td>Memory usage limit</a></td>"
00726           "<td>If %s %.1f%% for %d cycle(s) then %s</td></tr>", 
00727           operatornames[q->operator],
00728           q->limit/10.0, q->max_cycle, 
00729           actionnames[q->action]);
00730     break;
00731     
00732       case RESOURCE_ID_MEM_KBYTE: 
00733       
00734     out_print(res,"<tr><td>Memory amount limit</a></td>"
00735           "<td>If %s %ld for %d cycle(s) then %s</td></tr>", 
00736           operatornames[q->operator],
00737           q->limit, q->max_cycle, 
00738           actionnames[q->action]);
00739     break;
00740     
00741       case RESOURCE_ID_LOAD1: 
00742       
00743     out_print(res,"<tr><td>Load average (1min)</a></td>"
00744           "<td>If %s %.1f for %d cycle(s) then %s</td></tr>", 
00745           operatornames[q->operator],
00746           q->limit/10.0, q->max_cycle, 
00747           actionnames[q->action]);
00748     break;
00749     
00750       case RESOURCE_ID_LOAD5: 
00751       
00752     out_print(res,"<tr><td>Load average (5min)</a></td>"
00753           "<td>If %s %.1f for %d cycle(s) then %s</td></tr>", 
00754           operatornames[q->operator],
00755           q->limit/10.0, q->max_cycle, 
00756           actionnames[q->action]);
00757     break;
00758     
00759       case RESOURCE_ID_LOAD15: 
00760     out_print(res,"<tr><td>Load average (15min)</a></td>"
00761           "<td>If %s %.1f for %d cycle(s) then %s</td></tr>", 
00762           operatornames[q->operator],
00763           q->limit/10.0, q->max_cycle, 
00764           actionnames[q->action]);
00765     break;
00766     
00767       }    
00768     }
00769   }
00770   out_print(res,
00771         "<tr><td>Check process</a></td><td>Every %d cycle</td></tr>",
00772         p->every?p->every:1);
00773   out_print(res,
00774     "<tr><td>Timeout</a></td><td>Timeout if %d restart within %d cycles"
00775     "</td></tr>", p->to_start, p->to_cycle);
00776   {
00777     Mail_T r;
00778     for(r= p->maillist; r; r= r->next) {
00779       out_print(res,
00780         "<tr bgcolor=\"#EFEFEF\"><td>Alert mail to</a></td><td>%s</td></tr>",
00781         r->to?r->to:"");
00782       out_print(res,
00783     "<tr><td>Alert from</a></td><td>%s</td></tr>",
00784               r->from?r->from:"(default)");
00785       out_print(res,
00786         "<tr><td>Alert subject</a></td><td>%s</td></tr>",
00787           r->subject?r->subject:"(default)");
00788       out_print(res,
00789     "<tr><td>Alert message</a></td><td>%s</td></tr>",
00790           r->message?r->message:"(default)");
00791       out_print(res,
00792     "<tr><td>Alert on timeout</a></td><td>%s</td></tr>",
00793         r->alert_on_timeout?"yes":"no");
00794       out_print(res,
00795     "<tr><td>Alert on restart</a></td><td>%s</td></tr>",
00796         r->alert_on_restart?"yes":"no");
00797       out_print(res,
00798     "<tr><td>Alert on checksum</a></td><td>%s</td></tr>",
00799         r->alert_on_checksum?"yes":"no");
00800       out_print(res,
00801     "<tr><td>Alert on exceeded resource</a></td><td>%s</td></tr>",
00802         r->alert_on_resource?"yes":"no");
00803       out_print(res,
00804     "<tr><td>Alert on stop</a></td><td>%s</td></tr>",
00805         r->alert_on_stop?"yes":"no");
00806       out_print(res,
00807     "<tr><td>Alert on timestamp</a></td><td>%s</td></tr>",
00808         r->alert_on_timestamp?"yes":"no");
00809     }
00810   }
00811   out_print(res, "</table>");
00812   out_print(res, "<table cellspacing=16><tr nowrap><td><font size=+1>");
00813   /* Start program */
00814   if(p->start)
00815      out_print(res, 
00816        "<td><form method=GET action=/%s>"
00817        "<input type=hidden value='start' name=action>"
00818        "<input type=submit value='Start program' style='font-size: 12pt'></font>"
00819        "</form></td>", name);
00820    /* Stop program */
00821   if(p->stop)
00822     out_print(res, 
00823        "<td><form method=GET action=/%s>"
00824        "<input type=hidden value='stop' name=action>"
00825        "<input type=submit value='Stop program' style='font-size: 12pt'></font>"
00826        "</form></td>", name);
00827   out_print(res, "</tr></table>");
00828 
00829   FOOT
00830 
00831   
00832 }
00833 
00834 
00835 static void print_status(Process_T p, HttpResponse res) {
00836 
00837   pid_t  pid= -1;
00838   FILE *out= res->outputstream;
00839   
00840   res->is_committed= TRUE;
00841   
00842   if((pid= is_process_running(p))) {
00843     
00844     char *uptime= get_process_uptime(p->pidfile);
00845     ProcInfo_T pi= p->procinfo;
00846 
00847     if( Run.httpdssl ) {
00848 
00849       printf_ssl_socket(res->ssl, 
00850             "Process '%s' is running with pid [%d] \n\tUptime: %s "
00851             "CPU: %.1f%% Memory: %.1f%% [%ldkB]\n",
00852             p->name, (int)pid, uptime,
00853             pi->cpu_percent/10.0,
00854             pi->mem_percent/10.0,pi->mem_kbyte);
00855       
00856     } else {
00857 
00858       fprintf(out, 
00859           "Process '%s' is running with pid [%d] \n\tUptime: %s "
00860           "CPU: %.1f%% Memory: %.1f%% [%ldkB]\n",
00861           p->name, (int)pid, uptime,
00862           pi->cpu_percent/10.0,
00863           pi->mem_percent/10.0,pi->mem_kbyte);
00864 
00865     }    
00866 
00867     free(uptime);
00868     
00869   } else {
00870     
00871     if( Run.httpdssl ) {
00872 
00873       printf_ssl_socket(res->ssl, "Process '%s' is not running\n",  p->name);
00874 
00875     } else {
00876 
00877       fprintf(out, "Process '%s' is not running\n",  p->name);
00878 
00879     }
00880     
00881   }
00882 
00883 }
00884 
00885 
00886 static void printPixel(HttpResponse res) {
00887 
00888   static int l;
00889   static unsigned char *pixel= NULL;
00890 
00891   if ( ! pixel ) {
00892 
00893     pixel= xcalloc(sizeof(unsigned char), strlen(PIXEL_GIF));
00894     l= decode_base64(pixel, PIXEL_GIF);
00895 
00896   }
00897   if (l) {
00898     
00899     if ( Run.httpdssl ) {
00900 
00901       res->is_committed= TRUE;
00902 
00903       printf_ssl_socket(res->ssl, "HTTP/1.0 200 OK\r\n");
00904       printf_ssl_socket(res->ssl, "Content-length: %d\r\n", l);
00905       printf_ssl_socket(res->ssl, "Content-Type: image/gif\r\n");
00906       printf_ssl_socket(res->ssl, "Connection: close\r\n\r\n");
00907       
00908       send_ssl_socket(res->ssl, pixel, l);
00909 
00910     } else {
00911 
00912       FILE *out= res->outputstream;
00913       
00914       res->is_committed= TRUE;
00915       
00916       fprintf(out, "HTTP/1.0 200 OK\r\n");
00917       fprintf(out, "Content-length: %d\r\n", l);
00918       fprintf(out, "Content-Type: image/gif\r\n");
00919       fprintf(out, "Connection: close\r\n\r\n");
00920       
00921       fwrite(pixel, sizeof(unsigned char), l, out);
00922     
00923     }
00924   
00925   }
00926   
00927 }
00928 
00929 
00930 static void not_found(HttpRequest req, HttpResponse res) {
00931   
00932   send_error(res, SC_NOT_FOUND,
00933          "The requested URL was not found on this server");
00934   
00935 }
00936