[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
[0251]
[0252]
[0253]
[0254]
[0255]
[0256]
[0257]
[0258]
[0259]
[0260]
[0261]
[0262]
[0263]
[0264]
[0265]
[0266]
[0267]
[0268]
[0269]
[0270]
[0271]
[0272]
[0273]
[0274]
[0275]
[0276]
[0277]
[0278]
[0279]
[0280]
[0281]
[0282]
[0283]
[0284]
[0285]
[0286]
[0287]
[0288]
[0289]
[0290]
[0291]
[0292]
[0293]
[0294]
[0295]
[0296]
[0297]
[0298]
[0299]
[0300]
[0301]
[0302]
[0303]
[0304]
[0305]
[0306]
[0307]
[0308]
[0309]
[0310]
[0311]
[0312]
[0313]
[0314]
[0315]
[0316]
[0317]
[0318]
[0319]
[0320]
[0321]
[0322]
[0323]
[0324]
/*****************************************************************************/
/*
                                sHTTPDmon.c

Pronounced: ess-http-dee-mon

A CGI executable, browser viewable monitor, using the underlying HTTPDmon
executing in a PTD subprocess with the ANSI screen sequences converted into
HTML.

Also see SCREPER.C code.

Must be subject to WASD_CONFIG_AUTH authorisation!


HOW IT WORKS
------------
This was really just an exercise in screen-scraping the output of a "regular"
command-line application onto a browser HTML page.  The script uses JavaScript
and the HTML DOM to build and populate that page.

The script has two modes of operation.

   1) build the browser page with display element
   2) populate the display element with output from the CLI application

The /build/ mode provides a browser page with the basic HTML/CSS/JavaScript
resources.  Inside that page an XMLHttpRequest() initiates the execution of
another instance of the script this time with a query-string.

The presence of the query-string initiates the /populate/ mode where the script
uses the pseudo-terminal driver (PTD) to create a terminal session and then
spawn a subprocess attached to that terminal.  In that subprocess the CLI
application (in this case HTTPDmon) is invoked and its output to the
pseudo-terminal processed (scraped) to be HTML-escaped and otherwise munged for
representative display in the display element.  This munged output is
transmitted back to the browser XMLHttpRequest() in these chunks.  Each chunk
is parsed from the total output and displayed as that chunk.

Screen scraper code in module SCREPER.C


REQUIRED PRIVILEGES
-------------------
Same as required for HTTPDmon, so...

$ INSTALL REPLACE CGI-BIN:[000000]SHTTPDMON /PRIVILEGE=(SYSPRV,SYSLCK,WORLD)


COPYRIGHT
---------
Copyright (C) 2021 Mark G.Daniel

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


VERSION LOG
-----------
28-MAY-2021  MGD  initial
*/
/*****************************************************************************/

#define SOFTWAREVN "v1.0.0"
#define SOFTWARENM "SHTTPDMON"
#ifdef __ALPHA
#  define SOFTWAREID SOFTWARENM " " SOFTWAREVN " AXP"
#endif
#ifdef __ia64
#  define SOFTWAREID SOFTWARENM " " SOFTWAREVN " IA64"
#endif
#ifdef __x86_64
#  define SOFTWAREID SOFTWARENM " " SOFTWAREVN " X86"
#endif

#include <ctype.h>
#include <descrip.h>
#include <errno.h>
#include <fcntl.h>
#include <in.h>
#include <ints.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stat.h>
#include <unistd.h>
#include <unixio.h>

#include <dvidef.h>
#include <iodef.h>
#include <iosbdef.h>
#include <jpidef.h>
#include <libdef.h>
#include <lib$routines.h>
#include <starlet.h>
#include <ssdef.h>
#include <syidef.h>

#include "screper.h"

#define FI_LI "SHTTPMON",__LINE__

#ifndef UINT64PTR
/* mainly to allow easy use of the __unaligned directive */
#define UINTPTR __unaligned unsigned int*
#define ULONGPTR __unaligned unsigned long*
#define USHORTPTR __unaligned unsigned short*
#define UINT64PTR __unaligned uint64*
#define INT64PTR __unaligned int64*
#endif

int  dbug = 0,
     begun,
     inspect;
      
char  *CgiQueryString,
      *CgiRemoteUser,
      *CgiServerSoftware;

char  ScriptName [64];

char  *MonStyle =
"<style type=\"text/css\">\n\
body { font-family:arial,verdana,helvetica,sans; font-size:11pt; \
background-color:white; color:black; margin:1em; }\n\
h1 { font-size:1.3em; }\n\
.problem { color:red; }\n\
</style>\n";

/* prototypes */
void sHttpdMonExit (int, int);

/*****************************************************************************/
/*
*/

int main (int argc, char *argv[])

{
   static unsigned long  JpiPidItem = JPI$_PID;
   static unsigned long  SyiNodeNameItem = SYI$_NODENAME;
   static char  SyiNodeName [16];
   static $DESCRIPTOR (SyiNodeNameDsc, SyiNodeName);

   int  status;
   ushort  slen;
   char  *cptr, *rptr, *sptr, *zptr;;
   char  scrdo [128];
   void  *scrptr;

   /*********/
   /* begin */
   /*********/

   if (argc > 1)
   {
      if (!strncasecmp (argv[1], "/VERSION", 4))
         fprintf (stdout, "%s\n%s\n", SOFTWAREID, ScreperDo(NULL,"-version"));
      exit (SS$_NORMAL);
   }

   if (!(stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")))
      sHttpdMonExit (vaxc$errno, __LINE__);

   lib$getsyi (&SyiNodeNameItem, 0, &SyiNodeNameDsc, &slen, 0, 0);
   SyiNodeName[slen] = '\0';

   if (!(CgiServerSoftware = getenv ("WWW_SERVER_SOFTWARE")))
      CgiServerSoftware = getenv ("SERVER_SOFTWARE");

   if (!CgiServerSoftware) sHttpdMonExit (SS$_NORMAL, __LINE__);

   if (cptr = getenv ("SHTTPDMON_INSPECT"))
      inspect = atol (cptr);

   if (!(CgiRemoteUser = getenv ("SHTTPDMON_REMOTE_USER")))
      if (!(CgiRemoteUser = getenv ("WWW_REMOTE_USER")))
         if (!(CgiRemoteUser = getenv ("REMOTE_USER")))
            CgiRemoteUser = "";

   if (!*CgiRemoteUser)
   {
      fprintf (stdout,
"Status: 403 Forbidden\r\n\
Content-Type: text/html\r\n\
\r\n\
<!DOCTYPE html>\n\
<html>\n\
<head>\n\
<meta name=\"generator\" content=\"%s\">\n\
<title>%s:: %s</title>\n\
%s\
</head>\n\
<body>\n\
<pre><span class=\"problem\">authorization failure</span></pre>\n\
</body>\n\
</html>\n",
               SOFTWAREID, SyiNodeName, ScriptName, MonStyle);
      sHttpdMonExit (SS$_NORMAL, __LINE__);
   }

   if (!(CgiQueryString = getenv ("WWW_QUERY_STRING")))
      if (!(CgiQueryString = getenv ("QUERY_STRING")))
         CgiQueryString = "";

   strcpy (ScriptName, "sHTTPDmon"); 

   if (strstr (CgiQueryString, "populate="))
   {
      /************/
      /* populate */
      /************/

      scrptr = ScreperInit ();

      /* facilitate development - no referer then is populate=1 directly */
      if (!(rptr = getenv ("WWW_HTTP_REFERER")))
         rptr = getenv ("HTTP_REFERER");

      if (inspect && rptr)
         fputs ("Status: 200 OK\r\n\
Content-Type: text/plain\r\n\
Script-Control: X-record-mode=1\r\n\
\n\n", stdout);
      else
         fputs ("Status: 200 OK\r\n\
Content-Type: text/html\r\n\
Script-Control: X-stream-mode=1\r\n\
Script-Control: X-timeout-output=none\r\n\
Script-Control: X-content-encoding-gzip=0\r\n\
\r\n", stdout);
      fflush (stdout);
      begun = 1;

      if (!rptr)
         /* no referer then is populate=1 directly */
         fprintf (stdout, "<!DOCTYPE html>\n<html>\n%s<body>\n<pre>\n",
                  ScreperDo(NULL,"-css"));

      sprintf (scrdo, "-inspect=%d -utility=\"%s\" -page=32 -snap=17 -dcl=\
SET PROCESS /PRIVILEGE=(SYSPRV,SYSLCK,WORLD)\n\
@WASD_FILE_DEV\n\
HTTPDMON = \"$HT_EXE:HTTPDMON\"\n\
HTTPDMON /STATUS", inspect, "sHTTPDmon");

      sptr = ScreperDo (scrptr, scrdo);
      if (*(USHORTPTR)sptr == '%X')
         status = strtol (sptr+2, NULL, 16);
      else
         status = SS$_BUGCHECK;
      if (status & 1) sys$hiber();
      sHttpdMonExit (status, __LINE__);
   }
   else
   {
      /**************/
      /* build page */
      /**************/

      fprintf (stdout,
"Status: 200 OK\r\n\
Content-Type: text/html\r\n\
Script-Control: X-stream-mode\r\n\
\r\n\
<!DOCTYPE html>\n\
<html>\n\
<head>\n\
<meta name=\"generator\" content=\"%s\">\n\
<title>%s:: %s</title>\n\
%s\
%s\
<style type=\"text/css\">\n\
.problem { color:red; }\n\
</style>\n\
</head>\n\
<body onload=\"doScreper()\">\n\
%s\
</body>\n\
</html>\n",
               SOFTWAREID, SyiNodeName, ScriptName,
               ScreperDo(NULL,"-css"),
               ScreperDo(NULL,"-javascript"),
               ScreperDo (NULL,"-screen"));
      begun = 1;
   }

   sHttpdMonExit (SS$_NORMAL, __LINE__);
}

/*****************************************************************************/
/*
Provide some WATCHable exit information.
*/

void sHttpdMonExit (int status, int line)

{
   /*********/
   /* begin */
   /*********/

   if (!begun)
      fputs ("Status: 200 OK\r\n\
Content-Type: text/plain\r\n\
Script-Control: X-record-mode=1\r\n\
\r\n", stdout);

    fprintf (stdout, "\n<!-- sHTTPDmon:%d %%X%08.08X -->\n", line, status);

    exit (status);
}

/*****************************************************************************/