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 
00095 /* ------------------------------------------------------------------ Public */
00096 
00097 
00102 void init_service() {
00103   
00104   add_Impl(doGet, doPost);
00105   
00106 }
00107 
00108 
00109 /* ----------------------------------------------------------------- Private */
00110 
00111 
00116 static void doPost(HttpRequest req, HttpResponse res) {
00117 
00118   doGet(req, res);
00119 
00120 }
00121 
00122 
00127 static void doGet(HttpRequest req, HttpResponse res) {
00128 
00129   set_content_type(res, "text/html");
00130 
00131   if ( ACTION(HOME) ) {
00132     
00133     LOCK(Run.mutex)
00134     do_home(req, res);
00135     END_LOCK;
00136     
00137   }
00138   else if ( ACTION(RUN) ) {
00139     
00140     LOCK(Run.mutex)
00141     do_runtime(req, res);
00142     END_LOCK;
00143     
00144   }
00145   else if ( ACTION(TEST) ) {
00146     
00147     is_monit_running(req, res);
00148     
00149   }
00150   else if ( ACTION(VIEWLOG) ) {
00151     
00152     do_viewlog(req, res);
00153     
00154   }
00155   else if ( ACTION(ABOUT) ) {
00156     
00157     do_about(req, res);
00158     
00159   }
00160   else if ( ACTION(STOP) ) {
00161     
00162     send_error(res, SC_SERVICE_UNAVAILABLE, "The monit http server is stopped");
00163     stop_httpd();
00164     
00165   }  
00166   else if ( ACTION(PIXEL) ) {
00167     
00168     printPixel(res);
00169     
00170   } else {
00171     
00172     handle_action(req, res);
00173     
00174   }
00175   
00176    
00177 }
00178 
00179 
00180 /* ----------------------------------------------------------------- Helpers */
00181 
00182 
00183 static void is_monit_running(HttpRequest req, HttpResponse res) {
00184 
00185   int monit= exist_daemon();
00186   int status;
00187   char *msg= NULL;
00188 
00189   if ( monit ) {
00190     
00191     status= SC_OK;
00192     msg= get_status_string(status);
00193     
00194   } else {
00195     
00196     status= SC_GONE;
00197     msg= get_status_string(status);
00198     
00199   }
00200 
00201   set_status(res, status, msg);
00202 
00203   free(msg);
00204   
00205 }
00206     
00207 
00208 static void do_home(HttpRequest req, HttpResponse res) {
00209 
00210   int on= TRUE;
00211   struct myprocess *p;
00212   char *uptime= get_process_uptime(Run.pidfile);
00213  
00214   if ( Run.doprocess ) {
00215   HEAD("", Run.polltime)
00216       out_print(res,
00217 "<table cellspacing=\"0\" cellpadding=\"5\" width=\"100%%\" border=\"0\">"
00218 " <tr bgcolor=\"#BBDDFF\">"
00219 "  <td colspan=2 valign=\"top\" align=\"left\" bgcolor=\"#EFF7FF\" width=\"100%%\">"
00220 "  <br><h2 align=\"center\">Monit Process Manager</h2>"
00221 "  <p align=\"center\">Monit is <a href='/_runtime'>running</a> on %s "
00222 "  with <i>uptime, %s</i> and monitoring:</p><br>"
00223 "  </td>"
00224 " </tr>"
00225 "</table>"
00226 "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%%\" border=\"0\">"
00227 "  <tr valign=\"middle\" bgcolor=\"#6F6F6F\">"
00228 "    <td><img src=\"/_pixel\" width=\"1\" height=\"1\" alt=\"\"></td>"
00229 "  </tr>"
00230 "</table>"
00231 "<br><p>&nbsp;</p>"
00232 "<table cellspacing=0 cellpadding=3 border=0 width=\"70%\">"
00233 "<tr><td><h3><b>Server</b></h3></td>"
00234 "<td align=\"right\"><h3><b>Status</b></h3></td>"
00235 "<td align=\"right\"><h3><b>Uptime</b></h3></td>"
00236 "<td align=\"right\"><h3><b>CPU</b></h3></td>"
00237 "<td align=\"right\"><h3><b>Memory</b></h3></td>"
00238 "</tr>"
00239 "<tr><td>&nbsp;</td><td>&nbsp;</td></tr>", Run.localhostname, uptime);
00240   } else {
00241   HEAD("", Run.polltime)
00242       out_print(res,
00243 "<table cellspacing=\"0\" cellpadding=\"5\" width=\"100%%\" border=\"0\">"
00244 " <tr bgcolor=\"#BBDDFF\">"
00245 "  <td colspan=2 valign=\"top\" align=\"left\" bgcolor=\"#EFF7FF\" width=\"100%%\">"
00246 "  <br><h2 align=\"center\">Monit Process Manager</h2>"
00247 "  <p align=\"center\">Monit is <a href='/_runtime'>running</a> on %s "
00248 "  with <i>uptime, %s</i> and monitoring:</p><br>"
00249 "  </td>"
00250 " </tr>"
00251 "</table>"
00252 "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%%\" border=\"0\">"
00253 "  <tr valign=\"middle\" bgcolor=\"#6F6F6F\">"
00254 "    <td><img src=\"/_pixel\" width=\"1\" height=\"1\" alt=\"\"></td>"
00255 "  </tr>"
00256 "</table>"
00257 "<br><p>&nbsp;</p>"
00258 "<table cellspacing=0 cellpadding=3 border=0 width=\"70%\">"
00259 "<tr><td><h3><b>Server</b></h3></td>"
00260 "<td align=\"right\"><h3><b>Status</b></h3></td></tr>"
00261 "<tr><td>&nbsp;</td><td>&nbsp;</td></tr>", Run.localhostname, uptime);
00262   }
00263 
00264   free(uptime);
00265   
00266   for (p= processlist; p; p= p->next) {
00267     
00268     int isrunning= is_process_running(p);
00269     char *uptime= get_process_uptime(p->pidfile);
00270     
00271     if ( Run.doprocess ) {
00272       ProcInfo_T pi= p->procinfo;
00273       if ( isrunning ) {
00274     out_print(res,"<tr %s><td><a href='/%s'>%s</a></td><td align=\"right\">"
00275           "%s</td><td align=\"right\">%s</td>"
00276           "<td align=\"right\">%.1f%%</td>"
00277           "<td align=\"right\">%.1f%% [%ldkB]</td></tr>",
00278           on?"bgcolor=\"#EFEFEF\"":"",
00279           p->name, p->name,
00280           p->has_checksum_error?
00281           "<font color='#ff0000'>Cheksum Error</font>": 
00282           isrunning?
00283           "<font color=green>running</font>":
00284           "<font color=red>not running</font>",
00285           uptime,
00286           pi->cpu_percent/10.0,
00287           pi->mem_percent/10.0,pi->mem_kbyte
00288           );
00289       } else {
00290     out_print(res,"<tr %s><td><a href='/%s'>%s</a></td>"
00291           "<td align=\"right\">%s</td>"
00292           "<td align=\"right\">-</td>"
00293           "<td align=\"right\">- </td>"
00294           "<td align=\"right\">- [-]</td></tr>",
00295           on?"bgcolor=\"#EFEFEF\"":"",
00296           p->name, p->name,
00297           p->has_checksum_error?
00298           "<font color='#ff0000'>Cheksum Error</font>": 
00299           "<font color=red>not running</font>"
00300           );
00301       }
00302     } else {
00303       out_print(res,"<tr %s><td><a href='/%s'>%s</a></td><td align=\"right\">"
00304         "%s %s</td></tr>",
00305         on?"bgcolor=\"#EFEFEF\"":"",
00306         p->name, p->name,
00307         p->has_checksum_error?
00308         "<font color='#ff0000'>Cheksum Error</font>":   
00309         isrunning?
00310         "<font color=green>running</font>":
00311         "<font color=red>not running</font>",
00312         isrunning?uptime:"");
00313     }
00314 
00315 
00316     on= on?FALSE:TRUE;
00317     free(uptime);
00318     
00319   }
00320   out_print(res, "</table>");
00321   FOOT
00322       
00323 }
00324 
00325 
00326 static void do_about(HttpRequest req, HttpResponse res) {
00327 
00328   out_print(res,
00329     "<html><head><title>about monit</title><body bgcolor=white>"
00330     "<br><br><center><a href='http://www.tildeslash.com/monit/'><font size=+2>"
00331     "monit " VERSION "</font></a></center><br><br>");
00332   out_print(res,
00333     "<ul>"
00334     "<li>Copyright &copy; 2000-2002 by <a "
00335     "href=\"http://www.tildeslash.com/monit/who.html\">Contributors</a> "
00336     "to the monit codebase. All Rights Reserved.<br> </small><p>"
00337     "<li>Portions of this software are copyright &copy; 1995, 1996 "
00338     "<a href='http://www.gnu.org/'>Free Software Foundation, Inc.</a>"
00339     "</ul><p><br><p>");
00340   out_print(res,
00341    "<table cellspacing=\"0\" cellpadding=\"0\" width=\"100%%\" border=\"0\">"
00342    " <tr bgcolor=\"#6F6F6F\">"
00343    " <td valign=\"bottom\"><img src=\"/_pixel\" width=\"1\" height=\"1\" "
00344    "alt=\"\"></td></tr></table>");
00345   out_print(res,
00346     "<p>This program is free software; you can redistribute it and/or "
00347     "modify it under the terms of the GNU General Public License "
00348     "as published by the Free Software Foundation; either version 2 of "
00349     "the License, or (at your option) any later version.<p>"
00350     "This program is distributed in the hope that it will be useful, but "
00351     "WITHOUT ANY WARRANTY; without even the implied warranty of "
00352     "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
00353     "<a href='http://www.tildeslash.com/gpl.html'>GNU "
00354     "General Public License</a> for more details.");
00355 
00356 }
00357 
00358 
00359 static void do_runtime(HttpRequest req, HttpResponse res) {
00360 
00361   int pid=  exist_daemon();
00362   
00363   HEAD("_runtime", 1000)
00364   out_print(res,
00365     "<center><h3>monit runtime status</h3><center><br>");
00366   out_print(res,"<table cellspacing=0 cellpadding=3 border=1 width=\"90%\">"
00367         "<tr><td width=\"40%\"><b>Parameter</b></td>"
00368         "<td width=\"60%\"><b>Value</b></td></tr>");
00369   out_print(res,
00370     "<tr><td>Host</a></td><td>%s</td></tr>",
00371         Run.localhostname);
00372   out_print(res,
00373     "<tr><td>Process id</a></td><td>%d</td></tr>", pid);
00374   out_print(res,
00375         "<tr><td>Effective user running monit</a></td>"
00376         "<td>%s</td></tr>", Run.Env.user);
00377   out_print(res,
00378     "<tr><td>Controlfile</a></td><td>%s</td></tr>", Run.controlfile);
00379   out_print(res,
00380     "<tr><td>Logfile</a></td><td>%s</td></tr>",
00381         Run.logfile);
00382   out_print(res,
00383     "<tr><td>Pidfile</a></td><td>%s</td></tr>", Run.pidfile);
00384   out_print(res,
00385     "<tr><td>Debug</a></td><td>%s</td></tr>",
00386         Run.debug?"True":"False");
00387   out_print(res,
00388     "<tr><td>Log</a></td><td>%s</td></tr>", Run.dolog?"True":"False");
00389   out_print(res,
00390     "<tr><td>Use syslog</a></td><td>%s</td></tr>",
00391         Run.use_syslog?"True":"False");
00392   out_print(res,
00393     "<tr><td>Mail server</a></td><td>%s</td></tr>",
00394         Run.mailserver?Run.mailserver:"Not defined");
00395   out_print(res,
00396     "<tr><td>Mail from</a></td><td>%s</td></tr>",
00397             Run.MailFormat.from?Run.MailFormat.from:"Not defined");
00398   out_print(res,
00399     "<tr><td>Mail subject</a></td><td>%s</td></tr>",
00400             Run.MailFormat.subject?Run.MailFormat.subject:"Not defined");
00401   out_print(res,
00402     "<tr><td>Mail message</a></td><td>%s</td></tr>",
00403             Run.MailFormat.message?Run.MailFormat.message:"Not defined");
00404   out_print(res,
00405     "<tr><td>Poll time</a></td><td>%d seconds</td></tr>",
00406         Run.polltime);
00407   out_print(res,
00408         "<tr><td>httpd bind address</a>"
00409         "</td><td>%s</td></tr>", Run.bind_addr?Run.bind_addr:"Any/All");
00410   out_print(res,
00411         "<tr><td>httpd auth. style</a></td><td>%s</td></tr>",
00412         Run.Auth.defined&&has_hosts_allow()?
00413         "Basic Authentication and Host allow list":
00414         Run.Auth.defined?"Basic Authentication":
00415         has_hosts_allow()?"Host allow list":
00416         "No authentication");
00417   out_print(res,"</table>");
00418   out_print(res, "<table cellspacing=16><tr nowrap><td><font size=+1>"
00419      "<font color='#f0000'>Stop monit http server?</font></font>"
00420      "<td align=right><form method=GET action=%s>"
00421      "<input type=submit value=Go style='font-size: 12pt'></font>"
00422      "</form></td>", STOP);
00423   if ( Run.dolog && !Run.use_syslog ) {
00424     out_print(res, "<td><font size=+1>"
00425      "View monit logfile?</font>"
00426      "<td align=right><form method=GET action=%s>"
00427      "<input type=submit value=Go style='font-size: 12pt'></font>"
00428      "</form></td>", VIEWLOG);
00429   }
00430   out_print(res, "</tr></table>");
00431   
00432   FOOT
00433 
00434 }
00435 
00436 
00437 static void do_viewlog(HttpRequest req, HttpResponse res) {
00438 
00439   HEAD("_viewlog", 100)
00440       
00441   if ( Run.dolog && !Run.use_syslog ) {
00442     
00443     struct stat sb;
00444     
00445     if ( !stat(Run.logfile, &sb) ) {
00446       
00447       FILE *f= fopen(Run.logfile, "r");
00448       if ( f ) {
00449     
00450     int n;
00451     char buf[8192];
00452     
00453     out_print(res, "<br><p><form><textarea cols=80 rows=30>");
00454     
00455     while ( (n= fread(buf, sizeof(char), 8192, f)) > 0 ) {
00456       
00457       buf[n]= 0;
00458       out_print(res, "%s", buf);
00459       
00460     }
00461     
00462         fclose(f);
00463     out_print(res, "</textarea></form>");
00464     
00465       } else {
00466     
00467     out_print(res, "Error opening logfile: %s", STRERROR);
00468     
00469       }
00470       
00471     } else {
00472       
00473       out_print(res, "Error stating logfile: %s", STRERROR);
00474       
00475     }
00476     
00477   } else {
00478     
00479     out_print(res,
00480     "<b>Cannot view logfile:</b><br>");
00481     if ( !Run.dolog ) {
00482       
00483       out_print(res, "monit was started without logging");
00484       
00485     } else {
00486       
00487       out_print(res, "monit uses syslog");
00488       
00489     }
00490     
00491   }
00492   
00493   FOOT
00494   
00495 }
00496 
00497 
00498 static void handle_action(HttpRequest req, HttpResponse res) {
00499 
00500   char *name= req->url;
00501   char *action= get_parameter(req, "action");
00502   
00503   if(exist_process(++name)) {
00504     
00505     if(action) {
00506       
00507       struct myprocess *p= get_process(name);
00508       
00509       if(is(action, "start")) {
00510     
00511     LOCK(Run.mutex)
00512         p->do_validate= TRUE;
00513     END_LOCK;
00514     start_process(p);
00515     
00516       }
00517       
00518       if(is(action, "stop")) {
00519     
00520     LOCK(Run.mutex)
00521         p->do_validate= FALSE;
00522     END_LOCK;
00523     stop_process(p);
00524     
00525       }
00526 
00527       if(is(action, "status")) {
00528 
00529     print_status(p, res);
00530     goto quit;
00531     
00532       }
00533       
00534       sleep(2);
00535       
00536     }
00537     
00538     LOCK(Run.mutex)
00539     do_process(req, res, name);
00540     END_LOCK;
00541     
00542   } else {
00543     
00544     not_found(req, res);
00545     
00546   }
00547 
00548   quit:
00549   free(action);
00550   
00551 }
00552 
00553 
00554 static void do_process(HttpRequest req, HttpResponse res, char *name) {
00555   
00556   struct myprocess *p= get_process(name);
00557   int run= is_process_running(p);
00558 
00559   HEAD(name, 1000)
00560   out_print(res,
00561     "<p><br><h3>Process status</h3><br>");
00562   out_print(res,"<table cellspacing=0 cellpadding=3 border=1 width=\"90%\">"
00563         "<tr><td width=\"30%\"><b>Parameter</b></td><td width=\"70%\"><b>Value</b></td></tr>");
00564   out_print(res,
00565     "<tr><td>Name</a></td><td>%s</td></tr>", p->name);
00566   out_print(res,
00567     "<tr><td>Group</a></td><td><font color='#0000ff'>%s</font></td></tr>",
00568         p->group?p->group:"(not defined)");
00569   out_print(res,
00570     "<tr><td>Process id </a></td><td>%d</td></tr>", run);
00571   out_print(res,
00572     "<tr><td>Process status</a></td><td>%s %s</td></tr>",
00573         run?"<font color='#00ff00'>Running</font>":
00574         "<font color='#ff0000'>Not Running</font>",
00575         p->has_checksum_error?
00576         "<font color='#ff0000'><b>Checksum error!</b></font>":"");
00577   out_print(res,
00578     "<tr><td>Pid file</a></td><td>%s</td></tr>",
00579         p->pidfile);
00580   if ( Run.doprocess ) {
00581     ProcInfo_T pi= p->procinfo;
00582 
00583     out_print(res,
00584           "<tr><td>CPU usage</a></td><td>%.1f%%</td></tr>",
00585           pi->cpu_percent/10.0);
00586     out_print(res,
00587           "<tr><td>Memory usage</a></td><td>%.1f%% [%ldkB]</td></tr>",
00588           pi->mem_percent/10.0,pi->mem_kbyte);
00589   }
00590   out_print(res,
00591     "<tr><td>Start program</a></td><td>%s</td></tr>",
00592         p->start?p->start->arg[0]:"(not defined)");
00593   out_print(res,
00594     "<tr><td>Stop program</a></td><td>%s</td></tr>",
00595         p->stop?p->stop->arg[0]:"(not defined)");
00596   {
00597     struct mychecksum *c;
00598     for(c= p->checksumlist; c; c= c->next)
00599     out_print(res, "<tr><td>Associated checksum</a></td><td>%s %s</td>"
00600           "</tr>", c->md5, c->file);
00601   }
00602   out_print(res,
00603     "<tr><td>Timeout</a></td><td>Timeout if %d restart within %d cycles"
00604     "</td></tr>", p->to_start, p->to_cycle);
00605   {
00606     Mail_T r;
00607     for(r= p->maillist; r; r= r->next) {
00608       out_print(res,
00609         "<tr bgcolor=\"#EFEFEF\"><td>Alert mail to</a></td><td>%s</td></tr>",
00610         r->to?r->to:"");
00611       out_print(res,
00612     "<tr><td>Alert from</a></td><td>%s</td></tr>",
00613               r->from?r->from:"(default)");
00614       out_print(res,
00615         "<tr><td>Alert subject</a></td><td>%s</td></tr>",
00616           r->subject?r->subject:"(default)");
00617       out_print(res,
00618     "<tr><td>Alert message</a></td><td>%s</td></tr>",
00619           r->message?r->message:"(default)");
00620       out_print(res,
00621     "<tr><td>Alert on timeout</a></td><td>%s</td></tr>",
00622         r->alert_on_timeout?"yes":"no");
00623       out_print(res,
00624     "<tr><td>Alert on restart</a></td><td>%s</td></tr>",
00625         r->alert_on_restart?"yes":"no");
00626       out_print(res,
00627     "<tr><td>Alert on checksum</a></td><td>%s</td></tr>",
00628         r->alert_on_checksum?"yes":"no");
00629       out_print(res,
00630     "<tr><td>Alert on exceeded resource</a></td><td>%s</td></tr>",
00631         r->alert_on_resource?"yes":"no");
00632       out_print(res,
00633     "<tr><td>Alert on stop</a></td><td>%s</td></tr>",
00634         r->alert_on_stop?"yes":"no");
00635     }
00636   }
00637   out_print(res,
00638         "<tr><td>Check process</a></td><td>Every %d cycle</td></tr>",
00639         p->every?p->every:1);
00640   {
00641     Port_T n;
00642     for(n= p->portlist; n; n= n->next) {
00643 
00644       if ( n->family == AF_INET ) {
00645 
00646     out_print(res,
00647         "<tr><td>Host:Port</a></td><td>%s:%d%s [%s]</td></tr>",
00648         n->hostname, n->port, n->request?n->request:"",
00649           n->protocol->name);
00650 
00651       } else if ( n->family == AF_UNIX ) {
00652 
00653     out_print(res,
00654         "<tr><td>Unix Socket</a></td><td>%s [%s]</td></tr>",
00655         n->pathname, n->protocol->name);
00656 
00657       }
00658     }
00659   }
00660   {
00661     Resource_T q;
00662 
00663     for (q= p->resourcelist; q; q= q->next) {
00664       switch (q->resource_id) {
00665 
00666       case RESOURCE_ID_CPU_PERCENT: 
00667 
00668     out_print(res,"<tr><td>Max. CPU usage</a></td>"
00669           "<td>If %s %.1f%% for %d/%d cycle(s) then %s</td></tr>", 
00670           operatornames[q->operator],
00671           q->limit/10.0, q->cycle, q->max_cycle, 
00672           actionnames[q->action]);
00673     break;
00674 
00675       case RESOURCE_ID_MEM_PERCENT: 
00676     
00677     out_print(res,"<tr><td> Max. memory usage</a></td>"
00678           "<td>If %s %.1f%% for %d/%d cycle(s) then %s</td></tr>", 
00679           operatornames[q->operator],
00680           q->limit/10.0, q->cycle, q->max_cycle, 
00681           actionnames[q->action]);
00682     break;
00683     
00684       case RESOURCE_ID_MEM_KBYTE: 
00685       
00686     out_print(res,"<tr><td>Max. memory amount</a></td>"
00687           "<td>If %s %ld for %d/%d cycle(s) then %s</td></tr>", 
00688           operatornames[q->operator],
00689           q->limit, q->cycle, q->max_cycle, 
00690           actionnames[q->action]);
00691     break;
00692     
00693       case RESOURCE_ID_LOAD1: 
00694       
00695     out_print(res,"<tr><td>Load average (1min)</a></td>"
00696           "<td>If %s %.1f for %d/%d cycle(s) then %s</td></tr>", 
00697           operatornames[q->operator],
00698           q->limit/10.0, q->cycle, q->max_cycle, 
00699           actionnames[q->action]);
00700     break;
00701     
00702       case RESOURCE_ID_LOAD5: 
00703       
00704     out_print(res,"<tr><td>Load average (5min)</a></td>"
00705           "<td>If %s %.1f for %d/%d cycle(s) then %s</td></tr>", 
00706           operatornames[q->operator],
00707           q->limit/10.0, q->cycle, q->max_cycle, 
00708           actionnames[q->action]);
00709     break;
00710     
00711       case RESOURCE_ID_LOAD15: 
00712     out_print(res,"<tr><td>Load average (15min)</a></td>"
00713           "<td>If %s %.1f for %d/%d cycle(s) then %s</td></tr>", 
00714           operatornames[q->operator],
00715           q->limit/10.0, q->cycle, q->max_cycle, 
00716           actionnames[q->action]);
00717     break;
00718     
00719       }    
00720     }
00721   }
00722   out_print(res, "</table>");
00723   out_print(res, "<table cellspacing=16><tr nowrap><td><font size=+1>");
00724   /* Start program */
00725   out_print(res, 
00726      "<td><form method=GET action=/%s>"
00727      "<input type=hidden value='start' name=action>"
00728      "<input type=submit value='Start program' style='font-size: 12pt'></font>"
00729      "</form></td>", name);
00730    /* Stop program */
00731   out_print(res, 
00732      "<td><form method=GET action=/%s>"
00733      "<input type=hidden value='stop' name=action>"
00734      "<input type=submit value='Stop program' style='font-size: 12pt'></font>"
00735      "</form></td>", name);
00736   out_print(res, "</tr></table>");
00737 
00738   FOOT
00739 
00740   
00741 }
00742 
00743 
00744 static void print_status(Process_T p, HttpResponse res) {
00745 
00746   FILE *out= res->outputstream;
00747   pid_t  pid= -1;
00748   
00749   res->is_committed= TRUE;
00750   
00751   if((pid= is_process_running(p))) {
00752     
00753     char *uptime= get_process_uptime(p->pidfile);
00754     ProcInfo_T pi= p->procinfo;
00755     
00756     fprintf(out, 
00757         "Process '%s' is running with pid [%d] \n\tUptime: %s "
00758         "CPU: %.1f%% Memory: %.1f%% [%ldkB]\n",
00759         p->name, (int)pid, uptime,
00760         pi->cpu_percent/10.0,
00761         pi->mem_percent/10.0,pi->mem_kbyte);
00762     
00763     free(uptime);
00764     
00765   } else {
00766     
00767     fprintf(out, "Process '%s' is not running\n",  p->name);
00768     
00769   }
00770 
00771 }
00772 
00773 
00774 static void printPixel(HttpResponse res) {
00775 
00776   static int l;
00777   static unsigned char *pixel= NULL;
00778 
00779   if ( ! pixel ) {
00780 
00781     pixel= xcalloc(sizeof(unsigned char), strlen(PIXEL_GIF));
00782     l= decode_base64(pixel, PIXEL_GIF);
00783 
00784   }
00785   if (l) {
00786     
00787     FILE *out= res->outputstream;
00788     
00789     res->is_committed= TRUE;
00790     
00791     fprintf(out, "HTTP/1.0 200 OK\r\n");
00792     fprintf(out, "Content-length: %d\r\n", l);
00793     fprintf(out, "Content-Type: image/gif\r\n");
00794     fprintf(out, "Connection: close\r\n\r\n");
00795 
00796     fwrite(pixel, sizeof(unsigned char), l, out);
00797   
00798   }
00799   
00800 }
00801 
00802 
00803 static void not_found(HttpRequest req, HttpResponse res) {
00804   
00805   send_error(res, SC_NOT_FOUND,
00806          "The requested URL was not found on this server");
00807   
00808 }
00809