/*****************************************************************************/ /* sOPCOM.c Pronounced: sop-com. Allows OPCOM messages to be screped and displayed on a browser page. Also see SCREPER.C code. sOPCOM is a little different to most other screper applications. It doesn't execute a command that when complete restarts or terminates. It must REPLY/ENABLE and then sit at the CLI command prompt waiting for output to the terminal. Hence the "-noext" to the screper. To specify a specific or range of /ENABLE=(keywords) add a query string containing those keywords between parentheses. For example /cgi-bin/sopcom?(network,central) By default sOPCOM automatically scrolls to the end of the display page (maximum 255 lines). This can be suppressed by adding "scroll=0" to the query string. sOPCOM requires server authorisation. If access for the great unwashed is desired (NOT RECOMMENDED), define the logical name SOPCOM_REMOTE_USER to anything at all. The script quits if there is not activity during any one hour period. Logical name SOPCOM_NOPROGRESS allows this to changed. Just define the number of seconds required. For example eight hours would be $ DEFINE /SYSTEM SOPCOM_NOPROGRESS 28800 HOW IT WORKS ------------ See the prologue to SCREPER.C. REQUIRED PRIVILEGES ------------------- For non-security related messages only... $ INSTALL REPLACE CGI-BIN:[000000]SOPCOM /PRIVILEGE=(OPER) To include security related messages... $ INSTALL REPLACE CGI-BIN:[000000]SOPCOM /PRIVILEGE=(OPER,SECURITY) COPYRIGHT --------- Copyright (C) 2022 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 ----------- 25-SEP-2022 MGD v1.0.0, initial */ /*****************************************************************************/ #define SOFTWAREVN "v1.0.0" #define SOFTWARENM "SOPCOM" #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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 begun, inspect; char *CgiQueryString, *CgiRemoteUser, *CgiRequestUri, *CgiScriptName, *CgiServerSoftware; static char ScriptName [64], SyiNodeName [16]; void *scrptr; char *sopcomStyle = "\n"; /* prototypes */ void sopcomExit (int, int); void sopcomPopulate (); void sopcomTerminal (); /*****************************************************************************/ /* */ int main (int argc, char *argv[]) { static unsigned long JpiPidItem = JPI$_PID; static unsigned long SyiNodeNameItem = SYI$_NODENAME; static $DESCRIPTOR (SyiNodeNameDsc, SyiNodeName); int interval, page; ushort slen; char *cptr, *sptr, *zptr;; char cmd [256]; /*********/ /* 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"))) sopcomExit (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) sopcomExit (SS$_NORMAL, __LINE__); strcpy (ScriptName, "sOPCOM"); if (!(CgiRemoteUser = getenv ("SOPCOM_REMOTE_USER"))) if (!(CgiRemoteUser = getenv ("WWW_REMOTE_USER"))) if (!(CgiRemoteUser = getenv ("REMOTE_USER"))) CgiRemoteUser = ""; if (!*CgiRemoteUser) { begun = 1; fprintf (stdout, "Status: 403 Forbidden\r\n\ Content-Type: text/html\r\n\ \r\n\ \n\ \n\ \n\ \n\ %s:: %s\n\ %s\ \n\ \n\
authorization failure
\n\ \n\ \n", SOFTWAREID, SyiNodeName, ScriptName, sopcomStyle); sopcomExit (SS$_NORMAL, __LINE__); } scrptr = ScreperInit (); if (cptr = getenv ("SOPCOM_INSPECT")) inspect = atol (cptr); if (!(CgiRequestUri = getenv ("WWW_REQUEST_URI"))) if (!(CgiRequestUri = getenv ("REQUEST_URI"))) CgiRequestUri = ""; if (!(CgiScriptName = getenv ("WWW_SCRIPT_NAME"))) if (!(CgiScriptName = getenv ("SCRIPT_NAME"))) CgiScriptName = ""; if (!(CgiQueryString = getenv ("WWW_QUERY_STRING"))) if (!(CgiQueryString = getenv ("QUERY_STRING"))) CgiQueryString = ""; if (*CgiQueryString) { if (strstr (CgiQueryString, "populate=")) sopcomPopulate (); else sopcomTerminal (); } else sopcomTerminal (); sopcomExit (SS$_NORMAL, __LINE__); } /*****************************************************************************/ /* A page with the embedded terminal screen output. */ void sopcomTerminal () { int status; void *scrptr; /*********/ /* begin */ /*********/ scrptr = ScreperInit (); begun = 1; fprintf (stdout, "Status: 200 OK\r\n\ Content-Type: text/html\r\n\ Script-Control: X-stream-mode=1\r\n\ %s\ \r\n\ \n\ \n\ \n\ \n\ %s:: %s\n\ %s\ %s\ \n\ \n\ %s\ \n\ \n", ScreperDo (scrptr,"-csp"), SOFTWAREID, SyiNodeName, ScriptName, ScreperDo (scrptr, "-css"), ScreperDo (scrptr, "-javascript"), ScreperDo (scrptr, "-screen")); sopcomExit (SS$_NORMAL, __LINE__); } /*****************************************************************************/ /* Spawn the command subprocess and provide the HTML-ified, scraped terminal screen output back to the embedded virtual screen. */ void sopcomPopulate () { int number, scroll, status; char *aptr, *cptr, *rptr, *sptr, *zptr; char keyword [256], scratch [256], scrdo [512]; void *scrptr; /*********/ /* begin */ /*********/ keyword[0] = '\0'; for (cptr = CgiQueryString; *cptr && *cptr != '('; cptr++); for (aptr = cptr; *aptr && *aptr != ')'; aptr++); if (*cptr && aptr > cptr) { zptr = (sptr = keyword) + sizeof(keyword)-1; *sptr++ = '='; while (cptr <= aptr && sptr < zptr) *sptr++ = toupper(*cptr++); *sptr = '\0'; } if (cptr = strstr (CgiQueryString, "scroll=")) scroll = atoi (cptr + 7); else scroll = 1; number = 3600; /* one hour */ if (cptr = getenv ("SOPCOM_NOPROGRESS")) if ((number = atoi(cptr)) < 60) number = 60; /* facilitate development - no referer then is populate=1 directly */ if (!(rptr = getenv ("WWW_HTTP_REFERER"))) rptr = getenv ("HTTP_REFERER"); scrptr = ScreperInit (); sprintf (scrdo, "-inspect=%d -scroll=%d -utility=\"%s\" \ -page=255 -width=96 -noecho \ -noetx -snapshot=10 -noprogress=%d \ -exit=\"%s\" \ -dcl=" "SET PROCESS /PRIVILEGE=(ALL)\n" "REPLY/ENABLE%s\n", inspect, scroll, ScriptName, number, "An illegal operator request was made", keyword); begun = 1; if (inspect && rptr) fprintf (stdout, "Status: 200 OK\r\n\ Content-Type: text/plain\r\n\ Script-Control: X-record-mode=1\r\n\ %s\ \r\n", ScreperDo(scrptr,"-csp")); else fprintf (stdout, "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\ %s\ \r\n", ScreperDo(scrptr,"-csp")); fflush (stdout); if (!rptr) /* no referer then is populate=1 directly */ fprintf (stdout, "\n\n%s\n
\n",
               ScreperDo (scrptr, "-css"));
 
   if (inspect)
   {
      fprintf (stdout, "|%s|\n", scrdo);
      fflush (stdout);
   }

   sptr = ScreperDo (scrptr, scrdo);
   if (*(USHORTPTR)sptr == '%X')
   {
      fprintf (stdout, "%s\n", sptr);
      status = strtol (sptr+2, NULL, 16);
   }
   else
      status = SS$_BUGCHECK;

   sopcomExit (status, __LINE__);
}

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

void sopcomExit (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", line, status);

    exit (SS$_NORMAL);
}

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