/*****************************************************************************/ /* hdisk.c This application links to the Gift.c application's GIF and graphic code! Functions begining Gift...() and storage beginning Graphic... is Gift.c code. HyperDisk! Provides disk details, including a usage bar graph, for one or more disks specified as part of the path or as a CGI form variable "DISKS=". Disk device names may be specified separated by commas, forward-slashes, or (probably most simply) just with a full-colon (which is used by VMS as a device name separator). Disk details include blocks and Mbytes total, used and free, as well as error count. Component devices of volumes sets are displayed individually. Variations allowed in specifying disks: http://host/disk/device http://host/disk/device1:device2:device3 http://host/disk/device1,device2,device3 http://host/disk/device1/device2/device3 http://host/disk?disk=device http://host/disk?disk=device1:device2:device3 http://host/disk?disk=device1,device2,device3 http://host/disk?disk=device1/device2/device3 If the string "graphiconly" occurs in the query string only a bar-graph GIF for the specified device is generated and sent. This allows documents to include a tag such as to include the usage bar-graph for any given device (of course only one may be specified with each use). Page colouration and "button" labels may be specified via the appropriate command-line qualifiers (or corresponding logical name). Defaults for any not specified. Specifiy as /WHATEVER="" to NOT specify the corresponding colour (i.e. leave it to the browser). See "Qualifiers" section below, and also about the logical name "HDISK$PARAM". An example of changing the page colour to white and the banner to red! /PBGCOLOR="#ffffff" /PHBGCOLOR="#ff0000" The script can format a page in either of two layouts. 1. Tables are used to create a coloured header and button bar (DEFAULT). Default colours are white page with grey heading and button outlines. 2. Textual header, horizontal rules and a textual button bar. No default colours. ACKNOWLEDGEMENT --------------- Although the graphic generation and GIF header code is mine the actual GIF compression code employed is derived from the PBM suite, is copyright, and used within the owner's guidelines: * GIF Image compression - LZW algorithm implemented with Trie type * structure. * Written by Bailey Brown, Jr. * last change May 24, 1990 * file: compgif.c * * You may use or modify this code as you wish, as long as you mention * my name in your documentation. * * - Bailey Brown, Jr. QUALIFIERS ---------- /DBUG turns on all "if (Debug)" statements /PBACKGROUND= background image path /PBGCOLOR= background colour /PBBGCOLOR= button background color /PBBORDER= width of button border /PHBGCOLOR= heading background color /PHBORDER= width of heading and button-bar border /PHLOCAL= local information to be included in header /PHTEXT= heading text colour /PLAYOUT= 1 is coloured header & buttons, 2 is text & horizontal rules /PLINK= link colour /PTEXT= text colour /PVLINK= visited link colour CGI VARIABLES ------------- WWW_FORM_BRIEF if the word brief occurs in the query string only the bar graph is generated, no device details WWW_FORM_DISK one of more disk device names WWW_FORM_DISKS ditto WWW_FORM_HEIGHT height in pixels of the bar-graph WWW_FORM_GRAPHICONLY if the word graphiconly occurs in the query string a gif representing the device is generated and returned WWW_FORM_HELP if the word help occurs in the query string it results in a redirection to the help document WWW_FORM_PERCENTAGE results in a bar graph GIF being returned WWW_FORM_WIDTH width in pixels of the bar-graph WWW_SCRIPT_NAME script name WWW_SERVER_NAME server host name WWW_SERVER_PORT server IP port WWW_QUERY_STRING query string WWW_PATH_INFO document path (everything following the script name) OSU ENVIRONMENT --------------- Script responses are returned in OSU "raw" mode; the script taking care of the full response header and correctly carriage-controlled data stream, text or binary!! The script standard output stream is reopened in binary mode (no translation of '\n') with a maximum record size set to 4096 bytes (failure to set this results in the OSU server reporting %SYSTEM-F-DATAOVERUN errors). The binary output is enclosed by suitably fflushed() "" and "" control tags (the flush make them individual records as required by OSU). If in debug the script output is placed into "text" mode. COPYRIGHT --------- Copyright (C) 1996-2008 Mark G.Daniel This program, comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version. http://www.gnu.org/licenses/gpl.txt BUILD DETAILS ------------- See BUILD_HDISK.COM procedure. VERSION HISTORY (update SOFTWAREVN as well!) --------------- 06-AUG-2008 MGD v1.4.0, some refinements 04-MAY-2004 MGD v1.3.4, correct percentage for large devices, minor cosmetic changes to device info table 23-DEC-2003 MGD v1.3.3, minor conditional mods to support IA64 12-APR-2003 MGD v1.3.2, link colour changed to 0000cc 30-OCT-1998 MGD v1.3.1, refined help path redirection for OSU use 12-OCT-1998 MGD v1.3.0, accomodations for OSU environment 24-JUL-1998 MGD v1.2.1, suppress table background colours if empty 29-APR-1998 MGD v1.2.0, cosmetic changes 18-APR-1997 MGD v1.1.0, graphics pre-expired (generated each time accessed) 06-AUG-1996 MGD v1.0.0, YAQH (wanted to try generating coloured GIFs :^) */ /*****************************************************************************/ #define SOFTWAREVN "1.4.0" #define SOFTWARENM "HDISK" #ifdef __ALPHA char SoftwareID [] = SOFTWARENM " AXP-" SOFTWAREVN; #endif #ifdef __ia64 char SoftwareID [] = SOFTWARENM " IA64-" SOFTWAREVN; #endif #ifdef __VAX char SoftwareID [] = SOFTWARENM " VAX-" SOFTWAREVN; #endif /* standard C header files */ #include #include #include #include /* VMS header files */ #include #include #include #include #include #include #include #include /* application header file */ #ifdef OSU_HDISK #include "gift.h" #else #include "[-.gift]gift.h" #endif /* Can't find any UCB definitions anywhere. Cobbled these up out of the $GETDVI system service description of DVI$_STS item and the VMS Device Support Reference describing Unit Control Blocks. */ #define UCB$V_TIM 0x1 #define UCB$V_INT 0x2 #define UCB$V_ERLOGIP 0x4 #define UCB$V_CANCEL 0x8 #define UCB$V_ONLINE 0x10 #define UCB$V_POWER 0x20 #define UCB$V_TIMOUT 0x40 #define UCB$V_INTTYPE 0x80 #define UCB$V_BSY 0x100 #define UCB$V_MOUNTING 0x200 #define UCB$V_DEADMO 0x400 #define UCB$V_VALID 0x800 #define UCB$V_UNLOAD 0x1000 #define UCB$V_TEMPLATE 0x2000 #define UCB$V_MNTVERIP 0x4000 #define UCB$V_WRONGVOL 0x8000 #define UCB$V_DELETEUCB 0x10000 #define UCB$V_LCL_VALID 0x20000 #define UCB$V_SUPMVMSG 0x40000 #define UCB$V_MNTVERPND 0x80000 #define UCB$V_DISMOUNT 0x100000 #define UCB$V_CLUTRAN 0x200000 #define UCB$V_WRTLOCKMV 0x400000 #define UCB$V_SVPN_END 0x800000 #define VMSok(x) ((x) & STS$M_SUCCESS) #define VMSnok(x) !(((x) & STS$M_SUCCESS)) #define boolean int #define true 1 #define false 0 /* macro provides NULL pointer if CGI variable does not exist */ #define GetCgiVarIfExists(CharPointer,CgiVariableName) \ CharPointer = getenv(CgiVariableName) /* macro provides pointer to empty string even if CGI variable does not exist */ #define GetCgiVar(CharPointer,CgiVariableName) \ if ((CharPointer = getenv(CgiVariableName)) == NULL) \ CharPointer = ""; \ if (Debug) fprintf (stdout, "%s |%s|\n", CgiVariableName, CharPointer); #define ExcessiveErrorCount 5 #define DEFAULT_CHARSET "ISO-8859-1" #define DEFAULT_HELP_PATH "/hdisk/-/hdisk.html" #define DEFAULT_BUTTONS "Help" /* this macro just plugs in some script-specific code into ButtonBar() */ #define SCRIPT_SPECIFIC_BUTTON_CODE \ ButtonInternal[0] = HelpPathPtr; #define DEFAULT_PS_BGCOLOR "#ffffff" #define DEFAULT_PS_TEXT "#000000" #define DEFAULT_PS_LINK "#0000cc" #define DEFAULT_PS_VLINK "#0000cc" #define DEFAULT_PS_HEADBGCOLOR "#cccccc" #define DEFAULT_PS_HEADBORDER "0" #define DEFAULT_PS_HEADTEXT "#000000" #define DEFAULT_PS_BUTTONBGCOLOR "#ffffff" #define DEFAULT_PS_BUTTONBORDER "1" #define PS_BACKGROUND 0 #define PS_BGCOLOR 1 #define PS_TEXT 2 #define PS_LINK 3 #define PS_VLINK 4 #define PS_HEADBGCOLOR 5 #define PS_HEADTEXT 6 #define PS_HEADBORDER 7 #define PS_BUTTONBGCOLOR 8 #define PS_BUTTONBORDER 9 #define PS_BODYTAG 10 #define PS_LAYOUT 11 #define PS_HEADLOCAL 12 #define PS_HEADPADDING 13 char *PageScheme [16]; char *MonthName [] = { "", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; char *DayName [] = { "", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; char Utility [] ="HDISK"; struct DiskInfoStruct { struct DiskInfoStruct *NextPtr; long DevClass, DevChar, DevChar2, ErrCnt, FreeBlocks, MaxBlock, UsedBlocks, VolNumber, VolSetMem; char FullDevName [65], NextDevName [65], MediaName [65]; struct { unsigned long lo32; unsigned long hi32; } UcbStatus; }; boolean Debug, DoDiskInfoTable, DoGraphicOnly, HttpHasBeenOutput, OsuEnvironment; unsigned long DayOfWeek; unsigned long CurrentBinTime [2]; unsigned short CurrentNumTime [7]; char ContentTypeCharset [64], DayDateTime [64]; char *ButtonPtr = DEFAULT_BUTTONS, *CgiFormDiskPtr, *CgiFormHeightPtr, *CgiFormPercentagePtr, *CgiFormWidthPtr, *CgiPathInfoPtr, *CgiQueryStringPtr, *CgiRequestSchemePtr, *CgiScriptNamePtr, *CgiServerNamePtr, *CgiServerSoftwarePtr, *CgiServerPortPtr, *CgiTypePtr, *CharsetPtr, *CliCharsetPtr, *HelpPathPtr = DEFAULT_HELP_PATH; /* for historical reasons GIFT uses an output stream named "HttpOut" */ FILE *HttpOut; /* storage in the Gift.c module */ extern boolean GraphicNoCacheGif; extern int GraphicHeight, GraphicWidth; extern struct GraphicFontStruct Font []; /* required function prototypes */ AtOsuExit (); /*****************************************************************************/ /* */ main () { register char *cptr, *sptr, *zptr; int status, Percentage; char UpCaseDiskName [256]; /*********/ /* begin */ /*********/ if (getenv ("WWWEXEC_RUNDOWN_STRING") != NULL) { OsuEnvironment = true; atexit (&AtOsuExit); } if (getenv ("HDISK$DBUG") != NULL) { Debug = true; if (OsuEnvironment) fprintf (stdout, "\n200 Success\n"); else fprintf (stdout, "Content-Type: text/plain\n\n"); } GetParameters (); SetPageScheme (); if (OsuEnvironment) CgiTypePtr = "OSU"; else CgiTypePtr = "standard"; if (Debug) system ("show sym *"); else { if (OsuEnvironment) { /* reopen so that '\r' and '\n' are not filtered, maximum record size */ if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin", "mrs=4096")) == NULL) exit (vaxc$errno); fprintf (stdout, ""); fflush (stdout); } else { /* reopen so that '\r' and '\n' are not filtered */ if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL) exit (vaxc$errno); } } if ((CharsetPtr = CliCharsetPtr) == NULL) { GetCgiVar (CharsetPtr, "WWW_REQUEST_CHARSET"); if (!CharsetPtr[0]) GetCgiVar (CharsetPtr, "WWW_SERVER_CHARSET"); if (!CharsetPtr[0]) CharsetPtr = DEFAULT_CHARSET; } if (CharsetPtr[0]) sprintf (ContentTypeCharset, "; charset=%s", CharsetPtr); else ContentTypeCharset[0] = '\0'; /* for historical reasons GIFT uses an output stream named "HttpOut" */ HttpOut = stdout; /***********/ /* process */ /***********/ GetCgiVar (CgiServerSoftwarePtr, "WWW_SERVER_SOFTWARE"); GetCgiVar (CgiScriptNamePtr, "WWW_SCRIPT_NAME"); GetCgiVar (CgiPathInfoPtr, "WWW_PATH_INFO"); GetCgiVar (CgiQueryStringPtr, "WWW_QUERY_STRING"); if (strstr (CgiQueryStringPtr, "hyperdisk") != NULL || strstr (CgiQueryStringPtr, "HYPERDISK") != NULL) { GiftButton ("", "HyperDisk", 14); exit (SS$_NORMAL); } if (strstr (CgiQueryStringPtr, "furtherinfo") != NULL || strstr (CgiQueryStringPtr, "FURTHERINFO") != NULL) { GiftButton ("", " further\ninformation", 8); exit (SS$_NORMAL); } if (strstr (CgiQueryStringPtr, "brief") != NULL || strstr (CgiQueryStringPtr, "BRIEF") != NULL) DoDiskInfoTable = false; else DoDiskInfoTable = true; if (strstr (CgiQueryStringPtr, "graphiconly") != NULL || strstr (CgiQueryStringPtr, "GRAPHICONLY") != NULL) DoGraphicOnly = GraphicNoCacheGif = true; else DoGraphicOnly = GraphicNoCacheGif = false; GetCgiVar (CgiFormWidthPtr, "WWW_FORM_WIDTH"); if (CgiFormWidthPtr[0]) { GraphicWidth = atol(CgiFormWidthPtr); if (GraphicWidth <= 0 || GraphicWidth >= MaxGraphicWidth) exit (ErrorGeneral ("Graphic width error.", __FILE__, __LINE__)); } GetCgiVar (CgiFormHeightPtr, "WWW_FORM_HEIGHT"); if (CgiFormHeightPtr[0]) { GraphicHeight = atol(CgiFormHeightPtr); if (GraphicHeight <= 0 || GraphicHeight >= MaxGraphicHeight) exit (ErrorGeneral ("Graphic height error.", __FILE__, __LINE__)); } GetCgiVar (CgiFormPercentagePtr, "WWW_FORM_PERCENTAGE"); if (CgiFormPercentagePtr[0]) { /* provide a bar graph */ Percentage = atol (CgiFormPercentagePtr); if (!isdigit(CgiFormPercentagePtr[0]) || Percentage > 100) exit (ErrorGeneral ("Percentage is not acceptable.", __FILE__, __LINE__)); GiftUsageBar (Percentage, 85, ""); exit (SS$_NORMAL); } if (strlen(CgiPathInfoPtr) > 1) cptr = CgiPathInfoPtr+1; else { /* disks not in path, see if they are specified from a form */ GetCgiVar (CgiFormDiskPtr, "WWW_FORM_DISK"); /* nothing in singular "_disk", try plural "_disks" */ if (!CgiFormDiskPtr[0]) GetCgiVar (CgiFormDiskPtr, "WWW_FORM_DISKS"); /* no, no disks at all, provide some help! */ if (!CgiFormDiskPtr[0]) { char ServerPort [32]; GetCgiVar (CgiRequestSchemePtr, "WWW_REQUEST_SCHEME"); GetCgiVar (CgiServerNamePtr, "WWW_SERVER_NAME"); GetCgiVar (CgiServerPortPtr, "WWW_SERVER_PORT"); if (!CgiRequestSchemePtr[0]) CgiRequestSchemePtr = "http:"; if (!strcmp (CgiServerPortPtr, "80")) ServerPort[0] = '\0'; else sprintf (ServerPort, ":%s", CgiServerPortPtr); fprintf (stdout, "HTTP/1.0 302 Redirection\r\n\ Location: %s//%s%s%s\r\n\ Server: %s\r\n\ \r\n", CgiRequestSchemePtr, CgiServerNamePtr, ServerPort, HelpPathPtr, CgiServerSoftwarePtr); exit (SS$_NORMAL); } cptr = CgiFormDiskPtr; } zptr = (sptr = UpCaseDiskName) + sizeof(UpCaseDiskName); for (/* see above*/; *cptr && sptr < zptr; *sptr++ = toupper(*cptr++)); if (sptr >= zptr) exit (ErrorGeneral ("String too small.", __FILE__, __LINE__)); *sptr = '\0'; if (DoGraphicOnly) { OneDiskInfo (UpCaseDiskName); exit (SS$_NORMAL); } sys$gettim (&CurrentBinTime); sys$numtim (&CurrentNumTime, &CurrentBinTime); if (VMSnok (status = lib$day_of_week (&CurrentBinTime, &DayOfWeek))) exit (ErrorVmsStatus (status, "day of week", 0, __FILE__, __LINE__)); sprintf (DayDateTime, "%s, %d %s %d %02.02d:%02.02d:%02.02d", DayName[DayOfWeek], CurrentNumTime[2], MonthName[CurrentNumTime[1]], CurrentNumTime[0], CurrentNumTime[3], CurrentNumTime[4], CurrentNumTime[5]); ReportDiskInfo (UpCaseDiskName); exit (SS$_NORMAL); } /*****************************************************************************/ /* Script executing in OSU environment exits. */ AtOsuExit () { if (Debug) fprintf (stdout, "\n"); else { fflush (stdout); fprintf (stdout, ""); fflush (stdout); } } /*****************************************************************************/ /* Get "command-line" parameters, whether from the command-line or from a configuration logical containing the equivalent. */ GetParameters () { static char CommandLine [256]; static unsigned long Flags = 0; register char *aptr, *cptr, *clptr, *sptr; int status; unsigned short Length; char ch; $DESCRIPTOR (CommandLineDsc, CommandLine); /*********/ /* begin */ /*********/ if ((clptr = getenv ("HDISK$PARAM")) == NULL) { /* get the entire command line following the verb */ if (VMSnok (status = lib$get_foreign (&CommandLineDsc, 0, &Length, &Flags))) exit (status); (clptr = CommandLine)[Length] = '\0'; } aptr = NULL; ch = *clptr; for (;;) { if (aptr != NULL) *aptr = '\0'; if (!ch) break; *clptr = ch; if (Debug) fprintf (stdout, "clptr |%s|\n", clptr); while (*clptr && isspace(*clptr)) *clptr++ = '\0'; aptr = clptr; if (*clptr == '/') clptr++; while (*clptr && !isspace (*clptr) && *clptr != '/') { if (*clptr != '\"') { clptr++; continue; } cptr = clptr; clptr++; while (*clptr) { if (*clptr == '\"') if (*(clptr+1) == '\"') clptr++; else break; *cptr++ = *clptr++; } *cptr = '\0'; if (*clptr) clptr++; } ch = *clptr; if (*clptr) *clptr = '\0'; if (Debug) fprintf (stdout, "aptr |%s|\n", aptr); if (!*aptr) continue; if (strsame (aptr, "/CHARSET=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; CliCharsetPtr = cptr; continue; } if (strsame (aptr, "/DBUG", -1)) { Debug = true; continue; } if (strsame (aptr, "/HELP=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; HelpPathPtr = cptr; return (true); } if (GetPageParameter (aptr)) continue; if (*aptr != '/') { fprintf (stdout, "%%%s-E-MAXPARM, too many parameters\n \\%s\\\n", Utility, aptr); exit (STS$K_ERROR | STS$M_INHIB_MSG); } else { fprintf (stdout, "%%%s-E-IVQUAL, unrecognized qualifier\n \\%s\\\n", Utility, aptr+1); exit (STS$K_ERROR | STS$M_INHIB_MSG); } } } /*****************************************************************************/ /* Get command-line parameters associated with page scheme. */ boolean GetPageParameter (char *aptr) { register char *cptr; /*********/ /* begin */ /*********/ if (strsame (aptr, "/PBACKGROUND=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_BACKGROUND] = cptr; return (true); } if (strsame (aptr, "/PBGCOLOR=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_BGCOLOR] = cptr; return (true); } if (strsame (aptr, "/PBBGCOLOR=", 5)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_BUTTONBGCOLOR] = cptr; return (true); } if (strsame (aptr, "/PBBORDER=", 5)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_BUTTONBORDER] = cptr; return (true); } if (strsame (aptr, "/PHBGCOLOR=", 5)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_HEADBGCOLOR] = cptr; return (true); } if (strsame (aptr, "/PHBORDER=", 5)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_HEADBORDER] = cptr; return (true); } if (strsame (aptr, "/PHTEXT=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_HEADTEXT] = cptr; return (true); } if (strsame (aptr, "/PLAYOUT=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_LAYOUT] = cptr; return (true); } if (strsame (aptr, "/PLINK=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_LINK] = cptr; return (true); } if (strsame (aptr, "/PHLOCAL=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_HEADLOCAL] = cptr; return (true); } if (strsame (aptr, "/PTEXT=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_TEXT] = cptr; return (true); } if (strsame (aptr, "/PVLINK=", 4)) { for (cptr = aptr; *cptr && *cptr != '='; cptr++); if (*cptr) cptr++; PageScheme[PS_VLINK] = cptr; return (true); } return (false); } /*****************************************************************************/ /* Set the page layout and colouration. */ SetPageScheme () { int size; char *sptr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "SetPageScheme()\n"); if (PageScheme[PS_LAYOUT] == NULL) PageScheme[PS_LAYOUT] = "1"; if (PageScheme[PS_BACKGROUND] == NULL) PageScheme[PS_BACKGROUND] = ""; if (PageScheme[PS_HEADLOCAL] == NULL) PageScheme[PS_HEADLOCAL] = ""; if (PageScheme[PS_LAYOUT][0] == '2') { if (PageScheme[PS_BGCOLOR] == NULL) PageScheme[PS_BGCOLOR] = ""; if (PageScheme[PS_TEXT] == NULL) PageScheme[PS_TEXT] = ""; if (PageScheme[PS_LINK] == NULL) PageScheme[PS_LINK] = ""; if (PageScheme[PS_VLINK] == NULL) PageScheme[PS_VLINK] = ""; if (PageScheme[PS_HEADBGCOLOR] == NULL) PageScheme[PS_HEADBGCOLOR] = ""; if (PageScheme[PS_HEADBORDER] == NULL) PageScheme[PS_HEADBORDER] = ""; if (PageScheme[PS_HEADTEXT] == NULL) PageScheme[PS_HEADTEXT] = ""; if (PageScheme[PS_BUTTONBGCOLOR] == NULL) PageScheme[PS_BUTTONBGCOLOR] = ""; if (PageScheme[PS_BUTTONBORDER] == NULL) PageScheme[PS_BUTTONBORDER] = ""; } else { if (PageScheme[PS_BGCOLOR] == NULL) PageScheme[PS_BGCOLOR] = DEFAULT_PS_BGCOLOR; if (PageScheme[PS_TEXT] == NULL) PageScheme[PS_TEXT] = DEFAULT_PS_TEXT; if (PageScheme[PS_LINK] == NULL) PageScheme[PS_LINK] = DEFAULT_PS_LINK; if (PageScheme[PS_VLINK] == NULL) PageScheme[PS_VLINK] = DEFAULT_PS_VLINK; if (PageScheme[PS_HEADBGCOLOR] == NULL) PageScheme[PS_HEADBGCOLOR] = DEFAULT_PS_HEADBGCOLOR; if (PageScheme[PS_HEADBORDER] == NULL) PageScheme[PS_HEADBORDER] = DEFAULT_PS_HEADBORDER; if (PageScheme[PS_HEADTEXT] == NULL) PageScheme[PS_HEADTEXT] = DEFAULT_PS_HEADTEXT; if (PageScheme[PS_BUTTONBGCOLOR] == NULL) PageScheme[PS_BUTTONBGCOLOR] = DEFAULT_PS_BUTTONBGCOLOR; if (PageScheme[PS_BUTTONBORDER] == NULL) PageScheme[PS_BUTTONBORDER] = DEFAULT_PS_BUTTONBORDER; } /* tag attributes */ size = strlen(PageScheme[PS_BACKGROUND]) + strlen(PageScheme[PS_BGCOLOR]) + strlen(PageScheme[PS_TEXT]) + strlen(PageScheme[PS_LINK]) + strlen(PageScheme[PS_VLINK]); if (size) { if ((sptr = calloc (1, size+64)) == NULL) exit (vaxc$errno); PageScheme[PS_BODYTAG] = sptr; if (PageScheme[PS_BACKGROUND][0]) sptr += sprintf (sptr, " BACKGROUND=\"%s\"", PageScheme[PS_BACKGROUND]); if (PageScheme[PS_BGCOLOR][0]) sptr += sprintf (sptr, " BGCOLOR=\"%s\"", PageScheme[PS_BGCOLOR]); if (PageScheme[PS_TEXT][0]) sptr += sprintf (sptr, " TEXT=\"%s\"", PageScheme[PS_TEXT]); if (PageScheme[PS_LINK][0]) sptr += sprintf (sptr, " LINK=\"%s\"", PageScheme[PS_LINK]); if (PageScheme[PS_VLINK][0]) sptr += sprintf (sptr, " VLINK=\"%s\"", PageScheme[PS_VLINK]); } else PageScheme[PS_BODYTAG] = ""; if (PageScheme[PS_HEADBGCOLOR][0]) { if ((sptr = calloc (1, strlen(PageScheme[PS_HEADBGCOLOR])+16)) == NULL) exit (vaxc$errno); sprintf (sptr, " BGCOLOR=\"%s\"", PageScheme[PS_HEADBGCOLOR]); PageScheme[PS_HEADBGCOLOR] = sptr; PageScheme[PS_HEADPADDING] = "10"; } else PageScheme[PS_HEADPADDING] = "0"; if (PageScheme[PS_BUTTONBGCOLOR][0]) { if ((sptr = calloc (1, strlen(PageScheme[PS_BUTTONBGCOLOR])+16)) == NULL) exit (vaxc$errno); sprintf (sptr, " BGCOLOR=\"%s\"", PageScheme[PS_BUTTONBGCOLOR]); PageScheme[PS_BUTTONBGCOLOR] = sptr; } } /*****************************************************************************/ /* Provides a divider for top and bottom of the content of the page. This can be a coloured bar (using ) or a horizontal rule depending on the page layout. "Buttons" providing script-internal and/or additional user-specified links ('ButtonPtr' string) can be placed with(in) this bar. All button labels are derived from 'ButtonPtr', with script-internal buttons using link-paths set up via 'ButtonInternal[]' array, or any user-specified path depending on requirement. An empty path (i.e. PathPtr[0] == '\0') obviously does not have a link created, it just displays the button label. For a button-bar at the top of the document use 1, bottom of the document use 2, and for just a bar with no buttons at all use 0. */ ButtonBar (int Top1Bottom2) { #define MAX_BUTTON_COUNT 8 static int ButtonCount = -1; static char *ButtonInternal [MAX_BUTTON_COUNT], *ButtonLabel [MAX_BUTTON_COUNT], *ButtonPath [MAX_BUTTON_COUNT]; int idx; char *PathPtr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ButtonBar() %d\n", Top1Bottom2); if (ButtonCount == -1) { register char *cptr, *sptr; if (Debug) fprintf (stdout, "|%s|\n", ButtonPtr); cptr = ButtonPtr; for (ButtonCount = 0; ButtonCount < MAX_BUTTON_COUNT && *cptr; ButtonCount++) { for (sptr = cptr; *sptr && *sptr != '=' && *sptr != ';'; sptr++) if (*sptr == '\\') memcpy (sptr, sptr+1, strlen(sptr)); if (*sptr == '=') *sptr++ = '\0'; ButtonLabel[ButtonCount] = cptr; cptr = sptr; for (sptr = cptr; *sptr && *sptr != ';'; sptr++) if (*sptr == '\\') memcpy (sptr, sptr+1, strlen(sptr)); if (*sptr) *sptr++ = '\0'; ButtonPath[ButtonCount] = cptr; cptr = sptr; } } if (Top1Bottom2) { /***********************************/ /* set up script-specified buttons */ /***********************************/ SCRIPT_SPECIFIC_BUTTON_CODE } if (PageScheme[PS_LAYOUT][0] == '2') { /************/ /* format 2 */ /************/ if (Top1Bottom2 == 2 || !Top1Bottom2) { fprintf (stdout, "
\n"); if (!Top1Bottom2) return; } fprintf (stdout, "\n"); for (idx = 0; idx < ButtonCount; idx++) { if (ButtonInternal[idx] == NULL) PathPtr = ButtonPath[idx]; else PathPtr = ButtonInternal[idx]; if (idx) fprintf (stdout, " "); if (PathPtr[0]) fprintf (stdout, "[%s]\n", PathPtr, ButtonLabel[idx]); else fprintf (stdout, "[%s]\n", ButtonLabel[idx]); } fprintf (stdout, "\n"); if (Top1Bottom2 == 1) fprintf (stdout, "
\n"); } else { /************/ /* format 1 */ /************/ fprintf (stdout, "
\ \
\n\ \n\ \n", PageScheme[PS_HEADBORDER], PageScheme[PS_HEADBORDER], PageScheme[PS_HEADBGCOLOR]); if (ButtonCount == 0 || !Top1Bottom2) fprintf (stdout, " \n"); else { fprintf (stdout, "
\n", PageScheme[PS_BUTTONBORDER]); for (idx = 0; idx < ButtonCount; idx++) { if (ButtonInternal[idx] == NULL) PathPtr = ButtonPath[idx]; else PathPtr = ButtonInternal[idx]; if (PathPtr[0]) fprintf (stdout, "\n", PageScheme[PS_BUTTONBGCOLOR], PathPtr, ButtonLabel[idx]); else fprintf (stdout, "\n", PageScheme[PS_BUTTONBGCOLOR], ButtonLabel[idx]); } fprintf (stdout, "
\   %s  \   %s  
\n"); } fprintf (stdout, "\n\ \n\ \ \
\n"); } } /*****************************************************************************/ /* */ ReportDiskInfo (char *DiskName) { register char *cptr, *sptr; register int cnt; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "ProvideDiskInfo()\n"); fprintf (stdout, "HTTP/1.0 200 Success\r\n\ Server: %s\r\n\ Content-Type: text/html%s\r\n\ Expires: Fri, 13 Jan 1978 14:00:00 GMT\r\n\ \r\n\ \n\ \n\ \n\ \n\ hyperDISK ... %s\n\ \n\ \n\ \n\ \n\ \n\ %s\n\
\n\ \n\  *hyperDISK\n\ \n\ %s
\n\
\n\
\n", CgiServerSoftwarePtr, ContentTypeCharset, SoftwareID, CgiTypePtr, DiskName, PageScheme[PS_BODYTAG], PageScheme[PS_HEADBORDER], PageScheme[PS_HEADPADDING], PageScheme[PS_HEADBGCOLOR], PageScheme[PS_HEADTEXT], DayDateTime, PageScheme[PS_HEADTEXT], PageScheme[PS_HEADLOCAL]); HttpHasBeenOutput = true; cptr = DiskName; while (*cptr) { sptr = cptr; while (*cptr && isspace(*cptr)) cptr++; while (*cptr && *cptr != ':' && *cptr != ',' && *cptr != '/') cptr++; if (*cptr) *cptr++ = '\0'; if (!*sptr) continue; OneDiskInfo (sptr); } fprintf (stdout, "
\n\

\n"); ButtonBar (2); fprintf (stdout, "\n\ \n"); } /*****************************************************************************/ /* */ OneDiskInfo (char *DiskName) { int status, ErrorCount, VolumeCount; unsigned long TotalMaxBlock, TotalFreeBlocks, TotalUsedBlocks; double dGBytesFree, dGBytesMax, dGBytesUsed, dPercentUsed, dPercentFree; struct DiskInfoStruct *DiskInfoPtr, *FirstDiskInfoPtr, *NextDiskInfoPtr; /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "OneDiskInfo()\n"); if ((FirstDiskInfoPtr = calloc (sizeof(struct DiskInfoStruct), 1)) == NULL) exit (ErrorVmsStatus (vaxc$errno, "allocating memory", "", __FILE__, __LINE__)); if (VMSnok (status = GetDiskInfo (DiskName, FirstDiskInfoPtr))) { free (FirstDiskInfoPtr); if (status == SS$_NOSUCHDEV) { if (DoGraphicOnly) GiftUsageBar (0, 100, "NO SUCH DEVICE!"); else fprintf (stdout, "

%s ... NO SUCH DEVICE!

\n", DiskName); return; } exit (ErrorVmsStatus (status, DiskName, "", __FILE__, __LINE__)); } if (!(FirstDiskInfoPtr->DevClass & DC$_DISK)) { free (FirstDiskInfoPtr); if (DoGraphicOnly) GiftUsageBar (0, 100, "NOT A DISK DEVICE!"); else fprintf (stdout, "

%s ... NOT A DISK DEVICE!

\n", DiskName); return; } if (!(FirstDiskInfoPtr->DevChar & DEV$M_MNT)) { free (FirstDiskInfoPtr); if (DoGraphicOnly) GiftUsageBar (0, 100, "NOT MOUNTED!"); else fprintf (stdout, "

%s ... NOT MOUNTED!

\n", DiskName); return; } /* on-line bit should normally be 1 */ if (!(FirstDiskInfoPtr->UcbStatus.lo32 & UCB$V_ONLINE)) { free (FirstDiskInfoPtr); if (DoGraphicOnly) GiftUsageBar (0, 100, "NOT ONLINE!"); else fprintf (stdout, "

%s ... NOT ONLINE!

\n", DiskName); return; } /* unit timeout bit should normally be 0 */ if (FirstDiskInfoPtr->UcbStatus.lo32 & UCB$V_TIMOUT) { free (FirstDiskInfoPtr); if (DoGraphicOnly) GiftUsageBar (0, 100, "MOUNT VERIFY TIMEOUT!"); else fprintf (stdout, "

%s ... MOUNT VERIFY HAS TIMED-OUT!

\n\

This device was in a mount verify state, but that has now \ timed-out. It could have been off-line, had the wrong volume on-line, \ had excessive errors or a corrupted file system. In short ... \ there is a major problem that should investigated ASAP.\n", DiskName); return; } /* mount verify bit should normally be 0 */ if (FirstDiskInfoPtr->UcbStatus.lo32 & UCB$V_MNTVERIP) { free (FirstDiskInfoPtr); if (DoGraphicOnly) GiftUsageBar (0, 100, "IN MOUNT VERIFY!"); else fprintf (stdout, "

%s ... IN MOUNT VERIFY!

\n\

This device is in a mount verify state. It could be off-line, \ have the wrong volume on-line, have excessive errors or a corrupted \ file system. In short ... there is a major problem that should \ investigated ASAP.\n", DiskName); return; } if (FirstDiskInfoPtr->VolSetMem && FirstDiskInfoPtr->VolNumber > 1) { free (FirstDiskInfoPtr); if (DoGraphicOnly) GiftUsageBar (0, 100, "NOT PRIMARY VOLUME SET MEMBER!"); else fprintf (stdout, "

%s ... NOT PRIMARY MEMBER!

\n\

This device is part of a volume set, but is not the primary member \ of that set. Specify only the primary member!\n", DiskName); return; } /***************************************/ /* additional devices for a volume set */ /***************************************/ DiskInfoPtr = FirstDiskInfoPtr; while (DiskInfoPtr->NextDevName[0]) { if ((DiskInfoPtr->NextPtr = calloc (sizeof(struct DiskInfoStruct), 1)) == NULL) exit (ErrorVmsStatus (vaxc$errno, "allocating memory", "", __FILE__, __LINE__)); GetDiskInfo (DiskInfoPtr->NextDevName, DiskInfoPtr->NextPtr); DiskInfoPtr = DiskInfoPtr->NextPtr; } /********************/ /* calculate totals */ /********************/ dGBytesFree = dGBytesMax = dGBytesUsed = 0.0; ErrorCount = TotalMaxBlock = TotalFreeBlocks = TotalUsedBlocks = VolumeCount = 0; DiskInfoPtr = FirstDiskInfoPtr; while (DiskInfoPtr != NULL) { VolumeCount++; ErrorCount += DiskInfoPtr->ErrCnt; dGBytesMax += (double)DiskInfoPtr->MaxBlock * 512.0 / 1000000000.0; TotalMaxBlock += DiskInfoPtr->MaxBlock; dGBytesFree += (double)DiskInfoPtr->FreeBlocks * 512.0 / 1000000000.0; TotalFreeBlocks += DiskInfoPtr->FreeBlocks; dGBytesUsed += (double)DiskInfoPtr->UsedBlocks * 512.0 / 1000000000.0; TotalUsedBlocks += DiskInfoPtr->UsedBlocks; DiskInfoPtr = DiskInfoPtr->NextPtr; } dPercentUsed = dGBytesUsed * 100.0 / dGBytesMax; dPercentFree = dGBytesFree * 100.0 / dGBytesMax; /****************/ /* graphic only */ /****************/ if (DoGraphicOnly) { /* local storage */ char String [256]; if (dPercentUsed == 100.0) sprintf (String, "%s %.*fGB %.0f%% used", DiskName, GBytesPrecision(dGBytesMax), dGBytesMax, dPercentUsed); else if (dPercentUsed > 0.1) sprintf (String, "%s %.*fGB %.0f%% used %.0f%% free", DiskName, GBytesPrecision(dGBytesMax), dGBytesMax, dPercentUsed, dPercentFree); else sprintf (String, "%s %.*fGB %.0f%% free", DiskName, GBytesPrecision(dGBytesMax), dGBytesMax, dPercentFree); GiftUsageBar ((int)dPercentUsed, 85, String); /* no need to deallocate memory, will be exit()ing shortly */ return; } /*********************/ /* graphic image tag */ /*********************/ fprintf (stdout, "

%s ... used: %.0f%% free: %.0f%%", DiskName, dPercentUsed, dPercentFree); if (ErrorCount >= ExcessiveErrorCount) fprintf (stdout, " ERRORS!"); fprintf (stdout, "

\n\ \"[disk\n", CgiScriptNamePtr, dPercentUsed); if (DoDiskInfoTable) { /***************************************/ /* present table of device information */ /***************************************/ if (VolumeCount == 1) fprintf (stdout, "

\n"); else fprintf (stdout, "

Volume set comprising %d devices.\n
\n", VolumeCount); fprintf (stdout, "\n\ \n\ \n
\n\ \n\ \ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \ \ \ \ \n"); /* all disks (just one, or multiple if a volume set) */ DiskInfoPtr = FirstDiskInfoPtr; while (DiskInfoPtr != NULL) { fprintf (stdout, "\ \ \ \ \ \ \ \ \ \ \ \ \n", DiskInfoPtr->FullDevName, DiskInfoPtr->MaxBlock, GBytesPrecision((double)DiskInfoPtr->MaxBlock * 512.0 / 1000000000.0), (double)DiskInfoPtr->MaxBlock * 512.0 / 1000000000.0, DiskInfoPtr->UsedBlocks, GBytesPrecision((double)DiskInfoPtr->UsedBlocks * 512.0 / 1000000000.0), (double)DiskInfoPtr->UsedBlocks * 512.0 / 1000000000.0, ((double)DiskInfoPtr->UsedBlocks * 512.0 / 1000000000.0) * 100.0 / dGBytesMax, DiskInfoPtr->FreeBlocks, GBytesPrecision((double)DiskInfoPtr->FreeBlocks * 512.0 / 1000000000.0), (double)DiskInfoPtr->FreeBlocks * 512.0 / 1000000000.0, ((double)DiskInfoPtr->FreeBlocks * 512.0 / 1000000000.0) * 100.0 / dGBytesMax, DiskInfoPtr->ErrCnt, DiskInfoPtr->MediaName); DiskInfoPtr = DiskInfoPtr->NextPtr; } /* block and Mbyte totals */ fprintf (stdout, "\ \ \ \ \ \ \ \ \ \ \ \ \n\ \ \ \ \ \ \ \ \ \ \n", TotalMaxBlock, TotalUsedBlocks, TotalFreeBlocks, GBytesPrecision(dGBytesMax), dGBytesMax, GBytesPrecision(dGBytesUsed), dGBytesUsed, GBytesPrecision(dGBytesFree), dGBytesFree); fprintf (stdout, "
TotalUsedFreeErrorsMedia
\ blocksGBytesblocksGBytespercentblocksGBytespercent
%s%d%.*f%d%.*f%.0f%%%d%.*f%.0f%%%d%s
%d%d%d
%.*f%.*f%.*f
\n
\n"); } /*************************/ /* free allocated memory */ /*************************/ NextDiskInfoPtr = FirstDiskInfoPtr; while (NextDiskInfoPtr != NULL) { DiskInfoPtr = NextDiskInfoPtr; NextDiskInfoPtr = NextDiskInfoPtr->NextPtr; free (DiskInfoPtr); } } /*****************************************************************************/ /* */ int GBytesPrecision (double GBytes) { /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "GBytesPrecision() |%f|\n", GBytes); if (GBytes < 1.0) return (3); if (GBytes < 10.0) return (2); return (1); } /*****************************************************************************/ /* */ GetDiskInfo ( char *DiskName, struct DiskInfoStruct *diptr ) { static long DviDevClass = DVI$_DEVCLASS, DviDevChar = DVI$_DEVCHAR, DviDevChar2 = DVI$_DEVCHAR2, DviFullDevNam = DVI$_FULLDEVNAM, DviFreeBlocks = DVI$_FREEBLOCKS, DviErrCnt = DVI$_ERRCNT, DviMaxBlock = DVI$_MAXBLOCK, DviMediaName = DVI$_MEDIA_NAME, DviNextDevNam = DVI$_NEXTDEVNAM, DviSts = DVI$_STS, DviVolNumber = DVI$_VOLNUMBER, DviVolSetMem = DVI$_VOLSETMEM; register char *cptr, *sptr; int status; unsigned short StringItemLength; $DESCRIPTOR (DeviceNameDsc, ""); $DESCRIPTOR (StringItemDsc, ""); /*********/ /* begin */ /*********/ if (Debug) fprintf (stdout, "GetDiskInfo() |%s|\n", DiskName); diptr->MaxBlock = diptr->FreeBlocks = diptr->UsedBlocks = 0; diptr->FullDevName[0] = diptr->NextDevName[0] = diptr->MediaName[0] = '\0'; diptr->UcbStatus.lo32 = diptr->UcbStatus.hi32 = 0; DeviceNameDsc.dsc$w_length = strlen (DiskName); DeviceNameDsc.dsc$a_pointer = DiskName; if (VMSnok (status = lib$getdvi (&DviDevClass, 0, &DeviceNameDsc, &diptr->DevClass, 0, 0))) return (status); if (!(diptr->DevClass & DC$_DISK)) return (SS$_NORMAL); if (VMSnok (status = lib$getdvi (&DviDevChar, 0, &DeviceNameDsc, &diptr->DevChar, 0, 0))) return (status); if (!(diptr->DevChar & DEV$M_MNT)) return (SS$_NORMAL); if (VMSnok (status = lib$getdvi (&DviDevChar2, 0, &DeviceNameDsc, &diptr->DevChar2, 0, 0))) return (status); if (VMSnok (status = lib$getdvi (&DviSts, 0, &DeviceNameDsc, &diptr->UcbStatus, 0, 0))) return (status); StringItemDsc.dsc$w_length = sizeof(diptr->FullDevName); StringItemDsc.dsc$a_pointer = diptr->FullDevName; if (VMSnok (status = lib$getdvi (&DviFullDevNam, 0, &DeviceNameDsc, 0, &StringItemDsc, &StringItemLength))) return (status); diptr->FullDevName[StringItemLength] = '\0'; if (diptr->FullDevName[0] == '_') { /* copy the string over itself to get rid of the leading underscore */ cptr = diptr->FullDevName; sptr = diptr->FullDevName+1; while (*sptr != '\0' && *sptr != ' ') *cptr++ = *sptr++; *cptr = '\0'; } StringItemDsc.dsc$w_length = sizeof(diptr->MediaName); StringItemDsc.dsc$a_pointer = diptr->MediaName; if (VMSnok (status = lib$getdvi (&DviMediaName, 0, &DeviceNameDsc, 0, &StringItemDsc, &StringItemLength))) return (status); /* terminate the device name at the first white-space */ diptr->MediaName[StringItemLength] = '\0'; cptr = diptr->MediaName; while (*cptr != '\0' && *cptr != ' ') cptr++; *cptr = '\0'; if (VMSnok (status = lib$getdvi (&DviVolSetMem, 0, &DeviceNameDsc, &diptr->VolSetMem, 0, 0))) return (status); if (diptr->VolSetMem) { if (VMSok (status)) status = lib$getdvi (&DviVolNumber, 0, &DeviceNameDsc, &diptr->VolNumber, 0, 0); StringItemDsc.dsc$w_length = sizeof(diptr->NextDevName); StringItemDsc.dsc$a_pointer = diptr->NextDevName; status = lib$getdvi (&DviNextDevNam, 0, &DeviceNameDsc, 0, &StringItemDsc, &StringItemLength); diptr->NextDevName[StringItemLength] = '\0'; if (diptr->NextDevName[0] == '_') { /* copy the string over itself to get rid of the leading underscore */ cptr = diptr->NextDevName; sptr = diptr->NextDevName+1; while (*sptr != '\0' && *sptr != ' ') *cptr++ = *sptr++; *cptr = '\0'; } } if (VMSnok (status = lib$getdvi (&DviMaxBlock, 0, &DeviceNameDsc, &diptr->MaxBlock, 0, 0))) return (status); if (VMSnok (status = lib$getdvi (&DviFreeBlocks, 0, &DeviceNameDsc, &diptr->FreeBlocks, 0, 0))) return (status); diptr->UsedBlocks = diptr->MaxBlock - diptr->FreeBlocks; if (Debug) fprintf (stdout, "**********\n\ UcbStatus.lo32: %08.08X\n\ UcbStatus.hi32: %08.08X\n\ DevClass: %d\n\ DevChar: %d\n\ DevChar2: %d\n\ MaxBlock: %d\n\ FreeBlocks: %d\n\ UsedBlocks: %d\n\ VolNumber: %d\n\ VolSetMem: %d\n\ ErrCnt: %d\n\ FullDevName: %s\n\ NextDevName: %s\n\ MediaName: %s\n\ **********\n", diptr->UcbStatus.lo32, diptr->UcbStatus.hi32, diptr->DevClass, diptr->DevChar, diptr->DevChar2, diptr->MaxBlock, diptr->FreeBlocks, diptr->UsedBlocks, diptr->VolNumber, diptr->VolSetMem, diptr->ErrCnt, diptr->FullDevName, diptr->NextDevName, diptr->MediaName); return (SS$_NORMAL); } /*****************************************************************************/ /* */ ErrorGeneral ( char *Text, char *SourceFileName, int SourceLineNumber ) { register char *cptr; /*********/ /* begin */ /*********/ /* The source file format provided by the "__FILE__" macro will be "device:[directory]name.type;ver". Reduce that to "name.type". */ for (cptr = SourceFileName; *cptr && *cptr != ';'; cptr++); if (*cptr) { while (*cptr != '.') cptr--; *cptr-- = '\0'; } while (*cptr != ']') cptr--; cptr++; if (HttpHasBeenOutput) { fprintf (stdout, "


\n\

ERROR!

\n\ \n\

Reported by server.\n\

%s\n\ \n\ \n", SoftwareID, cptr, SourceLineNumber, Text); } else { fprintf (stdout, "HTTP/1.0 404 Error\r\n\ Server: %s\r\n\ Content-Type: text/html%s\r\n\ \r\n\ \n\ \n\ \n\ \n\ \n\ Error 404\n\ \n\ \n\

ERROR!

\n\

Reported by server.\n\

%s\n\ \n\ \n", CgiServerSoftwarePtr, ContentTypeCharset, SoftwareID, cptr, SourceLineNumber, Text); } return (SS$_NORMAL); } /*****************************************************************************/ /* */ ErrorVmsStatus ( int StatusValue, char *Text, char *HiddenText, char *SourceFileName, int SourceLineNumber ) { static char Message [256]; static $DESCRIPTOR (MessageDsc, Message); register char *cptr; int status; short int Length; /*********/ /* begin */ /*********/ if (VMSok (status = sys$getmsg (StatusValue, &Length, &MessageDsc, 1, 0))) { Message[Length] = '\0'; Message[0] = toupper(Message[0]); } else strcpy (Message, ""sys$getmsg() failed""); /* The source file format provided by the "__FILE__" macro will be "device:[directory]name.type;ver". Reduce that to "name.type". */ for (cptr = SourceFileName; *cptr && *cptr != ';'; cptr++); if (*cptr) { while (*cptr != '.') cptr--; *cptr-- = '\0'; } while (*cptr != ']') cptr--; cptr++; if (HttpHasBeenOutput) { fprintf (stdout, "


\n\

ERROR!

\n\ \n\

Reported by server.\n\

%s ... %s\n\ \n\ \n\ \n", SoftwareID, cptr, SourceLineNumber, Message, Text, StatusValue, HiddenText); } else { fprintf (stdout, "HTTP/1.0 404 Error\r\n\ Server: %s\r\n\ Content-Type: text/html%s\r\n\ \r\n\ \n\ \n\ \n\ \n\ \n\ Error 404\n\ \n\ \n\

ERROR!

\n\

Reported by server.\n\

%s ... %s\n\ \n\ \n\ \n", CgiServerSoftwarePtr, ContentTypeCharset, SoftwareID, cptr, SourceLineNumber, Message, Text, StatusValue, HiddenText); } return (SS$_NORMAL); } /****************************************************************************/ /* Does a case-insensitive, character-by-character string compare and returns true if two strings are the same, or false if not. If a maximum number of characters are specified only those will be compared, if the entire strings should be compared then specify the number of characters as 0. */ boolean strsame ( register char *sptr1, register char *sptr2, register int count ) { while (*sptr1 && *sptr2) { if (toupper (*sptr1++) != toupper (*sptr2++)) return (false); if (count) if (!--count) return (true); } if (*sptr1 || *sptr2) return (false); else return (true); } /*****************************************************************************/