/******************************************************************** * wilkinson * 3.27VMS * 1996/01/24 11:00 * gopher_root1:[gopher.g2.vms2_13.gopherd]index.c,v * Exp * * Paul Lindner, University of Minnesota CIS. * * Copyright 1991, 1992 by the Regents of the University of Minnesota * see the file "Copyright" in the distribution for conditions of use. ********************************************************************* * MODULE: index.c * Routines to deal with various types of indexes. ********************************************************************* * Revision History: * index.c,v * Revision 3.27VMS-1 1996/01/24 11:00 wilkinson * Made OPCOM message console selection configurable * * Revision 3.27VMS 1995/09/25 14:45 wilkinson * Consolodate VMS/Unix source code for server as well as client * * Revision 3.27 1995/02/16 22:32:40 lindner * HTML icon support * * Revision 3.26 1994/11/29 05:07:10 lindner * Allow script paths with spaces, better error messages * * Revision 3.25 1994/10/19 03:32:17 lindner * NO_INDEXING hack * * Revision 3.24 1994/10/13 05:17:49 lindner * Compiler complaint fixes * * Revision 3.23 1994/10/02 02:58:08 lindner * Fix for gopher+ index accesses * * Revision 3.22 1994/07/21 17:22:27 lindner * /dev/null code from Brian * * Revision 3.21 1994/06/29 05:25:43 lindner * Add Gticket * * Revision 3.20 1994/05/14 04:18:14 lindner * Fix weird prob... * * Revision 3.19 1994/04/27 19:22:20 lindner * compatible.h added * * Revision 3.18 1994/04/08 21:08:07 lindner * Fix a bug in the Shell Search code * * Revision 3.17 1994/03/08 15:56:04 lindner * gcc -Wall fixes * * Revision 3.16 1994/01/21 03:55:38 lindner * Remove old dead HTML code, update function declarations * * Revision 3.15 1993/11/02 06:01:43 lindner * HTML mods * * Revision 3.14 1993/09/30 16:57:05 lindner * Fix for WAIS and $ requests * * Revision 3.13 1993/09/21 02:47:36 lindner * Fix index problem closing null file handle * * Revision 3.12 1993/09/11 04:40:44 lindner * Don't fork for localhost mindex databases * * Revision 3.11 1993/08/23 18:34:28 lindner * Add fixfile() call * * Revision 3.10 1993/08/06 14:30:44 lindner * Fixes for better security logging * * Revision 3.9 1993/08/05 20:44:02 lindner * Use Gpopen instead of popen, remove extra filtering code * * Revision 3.8 1993/08/04 22:12:43 lindner * Mods to use Gpopen * * Revision 3.7 1993/07/27 05:27:50 lindner * Mondo Debug overhaul from Mitra * * Revision 3.6 1993/07/26 15:31:13 lindner * mods for application/gopher-menu * * Revision 3.5 1993/07/20 23:56:44 lindner * LOGGopher mods * * Revision 3.4 1993/04/15 21:41:38 lindner * Added $ to list of naughty characters (just in case) * * Revision 3.3 1993/04/09 15:54:29 lindner * Fixes for indexes with gopher+ * * Revision 3.2 1993/03/26 19:47:06 lindner * First crack at gopherplussing Indexing * * Revision 3.1.1.1 1993/02/11 18:02:52 lindner * Gopher+1.2beta release * * Revision 1.3 1993/01/30 23:57:44 lindner * Removed html code, moved parsing of the inputline to gopherd.c * * Revision 1.2 1992/12/14 21:36:05 lindner * Fixed problem in ShellIndexQuery, cp wasn't being incremented. * Also added special character elimination from GrepIndexQuery * * Revision 1.1 1992/12/10 23:13:27 lindner * gopher 1.1 release * * *********************************************************************/ #include "compatible.h" #include "gopherd.h" #include "command.h" #include "fileio.h" #include "Debug.h" #ifdef VMS_SERVER #undef stat /** Stupid openers thing **/ #undef chdir /** Use the real runtime routine under VMS **/ #include "serverutil.h" #include #endif #include #ifndef NO_INDEXING #define WAISTYPE 1 #define NEXTTYPE 2 #define SHLLTYPE 3 #define GREPTYPE 4 #ifdef VMS_SERVER #define CMD1TYPE 5 #include void SearchVersion(int, GopherObj *, GopherDirObj *); void Kaboom(int, GopherObj *, GopherDirObj *); void CreateGO4link(GopherObj *, GopherDirObj *, char *); void CreateFTPlink(GopherObj *, GopherDirObj *, char *); void CreateEXElink(GopherObj *, GopherDirObj *, char *, char, char *); void GDpostprocVMS(GopherDirObj *, GDCobj *, int, boolean); #ifdef system #undef system #endif #define system(a) VMS$system(a) boolean Do_Sort; boolean Do_DateNsize; boolean Do_Gplus; boolean tried_support; #endif void Do_IndexTrans(sockfd, IndexDirectory, cmd, SendEOF) int sockfd; char *IndexDirectory; CMDobj *cmd; boolean SendEOF; { char *cp = NULL; char *dbName = NULL; #ifndef VMS_SERVER char INDEXHost[256], INDEXPath[256]; /** Hard coded limits, ugh! **/ #else String *INDEXHost; /** No hard coded limits this way **/ String *INDEXPath; int status; char *inputline = CMDgetSelstr(cmd); #endif int INDEXPort=0; int Index_type=0; char *SearchString = CMDgetSearch(cmd); boolean isgplus; char *view = CMDgetView(cmd); char tmp_IndexDirectory[256]; Debug("Index Dir is %s\n", IndexDirectory); #ifdef VMS_SERVER { /** First siphon off the sorting & DateNsize tokens, if any **/ char *cp; Do_Sort = -1; /* Do Sort: Not TRUE, Not FALSE */ Do_DateNsize = -1; /* Same for Do DateNsize */ Do_Gplus = FALSE; /* G+ is *not* the default */ cp = inputline; while (*cp==':') { if (strncasecmp(cp,":sort:",strlen(":sort:"))==0) { inputline = (cp += strlen(":sort")) + 1; Do_Sort = TRUE; } else if (strncasecmp(cp,":nosort:",strlen(":nosort:"))==0) { inputline = (cp += strlen(":nosort")) + 1; Do_Sort = FALSE; } else if (strncasecmp(cp,":G+:",strlen(":G+:"))==0) { inputline = (cp += strlen(":G+")) + 1; Do_Gplus = TRUE; } else if (strncasecmp(cp,":noG+:",strlen(":noG+:"))==0) { inputline = (cp += strlen(":noG+")) + 1; Do_Gplus = FALSE; } else if (strncasecmp(cp,":G0:",strlen(":G0:"))==0) { inputline = (cp += strlen(":G0")) + 1; Do_Gplus = FALSE; } else if (strncasecmp(cp,":D&Sz:",strlen(":D&Sz:"))==0) { inputline = (cp += strlen(":D&Sz")) + 1; Do_DateNsize = TRUE; } else if (strncasecmp(cp,":noD&Sz:",strlen(":noD&Sz:"))==0) { inputline = (cp += strlen(":noD&Sz")) + 1; Do_DateNsize = FALSE; } } } #endif Index_type = Find_index_type(IndexDirectory); isgplus = CMDisGplus(cmd); Debug("Index type is %d\n", Index_type); if (Index_type < 0) { /**** Error condition, unknown index type... ****/ #ifdef VMS_SERVER SetAbrtFile(IndexErr, NULL /* AbortGS ??? */, KeepAbrtGS, NULL); #endif Abortoutput(sockfd, "Unknown index type"); return; } if (Index_type == WAISTYPE) { /*** The selector string has both the directory and the dbname... ***/ cp = strrchr(IndexDirectory, '/'); if (cp == NULL) dbName = "index"; else { dbName= cp+1; *cp='\0'; } } #ifndef VMS_SERVER else if (Index_type == SHLLTYPE) { /*** The selector string has both the directory and the dbname... ***/ cp = strrchr(IndexDirectory, '/'); if (cp == NULL) { dbName = IndexDirectory; IndexDirectory = tmp_IndexDirectory; strcpy (tmp_IndexDirectory, "/"); } else { dbName= cp+1; *cp='\0'; } } if (Read_hostdata(IndexDirectory, INDEXHost, &INDEXPort, INDEXPath, dbName) <0) { LOGGopher(sockfd, "Malformed hostdata file"); writestring(sockfd, "0Error on server, malformed hostdata\t\t\t1\r\n.\r\n"); return; } if (Index_type == SHLLTYPE) { if (IndexDirectory == tmp_IndexDirectory) IndexDirectory = dbName; else *(dbName-1) = '/'; } /* Doctor up the indexdirectory path if we're not running chroot() * we use fixfile to keep things secure.... */ if (!dochroot) IndexDirectory = fixfile(IndexDirectory); #else else if (Index_type == SHLLTYPE) if (tried_support) uchdir(GDCgetSupportDir(Config)); INDEXHost = STRnew(); STRset(INDEXHost, GDCgetHostname(Config)); INDEXPath = STRnew(); STRset(INDEXPath, IndexDirectory); INDEXPort = GDCgetPort(Config); #endif /** And call the appropriate query function **/ switch (Index_type) { case NEXTTYPE: NeXTIndexQuery(sockfd, SearchString, IndexDirectory, NULL, INDEXHost, INDEXPort, INDEXPath, isgplus, view); break; case WAISTYPE: WaisIndexQuery(sockfd, IndexDirectory, SearchString, dbName, INDEXHost, INDEXPort, INDEXPath, isgplus, view); break; case GREPTYPE: #ifndef VMS_SERVER GrepIndexQuery(sockfd, IndexDirectory, SearchString, INDEXHost, INDEXPort, INDEXPath); #else if (Do_DateNsize == -1) Do_DateNsize = TRUE; if (Do_Sort == -1) Do_Sort = GDCgetSortGREP(Config); if (Do_Gplus == -1) Do_Gplus = GDCgetIsGplus(Config); GrepIndexQuery(sockfd, IndexDirectory, SearchString, STRget(INDEXHost), INDEXPort, STRget(INDEXPath)); #endif break; case SHLLTYPE: #ifndef VMS_SERVER ShellIndexQuery(sockfd, IndexDirectory, SearchString, isgplus); #else if (Do_DateNsize == -1) Do_DateNsize = TRUE; if (Do_Sort == -1) Do_Sort = GDCgetSortShell(Config); if (Do_Gplus == -1) Do_Gplus = GDCgetIsGplus(Config); ShellIndexQuery(sockfd, IndexDirectory, SearchString, isgplus, STRget(INDEXHost), INDEXPort, STRget(INDEXPath)); #endif break; #ifdef VMS_SERVER case CMD1TYPE: if (Do_DateNsize == -1) Do_DateNsize = TRUE; if (Do_Sort == -1) Do_Sort = GDCgetSortCMD1(Config); if (Do_Gplus == -1) Do_Gplus = GDCgetIsGplus(Config); CMD1IndexQuery(sockfd, IndexDirectory, SearchString, STRget(INDEXHost), INDEXPort, STRget(INDEXPath)); break; #endif } #ifdef VMS_SERVER STRdestroy(INDEXHost); STRdestroy(INDEXPath); #endif /** Finish the transmission attempt **/ if (SendEOF) writestring(sockfd, ".\r\n"); /** Log it here so we get the query in the logfile **/ if (dbName) LOGGopher(sockfd,"search %s/%s for %s", IndexDirectory, dbName, SearchString); else LOGGopher(sockfd, "search %s for %s", IndexDirectory, SearchString); } /* * Try to figure out what each type of object is * * index types are * Error == -1 * WAIS == 1 * NeXT == 2 * ShellScript == 3 * Grep == 4 */ int Find_index_type(gopherpath) char *gopherpath; { char Teststr[512]; FILE *Testfile; #ifdef VMS_SERVER char VMSdirectory[256]; char *cp; tried_support = FALSE; /*** Check for the VMS CMD1TYPE designator ($) ***/ if (gopherpath[0] == '$') { cp = skip_whitespace(gopherpath+1); strcpy(Teststr, cp); if ((cp=strchr(Teststr,' '))!=NULL) *cp = '\0'; /*** Check for a valid CMD1TYPE sub-type ***/ if ((strcasecmp(Teststr,"SEARCH")==0) || (strcasecmp(Teststr,"SEARCH&")==0) || (strcasecmp(Teststr,"SEARCH|")==0) || (strcasecmp(Teststr,"SEARCH~&")==0) || (strcasecmp(Teststr,"SEARCH~|")==0) || (strcasecmp(Teststr,"SINCE")==0) || (strcasecmp(Teststr,"BEFORE")==0) || (strcasecmp(Teststr,"VERSION")==0) || (strcasecmp(Teststr,"KABOOM")==0) || (strcasecmp(Teststr,"GO4LINK")==0) || (strcasecmp(Teststr,"FTPLINK")==0) || (strcasecmp(Teststr,"EXELINK")==0)) { return(CMD1TYPE); } } { char *cp1, path[256]; strcpy(Teststr, gopherpath); /* find end of first selector token */ if ((cp=strchr(Teststr,' '))!=NULL) *cp = '\0'; if (Teststr[0] == '/') { /* Convert to VMS pathspec before testing */ strcpy(path, (cp1=VMS$WWW_to_VMS(Teststr, A_FILE)) ? cp1 : Teststr); strcpy(Teststr, path); } else strcpy(path, Teststr); /* In case we need it later... */ Try_Support: Testfile = fopen_VMSopt(Teststr, "r"); if (Testfile != NULL) { /** Shell script? **/ if (strcasecmp(Teststr+strlen(Teststr)-strlen(".SHELL"),".SHELL")==0) if (getc(Testfile) == '$') if (getc(Testfile) == '!') { fclose(Testfile); return(SHLLTYPE); } } else if (!tried_support) { tried_support = TRUE; strcpy(Teststr, GDCgetSupportDir(Config)); strcat(Teststr, path); /* Told ya we'd need it... */ goto Try_Support; } } strcpy(Teststr, gopherpath); if (Teststr[0] == '/') { /* Convert to VMS pathspec */ char *cp1, path[256]; strcpy(path, (cp1=VMS$WWW_to_VMS(Teststr, A_FILE)) ? cp1 : Teststr); strcpy(Teststr, path); } if ((cp=strchr(Teststr,'[')) && strchr(cp,']')) return(GREPTYPE); #else strcpy(Teststr, gopherpath); strcat(Teststr, "/.index/index.ixif"); Testfile = rfopen(Teststr, "r"); if (Testfile != NULL) { /*** Next Index ***/ fclose(Testfile); return(NEXTTYPE); } strcpy(Teststr, gopherpath); strcat(Teststr, ".inv"); Testfile = rfopen(Teststr, "r"); if (Testfile != NULL) { /*** WAIS Index ***/ fclose(Testfile); return(WAISTYPE); } strcpy(Teststr, gopherpath); if (isadir(Teststr) == 1) { return(GREPTYPE); } Testfile = rfopen(Teststr, "r"); if (Testfile != NULL) { /** Shell script? **/ if (getc(Testfile) == '#') if (getc(Testfile) == '!') { fclose(Testfile); return(SHLLTYPE); } } #endif return(-1); } #ifndef VMS_SERVER /* * Read in the data from a hostdata file... * * Try ".hostdata" first, fall back to "hostdata" otherwise */ int Read_hostdata(IndexDirectory, INDEXHost, INDEXPort, INDEXPath, dbName) char *IndexDirectory; char *INDEXHost, *INDEXPath; int *INDEXPort; char *dbName; { FILE *Hostfile; char hostdataName[256]; /** Read in the proper hostdata file.... **/ rchdir(IndexDirectory); /** Change into the index directory **/ sprintf(hostdataName, "%s.hostdata", dbName); /* try idx.hostdata */ if ((Hostfile = ufopen(hostdataName, "r")) == NULL) Hostfile = ufopen("hostdata", "r"); if (Hostfile == NULL) { /*** Use the current host/port as the default ***/ strcpy(INDEXHost, Zehostname); *INDEXPort = GopherPort; strcpy(INDEXPath, Data_Dir); } else { char tempbuf[255]; if (fgets(INDEXHost, 64, Hostfile) == NULL) return(-1); ZapCRLF(INDEXHost); if (fgets(tempbuf, 255, Hostfile) == NULL) return(-1); if ((*INDEXPort=atoi(tempbuf))==0) return(-1); if (fgets(INDEXPath, 256, Hostfile) == NULL) return(-1); ZapCRLF(INDEXPath); fclose(Hostfile); } return(0); } #endif /* * This is a searching function that runs grep across files * in a single directory... */ void GrepIndexQuery(sockfd, Indexdir, Searchstr, INDEXHost, INDEXPort, INDEXPath) int sockfd; char *Indexdir; char *Searchstr; char *INDEXHost; int INDEXPort; char *INDEXPath; { FILE *moocow; char command[512]; char inputline[512]; char *cp; GopherObj *gs; GopherDirObj *gd; #ifdef VMS_SERVER char path[256]; char *c2, *c3; if (Indexdir[0] == '/') { /* Convert to VMS pathspec */ strcpy(path, (c2=VMS$WWW_to_VMS(Indexdir, A_FILE)) ? c2 : Indexdir); strcpy(Indexdir, path); } c3 = c2 = (char *) malloc(sizeof(char)*strlen(Indexdir)+1); strcpy(c3,Indexdir); while (strlen(c2)) { cp = strpbrk(c2,","); if (cp) *cp = '\0'; if (!VMS$Validate_Filespec(c2)) { LOGGopher(sockfd, "GREP Illegal syntax for %s", Indexdir); SetAbrtFile(SyntaxErr, NULL /* AbortGS ??? */, KeepAbrtGS, NULL); Abortoutput(sockfd, "Eh? Confusing Request"); free(c3); return; } c2 += strlen(c2) + ((cp==NULL) ? 0 : 1); } free(c3); #endif gs = GSnew(); gd = GDnew(32); #ifndef VMS_SERVER cp = Searchstr; while (*cp != '\0') { if (*cp == ';' ||*cp == '"' || *cp == '`' || *cp == '$') *cp = '.'; cp++; } sprintf(command, "egrep \"%s\" \"%s\"/*", Searchstr, Indexdir); #else GSsetDefaults(gs); /* Oughtn't Unix do this to? */ strcpy(vms_pipe_file, cp=tempnam(GDCgetScratchDir(Config),NULL)); free(cp); /*** If not Inetd/MULTINET_SERVER and no EGREP, use SEARCH ***/ if (!RunFromInetd && getenv("EGREP") == NULL) { while(cp=strpbrk(Searchstr," \t\r\n")) { if (*(cp-1)==',') strcpy(cp,cp+1); else *cp = ','; } sprintf(command,"$ search/nohead/output=%s/window=0 %s %s", vms_pipe_file, Indexdir, Searchstr); } /*** Use EGREP ***/ else { cp = Searchstr; while (*cp != '\0') { if (*cp == '"' || *cp == '`') *cp = '.'; cp++; } if (Indexdir[strlen(Indexdir)-1] == ']') sprintf(command,"$ egrep -il \">%s\" -e \"%s\" \"%s*.*;\"", vms_pipe_file, Searchstr, Indexdir); else sprintf(command,"$ egrep -il \">%s\" -e \"%s\" \"%s\"", vms_pipe_file, Searchstr, Indexdir); } if (strlen(Searchstr)==0) { writestring(sockfd, ".\r\n"); LOGGopher(sockfd, "Null Search String"); GSdestroy(gs); GDdestroy(gd); return; } #endif Debug("Grep command is %s\n", command); moocow = Gpopen(sockfd, command, "r"); if (moocow == NULL) { LOGGopher(sockfd, "Couldn't open grep command"); #ifdef VMS_SERVER GSdestroy(gs); /* Oughtn't Unix do this too? */ GDdestroy(gd); #endif return; } while (fgets(inputline, 512, moocow)) { ZapCRLF(inputline); GSsetType(gs, A_FILE); #ifndef VMS_SERVER cp = strstr(inputline, INDEXPath) + strlen(INDEXPath); GSsetTitle(gs, cp); cp = strchr(inputline, ':'); *cp='\0'; cp =strstr(inputline, INDEXPath) + strlen(INDEXPath); #else if (isadir(inputline)==1) GSsetType(gs,A_DIRECTORY); /* force names lowercase */ str_tolower(cp=inputline); /* create the path and filename */ strcpy(path, cp); c2 = strchr(path,']') + 1; *c2 = '\0'; c2 = strchr(inputline,';'); *c2 = '\0'; c2 = strchr(inputline,']')+1; if (GDCignore(Config,c2)) continue; if (chdir(path)<0) continue; c2 = (char *)malloc(2+strlen(inputline)); *c2 = GSgetType(gs); strcpy(c2+1,inputline); strcpy(inputline, c2); free(c2); cp = inputline; #endif GSsetPath(gs, cp); GSsetHost(gs, INDEXHost); GSsetPort(gs, INDEXPort); GDaddGS(gd, gs); } #ifdef VMS_SERVER if (GDgetNumitems(gd)) { GDpostprocVMS(gd,Config,GopherPort,Do_Gplus); if (Do_DateNsize) GDaddDateNsize(gd); if (Do_Sort) GDsort(gd); #endif if (UsingHTML) GDtoNet(gd, sockfd, GSFORM_HTML, Gticket, NULL); else { GDtoNet(gd, sockfd, GSFORM_G0, Gticket, NULL); } #ifdef VMS_SERVER } GSdestroy(gs); GDdestroy(gd); #endif pclose(moocow); } /* * This starts up a shell script that's defined to be an index gateway * * The shell script should write out standard gopher directory protocol. */ #ifndef VMS_SERVER void ShellIndexQuery(sockfd, Script, Searchstring, isgplus) #else void ShellIndexQuery(sockfd, Script, Searchstring, isgplus, INDEXHost, INDEXPort, INDEXPath) char *INDEXHost; int INDEXPort; char *INDEXPath; #endif int sockfd; char *Script; char *Searchstring; boolean isgplus; { GopherDirObj *gd; char Command[512]; #ifndef VMS_SERVER FileIO *Searchf; #else FILE *Searchf; #endif int result; #ifdef VMS_SERVER char *cp; char *cfg; int status; if((cp=strchr(Script,' '))!=NULL) { char *cp1, path[256]; *cp = '\0'; if(Script[0] == '/') /* Convert to first pathspec to VMS syntax */ sprintf(path, "%s ", (cp1=VMS$WWW_to_VMS(Script, A_FILE)) ? cp1 : Script); else sprintf(path, "%s ", Script); if(*(cp+1) == '/') /* Convert to second pathspec to VMS syntax */ strcat(path, (cp1=VMS$WWW_to_VMS(cp+1, A_FILE)) ? cp1 : cp+1); else strcat(path, cp+1); *cp = ' '; strcpy(Script, path); strcpy(vms_pipe_file, Script); if ((cp=strchr(vms_pipe_file,' '))!=NULL) *cp = '\0'; if (!VMS$Validate_Filespec(vms_pipe_file)) { LOGGopher(sockfd, "SHELL Illegal syntax for %s", Script); SetAbrtFile(SyntaxErr, NULL /* AbortGS ??? */, KeepAbrtGS, NULL); Abortoutput(sockfd, "Eh? Confusing Request","syntax"); return; } /*** Clean up the arguments, remove ; and " and `**/ cp = Searchstring; while (*cp != '\0') { if (*cp == ';' ||*cp == '"' || *cp == '`') *cp = '.'; cp++; } } #endif gd = GDnew(32); #ifndef VMS_SERVER sprintf(Command, "\"%s\" %s", Script, Searchstring); Searchf = FIOopenCmdline(Command, "r"); #else strcpy(vms_pipe_file, cp=tempnam(GDCgetScratchDir(Config),NULL)); free(cp); cp = GDCgetDatadir(Config); cfg = (char *) malloc(sizeof(char)*strlen(cp+1)); strcpy(cfg, cp); if ((cp=strchr(cfg,':'))!=NULL) *cp='\0'; sprintf(Command, "$ @%s %s \"%s\" \"%s\" %d %s", Script, vms_pipe_file, Searchstring, INDEXHost, INDEXPort, cfg); LOGGopher(sockfd, "Command: %s", Command); free(cfg); Searchf = Gpopen(sockfd, Command, "r"); #endif if (Searchf == NULL) { #ifdef VMS_SERVER SetAbrtFile(NothingThere, NULL /* AbortGS ??? */, KeepAbrtGS, NULL); #endif Abortoutput(sockfd,"Cannot execute shell script"); #ifdef VMS_SERVER GDdestroy(gd); /* Oughtn't Unix do this, too? */ return; #endif } #ifndef VMS_SERVER GDfromNet(gd, FIOgetfd(Searchf), NULL); #else GDfromNet(gd, fileno(Searchf), NULL); if (GDgetNumitems(gd)) { GDpostprocVMS(gd,Config,GopherPort,Do_Gplus); if (Do_DateNsize) GDaddDateNsize(gd); if (Do_Sort) GDsort(gd); #endif if (UsingHTML) GDtoNet(gd, sockfd, GSFORM_HTML, Gticket, NULL); else { if (isgplus) GDplustoNet(gd, sockfd, NULL, Gticket); else GDtoNet(gd, sockfd, GSFORM_G0, Gticket, NULL); } #ifdef VMS_SERVER } result = pclose(Searchf); #else result = FIOclose(Searchf); #endif GDdestroy(gd); } #ifndef WAISSEARCH void WaisIndexQuery(sockfd, index_directory, SearchWords, new_db_name, INDEXHost, INDEXPort, INDEXPath, isgplus, view) int sockfd; char *index_directory; char *SearchWords; char *new_db_name; char *INDEXHost; int INDEXPort; char *INDEXPath; boolean isgplus; char *view; { #ifdef VMS_SERVER LOGGopher(sockfd, "WAIS index %s, srch '%s', Db %s", index_directory, SearchWords, new_db_name); SetAbrtFile(IndexErr, NULL, KeepAbrtGS, NULL); Abortoutput(sockfd, "Sorry, no WAIS indexing supported"); #else Abortoutput(sockfd, "This Server doesn't have WAIS compiled in it..."); #endif return; } #endif #ifndef NEXTSEARCH void NeXTIndexQuery(sockfd, SearchWords, ZIndexDirectory, DatabaseNm, INDEXHost, INDEXPort, INDEXPath, isgplus, view) int sockfd; char *SearchWords; char *ZIndexDirectory; char *DatabaseNm; /*** Not used by the next indexer... ***/ char *INDEXHost; int INDEXPort; char *INDEXPath; boolean isgplus; char *view; { #ifdef VMS_SERVER LOGGopher(sockfd, "NeXT index %s, srch '%s'", ZIndexDirectory, SearchWords); SetAbrtFile(IndexErr, NULL, KeepAbrtGS, NULL); Abortoutput(sockfd, "Sorry, no NeXT indexing supported"); #else Abortoutput(sockfd, "This isn't a NeXT... is it?"); #endif return; } #endif #else /* NO_INDEXING */ void Do_IndexTrans(sockfd, IndexDirectory, cmd, SendEOF) int sockfd; char *IndexDirectory; CMDobj *cmd; { #ifdef VMS_SERVER SetAbrtFile(IndexErr, NULL, KeepAbrtGS, NULL); #endif Abortoutput(sockfd, "Sorry, no indexing in this server"); } #endif /* NO_INDEXING */ #if !defined(NO_INDEXING) && defined(VMS_SERVER) /* * This starts up a 1-line command that's defined to be an "index gateway" * Currently this is only implemented for VMS * * Currently "SEARCH", "SINCE", "BEFORE", "VERSION", "GO4LINK", "FTPLINK" * and "EXELINK" are supported. "KABOOM" is a debugging "feature." * * "SEARCH" performs a case-insensitive search for terms, without any * interpretation of printable characters, with leading and trailing spaces * trimmed, and with embedded spaces treated as the Boolean OR. The search * corresponds to the expectations of the client's Boldit() routine. SEARCH * may be suffixed by &, |, ~& or ~| to select the VMS /MATCH= operand, and * override the default, implicit /MATCH=OR. * * "SINCE" and "BEFORE" return lists of files modified since or before * the supplied term, a date specification. * * "VERSION" displays version information about the server. It's not really * a "search" even though it acts like one. * * "GO4LINK" uses a pseudo-SearchString (the Internet address of a Gopher * server) to create a link tuple which the client can use to connect to * a server there. * * "FTPLINK" uses a pseudo-SearchString (the Internet address of an FTP * archive) to create a link tuple which the client can pass to the server's * FTP gateway. * * "EXELINK" uses a pseudo-SearchString (the exec script arguments the user * wishes to pass) to create a link tuple which the client can pass to the * server for execution of a script. The type of output to be expected by * the client and the script to be executed are specified with the execlink * keyword. E.g., "Path=7$exelink Xscriptname" where "X" is the Type= * entry for the link tuple to be generated, and "scriptname" is the script * file name to be used in the Path=exec::scriptname tuple entry. The * , if any, are supplied by the user as the terms of the pseudo-search. * * "KABOOM" causes an access violation for debugging purposes. It will only * work when the local host alias and client requestor match the values * specified in the environment variables (symbols or logicals) named * GOPHERD_KABOOM_HOST and GOPHERD_KABOOM_CLIENT, respectively. * * The command must write output in the same format as the GrepIndexQuery() * output is formatted (that is, the result must be a menu of one entry or * more). * */ void CMD1IndexQuery(int sockfd, char *CMDcmd, char *Searchstr, char *INDEXHost, int INDEXPort, char *INDEXPath) { FILE *moocow; char command[512]; char inputline[512]; char *filename; char path[256]; char *cp; GopherObj *gs; GopherDirObj *gd; int status; char *c2, *c3; char *beg, *end; char VMSSearchstr[256]; char *match; char exectype; int i; if (filename=strchr((c2 = skip_whitespace(CMDcmd+1)),' ')) { filename++; if (*c2=='e' || *c2=='E') { exectype = *filename++; if (*filename==' ') filename=skip_whitespace(filename); } } else switch (*c2) { /* Some of these CMD1 searches don't need files */ case 'k': case 'K': goto files_valid; case 'g': case 'G': goto files_valid; case 'f': case 'F': goto files_valid; case 'v': case 'V': goto files_valid; default: goto illegal; } if (filename[0] == '/') { /* Convert to VMS pathspec */ char *cp1, path[256]; strcpy(path, (cp1=VMS$WWW_to_VMS(filename, A_FILE)) ? cp1 : filename); strcpy(filename, path); } c3 = c2 = (char *) malloc(sizeof(char)*strlen(filename)+1); strcpy(c3,filename); while (strlen(c2)) { cp = strpbrk(c2,","); if (cp) *cp = '\0'; if (!VMS$Validate_Filespec(c2)) { illegal: LOGGopher(sockfd, "CMD1 Illegal syntax for %s", CMDcmd); SetAbrtFile(SyntaxErr, NULL /* AbortGS ??? */, KeepAbrtGS, NULL); Abortoutput(sockfd, "Eh? Confusing Request"); free(c3); return; } c2 += strlen(c2) + ((cp==NULL) ? 0 : 1); } free(c3); files_valid: /*** Establish the output file for the VMS command ***/ strcpy(vms_pipe_file, cp=tempnam(GDCgetScratchDir(Config),NULL)); free(cp); /*** Get the CMD1TYPE sub-type ***/ cp = skip_whitespace(CMDcmd+1); if ((strncasecmp(cp, "SEARCH ", 7)==0) || (strncasecmp(cp, "SEARCH& ", 8)==0) || (strncasecmp(cp, "SEARCH| ", 8)==0) || (strncasecmp(cp, "SEARCH~& ", 9)==0) || (strncasecmp(cp, "SEARCH~| ", 9)==0)) { /*** Determine match qualification, if any ***/ match = NULL; if (strncmp(cp+6,"& ",2)==0) match = "/MATCH=AND"; else if (strncmp(cp+6,"| ",2)==0) match = "/MATCH=OR"; else if (strncmp(cp+6,"~& ",3)==0) match = "/MATCH=NAND"; else if (strncmp(cp+6,"~| ",3)==0) match = "/MATCH=NOR"; /*** Convert Searchstr for the VMS SEARCH command ***/ beg = Searchstr; end = beg + strlen(Searchstr); i = 0; /*** Trim any leading spaces and prefix a double-quote ***/ while (*(beg) == ' ' && beg < end) beg++; VMSSearchstr[i++] = '"'; while (beg < end) { /*** Reiterate any embedded double-quotes ***/ if (*beg == '"') { VMSSearchstr[i++] = '"'; VMSSearchstr[i++] = *(beg++); } /*** Replace any embedded spaces with a "," triplet ***/ /*** or omit trailing spaces ***/ else if (*beg == ' ') { while (*beg == ' ' && beg < end) beg++; if (beg < end) { VMSSearchstr[i++] = '"'; VMSSearchstr[i++] = ','; VMSSearchstr[i++] = '"'; } } /*** Otherwise, use the character as entered ***/ else VMSSearchstr[i++] = *(beg++); } /*** Append a double-quote and terminate ***/ VMSSearchstr[i++] = '"'; VMSSearchstr[i] = '\0'; } else if (strncasecmp(cp, "VERSION", 7)==0 || strncasecmp(cp, "KABOOM", 6)==0 || strncasecmp(cp, "GO4LINK", 7)==0 || strncasecmp(cp, "FTPLINK", 7)==0 || strncasecmp(cp, "EXELINK", 7)==0) { /*** No further validation required ***/ } else { /*** "SINCE" or "BEFORE" -- Validate the entry as a date ***/ if (!Validate_Date(Searchstr)) { LOGGopher(sockfd, "Illegal search term \"%s\" for %s", Searchstr, CMDcmd); SetAbrtFile(SyntaxErr, NULL /* AbortGS ??? */, KeepAbrtGS, NULL); Abortoutput(sockfd, "Eh? Unusable Search Term(s)"); return; } } gs = GSnew(); GSsetDefaults(gs); gd = GDnew(32); /*** Format the command string ***/ if (strncasecmp(cp, "SEARCH", 6)==0) { sprintf(command,"$search%s/nohead/output=%s/window=0 %s %s", match==NULL?"":match, vms_pipe_file, filename, VMSSearchstr); /*** Log the string actually used in the search ***/ LOGGopher(sockfd, "VMSSearchstr: %s", VMSSearchstr); } else if (strncasecmp(cp, "SINCE ", 6)==0) sprintf(command, "$dir/nohead/notrail/output=%s/since=%s %s", vms_pipe_file, Searchstr, filename); else if (strncasecmp(cp, "BEFORE ", 7)==0) sprintf(command, "$dir/nohead/notrail/output=%s/before=%s %s", vms_pipe_file, Searchstr, filename); else if (strncasecmp(cp, "VERSION", 7)==0) { sprintf(command, "determine version level"); vms_pipe_file[0] = '\0'; /* Won't need output file */ } else if (strncasecmp(cp, "KABOOM", 6)==0) { sprintf(command, "generate accvio exception"); vms_pipe_file[0] = '\0'; /* Won't need output file */ } else if (strncasecmp(cp, "GO4LINK", 7)==0) { sprintf(command, "create a Gopher Server tuple"); vms_pipe_file[0] = '\0'; /* Won't need output file */ } else if (strncasecmp(cp, "FTPLINK", 7)==0) { sprintf(command, "create an FTP gateway tuple"); vms_pipe_file[0] = '\0'; /* Won't need output file */ } else if (strncasecmp(cp, "EXELINK", 7)==0) { sprintf(command, "create an Exec script tuple"); vms_pipe_file[0] = '\0'; /* Won't need output file */ } Debug("CMD is %s\n", command); if (strlen(vms_pipe_file)==0) { /* One of our non-DCL commands...VERSION, GO4LINK, FTPLINK, EXELINK... */ moocow = NULL; GSsetHost(gs, INDEXHost); GSsetPort(gs, INDEXPort); switch(*cp) { case 'k': case 'K': Kaboom(sockfd, gs, gd); break; case 'g': case 'G': CreateGO4link(gs, gd, Searchstr); break; case 'f': case 'F': CreateFTPlink(gs, gd, Searchstr); break; case 'e': case 'E': CreateEXElink(gs, gd, Searchstr, exectype, filename); break; case 'v': case 'V': SearchVersion(sockfd, gs,gd); break; default: LOGGopher(sockfd, "Unknown non-DCL search %s",cp); } Do_Sort = Do_DateNsize = FALSE; } else { /* Read results much like we do for GREP indexes */ moocow = Gpopen(sockfd, command, "r"); if (moocow == NULL) { LOGGopher(sockfd,"Couldn't call/open CMD - %s", STRerror(errno)); GSdestroy(gs); GDdestroy(gd); return; } cp = inputline; while (fgets(cp+1, sizeof(inputline)-1, moocow)) { GSsetType(gs, A_FILE); if (isadir(cp+1)==1) GSsetType(gs,A_DIRECTORY); inputline[0] = GSgetType(gs); ZapCRLF(inputline); /* force names lowercase */ str_tolower(cp+1); /* create the path and filename */ strcpy(path, cp+1); c2 = strchr(path,']') + 1; *c2 = '\0'; c2 = strchr(inputline,';'); *c2 = '\0'; c2 = strchr(inputline,']')+1; if (GDCignore(Config,c2)) continue; if (chdir(path)<0) continue; GSsetPath(gs, inputline); GSsetHost(gs, INDEXHost); GSsetPort(gs, INDEXPort); GDaddGS(gd, gs); } pclose(moocow); } if (GDgetNumitems(gd)) { if (Do_Sort) GDsort(gd); GDpostprocVMS(gd,Config,GopherPort,Do_Gplus); if (Do_DateNsize) GDaddDateNsize(gd); if (UsingHTML) GDtoNet(gd, sockfd, GSFORM_HTML, Gticket, NULL); else { GDtoNet(gd, sockfd, GSFORM_G0, Gticket, NULL); } } GSdestroy(gs); GDdestroy(gd); } void SearchVersion(int sockfd, GopherObj *gs, GopherDirObj *gd) { FILE *fp; static long i; static char path[256]; char *x, *cp; char image[512]; time_t howlong = time(NULL) - ServerStarted + 1; int connperhour = (Connections * 3600) / howlong; char *started; struct stat stats_buf; struct dsc$descriptor_s dsc$tstamp = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0}; /* Structures IHDdef & IHIdef extrapolated from $IHDDEF and $IHIDEF, respectively, as found in SYS$LIBRARY:LIB.MLB, VMS v5.2 */ #ifndef __ALPHA struct IHDdef { short IHD$W_SIZE; short IHD$W_ACTIVOFF; short IHD$W_SYMDBGOFF; short IHD$W_IMGIDOFF; short IHD$W_PATCHOFF; short IHD$W_VERSION_ARRAY_OFF; /* There's more, but we don't need it... */ } *ihd$; struct IHIdef { char IHI$T_IMGNAM[40]; char IHI$T_IMGID[16]; char IHI$Q_LINKTIME[8]; char IHI$T_LINKID[16]; } *ihi$; #else struct IHIdef { char IHI$Q_LINKTIME[8]; char IHI$T_IMGNAM[40]; char IHI$T_IMGID[16]; char IHI$T_LINKID[16]; } *ihi$; #endif struct itmlst { unsigned short int length; unsigned short int code; char *bufadr; int *retlen; } itmlist[3] = { { 8, SYI$_VERSION, &path[100], (int *) &i}, { 31, SYI$_HW_NAME, &path[120], (int *) &i}, { 0, 0, 0, 0 } }; #define VCFG(a,b)\ { sprintf(path,(a),b);GSsetTitle(gs,path);GDaddGS(gd,gs); } #define VCFG2(a,b,c)\ { sprintf(path,(a),b,c);GSsetTitle(gs,path);GDaddGS(gd,gs); } #define IFAVAIL(a) (a?(strlen((a))==0?"N/A":(a)):"N/A") #define IFAVAILQ(a) (a?(strlen((a))==0?"":"\""):""), \ (a?(strlen((a))==0?"N/A":(a)):"N/A"), \ (a?(strlen((a))==0?"":"\""):"") bzero(image, sizeof(image)); bzero(path, sizeof(path)); GSsetGplus(gs,TRUE); GSsetNum(gs, 0); GSsetType(gs, path[0] = A_FILE); strcat(path,pname); if ((cp = strrchr(path, ';')) != 0) *cp = '\0'; GSsetPath(gs, path); if ((fp = ufopen(pname, "r")) == NULL) GSsetType(gs, A_ERROR); else { /* Read in 1st block of Image Header */ if (fread(image, sizeof(char), sizeof(image), fp) == 0) GSsetType(gs, A_ERROR); else { /* Pick up offset to Image Name & Ident */ #ifndef __ALPHA ihd$ = (struct IHDdef *)image; i = ihd$->IHD$W_IMGIDOFF; ihi$ = (struct IHIdef *)(image+i); #else ihi$ = (struct IHIdef *)(image+192); #endif strcpy(path,"%fn [%ts, %sz]"); GSsetTitle(gs,path); ustat(pname, &stats_buf); GSaddDateNsize(gs, stats_buf); sprintf(path, "Image: %s", GSgetTitle(gs)); GSsetTitle(gs,path); GSsetType(gs, A_UNIXBIN); sprintf(path,"%c%s", A_UNIXBIN, fgetname(fp,path+1)); GSsetPath(gs,path); GDaddGS(gd, gs); GSsetType(gs, A_INFO); GSsetPath(gs,""); if (DEBUG) { GSsetTitle(gs,"DEBUG Mode: Debugging"); GDaddGS(gd, gs); } strcpy(path,"Image Name: \""); strncat(path,ihi$->IHI$T_IMGNAM+1,ihi$->IHI$T_IMGNAM[0]); strcat(path, "\""); GSsetTitle(gs,path); GDaddGS(gd, gs); strcpy(path,"Image File ID: \""); strncat(path,ihi$->IHI$T_IMGID+1,ihi$->IHI$T_IMGID[0]); strcat(path, "\""); GSsetTitle(gs,path); GDaddGS(gd, gs); bzero(path,sizeof(path)-100); strcpy(path,"Link date/time: "); dsc$tstamp.dsc$a_pointer = path+strlen(path); dsc$tstamp.dsc$w_length = sizeof(path)-strlen(path); LIB$FORMAT_DATE_TIME(&dsc$tstamp,&(ihi$->IHI$Q_LINKTIME),0,&i,0); *(dsc$tstamp.dsc$a_pointer + i) = '\0'; if ((*dsc$tstamp.dsc$a_pointer) == ' ') memmove(dsc$tstamp.dsc$a_pointer,dsc$tstamp.dsc$a_pointer+1, i-1); GSsetTitle(gs,path); GDaddGS(gd, gs); strcpy(path,"Linker ID: \""); strncat(path,ihi$->IHI$T_LINKID+1,ihi$->IHI$T_LINKID[0]); strcat(path, "\""); GSsetTitle(gs,path); GDaddGS(gd, gs); } fclose(fp); } if (SS$_NORMAL!=SYS$GETSYIW(0,0,0,itmlist,0,0,0)) GSsetType(gs, A_ERROR); else { path[120+i] = '\0'; for (i=107; path[i]==' '; path[i--] = '\0'); str_tolower(&path[100]); sprintf(path, "Host System: %s, VMS %s",&path[120],&path[100]); GSsetTitle(gs,path); GDaddGS(gd, gs); } if (GSgetType(gs)==A_ERROR) LOGGopher(sockfd,"Could not report version information"); else LOGGopher(sockfd,"Reported version"); #ifdef MULTINET #define TCPIP_AGENT "TGV Multinet" #endif #ifdef UCX #define TCPIP_AGENT "UCX" #endif #ifdef WOLLONGONG #define TCPIP_AGENT "Wollongong" #endif #ifdef TCPIP_AGENT sprintf(path, "TCP/IP agent: %s", TCPIP_AGENT); GSsetTitle(gs,path); GDaddGS(gd, gs); #endif sprintf(path, "Revision Level: %s-%s", GOPHERD_VERSION, PATCH_LEVEL); GSsetTitle(gs, path); GDaddGS(gd, gs); if (Connections) { started = ctime(&ServerStarted); *(started+24) = '\0'; VCFG("Server Started: %s", started); VCFG("Connections: %d", Connections); VCFG("Connects/Hr: %d", connperhour); VCFG("Concurrent: %d", ActiveSessions); } GSsetType(gs, A_DIRECTORY); sprintf(path,"%c%s", A_DIRECTORY, GDCgetDatadir(Config)); GSsetPath(gs,path); VCFG("DataDirectory: %s", IFAVAIL(GDCgetDatadir(Config))); GSsetType(gs, A_FILE); sprintf(path,"%c%s", A_FILE, GDCgetConfig(Config)); if (cp=strchr(path,';')) *cp = '\0'; GSsetPath(gs,path); strcpy (image, path+1); VCFG("ConfigFile: %s", IFAVAIL(image)); VCFG("HostAlias: %s", IFAVAIL(GDCgetHostname(Config))); VCFG("Port: %d", GDCgetPort(Config)); VCFG("Site: %s", IFAVAIL(GDCgetSite(Config))); VCFG("Abstract: %s", IFAVAIL(GDCgetAbstract(Config))); VCFG("Admin: %s", IFAVAIL(GDCgetAdmin(Config))); VCFG("AdminEmail: %s", IFAVAIL(GDCgetAdminEmail(Config))); VCFG("Org: %s", IFAVAIL(GDCgetOrg(Config))); VCFG("Loc: %s", IFAVAIL(GDCgetLoc(Config))); VCFG("Lang: %s", IFAVAIL(GDCgetLang(Config))); VCFG("Geog: %s", IFAVAIL(GDCgetGeog(Config))); if (GDCgetTZ(Config)==-1) VCFG("TimeZone: %s", GDCgetTimeZone(Config)) else VCFG("TimeZone: %d", GDCgetTZ(Config)); VCFG("ReadTimeout: %d", GDCgetReadTimeout(Config)); if (GDCgetOPCOM(Config)==0) VCFG("Console: %s", "None") else { int opc = GDCgetOPCOM(Config); int ox; String *cbuf = STRnew(); for (ox=0; oxSecurityon) { int i; Site *temp; VCFG("Security: %s", "ON"); VCFG2("Access: %s: %s", "default", AccessLevelText(Config->Defaccess,0)); for (i=0; i< DAgetTop(Config->Sites); i++) { temp = SiteArrgetEntry(Config->Sites,i); VCFG2("Access: %s: %s", STRget(temp->domain), AccessLevelText(temp->Level,temp->maxsessions)); } if (Config->Authroutines || Config->Authitems || Config->Serverpw || Config->Tixfile) { /* Need to provide for an Authorizations routine dump */ } } if (Config->Extensions) { /* Need to provide for an extensions dump yet */ } if (Config->other_dirs) { /* Need to provide for an other_dirs dump yet */ } if (Config->other_gdcs) { /* Need to provide for an other_gdcs dump yet */ } if (Config->FileSeparators) { /* Need to provide for a FileSeparators dump yet */ } if (Config->BlkScriptBlocks) { /* Need to provide for a BlkScriptBlocks dump yet */ } if (Config->BlkScripts) { /* Need to provide for a BlkScripts dump yet */ } if (strcasecmp(GDCgetLogfile(Config),"syslog")==0) { path[0] = A_FILE; /* Kind of tough to display the syslog */ path[1] = '\0'; } else sprintf(path,"%c%s", A_FILE, GDCgetLogfile(Config)); GSsetType(gs,A_FILE); if (strlen(path)>1) { GSsetPath(gs,path); } else GSsetPath(gs,BummerMsg); VCFG("LogFile: %s", IFAVAIL(GDCgetLogfile(Config))); x = "Rollover: %s"; switch(GDCgetRollover(Config)) { case ROLLOVER_DAILY: VCFG(x,"DAILY"); break; case ROLLOVER_HOURLY: VCFG(x,"HOURLY"); break; case ROLLOVER_MONTHLY: VCFG(x,"MONTHLY"); break; case ROLLOVER_ANNUALLY: VCFG(x,"ANNUALLY"); break; case ROLLOVER_WEEKLY: VCFG(x,"WEEKLY"); break; case ROLLOVER_NEVER: default: VCFG(x,"NEVER"); } VCFG("LogTag: %s", IFAVAIL(GDCgetLogTag(Config))); sprintf(path,"%c%s", A_FILE, GDCgetErrorfile(Config)); if (strlen(path)>1) GSsetPath(gs,path); else GSsetPath(gs,NoSuchFile); VCFG("ErrorFile: %s", IFAVAIL(GDCgetErrorfile(Config))); sprintf(path,"%c%s", A_DIRECTORY, GDCgetScratchDir(Config)); if (strlen(path)>1) { GSsetPath(gs,path); GSsetType(gs,A_DIRECTORY); } else { GSsetPath(gs,BummerMsg); GSsetType(gs,A_FILE); } VCFG("ScratchDir: %s", IFAVAIL(GDCgetScratchDir(Config))); GSsetType(gs, A_FILE); sprintf(path,"%c%s", A_FILE, GDCgetSpawnInit(Config)); if (strlen(path)>1) GSsetPath(gs,path); else GSsetPath(gs,NoSuchFile); VCFG("SpawnInit: %s", IFAVAIL(GDCgetSpawnInit(Config))); sprintf(path,"%c%s", A_DIRECTORY, GDCgetSupportDir(Config)); if (strlen(path)>1) { GSsetPath(gs,path); GSsetType(gs,A_DIRECTORY); } else { GSsetPath(gs,BummerMsg); GSsetType(gs,A_FILE); } VCFG("SupportDir: %s", IFAVAIL(GDCgetSupportDir(Config))); } /** * Kaboom() causes the server to ACCVIO if, and only if, the environment * variables (that is, symbols or logicals) named GOPHERD_KABOOM_HOST * and GOPHERD_KABOOM_CLIENT match (case insensitive) the host name * this server is using and the client peer *name* making the pseudo- * search request. Otherwise reports that the request is denied. **/ void Kaboom(int sockfd, GopherObj *gs, GopherDirObj *gd) { char BoomBoom[256]; char *cp; void (*Die)() = NULL; GSsetDefaults(gs); GSsetType(gs, A_INFO); GSsetPath(gs, ""); sprintf(BoomBoom, "KaBOOM denied on %s for %s", GDCgetHostname(Config), CurrentPeerName); GSsetTitle(gs, BoomBoom); GDaddGS(gd, gs); if (cp = getenv("GOPHERD_KABOOM_HOST")) { if (strcasecmp(cp, GDCgetHostname(Config))) return; if (cp = getenv("GOPHERD_KABOOM_CLIENT")) if (strcasecmp(cp, CurrentPeerName)) return; } if (cp) { LOGGopher(sockfd,"KaBOOM authorized! BOOM!"); Die(); } } void CreateGO4link(GopherObj *gs, GopherDirObj *gd, char *GO4Site) { char GO4buf[256], *cp; GSsetType(gs, A_DIRECTORY); if (cp=strchr(GO4Site,' ')) { *cp = '\0'; GSsetPort(gs,atoi(++cp)); } else GSsetPort(gs,70); /* Hard coded since that's the Gopher standard, and we have to take a guess here */ GSsetHost(gs, GO4Site); GSsetPath(gs, ""); bzero(GO4buf, sizeof(GO4buf)); sprintf(GO4buf, "Link to Gopher host %s on port %d", GO4Site, GSgetPort(gs)); GSsetTitle(gs, GO4buf); GDaddGS(gd, gs); } void CreateFTPlink(GopherObj *gs, GopherDirObj *gd, char *FTPSite) { char ftpbuf[256], *cp; bzero(ftpbuf, sizeof(ftpbuf)); sprintf(ftpbuf, "%cftp:%s@/", A_DIRECTORY, FTPSite); GSsetType(gs, ftpbuf[0]); GSsetPath(gs, ftpbuf+1); cp = ftpbuf + strlen(ftpbuf); strcat(ftpbuf, "Link to aFTP host "); strcat(ftpbuf, FTPSite); GSsetTitle(gs, cp); GDaddGS(gd, gs); } void CreateEXElink(GopherObj *gs, GopherDirObj *gd, char *EXECargs, char EXECtype, char *EXECfile) { char exebuf[256], *cp; bzero(exebuf, sizeof(exebuf)); sprintf(exebuf, "%cexec:%s:%s", EXECtype, EXECargs, EXECfile); GSsetType(gs, exebuf[0]); GSsetPath(gs, exebuf+1); cp = exebuf + strlen(exebuf); strcat(exebuf, "Execute script with arguments "); strcat(exebuf, EXECargs); GSsetTitle(gs, cp); GDaddGS(gd, gs); } /* * *date locates a date specification. Make sure that's what it is, and * return TRUE or FALSE. */ boolean Validate_Date(char *date) { int status; char quadword[8]; $DESCRIPTOR(dsc$date,""); long flags = 0x7f; if (date==NULL) return(FALSE); dsc$date.dsc$a_pointer = date; dsc$date.dsc$w_length = strlen(date); status = LIB$CONVERT_DATE_STRING(&dsc$date, quadword,0,&flags,0,0); if ((status &1)!=1) return(FALSE); return(TRUE); } #endif .