/*****************************************************************************/ /* Admin.c Server administration support functions for HTTPd. Many of the reports and forms used for revision are produced by functions within the core-function module. The control function allow server restart, exit, abort, mapping file reload, authorization path reload and authentication cache purging. VERSION HISTORY --------------- 11-FEB-2024 MGD refine/expand server process log reports 12-SEP-2022 MGD move onclick=s to addEventListener()s to support content-security-policy: 'strict-dynamic' 09-APR-2022 MGD AdminMenu() [Request+] report 23-SEP-2021 MGD AdminServerOutputList() 10-MAR-2021 MGD accomodate PIPE from WASD_ROOT:[SRC.UTILS]WASTEE.C 27-OCT-2020 MGD bugfix; AdminMenu() activity hours 672 (ActHours[idx-1]) 14-APR-2020 MGD kludge; Safari (at least) does not honour HTTP cache control headers! Its back-forwardcache breaks stuff. 14-SEP-2019 MGD bugfix; AdminParsePath() extraneous OdsParseRelease() 18-JAN-2019 MGD add 418 to status code statistics 25-AUG-2018 MGD WatchSystemPlus() et.al. 28-APR-2018 MGD refactor Admin..() AST delivery 16-DEC-2017 MGD note decade-old border-collapse bug in Chrome https://bugs.chromium.org/p/chromium/issues/detail?id=356132 (Firefox, MS Edge, Safari render correctly) *** appears to be fixed from at least version 68... *** 10-OCT-2017 MGD SesolaReport..() relax from SSL-only to any service 14-NOV-2015 MGD excise much of the twenty years of reporting HTML cruft AdminRefresh() allow selection of a page refresh interval lift the GZIP restriction for all but main menu and WATCHing 28-SEP-2014 MGD AdminLookYouUp() and associated Server Admin item 12-MAR-2014 MGD "no module involved" datum 30-JAN-2014 MGD tweaks to menu layout to try and get MSIE 9 to behave 27-JUN-2010 MGD WebSockReport() 23-AUG-2009 MGD WasdCss[] and some refinements 26-JUL-2007 MGD bugfix; AdminMenu() JavaScript doIt() call 02-JUN-2007 MGD WebDAV and Cluster reports, remove file cache, authorization and proxy items from Server Statistics report (keeping it more-to-the-point) 27-OCT-2006 MGD AdminReportServerStat() quota percentages in use 23-SEP-2006 MGD AdminReportServerStat() last exit time 15-JUL-2006 MGD AdminMenu() instance [Active][Passive] functionality (service item) network connection [Purge][All] 04-JUL-2006 MGD AdminMenu() status panel (time, connect, request) mods use PercentOf32() for more accurate percentages 26-MAY-2005 MGD [/DO=] button/field and supporting functionality 03-MAR-2005 MGD AdminMetaConSource() changes to support search lists 30-NOV-2004 MGD zero proxy accounting 12-OCT-2004 MGD add status info (currently only access log write fail) to Server Admin page (beneath dates and accounting) 28-JUL-2004 MGD HTTP/1.1 items, server admin reports now have the response header generated after the report body so that the buffer length can be used as a content length (allowing connections to persist) 20-MAY-2004 MGD remove 'supervisor' from report menu 28-JAN-2004 MGD make process input/output reports plain-text, service access log report (via LoggingReport()), make some accomodations in reports for our old friend Netscape 3.03/Gold (on VMS) which doesn't render some table formatting correctly (or the way we intended anyway) 26-AUG-2003 MGD rework access to server configuration files, service directory located authorization databases 15-AUG-2003 MGD where CDATA constraints make using entity impossible use a field name of hidden$lf and ^ substituted for it 22-JUL-2003 MGD allow for CMKRNL when warning on privileges 08-JUN-2003 MGD cache statistics include permanent/volatile changes 31-JAN-2002 MGD no menu difference between category and module WATCHing 12-OCT-2002 MGD refine metacon reporting 16-JUN-2002 MGD greater hour granularity to activity report selection 30-MAY-2002 MGD restart when quiet 17-MAY-2002 MGD activity reports changed inline with GRAPH.C changes 04-APR-2002 MGD proxy cache STOP scan 28-DEC-2001 MGD add 'instance' selection 29-OCT-2001 MGD PERSONA_MACRO reporting 29-SEP-2001 MGD instance support 04-AUG-2001 MGD support module WATCHing 13-MAR-2001 MGD add throttle and supervisor reports 22-DEC-2000 MGD HTL list admin (partially implemented by HTADMIN.C), SSL client certificate CA verification 02-OCT-2000 MGD DETACH now an allowed privilege 13-SEP-2000 MGD ProxyMainReport() call refined 26-AUG-2000 MGD consolidated WATCH processing and peek 18-JUN-2000 MGD "All Services" directives, site log item, service configuration, add a little JavaScript to enhance the admin menu 28-MAY-2000 MGD use $getjpi ...lm values from server startup 04-MAR-2000 MGD use FaolToNet(), et.al. 13-JAN-2000 MGD improve log messages, add OPCOM messaging 30-OCT-1999 MGD unbundled WATCH functionality to its own module 10-OCT-1999 MGD show process report, move service statistics report to NET.C module, CacheReport() now only optionally reports cached files 04-SEP-1999 MGD remove WatchRequestHeader() 11-JUN-1999 MGD bugfix; WatchFilter() 12-APR-1999 MGD WatchDataDump() for request and response bodies 10-JAN-1999 MGD add proxy items to WATCH menu, add proxy report 07-NOV-1998 MGD WATCH facility 16-MAR-1998 MGD server abort changed to "exit NOW", added "restart NOW" 05-OCT-1997 MGD file cache 28-SEP-1997 MGD request durations 06-SEP-1997 MGD service list 09-AUG-1997 MGD message database 07-JUL-1997 MGD activity report and logging control functions, reworked the control function (it was getting untidy) 08-JUN-1997 MGD "Other" menu item, with "Clients" and "Scripting" reports, AdminRequestReport() and DclScriptingReport() functions 01-FEB-1997 MGD new for HTTPd version 4 */ /*****************************************************************************/ #ifdef WASD_VMS_V7 #undef _VMS__V6__SOURCE #define _VMS__V6__SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif /* standard C header files */ #include #include #include #include #include #include /* VMS related header files */ #include #include #include #include #include #include #include #include #include /* application related header files */ #include "wasd.h" #define WASD_MODULE "ADMIN" /******************/ /* global storage */ /******************/ /********************/ /* external storage */ /********************/ extern BOOL CacheEnabled, DclScriptDetachProcess, DclPersonaServicesAvailable, GzipAvailable, Http2Enabled, HttpdAlignFaultReport, InstanceNodeSupervisor, LoggingEnabled, LoggingFileError, NetAcceptEnabled, NetInstancePassive, NetRejectEnabled, OperateWithSysPrv, PersonaMacro, ProtocolHttpsConfigured, SesolaVerifyCAConfigured, WebDavEnabled; extern int ActivityTotalMinutes, CacheEntryCount, CacheEntriesMax, CacheHits0, CacheHits10, CacheHits100, CacheHits1000, CacheHits1000plus, CacheHitCount, CacheLoadCount, CacheMemoryInUse, CachePermEntryCount, CachePermMemoryInUse, CacheTotalKBytesMax, ControlStringSize, EfnWait, ExitStatus, GblPageCount, GblPagePermCount, GblSectionCount, GblSectionPermCount, GzipFindImageStatus, HttpdAlignFaultCount, HttpdTickSecond, InstanceEnvNumber, InstanceNodeCurrent, InstanceNumber, NoticeInvalid, OpcomMessages, RequestHistoryMax; extern int64 HttpdStartTime64; extern char BuildInfo[], CommandLine[], ErrorSanityCheck[], HttpdScriptAsUserName[], InConfigFileName[], ServerHostPort[], SoftwareID[], TcpIpAgentInfo[], TimeGmtString[], WatchQuotasAlert[]; extern char *AuthConfigHtaDirectory, *GzipZlibNamePtr, *GzipZlibVersionPtr; extern unsigned long SysPrvMask[]; #define acptr AccountingPtr extern ACCOUNTING_STRUCT *AccountingPtr; extern ACTIVITY_GBLSEC *ActivityGblSecPtr; extern CONFIG_STRUCT Config; extern HTTPD_GBLSEC *HttpdGblSecPtr; extern HTTPD_PROCESS HttpdProcess; extern MSG_STRUCT Msgs; extern MAPPING_META *MappingMetaPtr; extern PROXY_ACCOUNTING_STRUCT *ProxyAccountingPtr; extern LIST_HEAD ServiceList; extern SYS_INFO SysInfo; extern TCPIP_HOST_CACHE *TcpIpHostCachePtr; extern WATCH_STRUCT Watch; /*****************************************************************************/ /* Begin HTTPd server administration. */ void AdminBegin (REQUEST_STRUCT *rqptr) { BOOL ClusterDo, SlashDo, UseServerConfig; int status; unsigned short Length; char *cptr, *pinptr, *uriptr; char DoThis [128], FieldName [128], FieldValue [256], FilePath [ODS_MAX_FILE_NAME_LENGTH+1], Http2Connection [33], Md5HashHexString [33], NumberString [16], Path [ODS_MAX_FILE_NAME_LENGTH+1], ProcessIdString [16], ProcessIdUserName [13], RefreshInterval [16], VirtualHostPort [128]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminBegin()"); if (WATCHING (rqptr, WATCH_RESPONSE)) WatchThis (WATCHITM(rqptr), WATCH_RESPONSE, "ADMIN !AZ", rqptr->rqHeader.PathInfoPtr); if (!rqptr->AccountingDone++) InstanceGblSecIncrLong (&acptr->DoServerAdminCount); if (!rqptr->RemoteUser[0]) { rqptr->rqResponse.HttpStatus = 403; ErrorGeneral (rqptr, MsgFor(rqptr,MSG_AUTH_REQUIRED), FI_LI); AdminEnd (rqptr); return; } if (!rqptr->AdminTaskPtr) rqptr->AdminTaskPtr = VmGetHeap (rqptr, sizeof(ADMIN_TASK)); FaoBigNumber (NULL); pinptr = rqptr->rqHeader.PathInfoPtr; uriptr = rqptr->rqHeader.RequestUriPtr; /* for admin activities supply a full error report regardless */ rqptr->rqPathSet.ReportType = ERROR_REPORT_DETAILED; /* disable GZIP compression for the main menu and when WATCHing */ if (strsame (uriptr, HTTPD_ADMIN, -1)) rqptr->rqResponse.NoGzip = true; else if (strsame (uriptr, ADMIN_REPORT_WATCH, -1)) rqptr->rqResponse.NoGzip = true; /*********************/ /* per-service admin */ /*********************/ #ifdef NOT_FULLY_IMPLEMENTED_YET if (strsame (pinptr, HTTPD_VS_ADMIN, -1)) { AdminVirtualServerMenu (rqptr); return; } if (strsame (pinptr, ADMIN_VS_REVISE_HTA, sizeof(ADMIN_VS_REVISE_HTA)-1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else HTAdminBegin (rqptr); return; } if (strsame (pinptr, ADMIN_VS_REVISE_HTL, sizeof(ADMIN_VS_REVISE_HTL)-1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if ((pinptr+sizeof(ADMIN_VS_REVISE_HTL)-1)[0]) if (rqptr->rqHeader.QueryStringLength) HTAdminBegin (rqptr); else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); else HTAdminBegin (rqptr); return; } if (strsame (pinptr, ADMIN_VS_CONTROL, sizeof(ADMIN_VS_CONTROL)-1)) { AdminControl (rqptr, NULL, true); return; } #endif /** NOT_FULLY_IMPLEMENTED_YET **/ /********************************************/ /* modules that parse their own query field */ /********************************************/ if (strsame (pinptr, ADMIN_REVISE_HTA, sizeof(ADMIN_REVISE_HTA)-1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else HTAdminBegin (rqptr); return; } if (strsame (pinptr, ADMIN_REVISE_HTL, sizeof(ADMIN_REVISE_HTL)-1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if ((pinptr+sizeof(ADMIN_REVISE_HTL)-1)[0]) if (rqptr->rqHeader.QueryStringLength) HTAdminBegin (rqptr); else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); else HTAdminBegin (rqptr); return; } if (strsame (pinptr, ADMIN_REVISE_SITELOG, sizeof(ADMIN_REVISE_SITELOG)-1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) UpdBegin (rqptr, &AdminEnd); else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_ACTIVITY, -1)) { GraphActivityReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_MATCH, -1)) { StringMatchReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROCESS, -1)) { WatchProcessReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_WATCH, -1)) { if (rqptr->rqHeader.QueryStringLength) WatchBegin (rqptr); else WatchReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_WATCH_STRUCT, -1)) { WatchReportStruct (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_WEBDAV, -1)) { DavWebReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_WEBDAV_XML, -1)) { DavXmlReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_WEBSOCKET, -1)) { WebSockReport (rqptr); return; } if (strsame (pinptr, ADMIN_CONTROL_DELETE_PROCESS, -1)) { WatchDeleteProcess (rqptr); return; } /**********************/ /* parse query string */ /**********************/ ClusterDo = SlashDo = false; UseServerConfig = true; DoThis[0] = FilePath[0] = Http2Connection[0] = Md5HashHexString[0] = NumberString[0] = Path[0] = ProcessIdString[0] = ProcessIdUserName[0] = RefreshInterval[0] = VirtualHostPort[0] = '\0'; if (rqptr->rqHeader.QueryStringLength) cptr = rqptr->rqHeader.QueryStringPtr; else cptr = ""; while (*cptr) { status = StringParseQuery (&cptr, FieldName, sizeof(FieldName), FieldValue, sizeof(FieldValue)); if (VMSnok (status)) { /* error occured */ if (status == SS$_IVCHAR) rqptr->rqResponse.HttpStatus = 400; rqptr->rqResponse.ErrorTextPtr = "parsing query string"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } if (strsame (FieldName, "at", -1) || strsame (FieldName, "this", -1)) strzcpy (NumberString, FieldValue, sizeof(NumberString)); else if (strsame (FieldName, "cxr", -1)) { /* 'cxr' can be generated from an UPD edit window */ strzcpy (DoThis, "edit", sizeof(DoThis)); } else if (strsame (FieldName, "do", -1)) strzcpy (DoThis, FieldValue, sizeof(DoThis)); else if (strsame (FieldName, "edit", -1)) strzcpy (FilePath, FieldValue, sizeof(FilePath)); else if (strsame (FieldName, "entry", -1)) strzcpy (Md5HashHexString, FieldValue, sizeof(Md5HashHexString)); else if (strsame (FieldName, "file", -1)) { if (to_upper(FieldValue[0]) == 'Y') UseServerConfig = false; else if (to_upper(FieldValue[0]) == 'N') UseServerConfig = true; } else if (strsame (FieldName, "http2", -1)) strzcpy (Http2Connection, FieldValue, sizeof(Http2Connection)); else if (strsame (FieldName, "refresh", -1)) strzcpy (RefreshInterval, FieldValue, sizeof(RefreshInterval)); else if (strsame (FieldName, "puser", -1)) strzcpy (ProcessIdUserName, FieldValue, sizeof(ProcessIdUserName)); else if (strsame (FieldName, "path", -1)) strzcpy (Path, FieldValue, sizeof(Path)); else if (strsame (FieldName, "pid", -1)) strzcpy (ProcessIdString, FieldValue, sizeof(ProcessIdString)); else if (strsame (FieldName, "puser", -1)) strzcpy (ProcessIdUserName, FieldValue, sizeof(ProcessIdUserName)); else if (strsame (FieldName, "scope", -1)) { if (strsame (FieldValue, "cluster", -1)) ClusterDo = true; } else if (strsame (FieldName, "service", -1)) strzcpy (VirtualHostPort, FieldValue, sizeof(VirtualHostPort)); else if (strsame (FieldName, "server", -1)) { if (to_upper(FieldValue[0]) == 'Y') UseServerConfig = true; else if (to_upper(FieldValue[0]) == 'N') UseServerConfig = false; } else if (strsame (FieldName, "slashdo", -1)) { SlashDo = true; strzcpy (DoThis, FieldValue, sizeof(DoThis)); } else if (strsame (FieldName, "virtual", -1)) strzcpy (VirtualHostPort, FieldValue, sizeof(VirtualHostPort)); else { rqptr->rqResponse.HttpStatus = 400; ErrorGeneral (rqptr, "Unknown query field.", FI_LI); AdminEnd (rqptr); return; } } /***************/ /* do function */ /***************/ if (SlashDo) { if (!DoThis[0] || strsame (DoThis, "HELP", -1)) ControlDoHelp (rqptr); else if (strsame (DoThis, "STATUS", -1)) InstanceStatusCliReport (rqptr); else AdminControl (rqptr, DoThis, ClusterDo); return; } if (strsame (pinptr, HTTPD_ADMIN, -1) || strsame (pinptr, HTTPD_ADMIN_STATUS, -1) || strsame (pinptr, ADMIN_REPORT, -1) || strsame (pinptr, ADMIN_REVISE, -1) || strsame (pinptr, ADMIN_CONTROL, -1)) { /********/ /* menu */ /********/ AdminMenu (rqptr); return; } #if ALIGN_FAULT if (strsame (pinptr, ADMIN_REPORT_ALIGN, -1)) { HttpdAlignReport (rqptr); return; } #endif /* __x86_64 */ if (strsame (pinptr, ADMIN_REPORT_AUTH_USER, -1)) { AuthCacheReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_CACHE, -1)) { CacheReport (rqptr, false); return; } if (strsame (pinptr, ADMIN_REPORT_CACHE_ENTRIES, -1)) { if (Md5HashHexString[0]) CacheReportEntry (rqptr, Md5HashHexString); else CacheReport (rqptr, true); return; } if (strsame (pinptr, ADMIN_REPORT_CLUSTER, -1)) { WatchShowCluster (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_ACCEPT, -1) || strsame (pinptr, ADMIN_REVISE_ACCEPT, -1) || strsame (pinptr, ADMIN_REPORT_REJECT, -1) || strsame (pinptr, ADMIN_REVISE_REJECT, -1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else NetRejectReportAdmin (rqptr, DoThis); else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_CONFIG, -1) || strsame (pinptr, ADMIN_REVISE_CONFIG, -1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) { if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else if (strsame (pinptr, ADMIN_REPORT_CONFIG, -1)) ConfigReport (rqptr, UseServerConfig); else ConfigRevise (rqptr, UseServerConfig); } else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_DCL, -1)) { DclScriptingReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_HOSTCACHE, -1)) { TcpIpHostCacheReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROCESS, -1)) { WatchShowProcess (rqptr, ProcessIdString, ProcessIdUserName); return; } if (strsame (pinptr, ADMIN_REPORT_DECNET, -1)) { DECnetScriptingReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_HTTP, -1)) { Http2Report (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_HPACK, -1)) { HpackReport (rqptr, Http2Connection); return; } if (strsame (pinptr, ADMIN_REPORT_LOCK, -1)) { InstanceLockReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROCESS_OUTPUT_NOTICED, -1)) { AdminServerOutputNoticed (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROCESS_INPUT, -1)) { AdminServerInput (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROCESS_OUTPUT_RAW, -1)) { AdminServerOutputRaw (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROCESS_OUTPUT_DELTA, -1)) { AdminServerOutputFilter (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROCESS_OUTPUT_LIST, sizeof(ADMIN_REPORT_PROCESS_OUTPUT_LIST)-1)) { AdminServerOutputList (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_WASTEE, -1)) { AdminReportWAStee (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_MEMORY, -1) || strsame (pinptr, ADMIN_REPORT_MEMORY_PLUS, -1)) { VmReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_MESSAGES, -1) || strsame (pinptr, ADMIN_REVISE_MESSAGES, -1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) { if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else if (strsame (pinptr, ADMIN_REPORT_MESSAGES, -1)) MsgConfigReport (rqptr, UseServerConfig); else MsgConfigRevise (rqptr, UseServerConfig); } else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_AUTH_PATHS, -1) || strsame (pinptr, ADMIN_REVISE_AUTH_PATHS, -1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else AuthConfigReport (rqptr, UseServerConfig, VirtualHostPort); else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_INLINE, -1) || strsame (pinptr, ADMIN_REVISE_INLINE, -1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) { if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else if (strsame (pinptr, ADMIN_REPORT_INLINE, -1)) InConfigReport (rqptr, UseServerConfig); else InConfigReport (rqptr, UseServerConfig); } else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_PROXY, -1)) { ProxyMaintReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_PROXY_TUNNEL, -1)) { ProxyTunnelReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_REQUEST, sizeof(ADMIN_REPORT_REQUEST)-1)) { RequestReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_SERVICES, -1) || strsame (pinptr, ADMIN_REVISE_SERVICES, -1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) { if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else if (strsame (pinptr, ADMIN_REPORT_SERVICES, -1)) ServiceReport (rqptr, UseServerConfig); else ServiceConfigRevise (rqptr, UseServerConfig); } else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_SERVICE_LOG, -1)) { LoggingReport (rqptr, VirtualHostPort); return; } if (strsame (pinptr, ADMIN_REPORT_SHOW_PROCESS, -1)) { WatchShowProcess (rqptr, ProcessIdString, ProcessIdUserName); return; } if (strsame (pinptr, ADMIN_REPORT_STATS, -1)) { AdminReportServerStats (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_MAPPING, -1) || strsame (pinptr, ADMIN_REVISE_MAPPING, -1)) { if (VMSnok (status = AdminParsePath (rqptr, NULL))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (rqptr->rqHeader.QueryStringLength) if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else MapUrl_Report (rqptr, UseServerConfig, VirtualHostPort); else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_SSL, -1) || strsame (pinptr, ADMIN_REPORT_SSL_CLIENT, -1)) { SesolaReport (rqptr, VirtualHostPort); return; } if (strsame (pinptr, ADMIN_REPORT_SSL_CA, -1) || strsame (pinptr, ADMIN_REVISE_SSL_CA, -1)) { if (VMSnok (status = AdminParsePath (rqptr, VirtualHostPort))) AdminEnd (rqptr); else if (rqptr->rqHeader.Method == HTTP_METHOD_POST) PutBegin (rqptr, &AdminEnd); else if (strsame (DoThis, "edit", -1)) UpdBegin (rqptr, &AdminEnd); else if (strsame (DoThis, "report", -1)) SesolaReportCA (rqptr, VirtualHostPort); else FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->ParseOds.ExpFileName, "text/plain"); return; } if (strsame (pinptr, ADMIN_REPORT_SUPERVISOR, -1)) { HttpdSupervisorReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_SYSTEM, -1)) { WatchShowSystem (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_SYSTEM_PLUS, -1)) { sysPlusReport (rqptr); return; } if (strsame (pinptr, ADMIN_REPORT_THROTTLE, -1)) { ThrottleReport (rqptr); return; } if (strsame (pinptr, ADMIN_CONTROL, sizeof(ADMIN_CONTROL)-1)) { /******************/ /* server control */ /******************/ AdminControl (rqptr, NULL, ClusterDo); return; } /********************/ /* unknown function */ /********************/ rqptr->rqResponse.HttpStatus = 400; ErrorGeneral (rqptr, "Unknown function.", FI_LI); AdminEnd (rqptr); } /*****************************************************************************/ /* Declare the next function AST for admin processing. */ void AdminEnd (REQUEST_STRUCT *rqptr) { /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminEnd()"); rqptr->AdminTaskPtr = NULL; RequestEnd (rqptr); } /*****************************************************************************/ /* Compare the path info to each administration path and parses the corresponding real file represented by that path into the request ODS parse structure so that modules that expect this to be filled out appropriately (e.g. UPD.C and PUT.C) can use it. Returns a VMS status. */ int AdminParsePath ( REQUEST_STRUCT *rqptr, char *VirtualHostPort ) { int status; char *cptr, *dnaptr, *sptr, *zptr; char FileSpec [ODS_MAX_FILE_NAME_LENGTH+1]; SERVICE_STRUCT *svptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminParsePath() !&Z !&Z", rqptr->rqHeader.PathInfoPtr, VirtualHostPort); dnaptr = NULL; cptr = rqptr->rqHeader.PathInfoPtr; if (strsame (cptr, ADMIN_REPORT_ACCEPT, -1) || strsame (cptr, ADMIN_REVISE_ACCEPT, -1)) sptr = CONFIG_ACCEPT_FILE_NAME; else if (strsame (cptr, ADMIN_REPORT_CONFIG, -1) || strsame (cptr, ADMIN_REVISE_CONFIG, -1)) sptr = CONFIG_GLOBAL_FILE_NAME; else if (strsame (cptr, ADMIN_REPORT_INLINE, -1) || strsame (cptr, ADMIN_REVISE_INLINE, -1)) sptr = CONFIG_INLINE_FILE_NAME; else if (strsame (cptr, ADMIN_REPORT_MESSAGES, -1) || strsame (cptr, ADMIN_REVISE_MESSAGES, -1)) sptr = CONFIG_MSG_FILE_NAME; else if (strsame (cptr, ADMIN_REPORT_AUTH_PATHS, -1) || strsame (cptr, ADMIN_REVISE_AUTH_PATHS, -1)) sptr = CONFIG_AUTH_FILE_NAME; else if (strsame (cptr, ADMIN_REPORT_MAPPING, -1) || strsame (cptr, ADMIN_REVISE_MAPPING, -1)) sptr = CONFIG_MAP_FILE_NAME; else if (strsame (cptr, ADMIN_REPORT_REJECT, -1) || strsame (cptr, ADMIN_REVISE_REJECT, -1)) sptr = CONFIG_REJECT_FILE_NAME; else if (strsame (cptr, ADMIN_REPORT_SERVICES, -1) || strsame (cptr, ADMIN_REVISE_SERVICES, -1)) sptr = CONFIG_SERVICE_FILE_NAME; else if (strsame (cptr, ADMIN_REVISE_SITELOG, -1) || strsame (cptr, ADMIN_REVISE_SITELOG_ENTRY, -1)) { if (!(sptr = CONFIG_SITELOG_FILE_NAME)) sptr = DEFAULT_SITELOG_FILE_NAME; } else if (strsame (cptr, ADMIN_REPORT_SSL_CA, -1) || strsame (cptr, ADMIN_REVISE_SSL_CA, -1)) { if (VirtualHostPort[0]) { LIST_ITERATE (svptr, &ServiceList) { if (svptr->SchemeType != SCHEME_HTTPS) continue; if (strsame (svptr->ServerHostPort, VirtualHostPort, -1)) break; } if (svptr) sptr = ((SESOLA_CONTEXT*)svptr->SSLserverPtr)->CaFilePtr; else sptr = CONFIG_SSL_CAFILE; } else sptr = CONFIG_SSL_CAFILE; } else if (strsame (cptr, ADMIN_REVISE_HTA, sizeof(ADMIN_REVISE_HTA)-1)) { /* server admin of HTA database(s) */ zptr = (sptr = FileSpec) + sizeof(FileSpec)-1; if (rqptr->ConfigDirectoryLength) cptr = rqptr->ConfigDirectory; else cptr = AuthConfigHtaDirectory; while (*cptr && sptr < zptr) *sptr++ = *cptr++; cptr = rqptr->rqHeader.PathInfoPtr + sizeof(ADMIN_REVISE_HTA)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; sptr = FileSpec; dnaptr = HTA_FILE_TYPE; } else if (strsame (cptr, ADMIN_VS_REVISE_HTA, sizeof(ADMIN_VS_REVISE_HTA)-1)) { /* per-service admin of HTA database(s) */ if (!rqptr->ConfigDirectoryLength) { rqptr->rqResponse.HttpStatus = 403; ErrorGeneral (rqptr, "Service not configured to allow this.", FI_LI); return (STS$K_ERROR); } zptr = (sptr = FileSpec) + sizeof(FileSpec)-1; for (cptr = rqptr->ConfigDirectory; *cptr && sptr < zptr; *sptr++ = *cptr++); cptr = rqptr->rqHeader.PathInfoPtr + sizeof(ADMIN_VS_REVISE_HTA)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; sptr = FileSpec; dnaptr = HTA_FILE_TYPE; } else if (strsame (cptr, ADMIN_REVISE_HTL, sizeof(ADMIN_REVISE_HTL)-1)) { /* server admin of HTL list(s) */ zptr = (sptr = FileSpec) + sizeof(FileSpec)-1; if (rqptr->ConfigDirectoryLength) cptr = rqptr->ConfigDirectory; else cptr = AuthConfigHtaDirectory; while (*cptr && sptr < zptr) *sptr++ = *cptr++; cptr = rqptr->rqHeader.PathInfoPtr + sizeof(ADMIN_REVISE_HTL)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; sptr = FileSpec; dnaptr = HTL_FILE_TYPE; } else if (strsame (cptr, ADMIN_VS_REVISE_HTL, sizeof(ADMIN_VS_REVISE_HTL)-1)) { /* per-service admin of HTL list(s) */ if (!rqptr->ConfigDirectoryLength) { rqptr->rqResponse.HttpStatus = 403; ErrorGeneral (rqptr, "Service not configured to allow this.", FI_LI); return (STS$K_ERROR); } zptr = (sptr = FileSpec) + sizeof(FileSpec)-1; for (cptr = rqptr->ConfigDirectory; *cptr && sptr < zptr; *sptr++ = *cptr++); cptr = rqptr->rqHeader.PathInfoPtr + sizeof(ADMIN_VS_REVISE_HTL)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; sptr = FileSpec; dnaptr = HTL_FILE_TYPE; } else return (SS$_NORMAL); OdsStructInit (&rqptr->ParseOds, true); status = OdsParse (&rqptr->ParseOds, sptr, strlen(sptr), dnaptr, dnaptr ? strlen(dnaptr) : 0, NAM$M_SYNCHK, NULL, rqptr); if (VMSok(status)) status = rqptr->ParseOds.Fab.fab$l_sts; if (VMSok(status)) status = OdsParseTerminate (&rqptr->ParseOds); if (VMSok(status)) { if (WATCHING (rqptr, WATCH_RESPONSE)) WatchThis (WATCHITM(rqptr), WATCH_RESPONSE, "FILE !AZ !AZ", sptr, rqptr->ParseOds.ExpFileName); return (status); } rqptr->rqResponse.ErrorTextPtr = cptr; rqptr->rqResponse.ErrorOtherTextPtr = sptr; ErrorVmsStatus (rqptr, status, FI_LI); return (status); } /*****************************************************************************/ /* Execute server administration menu control actions. */ void AdminControl ( REQUEST_STRUCT *rqptr, char *DoThis, BOOL ClusterDo ) { int cnt, status, LockIndex; char *cptr, *sptr, *zptr; char String [256]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminControl() !BZ !&B !&Z", DoThis, ClusterDo, rqptr->rqHeader.PathInfoPtr); cptr = rqptr->rqHeader.PathInfoPtr; sptr = NULL; if (DoThis) sptr = DoThis; else if (strsame (cptr, ADMIN_CONTROL_AUTH_LOAD, -1)) sptr = CONTROL_AUTH_LOAD1; else if (strsame (cptr, ADMIN_CONTROL_AUTH_PURGE, -1)) sptr = CONTROL_AUTH_PURGE; else if (strsame (cptr, ADMIN_VS_CONTROL_AUTH_PURGE, -1)) sptr = CONTROL_AUTH_PURGE; else if (strsame (cptr, ADMIN_CONTROL_CACHE_ON, -1)) sptr = CONTROL_CACHE_ON; else if (strsame (cptr, ADMIN_CONTROL_CACHE_OFF, -1)) sptr = CONTROL_CACHE_OFF; else if (strsame (cptr, ADMIN_CONTROL_CACHE_PURGE, -1)) sptr = CONTROL_CACHE_PURGE; else if (strsame (cptr, ADMIN_CONTROL_DCL_PURGE, -1)) sptr = CONTROL_DCL_PURGE; else if (strsame (cptr, ADMIN_CONTROL_DCL_DELETE, -1)) sptr = CONTROL_DCL_DELETE; else if (strsame (cptr, ADMIN_CONTROL_EXIT, -1)) sptr = CONTROL_EXIT; else if (strsame (cptr, ADMIN_CONTROL_EXIT_NOW, -1)) sptr = CONTROL_EXIT_NOW; else if (strsame (cptr, ADMIN_CONTROL_HTTP2_PURGE, -1)) sptr = CONTROL_HTTP2_PURGE; else if (strsame (cptr, ADMIN_CONTROL_HTTP2_PURGE_ALL, -1)) sptr = CONTROL_HTTP2_PURGE_ALL; else if (strsame (cptr, ADMIN_CONTROL_INSTANCE_ACTIVE, -1)) sptr = CONTROL_INSTANCE_ACTIVE; else if (strsame (cptr, ADMIN_CONTROL_INSTANCE_PASSIVE, -1)) sptr = CONTROL_INSTANCE_PASSIVE; else if (strsame (cptr, ADMIN_CONTROL_INSTANCE, sizeof(ADMIN_CONTROL_INSTANCE)-1)) { sptr = cptr; while (*cptr) cptr++; while (cptr > sptr && *cptr != '/') cptr--; if (*cptr == '/') { cptr++; FaoToBuffer (String, sizeof(String), NULL, "!AZ!AZ", CONTROL_INSTANCE, cptr); sptr = String; } } else if (strsame (cptr, ADMIN_CONTROL_LOG_OPEN, -1)) sptr = CONTROL_LOG_OPEN; else if (strsame (cptr, ADMIN_CONTROL_LOG_CLOSE, -1)) sptr = CONTROL_LOG_CLOSE; else if (strsame (cptr, ADMIN_CONTROL_LOG_FLUSH, -1)) sptr = CONTROL_LOG_FLUSH; else if (strsame (cptr, ADMIN_CONTROL_MAP, -1)) sptr = CONTROL_MAP_LOAD1; else if (strsame (cptr, ADMIN_CONTROL_NET_ACCEPT_REJECT, -1)) sptr = CONTROL_ACCEPT_REJECT; else if (strsame (cptr, ADMIN_CONTROL_NET_PURGE, -1)) sptr = CONTROL_NET_PURGE; else if (strsame (cptr, ADMIN_CONTROL_NET_PURGE_ALL, -1)) sptr = CONTROL_NET_PURGE_ALL; else if (strsame (cptr, ADMIN_CONTROL_NET_PURGE_HTTP1, -1)) sptr = CONTROL_NET_PURGE_HTTP1; else if (strsame (cptr, ADMIN_CONTROL_NET_PURGE_HTTP2, -1)) sptr = CONTROL_NET_PURGE_HTTP2; else if (strsame (cptr, ADMIN_CONTROL_NET_PURGE_REJECT, -1)) sptr = CONTROL_REJECT_PURGE; else if (strsame (cptr, ADMIN_CONTROL_RESTART, -1)) sptr = CONTROL_RESTART; else if (strsame (cptr, ADMIN_CONTROL_RESTART_NOW, -1)) sptr = CONTROL_RESTART_NOW; else if (strsame (cptr, ADMIN_CONTROL_RESTART_QUIET, -1)) sptr = CONTROL_RESTART_QUIET; else if (strsame (cptr, ADMIN_CONTROL_SSL_CA_LOAD, -1)) sptr = CONTROL_SSL_CA_LOAD; else if (strsame (cptr, ADMIN_CONTROL_THROTTLE_RELEASE, -1)) sptr = CONTROL_THROTTLE_RELEASE; else if (strsame (cptr, ADMIN_CONTROL_THROTTLE_TERMINATE, -1)) sptr = CONTROL_THROTTLE_TERMINATE; else if (strsame (cptr, ADMIN_CONTROL_WEBSOCKET_DISCONNECT, -1)) sptr = CONTROL_WEBSOCKET_DISCONNECT; else if (strsame (cptr, ADMIN_CONTROL_THROTTLE_ZERO, -1)) sptr = CONTROL_THROTTLE_ZERO; else if (strsame (cptr, ADMIN_CONTROL_WATCH_END, -1)) sptr = CONTROL_WATCH_END; else if (strsame (cptr, ADMIN_CONTROL_ZERO_NOTICED, -1)) sptr = CONTROL_ZERO_NOTICED; else if (strsame (cptr, ADMIN_CONTROL_ZERO, -1)) sptr = CONTROL_ZERO; if (!sptr) { /* unknown function */ rqptr->rqResponse.HttpStatus = 400; ErrorGeneral (rqptr, "Unknown control function.", FI_LI); AdminEnd (rqptr); return; } if (ClusterDo) LockIndex = INSTANCE_CLUSTER_DO; else LockIndex = INSTANCE_NODE_DO; cptr = ControlEnqueueCommand (LockIndex, sptr); strzcat (cptr, ".", ControlStringSize); if (*cptr == '!') { rqptr->rqResponse.HttpStatus = 403; cptr[1] = to_upper(cptr[1]); ErrorGeneral (rqptr, cptr+1, FI_LI); } else { cptr[0] = to_upper(cptr[0]); ReportSuccess (rqptr, "Command !AZ", cptr); } AdminEnd (rqptr); } /*****************************************************************************/ /* Provide a menu of HTTPd server administration functions. */ void AdminMenu (REQUEST_STRUCT *rqptr) { static int ActHours [] = { 0,1,2,4,8,16,24,72,168,336,504,672,0 }; static char BeginPageFao [] = "!AZ\ \n\ \n\ !AZ\ !AZ\ !&@\ WASD !AZ ... Server Administration\n\ \ \n\ \ \n\ \ \n\ \n\

WASD !AZ

\n\

Server Administration!&@

\n\

\n\ \

\n\ \ \n\ \ \n\ \ \n\ \n\ \ \n\ \n\ \n"; static char EndPageFao [] = "
Configuration
\n\ \ \n\ \ \ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ !&@\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \
|Report|Revise|Action|
ServerStatistics!&@Site-LogEditZero
GlobalServerFileServerFileEdit
ServicesServerFileServerFileEditPurgeAll
MessagesServerFileServerFileEdit
Path MappingServerFileEdit\ Reload
Path AuthorizationServerFileEdit\ Reload
User AuthenticationServerHTA\ HTL\ Purge
Access ControlAcceptRejectAcceptRejectReloadPurge
Secure Sockets!&@!&@!&@!&@
Other Reports\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\
\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\
\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\ !&@\n\
\n\ !&@!&@!&@!&@!&@!&@!&@!&@!&@!&@!&@ \ hours activity\n\
\n\ \
Control\n\ \n\ \ \n\ \n\ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ \n\ \ !&@\ !&@\ !AZ\ !&@\ !AZ\ !AZ\ \
\ !20&W
!AZ (!AZ)
!&@
Time!AZ::!%D
!AZ:!%D
Image:!%D
CPU:!UL !2ZL:!2ZL:!2ZL.!2ZL
ConnectCurrent:!&L
Peak:!&L
Total:!&L
RequestCurrent:!&L
Peak:!&L
Total:!&L
Bytes:!&,@UQ
\n\ \
\n\ \ \n\ \n\ \n\
\n\ \ \n\ \n\ \n\ \n\ \n\ \n\
\ RESTART\
\ \ RESTARTNOW\ \
\ \ RESTARTQuiet\ \
\ EXIT\
\ \ EXITNOW\ \
\n\ \
\n\ \ \n\ \n\ \n\ \n\ \n\
Log!&@
Cache!&@
Instance\ !&@\ !&@"; static char EndInstanceFao [] = "
!&@
\n\ \
\ \ \
\n\
\n\ \
\n\ \ \n\ !AZ\ \ \n\ \n\ \n\ \n"; static unsigned long LibDeltaHours = LIB$K_DELTA_HOURS; static unsigned short SyiClusterNodes; static unsigned long JpiCpuTime, Pid = 0; static int64 ActivityUpTime64, Time64, ImageUpTime64, JpiLoginTime64, ProcessUpTime64, SystemUpTime64; static VMS_ITEM_LIST3 JpiItems [] = { { sizeof(JpiCpuTime), JPI$_CPUTIM, &JpiCpuTime, 0 }, { sizeof(JpiLoginTime64), JPI$_LOGINTIM, &JpiLoginTime64, 0 }, {0,0,0,0} }; static VMS_ITEM_LIST3 SyiItem [] = { { sizeof(SyiClusterNodes), SYI$_CLUSTER_NODES, &SyiClusterNodes, 0 }, { 0,0,0,0 } }; int cnt, idx, status, total, ClusterInstanceCount, InstanceStartupMax, NodeInstanceCount; int64 BytesTotal64; unsigned short Length; unsigned long ActivityDeltaHours; unsigned long *vecptr; unsigned long FaoVector [192]; char *accptr, *cptr, *rejptr, *ClusterInstancePtr, *NodeInstancePtr; IO_SB IOsb; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminMenu()"); if (HTTP2_REQUEST(rqptr)) Http2Ping (rqptr->Http2Ptr, 0, 0, NULL, 0); status = sys$getjpiw (EfnWait, &Pid, 0, &JpiItems, &IOsb, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) { rqptr->rqResponse.ErrorTextPtr = "sys$getjpiw()"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } status = sys$getsyiw (EfnWait, 0, 0, &SyiItem, &IOsb, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) { rqptr->rqResponse.ErrorTextPtr = "sys$getsyiw()"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } #ifdef WATCH_MOD if (!SyiClusterNodes) if (cptr = SysTrnLnm (WASD_CLUSTER_NODES)) SyiClusterNodes = atoi(cptr); #endif sys$gettim (&Time64); SystemUpTime64 = SysInfo.BootTime64 - Time64; ImageUpTime64 = HttpdStartTime64 - Time64; ProcessUpTime64 = JpiLoginTime64 - Time64; if (ActivityTotalMinutes) { InstanceMutexLock (INSTANCE_MUTEX_HTTPD); ActivityUpTime64 = ActivityGblSecPtr->StartTime64 - Time64; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); ActivityDeltaHours = -ActivityUpTime64 / TIME64_ONE_HOUR; if (!ActivityDeltaHours) ActivityDeltaHours = 1; } else ActivityDeltaHours = 1; /* get the number (if any) of other HTTP servers on this node/cluster */ NodeInstanceCount = InstanceLockList (INSTANCE_NODE_SUPERVISOR, "\n", &NodeInstancePtr); ClusterInstanceCount = InstanceLockList (INSTANCE_CLUSTER, "\n", &ClusterInstancePtr); vecptr = FaoVector; *vecptr++ = WASD_DOCTYPE; *vecptr++ = HtmlMetaInfo (rqptr, NULL); *vecptr++ = AdminWasdCss (); if (rqptr->rqPathSet.StyleSheetPtr) { *vecptr++ = "\n"; *vecptr++ = rqptr->rqPathSet.StyleSheetPtr; } else *vecptr++ = ""; *vecptr++ = ServerHostPort; *vecptr++ = GenerateCspNonce (rqptr); if (SyiClusterNodes > 1 && ClusterInstanceCount > NodeInstanceCount) { *vecptr++ = " scope = 'node instance!&?s\r\r';\n\ if (document.doallForm.scope[1].checked) {\n\ if (link.href.indexOf('?') >= 0) \ link.href = link.href.substring(0,link.href.indexOf('?'));\n\ link.href = link.href + '?scope=cluster';\n\ scope = 'cluster instances';\n\ }\n"; *vecptr++ = (NodeInstanceCount > 1); } else { *vecptr++ = " scope = 'node instance!&?s\r\r';\n"; *vecptr++ = (NodeInstanceCount > 1); } *vecptr++ = INSTANCE_MAX; *vecptr++ = AdminPing (NULL); *vecptr++ = ADMIN_BODY_TAG + 5; *vecptr++ = ServerHostPort; if (InstanceNodeCurrent > 1) { if (rqptr->ServicePtr->AdminService) *vecptr++ = "  -  !AZ"; else *vecptr++ = "    (!AZ)"; *vecptr++ = HttpdProcess.PrcNam; } else *vecptr++ = ""; /* statistics */ *vecptr++ = ADMIN_REPORT_STATS; if (HttpdProcess.SysOutputFile) { *vecptr++ = "\ Log\ \ ϟ\ ⁞⁞\ "; *vecptr++ = ADMIN_REPORT_PROCESS_OUTPUT_RAW; *vecptr++ = ADMIN_REPORT_PROCESS_OUTPUT_DELTA; *vecptr++ = ADMIN_REPORT_PROCESS_OUTPUT_NOTICED; *vecptr++ = rqptr->rqAuth.VmsUserProfileLength ? "href=" : ""; *vecptr++ = ADMIN_REPORT_PROCESS_OUTPUT_LIST; } else *vecptr++ = "Log"; *vecptr++ = ADMIN_REVISE_SITELOG_ENTRY; *vecptr++ = ADMIN_REVISE_SITELOG; *vecptr++ = ADMIN_CONTROL_ZERO; /* inline config */ if (SysTrnLnm (CONFIG_INLINE_FILE_NAME) || SysTrnLnm (CONFIG_INLINE_REPORT_FILE_NAME)) { *vecptr++ = "\n\ Inline\n\ \n\ Server\n\ File\n\ \n\ \n\ \n\ Edit\n\ \n\ \n"; *vecptr++ = InConfigFileName[0] ? "" : " dbttn"; *vecptr++ = InConfigFileName[0] ? "href=" : ""; *vecptr++ = ADMIN_REPORT_INLINE; if (SysTrnLnm (CONFIG_INLINE_REPORT_FILE_NAME)) { *vecptr++ = ""; *vecptr++ = "href="; } else { *vecptr++ = InConfigFileName[0] ? "" : " dbttn"; *vecptr++ = InConfigFileName[0] ? "href=" : ""; } *vecptr++ = ADMIN_REPORT_INLINE; *vecptr++ = InConfigFileName[0] ? "" : " dbttn"; *vecptr++ = InConfigFileName[0] ? "href=" : ""; *vecptr++ = ADMIN_REVISE_INLINE; } else *vecptr++ = ""; /* global */ *vecptr++ = ADMIN_REPORT_CONFIG; *vecptr++ = ADMIN_REPORT_CONFIG; *vecptr++ = ADMIN_REVISE_CONFIG; *vecptr++ = ADMIN_REVISE_CONFIG; *vecptr++ = ADMIN_REVISE_CONFIG; /* services */ *vecptr++ = ADMIN_REPORT_SERVICES; *vecptr++ = ADMIN_REPORT_SERVICES; *vecptr++ = ADMIN_REVISE_SERVICES; *vecptr++ = ADMIN_REVISE_SERVICES; *vecptr++ = ADMIN_REVISE_SERVICES; *vecptr++ = ADMIN_CONTROL_NET_PURGE; *vecptr++ = ADMIN_CONTROL_NET_PURGE_ALL; /* messages */ *vecptr++ = ADMIN_REPORT_MESSAGES; *vecptr++ = ADMIN_REPORT_MESSAGES; *vecptr++ = ADMIN_REVISE_MESSAGES; *vecptr++ = ADMIN_REVISE_MESSAGES; *vecptr++ = ADMIN_REVISE_MESSAGES; /* mapping */ *vecptr++ = ADMIN_REPORT_MAPPING; *vecptr++ = ADMIN_REPORT_MAPPING; *vecptr++ = ADMIN_REVISE_MAPPING; *vecptr++ = ADMIN_CONTROL_MAP; /* authorization */ *vecptr++ = ADMIN_REPORT_AUTH_PATHS; *vecptr++ = ADMIN_REPORT_AUTH_PATHS; *vecptr++ = ADMIN_REVISE_AUTH_PATHS; *vecptr++ = ADMIN_CONTROL_AUTH_LOAD; /* authentication */ *vecptr++ = ADMIN_REPORT_AUTH_USER; *vecptr++ = ADMIN_REVISE_HTA; *vecptr++ = ADMIN_REVISE_HTL; *vecptr++ = ADMIN_CONTROL_AUTH_PURGE; /* accept / reject */ *vecptr++ = NetAcceptEnabled ? "\" href=" : " dbttn\" h_ref="; *vecptr++ = ADMIN_REPORT_ACCEPT; *vecptr++ = NetRejectEnabled ? "\" href=" : " dbttn\" h_ref="; *vecptr++ = ADMIN_REPORT_REJECT; *vecptr++ = NetAcceptEnabled ? "\" href=" : " dbttn\" h_ref="; *vecptr++ = ADMIN_REVISE_ACCEPT; *vecptr++ = NetRejectEnabled ? "\" href=" : " dbttn\" h_ref="; *vecptr++ = ADMIN_REVISE_REJECT; *vecptr++ = (NetAcceptEnabled || NetRejectEnabled) ? "\" href=" : " dbttn\" h_ref="; *vecptr++ = ADMIN_CONTROL_NET_ACCEPT_REJECT; *vecptr++ = (NetAcceptEnabled || NetRejectEnabled) ? "\" href=" : " dbttn\" h_ref="; *vecptr++ = ADMIN_CONTROL_NET_PURGE_REJECT; /* secure socket layer */ if (ProtocolHttpsConfigured) { *vecptr++ = "Service"; *vecptr++ = ADMIN_REPORT_SSL; if (SesolaVerifyCAConfigured) { *vecptr++ = "CA"; *vecptr++ = ADMIN_REPORT_SSL_CA; *vecptr++ = rqptr->ServicePtr->ServerHostPort; *vecptr++ = "Edit-CA"; *vecptr++ = ADMIN_REVISE_SSL_CA; *vecptr++ = "Load-CA"; *vecptr++ = ADMIN_CONTROL_SSL_CA_LOAD; } else { *vecptr++ = "CA"; *vecptr++ = "Edit-CA"; *vecptr++ = "Load-CA"; } } else { *vecptr++ = "Service"; *vecptr++ = "CA"; *vecptr++ = "Edit-CA"; *vecptr++ = "Load-CA"; } /* other */ #ifdef ALIGN_FAULT if (HttpdAlignFaultReport) { *vecptr++ = "AlnFlt"; *vecptr++ = ADMIN_REPORT_ALIGN; } else #endif /* ALIGN_FAULT */ *vecptr++ = "AlnFlt"; *vecptr++ = "Cache"; *vecptr++ = ADMIN_REPORT_CACHE; if (SyiClusterNodes > 1) { *vecptr++ = "Cluster"; *vecptr++ = ADMIN_REPORT_CLUSTER; } else *vecptr++ = "Cluster"; *vecptr++ = "DCL"; *vecptr++ = ADMIN_REPORT_DCL; *vecptr++ = "DECnet"; *vecptr++ = ADMIN_REPORT_DECNET; if (TcpIpHostCachePtr) { *vecptr++ = "Host"; *vecptr++ = ADMIN_REPORT_HOSTCACHE; } else *vecptr++ = "Host"; *vecptr++ = "HTTP"; *vecptr++ = ADMIN_REPORT_HTTP; *vecptr++ = "Lock"; *vecptr++ = ADMIN_REPORT_LOCK; *vecptr++ = "Match"; *vecptr++ = ADMIN_REPORT_MATCH; *vecptr++ = "\ Memory\ +"; *vecptr++ = ADMIN_REPORT_MEMORY; *vecptr++ = ADMIN_REPORT_MEMORY_PLUS; *vecptr++ = "Process"; *vecptr++ = ADMIN_REPORT_PROCESS; if (ProxyServiceCount()) { *vecptr++ = "Proxy"; *vecptr++ = ADMIN_REPORT_PROXY; } else *vecptr++ = "Proxy"; *vecptr++ = "\ Request\ +"; *vecptr++ = ADMIN_REPORT_REQUEST; *vecptr++ = ADMIN_REPORT_REQUEST_PLUS; *vecptr++ = "\ System\ +"; *vecptr++ = ADMIN_REPORT_SYSTEM; *vecptr++ = ADMIN_REPORT_SYSTEM_PLUS; if (MappingMetaPtr->ThrottleTotal) { *vecptr++ = "Throttle"; *vecptr++ = ADMIN_REPORT_THROTTLE; } else *vecptr++ = "Throttle"; if (WATCH_CAT || !Watch.Disabled) { *vecptr++ = "WATCH"; *vecptr++ = ADMIN_REPORT_WATCH; } else *vecptr++ = "WATCH"; if (WebDavEnabled) { *vecptr++ = "WebDAV"; *vecptr++ = ADMIN_REPORT_WEBDAV; } else *vecptr++ = "WebDAV"; *vecptr++ = "WebSocket"; *vecptr++ = ADMIN_REPORT_WEBSOCKET; for (idx = 1; ActHours[idx]; idx++) { if (ActivityDeltaHours >= ActHours[idx]) { *vecptr++ = "!-!UL"; *vecptr++ = ADMIN_REPORT_ACTIVITY; *vecptr++ = ActHours[idx]; } else if (ActivityDeltaHours > ActHours[idx-1] && ActivityDeltaHours < ActHours[idx]) { *vecptr++ = "!-!UL"; *vecptr++ = ADMIN_REPORT_ACTIVITY; *vecptr++ = ActivityDeltaHours; } else { *vecptr++ = "!UL"; *vecptr++ = ActHours[idx]; } } *vecptr++ = &rqptr->rqTime.BeginTime64; *vecptr++ = rqptr->rqTime.GmDateTime; *vecptr++ = TimeGmtString; /* client using the Server Admin */ if (MATCH8 (&rqptr->ClientPtr->IpAddressString, rqptr->ClientPtr->Lookup.HostName)) { /* client IP address DNS lookup is disabled */ cptr = AdminLookYouUp (&rqptr->ClientPtr->IpAddress); if (cptr && *cptr) { *vecptr++ = "!AZ (!AZ) !&@"; *vecptr++ = cptr; } else *vecptr++ = "!AZ !&@"; } else { *vecptr++ = "!AZ (!AZ) !&@"; *vecptr++ = rqptr->ClientPtr->Lookup.HostName; } *vecptr++ = &rqptr->ClientPtr->IpAddressString; if (HTTP2_REQUEST(rqptr)) *vecptr++ = "HTTP/2"; else if (rqptr->rqResponse.HttpVersion == HTTP_VERSION_1_1) *vecptr++ = "HTTP/1.1"; else *vecptr++ = "HTTP/1.0"; /* informational accounting */ *vecptr++ = SysInfo.NodeName; *vecptr++ = &SystemUpTime64; if (NodeInstanceCount > 1) *vecptr++ = HttpdProcess.PrcNam; else *vecptr++ = "Process"; *vecptr++ = &ProcessUpTime64; *vecptr++ = &ImageUpTime64; *vecptr++ = JpiCpuTime / 8640000; /* CPU day */ *vecptr++ = (JpiCpuTime % 8640000) / 360000; /* CPU hour */ *vecptr++ = (JpiCpuTime % 360000) / 6000; /* CPU minute */ *vecptr++ = (JpiCpuTime % 6000 ) / 100; /* CPU second */ *vecptr++ = JpiCpuTime % 100; /* CPU 10 milliseconds */ *vecptr++ = acptr->CurrentConnected[HTTP12]; *vecptr++ = acptr->ConnectPeak[HTTP12]; *vecptr++ = acptr->ConnectCount[HTTP12]; *vecptr++ = acptr->CurrentProcessing[HTTP12]; *vecptr++ = acptr->ProcessingPeak[HTTP12]; *vecptr++ = acptr->ProcessingTotalCount[HTTP12]; BytesTotal64 = acptr->BytesRawRx64[HTTP12] + acptr->BytesRawTx64[HTTP12]; *vecptr++ = &BytesTotal64; if (HttpdGblSecPtr->AuthSkelKeyHttpdTickSecond) { *vecptr++ = "SKELKEY" "!AZ!&@ (!AZ)\n"; *vecptr++ = HttpdGblSecPtr->AuthSkelKeyUserName; if (HttpdGblSecPtr->AuthSkelKeyVmsName[0]) { *vecptr++ = "=!AZ"; *vecptr++ = HttpdGblSecPtr->AuthSkelKeyVmsName; } else *vecptr++ = ""; *vecptr++ = WatchToGo (HttpdGblSecPtr->AuthSkelKeyHttpdTickSecond - HttpdTickSecond); } else *vecptr++ = ""; if (Watch.SecondsToGo) { *vecptr++ = "WATCH" "!AZ (!UL bytes)\n"; *vecptr++ = WatchToGo(Watch.SecondsToGo); *vecptr++ = Watch.ByteCount; } else *vecptr++ = ""; if (WatchQuotasAlert[0] || LoggingFileError) *vecptr++ = ""; else *vecptr++ = ""; if (WatchQuotasAlert[0]) { *vecptr++ = "
!AZ
"; *vecptr++ = WatchQuotasAlert; } else *vecptr++ = ""; if (LoggingFileError) *vecptr++ = "
Problem writing access logs!
"; else *vecptr++ = ""; if (WatchQuotasAlert[0] || LoggingFileError) *vecptr++ = "\n"; else *vecptr++ = ""; /* server control menu items */ *vecptr++ = ADMIN_CONTROL_RESTART; *vecptr++ = ADMIN_CONTROL_RESTART_NOW; *vecptr++ = ADMIN_CONTROL_RESTART_QUIET; *vecptr++ = ADMIN_CONTROL_EXIT; *vecptr++ = ADMIN_CONTROL_EXIT_NOW; /* logging control menu items */ if (LoggingEnabled) { *vecptr++ = "On\ Off\ Flush"; *vecptr++ = ADMIN_CONTROL_LOG_CLOSE; *vecptr++ = ADMIN_CONTROL_LOG_FLUSH; } else { *vecptr++ = "On\ Off\ Flush"; *vecptr++ = ADMIN_CONTROL_LOG_OPEN; } /* cache control menu items */ if (CacheEnabled) { *vecptr++ = "On\ Off\ Purge"; *vecptr++ = ADMIN_CONTROL_CACHE_OFF; *vecptr++ = ADMIN_CONTROL_CACHE_PURGE; } else { *vecptr++ = "On\ Off\ Flush"; *vecptr++ = ADMIN_CONTROL_CACHE_ON; } InstanceMutexLock (INSTANCE_MUTEX_HTTPD); InstanceStartupMax = HttpdGblSecPtr->InstanceStartupMax; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); if (!InstanceStartupMax) { *vecptr++ = "Max"; *vecptr++ = ADMIN_CONTROL_INSTANCE; } else *vecptr++ = "Max"; if (InstanceStartupMax != INSTANCE_PER_CPU) { *vecptr++ = "CPU"; *vecptr++ = ADMIN_CONTROL_INSTANCE; } else *vecptr++ = "CPU"; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, BeginPageFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); for (cnt = 1; cnt <= INSTANCE_MAX; cnt++) { vecptr = FaoVector; if (cnt == InstanceStartupMax) { *vecptr++ = cnt; status = FaolToNet (rqptr, "!UL", &FaoVector); } else { *vecptr++ = cnt; *vecptr++ = ADMIN_CONTROL_INSTANCE; *vecptr++ = cnt; status = FaolToNet (rqptr, "!-!UL", &FaoVector); } if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); if (cnt == 2) FaolToNet (rqptr, "
\n", NULL); } vecptr = FaoVector; /* instance active/pass control menu items */ if (InstanceNodeCurrent == 1) { *vecptr++ = "Active\ Passive"; } else if (NetInstancePassive) { *vecptr++ = "Active\ Passive"; *vecptr++ = ADMIN_CONTROL_INSTANCE_ACTIVE; } else { *vecptr++ = "Active\ Passive"; *vecptr++ = ADMIN_CONTROL_INSTANCE_PASSIVE; } status = FaolToNet (rqptr, EndInstanceFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); InstanceStatusAdminReport (rqptr); vecptr = FaoVector; *vecptr++ = GenerateCspNonce (rqptr); *vecptr++ = AdminRefresh (rqptr); status = FaolToNet (rqptr, EndPageFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); if (NodeInstancePtr) VmFree (NodeInstancePtr, FI_LI); if (ClusterInstancePtr) VmFree (ClusterInstancePtr, FI_LI); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); AdminEnd (rqptr); } /*****************************************************************************/ /* Provide a menu of HTTPd per-service administration functions. */ void AdminVirtualServerMenu (REQUEST_STRUCT *rqptr) { char BeginPageFao [] = "!AZ\ \n\ \n\ !AZ\ WASD !AZ ... Virtual Server Administration\n\ \n\ !AZ\n\

WASD !AZ

\n\

Virtual Server Administration

\n\

\n\ \ \n\ \n\
\n\ \ \n\ \ \ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \
TimeLocal: !20&W
Universal:!AZ (!AZ)
System-Up:!%D
Authentication  HTA:[Access]
HTL:[Access]
Cache:[Purge]
\n\ \
\n\ \ \n\ \ \n\ \n\ \n"; static unsigned long LibDeltaHours = LIB$K_DELTA_HOURS; static unsigned long Pid = 0; static int64 Time64, JpiLoginTime64, SystemUpTime64; static VMS_ITEM_LIST3 JpiItems [] = { { sizeof(JpiLoginTime64), JPI$_LOGINTIM, &JpiLoginTime64, 0 }, {0,0,0,0} }; int status; unsigned short Length; unsigned long *vecptr; unsigned long FaoVector [32]; IO_SB IOsb; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminVirtualServerMenu()"); status = sys$getjpiw (EfnWait, &Pid, 0, &JpiItems, &IOsb, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) { rqptr->rqResponse.ErrorTextPtr = "sys$getjpiw()"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } sys$gettim (&Time64); SystemUpTime64 = SysInfo.BootTime64 - Time64; vecptr = FaoVector; *vecptr++ = WASD_DOCTYPE; *vecptr++ = HtmlMetaInfo (rqptr, NULL); *vecptr++ = ServerHostPort; *vecptr++ = ADMIN_BODY_TAG; *vecptr++ = ServerHostPort; *vecptr++ = &rqptr->rqTime.BeginTime64; *vecptr++ = rqptr->rqTime.GmDateTime; *vecptr++ = TimeGmtString; *vecptr++ = &SystemUpTime64; *vecptr++ = ADMIN_VS_REVISE_HTA; *vecptr++ = ADMIN_VS_REVISE_HTL; *vecptr++ = ADMIN_VS_CONTROL_AUTH_PURGE; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, BeginPageFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); AdminEnd (rqptr); } /*****************************************************************************/ /* The 'InstanceList' comprises a string containing instance process names in the format 'node::WASD:port' (e.g. DELTA::WASD:80") separated by newlines (the string is generated by InstanceLockList()). Parse this list using the process names to interogate locks taken out by each process to contain their per-instance administration IP address and port. Use this information to return a count of how many such ports are available. */ int AdminMenuInstanceCount ( REQUEST_STRUCT *rqptr, char *InstanceList ) { int status, AdminPortCount; char ch; char *cptr, *sptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminMenuInstanceCount() !&Z", InstanceList); AdminPortCount = 0; cptr = InstanceList; while (*cptr) { sptr = cptr; while (*cptr && *cptr != '\n') cptr++; ch = *cptr; if (*cptr) *cptr = '\0'; status = InstanceSocketForAdmin (sptr, NULL); if (VMSok (status)) AdminPortCount++; if (*cptr = ch) cptr++; } return (AdminPortCount); } /*****************************************************************************/ /* The 'InstanceList' comprises a string containing instance process names in the format 'node::WASD:port' (e.g. DELTA::WASD:80") separated by newlines (the string is generated by InstanceLockList()). Parse this list using the process names to interogate locks taken out by each process to contain their per-instance administration IP address and port. Use this information to generate links to each of the instances. */ void AdminMenuInstanceList ( REQUEST_STRUCT *rqptr, char *InstanceList ) { BOOL InsrancePassive; int status; unsigned short IpPort; unsigned long *vecptr; unsigned long FaoVector [16]; char ch; char *aptr, *cptr, *sptr, *zptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminMenuInstanceList() !&Z", InstanceList); cptr = InstanceList; while (*cptr) { sptr = cptr; while (*cptr && *cptr != '\n') cptr++; ch = *cptr; if (*cptr) *cptr = '\0'; vecptr = FaoVector; status = InstanceSocketForAdmin (sptr, &IpPort); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); aptr = ""; if (NetInstancePassive) { /* node::prcnam */ for (zptr = sptr; *zptr != ':'; zptr++); if (*zptr) { *zptr = '\0'; if (!strcmp (sptr, SysInfo.NodeName)) { if (InstanceNodeSupervisor && !strcmp (zptr+2, HttpdProcess.PrcNam)) aptr = "  active"; else aptr = "  passive"; } *zptr = ':'; } } if (IpPort) { *vecptr++ = "!AZ!AZ
\n"; *vecptr++ = rqptr->ServicePtr->RequestSchemeNamePtr; *vecptr++ = strchr(sptr,':') - sptr; *vecptr++ = sptr; *vecptr++ = IpPort; *vecptr++ = rqptr->rqHeader.PathInfoPtr; } else *vecptr++ = "!AZ!AZ
\n"; *vecptr++ = sptr; *vecptr++ = aptr; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, "!&@", &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); if (*cptr = ch) cptr++; } } /*****************************************************************************/ /* Return report on the HTTPd server's activities. */ void AdminReportServerStats (REQUEST_STRUCT *rqptr) { /* ALTPRI and SETPRI synonyms? */ #define IMAG_PRIV_0_ALLOWED \ (~(PRV$M_ALTPRI | PRV$M_CMKRNL | PRV$M_DETACH | PRV$M_OPER | \ PRV$M_PRMGBL | PRV$M_PRMMBX | PRV$M_SHMEM | PRV$M_SYSGBL | \ PRV$M_SYSNAM | PRV$M_SYSLCK | PRV$M_SYSPRV | PRV$M_PSWAPM | \ PRV$M_WORLD)) #define IMAG_PRIV_1_ALLOWED (~(0x40 /* PRV$M_SECURITY */)) static char BeginPageFao [] = "

\n\ \n\ \n\
Environment!AZ
\n\ \n\ \n\ \n\ \n\ !&@\ \n\ \ \n\ \n\ \n\
Version:!AZ
Build:!AZ
SSL:!AZ
TCP/IP:!AZ
System:!AZ with !UL CPU!%s and !AZ running VMS !AZ
Startup:!&;AZ
!#AZ:!&;AZ
\n\
\n\ \

\n\ \n\ \n\
Instances
\n\ \n\ \n\ \n\ \n\
NodeCluster
!AZ!AZ
!AZ
\n\
\n\ \

\n\ \n\ \n\
!&?Server\rInstance\r Process
\n\ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \n\ \n\ \ \n\ \ \ \n\ \ \ \n\ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \n\ \n\ \ \n\ \ \n\ !&@\
Name:!AZPID:!8XLUser:!AZ
AuthPriv:!AZImagPriv:!AZCurPriv:!AZ
Last Exit:!AZExit Time:!AZExit PID:!AZ
Image:!%DProcess:!%DCPU:!UL !2ZL:!2ZL:!2ZL.!2ZL
Pg.Faults:!ULStartup:!ULMode:!AZ
WsSize:!UL (!ULMB)WsPeak:!UL (!ULMB)VirtPeak:!UL (!ULMB)
AST:!UL / !UL (!UL%)BIO:!UL / !UL (!UL%)BYT:!UL / !UL (!UL%)
DIO:!UL / !UL (!UL%)ENQ:!UL / !UL (!UL%)FIL:!UL / !UL (!UL%)
PGFL:\ !UL / !UL (!UL/!ULMB !UL%)PRC:!&@TQ:!UL / !UL (!UL%)
Input:!&@
Output:!&@
\n\
\n\ \

\n\ \n\ \n\
System Resources
\n\ \n\ \ \n\ \n\ \n\ \n\
GBLPAGESGBLSECTIONS
Temporary:!UL!UL
Permanent:!UL!UL
Total:!UL!UL
\n\
\n"; static char StatisticsFao [] = "\n\

\n\ \n\ \n\
Request Processing
\n\ \n\ \n\ \ \n\ \n\
\n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \
Connection
Total:!&L
Current:!&L
Peak:!&L
Busy:!&L
HTTP2  /Total:!&L(!UL%)
/Current:!&L(!UL%)
/Peak:!&L
Persistent  /Current:!&L
/Peak:!&L
IPv4:!&L(!UL%)
IPv6:!&L(!UL%)
SSL:!&L(!UL%)
Total  /Rx:!&,@UQ
/Tx:!&,@UQ
Error  /Rx:!&L
/Tx:!&L
Accept:!&L
Reject:!&L
\n\ \
\n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \ \n\ \n\ \n\ \n\ \ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \
Request
Total:!&L
Current:!&L
Peak:!&L
Busy:!&L
HTTP2  /Total:!&L(!UL%)
/Current:!&L(!UL%)
/Peak:!&L
WebSocket  /Current:!&L
/Total:!&L
Raw  /Current:!&L(!UL%)
/Total:!&L(!UL%)
SSL:!&L(!UL%)
Throttle  /Queued:!&L
/Processing:!&L
/Busy:!UL%
Persistent  /Total:!&L
/Max:!&L
Pipeline  /Total:!&L
/Max:!&L!#AZ
\n\ \
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\
HTTP
2:!&L(!UL%)
1.1:!&L(!UL%)
1.0:!&L(!UL%)
0.9:!&L(!UL%)
 
Method
CONNECT:!&L
COPY:!&L
DELETE:!&L
GET:!&L
HEAD:!&L
LOCK:!&L
MKCOL:!&L
MOVE:!&L
OPTIONS:!&L
POST:!&L
PROPFIND:!&L
PROPPATCH:!&L
PUT:!&L
TRACE:!&L
UNLOCK:!&L
Extension:!&L
(SSH):!&L
\n\
\n\ \n\ \ \n\ \
\n\ \ \n\ \n\ \ \ \ \ \ \ \n\ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \ \n\ \ \ \ \n\ \ \ \n\
\ Response Status
1nn:!&L  2nn:!&L  3nn:!&L  4nn:!&L  5nn:!&L
100:!&L200:!&L300:!&L400:!&L500:!&L
101:!&L201:!&L301:!&L401:!&L501:!&L
102:!&L202:!&L302:!&L402:!&L502:!&L
203:!&L303:!&L403:!&L503:!&L
204:!&L304:!&L404:!&L504:!&L
205:!&L305:!&L405:!&L505:!&L
206:!&L306:!&L406:!&L
207:!&L307:!&L407:!&L507:!&L
408:!&L
409:!&L410:!&L411:!&L
412:!&L413:!&L414:!&L
415:!&L416:!&L417:!&L
418:!&L421:!&L422:!&L
423:!&L424:!&L
000:!&L???:!&L
\n\ \
 \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \ \n\ \ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
\ *Duration
Min:!AZ
Max:!AZ
Ave:!AZ
Total:!AZ
 
\ *Bytes/Second
Min  /Bps:!&L
/Bytes:!&,@UQ
/Duration:!AZ
Max  /Bps:!&L
/Bytes:!&,@UQ
/Duration:!AZ
Ave  /Bps:!&L
/Bytes:!&L
/Duration:!AZ
\ *excludes WebSocket and
 \ Proxy-Tunnel requests
\n\ \
\n\
\n\
\n\ \

\n\ \n\ \n\
Processing Modules
\n\ \n\ \n\ \
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
Admin:!&L
Cache  /Load:!&L
/Hit:!&L
/304:!&L
Directory:!&L
File  /All:!&L
/304:!&L
Put:!&L
Proxy:!&L
SSI:!&L
Update:!&L
WebDAV:!&L
WebSocket:!&L
none:!&L
\n\
\n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\ \n\
DCL
 As: !AZ
CGI:!&L
CGIplus  /All:!&L
/Reused:!&L
RTE  /All:!&L
/Reused:!&L
Autoscript:!&L
CLI:!&L
Proctor:!&L
WebSocket:!&L
$CREPRC:!&L
  $PERSONA!&?_MACRO\r\r  /All:!&L
/Default:!&L
/Invalid:!&L
/Privileged:!&L
$FORCEX:!&L
$DELPRC:!&L
\n\ \
\n\ \n\ \n\ \n\ \n\ \n\ \n\
DECnet
 As: !AZ
CGI:!&L
OSU:!&L
Total:!&L
\n\
\n\
\n"; static char GzipFao [] = "

\n\ \n\ \n\
Gzip Encoding!&?\r - DISABLED\r
\n\ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\
CountOf TotalBytes InBytes OutRatio
Deflate:!&L!UL%!&,@UQ!&,@UQ!UL%
Inflate:!&L!UL%!&,@UQ!&,@UQ!UL%
Total Tx:!&L100%!&,@UQ!&,@UQ!UL%
\n\
\n"; static char LookupFao [] = "

\n\ \n\ \n\
Host Resolution
\n\ \n\ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \n\
LiteralDNSCacheError
Address:!&L!&L
Address-to-name:!&L(!UL%)!&L!&L
Name-to-address:!&L(!UL%)!&L!&L
\n\
\n"; static char OtherFao [] = "

\n\ \n\ \n\
Other
\n\ \n\ \n" #if ODS_DIRECT "!AZ" #endif /* ODS_DIRECT */ #if ALIGN_FAULT "\n" #endif /* ALIGN_FAULT */ "\n\ \ \n\ \ \n\ \ \n\ \ \n\
Statistics Zeroed:!&L
Alignment Fault:!&L
Path Alert:!&L
NCS Conversion:!&L / !&L
StreamLF File Conversion:!&L
Errors Noticed:!&L!&@!&@!AZ
$HIBER spurious wake:!&L
\n\
\n\ \ \n\ \n\ \n"; static char SysPrvWarning[] = "SYSPRV"; static char PrivWarning[] = "WARNING"; static char PrivExpected[] = "as expected"; static char JpiPrcNam [16], JpiUserName [13], LastExitPid [16], LastExitStatus [16], LastExitTime [24]; static unsigned short SyiClusterNodes; static unsigned long JpiAstCnt, JpiBioCnt, JpiBytCnt, JpiCpuTime, JpiDioCnt, JpiEnqCnt, JpiFilCnt, JpiPageFlts, JpiPagFilCnt, JpiPid, JpiPrcCnt, JpiTqCnt, JpiVirtPeak, JpiWsSize, JpiWsPeak, Pid; static unsigned long JpiAuthPriv [2], JpiCurPriv [2], JpiImagPriv [2]; static int64 Time64, ImageUpTime64, JpiLoginTime64, ProcessUpTime64; static $DESCRIPTOR (LastExitPidDsc, LastExitPid); static $DESCRIPTOR (LastExitStatusDsc, LastExitStatus); static $DESCRIPTOR (LastExitPidFaoDsc, "!8XL\0"); static $DESCRIPTOR (LastExitStatusFaoDsc, "%X!XL\0"); static $DESCRIPTOR (LastExitTimeDsc, LastExitTime); static $DESCRIPTOR (LastExitTimeFaoDsc, "!20%D\0"); static VMS_ITEM_LIST3 JpiItems [] = { { sizeof(JpiAstCnt), JPI$_ASTCNT, &JpiAstCnt, 0 }, { sizeof(JpiAuthPriv), JPI$_AUTHPRIV, &JpiAuthPriv, 0 }, { sizeof(JpiBioCnt), JPI$_BIOCNT, &JpiBioCnt, 0 }, { sizeof(JpiBytCnt), JPI$_BYTCNT, &JpiBytCnt, 0 }, { sizeof(JpiCpuTime), JPI$_CPUTIM, &JpiCpuTime, 0 }, { sizeof(JpiCurPriv), JPI$_CURPRIV, &JpiCurPriv, 0 }, { sizeof(JpiDioCnt), JPI$_DIOCNT, &JpiDioCnt, 0 }, { sizeof(JpiEnqCnt), JPI$_ENQCNT, &JpiEnqCnt, 0 }, { sizeof(JpiFilCnt), JPI$_FILCNT, &JpiFilCnt, 0 }, { sizeof(JpiImagPriv), JPI$_IMAGPRIV, &JpiImagPriv, 0 }, { sizeof(JpiLoginTime64), JPI$_LOGINTIM, &JpiLoginTime64, 0 }, { sizeof(JpiPageFlts), JPI$_PAGEFLTS, &JpiPageFlts, 0 }, { sizeof(JpiPagFilCnt), JPI$_PAGFILCNT, &JpiPagFilCnt, 0 }, { sizeof(JpiPid), JPI$_PID, &JpiPid, 0 }, { sizeof(JpiPrcCnt), JPI$_PRCCNT, &JpiPrcCnt, 0 }, { sizeof(JpiPrcNam), JPI$_PRCNAM, &JpiPrcNam, 0 }, { sizeof(JpiTqCnt), JPI$_TQCNT, &JpiTqCnt, 0 }, { sizeof(JpiUserName), JPI$_USERNAME, &JpiUserName, 0 }, { sizeof(JpiVirtPeak), JPI$_VIRTPEAK, &JpiVirtPeak, 0 }, { sizeof(JpiWsSize), JPI$_WSSIZE, &JpiWsSize, 0 }, { sizeof(JpiWsPeak), JPI$_WSPEAK, &JpiWsPeak, 0 }, {0,0,0,0} }; static VMS_ITEM_LIST3 SyiItem [] = { { sizeof(SyiClusterNodes), SYI$_CLUSTER_NODES, &SyiClusterNodes, 0 }, { 0,0,0,0 } }; int64 bytes64; int cnt, idx, status, total, ConnectTotalCount, GzipDeflatePercent, GzipInflatePercent, MatchPercent, RequestHttpCount, StringTotal, TotalCount; unsigned int bit; unsigned long Remainder, Seconds, SubSeconds; unsigned long *vecptr; unsigned long FaoVector [180]; char *cptr, *sptr, *AuthPrivPtr, *CurPrivPtr, *ImagPrivPtr, *ClusterInstancePtr, *NodeInstancePtr; char EnvNumber [16]; IO_SB IOsb; ODS_STRUCT WasdRootOds; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminReportServerStats()"); status = sys$getjpiw (EfnWait, &Pid, 0, &JpiItems, &IOsb, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) { rqptr->rqResponse.ErrorTextPtr = "sys$getjpiw()"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } status = sys$getsyiw (EfnWait, 0, 0, &SyiItem, &IOsb, 0, 0); if (VMSok (status)) status = IOsb.Status; if (VMSnok (status)) { rqptr->rqResponse.ErrorTextPtr = "sys$getsyiw()"; ErrorVmsStatus (rqptr, status, FI_LI); AdminEnd (rqptr); return; } InstanceLockList (INSTANCE_NODE_SUPERVISOR, "
", &NodeInstancePtr); InstanceLockList (INSTANCE_CLUSTER, "
", &ClusterInstancePtr); JpiUserName[12] = '\0'; for (cptr = JpiUserName; *cptr && *cptr != ' '; cptr++); *cptr = '\0'; JpiPrcNam[15] = '\0'; for (cptr = JpiPrcNam; *cptr && *cptr != ' '; cptr++); *cptr = '\0'; sys$gettim (&Time64); ImageUpTime64 = HttpdStartTime64 - Time64; ProcessUpTime64 = JpiLoginTime64 - Time64; if ((JpiAuthPriv[0] & ~(PRV$M_NETMBX | PRV$M_TMPMBX)) || JpiAuthPriv[1]) AuthPrivPtr = PrivWarning; else AuthPrivPtr = PrivExpected; if ((JpiImagPriv[0] & IMAG_PRIV_0_ALLOWED) || (JpiImagPriv[1] & IMAG_PRIV_1_ALLOWED)) ImagPrivPtr = PrivWarning; else ImagPrivPtr = PrivExpected; if (OperateWithSysPrv) { if ((JpiCurPriv[0] & ~(PRV$M_NETMBX | PRV$M_TMPMBX | PRV$M_SYSPRV)) || JpiCurPriv[1]) CurPrivPtr = PrivWarning; else CurPrivPtr = SysPrvWarning; } else if ((JpiCurPriv[0] & ~(PRV$M_NETMBX | PRV$M_TMPMBX)) || JpiCurPriv[1]) CurPrivPtr = PrivWarning; else CurPrivPtr = PrivExpected; AdminPageTitle (rqptr, "Server Statistics"); InstanceMutexLock (INSTANCE_MUTEX_HTTPD); ConnectTotalCount = acptr->ConnectCount[HTTP12]; if (acptr->LastExitStatus) sys$fao (&LastExitStatusFaoDsc, 0, &LastExitStatusDsc, acptr->LastExitStatus); else strzcpy (LastExitStatus, "(none)", sizeof(LastExitStatus)); if (acptr->LastExitTime64) sys$fao (&LastExitTimeFaoDsc, 0, &LastExitTimeDsc, &acptr->LastExitTime64); else strzcpy (LastExitTime, "(none)", sizeof(LastExitTime)); if (acptr->LastExitPid) sys$fao (&LastExitPidFaoDsc, 0, &LastExitPidDsc, acptr->LastExitPid); else strzcpy (LastExitPid, "(none)", sizeof(LastExitPid)); /***************/ /* environment */ /***************/ vecptr = FaoVector; if (InstanceEnvNumber > 1) sprintf (*vecptr++ = EnvNumber, " %d", InstanceEnvNumber); else *vecptr++ = ""; *vecptr++ = SoftwareID; *vecptr++ = BuildInfo; if (cptr = SesolaVersion()) *vecptr++ = cptr; else *vecptr++ = "(none)"; if (Config.cfMisc.GzipResponseCompLevel) { *vecptr++ = "ZLIB:!&@\n"; if (VMSok(GzipFindImageStatus)) { *vecptr++ = "!AZ V!AZ"; *vecptr++ = GzipZlibNamePtr; *vecptr++ = GzipZlibVersionPtr; } else if (GzipFindImageStatus == RMS$_FNF) *vecptr++ = "%HTTPD-W-GZIP, shareable image not found"; else { *vecptr++ = "!AZ %!&M"; *vecptr++ = GzipZlibNamePtr; *vecptr++ = GzipFindImageStatus; } } else *vecptr++ = ""; *vecptr++ = TcpIpAgentInfo; *vecptr++ = SysInfo.HwName; *vecptr++ = SysInfo.AvailCpuCnt; *vecptr++ = SysInfo.MemoryMBGB; *vecptr++ = SysInfo.Version; *vecptr++ = CommandLine; cptr = CONFIG_WASD_ROOT; OdsStructInit (&WasdRootOds, true); OdsParse (&WasdRootOds, cptr, strlen(cptr), NULL, 0, NAM$M_NOCONCEAL | NAM$M_SYNCHK, 0, 0); sptr = strstr (WasdRootOds.ExpFileName, ".][000000]"); if (sptr) SET2(sptr,']\0'); *vecptr++ = strchr(cptr,':') - cptr; *vecptr++ = cptr; *vecptr++ = WasdRootOds.ExpFileName; /*************/ /* instances */ /*************/ *vecptr++ = NodeInstancePtr; if (SyiClusterNodes > 1) *vecptr++ = ClusterInstancePtr; else *vecptr++ = "(n/a)"; if (HttpdGblSecPtr->InstancePassive) *vecptr++ = "Node instances are currently PASSIVE."; else *vecptr++ = "Node instances are currently ACTIVE."; /***********/ /* process */ /***********/ *vecptr++ = (InstanceNodeCurrent <= 1); *vecptr++ = JpiPrcNam; *vecptr++ = ADMIN_REPORT_SHOW_PROCESS; *vecptr++ = JpiPid; if (DclPersonaServicesAvailable || HttpdScriptAsUserName[0]) { *vecptr++ = "&puser=!AZ"; *vecptr++ = (unsigned long)JpiUserName; } else *vecptr++ = ""; *vecptr++ = JpiPid; *vecptr++ = (unsigned long)JpiUserName; *vecptr++ = AuthPrivPtr; *vecptr++ = ImagPrivPtr; *vecptr++ = CurPrivPtr; *vecptr++ = LastExitStatus; *vecptr++ = LastExitTime; *vecptr++ = LastExitPid; *vecptr++ = &ImageUpTime64; *vecptr++ = &ProcessUpTime64; *vecptr++ = JpiCpuTime / 8640000; /* CPU day */ *vecptr++ = (JpiCpuTime % 8640000) / 360000; /* CPU hour */ *vecptr++ = (JpiCpuTime % 360000) / 6000; /* CPU minute */ *vecptr++ = (JpiCpuTime % 6000 ) / 100; /* CPU second */ *vecptr++ = JpiCpuTime % 100; /* CPU 10 milliseconds */ *vecptr++ = JpiPageFlts; *vecptr++ = acptr->StartupCount; *vecptr++ = HttpdProcess.ModeName; *vecptr++ = JpiWsSize; *vecptr++ = JpiWsSize * 512 / 1048576, *vecptr++ = JpiWsPeak; *vecptr++ = JpiWsPeak * 512 / 1048576, *vecptr++ = JpiVirtPeak; *vecptr++ = JpiVirtPeak * 512 / 1048576, *vecptr++ = JpiAstCnt; *vecptr++ = HttpdProcess.AstLm; *vecptr++ = 100 - PercentOf32(JpiAstCnt,HttpdProcess.AstLm); *vecptr++ = JpiBioCnt; *vecptr++ = HttpdProcess.BioLm; *vecptr++ = 100 - PercentOf32(JpiBioCnt,HttpdProcess.BioLm); *vecptr++ = JpiBytCnt; *vecptr++ = HttpdProcess.BytLm; *vecptr++ = 100 - PercentOf32(JpiBytCnt,HttpdProcess.BytLm); *vecptr++ = JpiDioCnt; *vecptr++ = HttpdProcess.DioLm; *vecptr++ = 100 - PercentOf32(JpiDioCnt,HttpdProcess.DioLm); *vecptr++ = JpiEnqCnt; *vecptr++ = HttpdProcess.EnqLm; *vecptr++ = 100 - PercentOf32(JpiEnqCnt,HttpdProcess.EnqLm); *vecptr++ = JpiFilCnt; *vecptr++ = HttpdProcess.FilLm; *vecptr++ = 100 - PercentOf32(JpiFilCnt,HttpdProcess.FilLm); *vecptr++ = JpiPagFilCnt; *vecptr++ = HttpdProcess.PgFlQuo; *vecptr++ = JpiPagFilCnt * 512 / 1048576; *vecptr++ = HttpdProcess.PgFlQuo * 512 / 1048576; *vecptr++ = 100 - PercentOf32(JpiPagFilCnt,HttpdProcess.PgFlQuo); if (DclScriptDetachProcess) *vecptr++ = "(detached)"; else { *vecptr++ = "!&L / !&L (!UL%)"; *vecptr++ = HttpdProcess.PrcLm - JpiPrcCnt; *vecptr++ = HttpdProcess.PrcLm; *vecptr++ = 100 - PercentOf32(HttpdProcess.PrcLm-JpiPrcCnt, HttpdProcess.PrcLm); } *vecptr++ = JpiTqCnt; *vecptr++ = HttpdProcess.TqLm; *vecptr++ = 100 - PercentOf32(JpiTqCnt,HttpdProcess.TqLm); if (HttpdProcess.SysInputFile) { *vecptr++ = "!AZ"; *vecptr++ = ADMIN_REPORT_PROCESS_INPUT; } *vecptr++ = HttpdProcess.SysInput; if (HttpdProcess.SysOutputFile) { *vecptr++ = "!AZ"; *vecptr++ = ADMIN_REPORT_PROCESS_OUTPUT_RAW; } *vecptr++ = HttpdProcess.SysOutput; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); if (cptr = SysTrnLnm (WASTEE_LOGFILE)) { *vecptr++ = "WAStee:\ !AZ\n"; *vecptr++ = ADMIN_REPORT_WASTEE; *vecptr++ = cptr; } else *vecptr++ = ""; *vecptr++ = GblPageCount; *vecptr++ = GblSectionCount; *vecptr++ = GblPagePermCount; *vecptr++ = GblSectionPermCount; *vecptr++ = GblPageCount + GblPagePermCount; *vecptr++ = GblSectionCount + GblSectionPermCount; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, BeginPageFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); /************/ /* services */ /************/ NetServiceReportStats (rqptr); /**************/ /* statistics */ /**************/ InstanceMutexLock (INSTANCE_MUTEX_HTTPD); vecptr = FaoVector; /* connections */ *vecptr++ = acptr->ConnectCount[HTTP12]; *vecptr++ = acptr->CurrentConnected[HTTP12]; *vecptr++ = acptr->ConnectPeak[HTTP12]; *vecptr++ = acptr->ConnectTooBusyCount; *vecptr++ = acptr->ConnectCount[HTTP2]; *vecptr++ = PercentOf32(acptr->ConnectCount[HTTP2], acptr->ConnectCount[HTTP12]); *vecptr++ = acptr->CurrentConnected[HTTP2]; *vecptr++ = PercentOf32(acptr->CurrentConnected[HTTP2], acptr->CurrentConnected[HTTP12]); *vecptr++ = acptr->ConnectPeak[HTTP2]; *vecptr++ = acptr->CurrentHttp1Persistent; *vecptr++ = acptr->ConnectPeakPersistent; *vecptr++ = acptr->ConnectIpv4Count; *vecptr++ = PercentOf32(acptr->ConnectIpv4Count, acptr->ConnectCount[HTTP12]); *vecptr++ = acptr->ConnectIpv6Count; *vecptr++ = PercentOf32(acptr->ConnectIpv6Count, acptr->ConnectCount[HTTP12]); *vecptr++ = acptr->ConnectSSLCount; *vecptr++ = PercentOf32(acptr->ConnectSSLCount, acptr->ConnectCount[HTTP12]); *vecptr++ = &acptr->BytesRawRx64; *vecptr++ = &acptr->BytesRawTx64; *vecptr++ = acptr->NetReadErrorCount; *vecptr++ = acptr->NetWriteErrorCount; *vecptr++ = acptr->ConnectAcceptedCount; *vecptr++ = acptr->ConnectRejectedCount; /* requests */ *vecptr++ = acptr->ProcessingTotalCount[HTTP12]; *vecptr++ = acptr->CurrentProcessing[HTTP12]; *vecptr++ = acptr->ProcessingPeak[HTTP12]; *vecptr++ = acptr->ProcessingTooBusyCount; *vecptr++ = acptr->ProcessingTotalCount[HTTP2]; *vecptr++ = PercentOf32(acptr->ProcessingTotalCount[HTTP2], acptr->ProcessingTotalCount[HTTP12]); *vecptr++ = acptr->CurrentProcessing[HTTP2]; *vecptr++ = PercentOf32(acptr->CurrentProcessing[HTTP2], acptr->CurrentProcessing[HTTP12]); *vecptr++ = acptr->ProcessingPeak[HTTP2]; for (total = cnt = 0; cnt <= InstanceNodeCurrent; cnt++) total += acptr->CurrentWebSockets[cnt]; *vecptr++ = total; StringTotal = total; *vecptr++ = acptr->WebSocketCount; for (total = cnt = 0; cnt <= InstanceNodeCurrent; cnt++) total += acptr->CurrentWebSocketsRaw[cnt]; *vecptr++ = total; *vecptr++ = PercentOf32(StringTotal,total); *vecptr++ = acptr->WebSocketRawCount; *vecptr++ = PercentOf32(acptr->WebSocketCount,acptr->WebSocketRawCount); *vecptr++ = acptr->RequestSSLCount; *vecptr++ = PercentOf32(acptr->RequestSSLCount, acptr->ProcessingTotalCount[HTTP12]); for (total = cnt = 0; cnt <= InstanceNodeCurrent; cnt++) total += acptr->CurrentThrottleQueued[cnt]; *vecptr++ = total; for (total = cnt = 0; cnt <= InstanceNodeCurrent; cnt++) total += acptr->CurrentThrottleProcessing[cnt]; *vecptr++ = total; *vecptr++ = acptr->ThrottleBusyMetric; *vecptr++ = acptr->RequestPersistentCount; *vecptr++ = acptr->RequestPersistentMax; *vecptr++ = acptr->PipelineRequestCount; *vecptr++ = acptr->PipelineRequestMax; /* force it to the left because of the following 'duration' width */ if (ConnectTotalCount < 10) *vecptr++ = 36; else if (ConnectTotalCount < 100) *vecptr++ = 30; else if (ConnectTotalCount < 1000) *vecptr++ = 24; else if (ConnectTotalCount < 10000) *vecptr++ = 18; else if (ConnectTotalCount < 100000) *vecptr++ = 12; else if (ConnectTotalCount < 1000000) *vecptr++ = 6; else *vecptr++ = 0; *vecptr++ = "      "; /* HTTP versions */ RequestHttpCount = acptr->RequestHttp2Count + acptr->RequestHttp11Count + acptr->RequestHttp10Count + acptr->RequestHttp09Count; *vecptr++ = acptr->RequestHttp2Count; *vecptr++ = PercentOf32 (acptr->RequestHttp2Count, RequestHttpCount); *vecptr++ = acptr->RequestHttp11Count; *vecptr++ = PercentOf32 (acptr->RequestHttp11Count, RequestHttpCount); *vecptr++ = acptr->RequestHttp10Count; *vecptr++ = PercentOf32 (acptr->RequestHttp10Count, RequestHttpCount); *vecptr++ = acptr->RequestHttp09Count; *vecptr++ = PercentOf32 (acptr->RequestHttp09Count, RequestHttpCount); /* HTTP methods */ *vecptr++ = acptr->MethodConnectCount; *vecptr++ = acptr->MethodWebDavCopyCount; *vecptr++ = acptr->MethodDeleteCount; *vecptr++ = acptr->MethodGetCount; *vecptr++ = acptr->MethodHeadCount; *vecptr++ = acptr->MethodWebDavLockCount; *vecptr++ = acptr->MethodWebDavMkColCount; *vecptr++ = acptr->MethodWebDavMoveCount; *vecptr++ = acptr->MethodOptionsCount; *vecptr++ = acptr->MethodPostCount; *vecptr++ = acptr->MethodWebDavPropFindCount; *vecptr++ = acptr->MethodWebDavPropPatchCount; *vecptr++ = acptr->MethodPutCount; *vecptr++ = acptr->MethodTraceCount; *vecptr++ = acptr->MethodWebDavUnLockCount; *vecptr++ = acptr->MethodExtensionCount; *vecptr++ = acptr->MethodSshCount; /* responses */ *vecptr++ = acptr->ResponseStatusCodeGroup[1]; *vecptr++ = acptr->ResponseStatusCodeGroup[2]; *vecptr++ = acptr->ResponseStatusCodeGroup[3]; *vecptr++ = acptr->ResponseStatusCodeGroup[4]; *vecptr++ = acptr->ResponseStatusCodeGroup[5]; /* see ResponseHttpStatusCode() for making sense of this array */ #define RHSI(n) RequestHttpStatusIndex(n) *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(100)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(200)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(300)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(400)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(500)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(101)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(201)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(301)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(401)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(501)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(102)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(202)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(302)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(402)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(502)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(203)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(303)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(403)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(503)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(204)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(304)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(404)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(504)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(205)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(305)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(405)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(505)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(206)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(306)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(406)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(207)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(307)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(407)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(507)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(408)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(409)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(410)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(411)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(412)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(413)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(414)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(415)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(416)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(417)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(418)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(421)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(422)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(423)]; *vecptr++ = acptr->ResponseStatusCodeCount[RHSI(424)]; *vecptr++ = acptr->ResponseStatusCodeGroup[0]; /* 000 */ *vecptr++ = acptr->ResponseStatusCodeCount[0]; /* ??? */ #undef RHSI /* response duration */ /* without this kludge we get %CC-W-ALIGNCONFLICT */ bytes64 = acptr->ResponseDurationMin64[HTTP12]; *vecptr++ = DurationString (rqptr, &bytes64); bytes64 = acptr->ResponseDurationMax64[HTTP12]; *vecptr++ = DurationString (rqptr, &bytes64); bytes64 = acptr->ResponseDuration64[HTTP12]; *vecptr++ = AverageDurationString (rqptr, &bytes64, acptr->ResponseDurationCount[HTTP12]); bytes64 = acptr->ResponseDuration64[HTTP12]; *vecptr++ = DurationString (rqptr, &bytes64); /* bytes per second */ *vecptr++ = acptr->BytesPerSecondMin[HTTP12]; *vecptr++ = &acptr->BytesPerSecondMinBytes64[HTTP12]; bytes64 = acptr->BytesPerSecondMinDuration64[HTTP12]; *vecptr++ = DurationString (rqptr, &bytes64); *vecptr++ = acptr->BytesPerSecondMax[HTTP12]; *vecptr++ = &acptr->BytesPerSecondMaxBytes64[HTTP12]; bytes64 = acptr->BytesPerSecondMaxDuration64[HTTP12]; *vecptr++ = DurationString (rqptr, &bytes64); *vecptr++ = acptr->BytesPerSecondAve[HTTP12]; *vecptr++ = (ulong)((float)acptr->BytesPerSecondRawTotal64[HTTP12] / (float)(acptr->RequestHttp2Count + acptr->RequestHttp11Count + acptr->RequestHttp10Count)); bytes64 = acptr->ResponseDuration64[HTTP12]; *vecptr++ = DurationString (rqptr, &bytes64); /* modules */ *vecptr++ = acptr->DoServerAdminCount; *vecptr++ = acptr->CacheLoadCount; *vecptr++ = acptr->CacheHitCount; *vecptr++ = acptr->CacheHitNotModifiedCount; *vecptr++ = acptr->DoDirectoryCount; *vecptr++ = acptr->DoFileCount; *vecptr++ = acptr->DoFileNotModifiedCount; *vecptr++ = acptr->DoPutCount; *vecptr++ = acptr->DoProxyCount; *vecptr++ = acptr->DoSsiCount; *vecptr++ = acptr->DoUpdateCount; *vecptr++ = acptr->DoWebDavCount; *vecptr++ = acptr->DoWebSockCount; *vecptr++ = acptr->DoNoModuleCount; if (HttpdScriptAsUserName[0]) *vecptr++ = HttpdScriptAsUserName; else *vecptr++ = HttpdProcess.UserName; *vecptr++ = acptr->DoScriptCount; *vecptr++ = acptr->DoCgiPlusScriptCount; *vecptr++ = acptr->DclCgiPlusReusedCount; *vecptr++ = acptr->DoRteScriptCount; *vecptr++ = acptr->DclRteReusedCount; *vecptr++ = acptr->DoAutoScriptCount; *vecptr++ = acptr->DoDclCommandCount; *vecptr++ = acptr->DclProctorCount; *vecptr++ = acptr->DclWebSocketCount; *vecptr++ = acptr->DclCrePrcCount; *vecptr++ = PersonaMacro; *vecptr++ = acptr->DclCrePrcPersonaCount; *vecptr++ = acptr->DclCrePrcPersonaDefaultCount; *vecptr++ = acptr->DclCrePrcPersonaInvUserCount; *vecptr++ = acptr->DclCrePrcPersonaPrvUserCount; *vecptr++ = acptr->DclForceXCount; *vecptr++ = acptr->DclDelPrcCount; if (HttpdScriptAsUserName[0]) *vecptr++ = HttpdScriptAsUserName; else *vecptr++ = HttpdProcess.UserName; *vecptr++ = acptr->DoDECnetCgiCount; *vecptr++ = acptr->DoDECnetOsuCount; *vecptr++ = acptr->DoDECnetCount; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, StatisticsFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); InstanceMutexLock (INSTANCE_MUTEX_HTTPD); if (Config.cfMisc.GzipResponseCompLevel) { /* GZIP compression (if enabled) */ vecptr = FaoVector; *vecptr++ = GzipAvailable; *vecptr++ = acptr->GzipDeflateCount; *vecptr++ = PercentOf32 (acptr->GzipDeflateCount, acptr->ProcessingTotalCount[HTTP12]); *vecptr++ = &acptr->GzipDeflateBytesIn64; *vecptr++ = &acptr->GzipDeflateBytesOut64; *vecptr++ = PercentOf64 (&acptr->GzipDeflateBytesOut64, &acptr->GzipDeflateBytesIn64); *vecptr++ = acptr->GzipInflateCount; *vecptr++ = PercentOf32 (acptr->GzipInflateCount, acptr->ProcessingTotalCount[HTTP12]); *vecptr++ = &acptr->GzipInflateBytesIn64; *vecptr++ = &acptr->GzipInflateBytesOut64; *vecptr++ = PercentOf64 (&acptr->GzipInflateBytesIn64, &acptr->GzipInflateBytesOut64); bytes64 = acptr->BytesRawTx64[HTTP12] + (acptr->GzipDeflateBytesIn64 - acptr->GzipDeflateBytesOut64); *vecptr++ = acptr->ProcessingTotalCount[HTTP12]; *vecptr++ = &bytes64; *vecptr++ = &acptr->BytesRawTx64[HTTP12]; *vecptr++ = PercentOf64 (&acptr->BytesRawTx64[HTTP12], &bytes64); FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, GzipFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } /* lookup */ vecptr = FaoVector; *vecptr++ = acptr->LookupLiteralCount; *vecptr++ = acptr->LookupLiteralErrorCount; *vecptr++ = acptr->LookupDnsAddressCount; *vecptr++ = PercentOf32 (acptr->LookupDnsAddressCount, acptr->LookupDnsAddressCount + acptr->LookupCacheAddressCount); *vecptr++ = acptr->LookupCacheAddressCount; *vecptr++ = acptr->LookupDnsAddressErrorCount; *vecptr++ = acptr->LookupDnsNameCount; *vecptr++ = PercentOf32 (acptr->LookupDnsNameCount, acptr->LookupDnsNameCount + acptr->LookupCacheNameCount); *vecptr++ = acptr->LookupCacheNameCount; *vecptr++ = acptr->LookupDnsNameErrorCount; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, LookupFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); /* other */ vecptr = FaoVector; *vecptr++ = acptr->ZeroedCount; #if ODS_DIRECT *vecptr++ = OdsDirectReport (rqptr); #endif /* ODS_DIRECT */ #if ALIGN_FAULT *vecptr++ = HttpdAlignFaultCount; #endif /* ALIGN_FAULT */ *vecptr++ = acptr->PathAlertCount; *vecptr++ = acptr->NcsCount; *vecptr++ = acptr->NcsConvertCount; *vecptr++ = acptr->StreamLfConversionCount; *vecptr++ = acptr->ErrorsNoticedCount; if (acptr->ErrorsNoticedCount) { *vecptr++ = "(!20%D"; *vecptr++ = &acptr->ErrorsNoticedTime64; if (HttpdProcess.SysOutputFile) { *vecptr++ = ", see Log"; *vecptr++ = ADMIN_REPORT_PROCESS_OUTPUT_RAW; } else *vecptr++ = ""; *vecptr++ = ")"; } else { *vecptr++ = ""; *vecptr++ = ""; *vecptr++ = ""; } *vecptr++ = acptr->SpuriousWakeCount; InstanceMutexUnLock (INSTANCE_MUTEX_HTTPD); FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, OtherFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); VmFree (NodeInstancePtr, FI_LI); VmFree (ClusterInstancePtr, FI_LI); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/html", &rqptr->NetWriteBufferDsc); AdminEnd (rqptr); } /*****************************************************************************/ /* Get the file module to output the server process log. */ void AdminServerInput (REQUEST_STRUCT *rqptr) { int status; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminServerInput()"); if (!HttpdProcess.SysInputFile) { rqptr->rqResponse.HttpStatus = 500; ErrorGeneral (rqptr, HttpdProcess.SysInput, FI_LI); AdminEnd (rqptr); return; } rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/plain", NULL); FileSetCacheAllowed (rqptr, false); FileSetAuthorizePath (rqptr, false); FileBegin (rqptr, &AdminEnd, NULL, NULL, HttpdProcess.SysInput, "text/plain"); } /*****************************************************************************/ /* Get the file module to output the server process log. */ void AdminServerOutputRaw (REQUEST_STRUCT *rqptr) { /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminServerOutputRaw()"); if (!HttpdProcess.SysOutputFile) { rqptr->rqResponse.HttpStatus = 500; ErrorGeneral (rqptr, HttpdProcess.SysOutput, FI_LI); AdminEnd (rqptr); return; } /* Q&D flush SYS$OUTPUT */ fsync (STDOUT_FILENO); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/plain", NULL); FileSetCacheAllowed (rqptr, false); FileSetAuthorizePath (rqptr, false); FileBegin (rqptr, &AdminEnd, NULL, NULL, HttpdProcess.SysOutput, "text/plain"); } /*****************************************************************************/ /* List the process logs (directory index) or output a specific log file. */ void AdminServerOutputList (REQUEST_STRUCT *rqptr) { int sizeofList = sizeof(ADMIN_REPORT_PROCESS_OUTPUT_LIST)-1; char *cptr, *pinptr, *sptr, *zptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminServerOutputList()"); /* Q&D flush SYS$OUTPUT */ fsync (STDOUT_FILENO); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; zptr = (sptr = rqptr->RequestMappedFile) + sizeof(rqptr->RequestMappedFile)-1; for (cptr = "WASD_SERVER_LOGS:"; *cptr; *sptr++ = *cptr++); *sptr = '\0'; for (cptr = pinptr = rqptr->rqHeader.PathInfoPtr; *cptr; cptr++); if ((cptr - pinptr) > sizeofList) { FileSetCacheAllowed (rqptr, false); FileSetAuthorizePath (rqptr, false); for (cptr = pinptr + sizeofList; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; FileBegin (rqptr, &AdminEnd, NULL, NULL, rqptr->RequestMappedFile, "text/plain"); } else DirBegin (rqptr, &AdminEnd, rqptr->RequestMappedFile, "httpd=index&these=*.log&delimit=footer&readme=no", "", false); } /*****************************************************************************/ /* From the Server Admin menu generate a report of errors noticed. */ void AdminServerOutputNoticed (REQUEST_STRUCT *rqptr) { static char ReportBeginFao [] = "

\n\ \n\
"; static char ReportEndFao [] = "
\n"; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "AdminServerOutputNoticed()"); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/plain", NULL); AdminServerOutputNoticed2 (rqptr); AdminEnd (rqptr); } /*****************************************************************************/ /* Generate a list of errors noticed by opening and reading relevant records from the current operator log. Relies on the $NOTE rule being enabled. */ void AdminServerOutputNoticed2 (REQUEST_STRUCT *rqptr) { int count, status; char *sptr; char buf [1024]; ODS_STRUCT OutputOds; ODS_STRUCT *odsptr = &OutputOds; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "AdminServerOutputNoticed2()"); if (!HttpdProcess.SysOutputFile) { FaoToNet (rqptr, "!&S\n", SS$_NOSUCHFILE); return; } /* Q&D flush SYS$OUTPUT */ fsync (STDOUT_FILENO); OdsStructInit (odsptr, true); status = OdsOpenShrUpdReadOnly (odsptr, HttpdProcess.SysOutput, false, true); if (VMSnok (status)) { FaoToNet (rqptr, "!&S\n", status); return; } count = 0; for (;;) { odsptr->Rab.rab$l_ubf = buf; odsptr->Rab.rab$w_usz = sizeof(buf) - 1; status = sys$get (&odsptr->Rab, 0, 0); if (VMSnok (status)) break; buf[odsptr->Rab.rab$w_rsz++] = '\n'; buf[odsptr->Rab.rab$w_rsz] = '\0'; if (!MATCH15 (buf, "%HTTPD-W-ALERT,") && !MATCH17 (buf, "%HTTPD-W-NOTICED,")) continue; for (;;) { if (count++) NetWriteBuffered (rqptr, NULL, "8< snip 8<\n", 11); NetWriteBuffered (rqptr, NULL, buf, odsptr->Rab.rab$w_rsz); for (;;) { /* all records associated with this notice */ odsptr->Rab.rab$l_ubf = buf; odsptr->Rab.rab$w_usz = sizeof(buf) - 1; status = sys$get (&odsptr->Rab, 0, 0); if (VMSnok (status)) break; /* if empty record */ if (!odsptr->Rab.rab$w_rsz) continue; buf[odsptr->Rab.rab$w_rsz++] = '\n'; /* if start of new message */ if (buf[0] == '%' && !MATCH15 (buf, "%HTTPD-W-ALERT,")) break; NetWriteBuffered (rqptr, NULL, buf, odsptr->Rab.rab$w_rsz); } if (VMSnok (status)) break; if (!MATCH15 (buf, "%HTTPD-W-ALERT,") && !MATCH17 (buf, "%HTTPD-W-NOTICED,")) break; } if (VMSnok (status)) break; } sys$close (&odsptr->Fab, 0, 0); if (count && status == RMS$_EOF) status = SS$_NORMAL; if (VMSnok (status)) { FaoToNet (rqptr, "!&S\n", status); return; } } /*****************************************************************************/ /* From the Server Admin menu generate a report sans NOTICED and REJECT records. */ void AdminServerOutputFilter (REQUEST_STRUCT *rqptr) { /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "AdminServerOutputFilter()"); rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/plain", NULL); AdminServerOutputFilter2 (rqptr); AdminEnd (rqptr); } /*****************************************************************************/ /* Generate an expurgated list of records by opening and reading relevant records from the current operator log. Relies on the $NOTE rule being enabled. */ void AdminServerOutputFilter2 (REQUEST_STRUCT *rqptr) { static char ReportEmptyFao [] = "empty\n"; int count, status; char *sptr; char buf [1024]; ODS_STRUCT OutputOds; ODS_STRUCT *odsptr = &OutputOds; /*********/ /* begin */ /*********/ if (WATCH_MODULE(WATCH_MOD_NET)) WatchThis (WATCHALL, WATCH_MOD_NET, "AdminServerOutputFilter2()"); if (!HttpdProcess.SysOutputFile) { FaoToNet (rqptr, "!&S\n", SS$_NOSUCHFILE); return; } /* Q&D flush SYS$OUTPUT */ fsync (STDOUT_FILENO); OdsStructInit (odsptr, true); status = OdsOpenShrUpdReadOnly (odsptr, HttpdProcess.SysOutput, false, true); if (VMSnok (status)) { FaoToNet (rqptr, "!&S\n", status); return; } count = 0; for (;;) { odsptr->Rab.rab$l_ubf = buf; odsptr->Rab.rab$w_usz = sizeof(buf) - 1; status = sys$get (&odsptr->Rab, 0, 0); if (VMSnok (status)) break; buf[odsptr->Rab.rab$w_rsz++] = '\n'; buf[odsptr->Rab.rab$w_rsz] = '\0'; if (MATCH16 (buf, "%HTTPD-I-REJECT,") || MATCH16 (buf, "%HTTPD-I-ACCEPT,")) { if (!count++) NetWriteBuffered (rqptr, NULL, "8< snip 8<\n", 11); continue; } if (MATCH15 (buf, "%HTTPD-W-ALERT,") || MATCH17 (buf, "%HTTPD-W-NOTICED,")) { for (;;) { if (!count++) NetWriteBuffered (rqptr, NULL, "8< snip 8<\n", 11); for (;;) { /* all records associated with this notice */ odsptr->Rab.rab$l_ubf = buf; odsptr->Rab.rab$w_usz = sizeof(buf) - 1; status = sys$get (&odsptr->Rab, 0, 0); if (VMSnok (status)) break; /* if start of new message */ if (buf[0] == '%') break; } if (VMSnok (status)) break; if (!MATCH15 (buf, "%HTTPD-W-ALERT,") && !MATCH17 (buf, "%HTTPD-W-NOTICED,")) break; } if (VMSnok (status)) break; continue; } count = 0; NetWriteBuffered (rqptr, NULL, buf, odsptr->Rab.rab$w_rsz); } sys$close (&odsptr->Fab, 0, 0); if (status == RMS$_EOF) status = SS$_NORMAL; if (VMSnok (status)) { FaoToNet (rqptr, "!&S\n", status); return; } } /*****************************************************************************/ /* See WASD_ROOT:[SRC.UTILS]WASTEE.C for background. */ void AdminReportWAStee (REQUEST_STRUCT *rqptr) { int len; char *sptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminReportWAStee()"); if (!(sptr = SysTrnLnm (WASTEE_LOGFILE))) { rqptr->rqResponse.HttpStatus = 500; ErrorGeneral (rqptr, "WASTEE_LOGFILE", FI_LI); AdminEnd (rqptr); return; } rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN; ResponseHeader200 (rqptr, "text/plain", NULL); FileSetCacheAllowed (rqptr, false); FileSetAuthorizePath (rqptr, false); FileBegin (rqptr, &AdminEnd, NULL, NULL, sptr, "text/plain"); } /*****************************************************************************/ /* Provide administration menu/report page titles. Will accept a small number of variable arguments to provide text following the titles themselves. */ int AdminPageTitle ( REQUEST_STRUCT *rqptr, char *Title, ... ) { static char PageTitleFao [] = "!AZ\ \n\ \n\ !AZ\ !AZ\ !&@\ WASD !AZ ... !AZ\n\ \n\ !AZ\n\

\n\

WASD !AZ

\n\

!AZ!&@

\n\ !20&W\n\ !&@"; int argcnt, status; unsigned long *vecptr; unsigned long FaoVector [32+16]; va_list argptr; /*********/ /* begin */ /*********/ va_count (argcnt); if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminPageTitle() !UL !&Z", argcnt, Title); if (argcnt > 32+4) { ErrorNoticed (rqptr, SS$_OVRMAXARG, NULL, FI_LI); return (SS$_OVRMAXARG); } vecptr = FaoVector; *vecptr++ = WASD_DOCTYPE; *vecptr++ = HtmlMetaInfo (rqptr, NULL); *vecptr++ = AdminWasdCss (); if (rqptr->rqPathSet.StyleSheetPtr) { *vecptr++ = "\n"; *vecptr++ = rqptr->rqPathSet.StyleSheetPtr; } else *vecptr++ = ""; *vecptr++ = ServerHostPort; *vecptr++ = Title; *vecptr++ = ADMIN_BODY_TAG; *vecptr++ = ServerHostPort; *vecptr++ = Title; if (InstanceNodeCurrent > 1) { if (rqptr->ServicePtr->AdminService) *vecptr++ = "  -  !AZ"; else *vecptr++ = "    (!AZ)"; *vecptr++ = HttpdProcess.PrcNam; } else *vecptr++ = ""; *vecptr++ = &rqptr->rqTime.BeginTime64; if (argcnt > 2) { va_start (argptr, Title); for (argcnt -= 2; argcnt; argcnt--) *vecptr++ = va_arg (argptr, unsigned long); va_end (argptr); } else *vecptr++ = ""; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, PageTitleFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); return (status); } /*****************************************************************************/ /* Provide a list of problems reported during a meta-config load in standard admininistration menu/report format. */ void AdminMetaConReport ( REQUEST_STRUCT *rqptr, META_CONFIG *mcptr, META_CONFIG *MetaConStartupPtr ) { static char ReportFao [] = "

\n\ \n\ \n\
\   !UL Informational,  !UL Warning,  \ !&?\r\r!-!UL Error!%s !-!&?\r\r \\ !&?At Startup\rDuring Load\r  
!AZ
\n"; int status; unsigned long *vecptr; unsigned long FaoVector [16]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminMetaConReport()"); if (!mcptr->LoadReport.ItemCount) return; vecptr = FaoVector; *vecptr++ = mcptr->LoadReport.InformCount; *vecptr++ = mcptr->LoadReport.WarningCount; *vecptr++ = mcptr->LoadReport.ErrorCount; *vecptr++ = (mcptr == MetaConStartupPtr); *vecptr++ = mcptr->LoadReport.TextPtr; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, ReportFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } /*****************************************************************************/ /* Provide a description of the source of this configuration in an administration standard menu/report format. */ void AdminMetaConSource ( REQUEST_STRUCT *rqptr, META_CONFIG *mcptr, META_CONFIG *MetaConStartupPtr ) { static char SourceFao [] = "

\n\ \n\ \n\
Source: "!&?Server\rFile\r"
\n\ \n\ !&@\n\ \n\ !&@\ !&@\
File:!AZ
!AZ!20&W
\n\
\n"; int status; unsigned long *vecptr; unsigned long FaoVector [16]; char *cptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminMetaConSource()"); vecptr = FaoVector; *vecptr++ = (mcptr == MetaConStartupPtr); *vecptr++ = mcptr->LoadReport.FileName; if (mcptr->LnmCount > 1) *vecptr++ = "(search list)"; else { *vecptr++ = "\ View\ Edit"; *vecptr++ = cptr = rqptr->rqHeader.PathInfoPtr; *vecptr++ = cptr; } if (mcptr == MetaConStartupPtr) { *vecptr++ = "Loaded:"; *vecptr++ = &mcptr->LoadReport.LoadTime64; } else { *vecptr++ = "Revised:"; *vecptr++ = &mcptr->LoadReport.FileTime64; } if (InConfigStartup (true)) { *vecptr++ = "From:!AZ\n\ \ View\ Edit\n\ \ Configuration derived from inline directives and file(s).
\ CAUTION: Using this interface may overwrite that!!\ \n"; *vecptr++ = InConfigFileName; *vecptr++ = ADMIN_REPORT_INLINE; *vecptr++ = ADMIN_REPORT_INLINE; InConfigStartup (false); } else *vecptr++ = ""; if (mcptr->IncludeFile) *vecptr++ = "\ Configuration derived from multiple files (e.g. [IncludeFile])
\ CAUTION: Using this interface may overwrite that!!\ \n"; else *vecptr++ = ""; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, SourceFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } /*****************************************************************************/ /* For administration menu configuration update pages provide the element and some leading, commented-out descriptive text for the configuration file. */ void AdminMetaConBeginUpdateForm (REQUEST_STRUCT *rqptr) { static char BeginFormFao [] = "

\n\ "; int status; unsigned long *vecptr; unsigned long FaoVector [16]; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminMetaConBeginUpdateForm()"); vecptr = FaoVector; *vecptr++ = rqptr->rqHeader.PathInfoPtr; *vecptr++ = ServerHostPort; *vecptr++ = SoftwareID; *vecptr++ = &rqptr->rqTime.BeginTime64; *vecptr++ = rqptr->RemoteUser; *vecptr++ = rqptr->rqAuth.RealmDescrPtr; *vecptr++ = rqptr->ClientPtr->Lookup.HostName; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, BeginFormFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } /*****************************************************************************/ /* For administration menu configuration update pages provide the update buttons and the
tag (complements AdminMetaConEndUpdateForm()). */ void AdminMetaConEndUpdateForm (REQUEST_STRUCT *rqptr) { static char EndForm [] = "

\n\

\n\ \n\ \n"; int status; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminMetaConEndUpdateForm()"); status = FaolToNet (rqptr, EndForm, NULL); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); } /*****************************************************************************/ /* For administration menu configuration update pages provide the update buttons and the tag (complements AdminMetaConEndUpdateForm()). */ void AdminVirtualServiceForm ( REQUEST_STRUCT *rqptr, char *FormAction, char *VirtualService, BOOL UseServerConfig ) { static char BeginFormFao [] = "

\n\ \n\ \n\ \n\
\n"; int status; unsigned long *vecptr; unsigned long FaoVector [16]; SERVICE_STRUCT *svptr; /*********/ /* begin */ /*********/ if (WATCHMOD (rqptr, WATCH_MOD__OTHER)) WatchThis (WATCHITM(rqptr), WATCH_MOD__OTHER, "AdminVirtualServiceForm()"); vecptr = FaoVector; *vecptr++ = FormAction; *vecptr++ = UseServerConfig; *vecptr++ = VirtualService[0]; *vecptr++ = (ServiceList.EntryCount == 1); FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, BeginFormFao, &FaoVector); if (VMSnok (status)) ErrorNoticed (rqptr, status, NULL, FI_LI); if (ServiceList.EntryCount > 1) { LIST_ITERATE (svptr, &ServiceList) { vecptr = FaoVector; *vecptr++ = svptr->ServerHostPort; *vecptr++ = strsame (svptr->ServerHostPort, VirtualService, -1); *vecptr++ = svptr->ServerHostPort; FaoCheck (sizeof(FaoVector), &FaoVector, vecptr, FI_LI); status = FaolToNet (rqptr, "