/********************************************************************
* 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 <opcdef.h>
#endif
#include <stdio.h>
#ifndef NO_INDEXING
#define WAISTYPE 1
#define NEXTTYPE 2
#define SHLLTYPE 3
#define GREPTYPE 4
#ifdef VMS_SERVER
#define CMD1TYPE 5
#include <syidef.h>
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 "<dbname>.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:<args>:scriptname tuple entry. The
* <args>, 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; ox<vms_OPC$M_num; ox++) {
if (opc & vms_OPC$M_NM[ox]) {
if (STRlen(cbuf))
STRcat(cbuf,"+");
STRcat(cbuf, vms_OPC$M_TXT[ox]);
}
}
VCFG("Console: %s", STRget(cbuf));
STRdestroy(cbuf);
}
VCFG("InetD: %s", GDCgetInetdActive(Config)==TRUE?"TRUE":"FALSE");
VCFG("IgnoreAll: %s", GDCgetIgnoreAll(Config)==TRUE?"TRUE":"FALSE");
VCFG("IsGPlus: %s", GDCgetIsGplus(Config)==TRUE?"TRUE":"FALSE");
VCFG("SortDir: %s", GDCgetSortDir(Config)==TRUE?"TRUE":"FALSE");
if (!GDCgetFTPPort(Config))
VCFG("FTPPort: %s", "NONE")
else
VCFG("FTPPort: %d", GDCgetFTPPort(Config));
if (!GDCgetEXECPort(Config))
VCFG("EXECPort: %s", "NONE")
else
VCFG("EXECPort: %d", GDCgetEXECPort(Config));
if (!GDCgetSRCHPort(Config))
VCFG("SRCHPort: %s", "NONE")
else
VCFG("SRCHPort: %d", GDCgetSRCHPort(Config));
if (!GDCgetOVERPort(Config) || (GDCgetOVERSize(Config)==-1))
VCFG("OVERPort: %s", "NONE")
else
VCFG2("OVERPort: %d, %d", GDCgetOVERPort(Config),
GDCgetOVERSize(Config));
VCFG("SortGREP: %s", GDCgetSortGREP(Config)==TRUE?"TRUE":"FALSE");
VCFG("SortCMD1: %s", GDCgetSortCMD1(Config)==TRUE?"TRUE":"FALSE");
VCFG("SortShell: %s", GDCgetSortShell(Config)==TRUE?"TRUE":"FALSE");
VCFG("Veronica: %s", GDCgetShouldIndex(Config)==TRUE?"TRUE":"FALSE");
VCFG("Cache: %s", GDCgetCaching(Config)==TRUE?"TRUE":"FALSE");
if (GDCgetCaching(Config))
VCFG("CacheTime: %d", GDCgetCachetime(Config));
VCFG("MaxLoad: %g", GDCgetMaxLoad(Config));
VCFG("MaxConnections: %d", GDCgetMaxconns(Config));
VCFG("Do_chroot: %s", GDCgetchroot(Config)==TRUE?"TRUE":"FALSE");
VCFG("BummerMsg: %s%s%s", IFAVAILQ(GDCgetBummerMsg(Config)));
VCFG("DName: %s%s%s", IFAVAILQ(GDCgetDName(Config)));
VCFG("DHead: %s%s%s", IFAVAILQ(GDCgetDHead(Config)));
VCFG("DFoot: %s%s%s", IFAVAILQ(GDCgetDFoot(Config)));
VCFG("Hidden: %s%s%s", IFAVAILQ(GDCgetHiddenPrefix(Config)));
VCFG("Link: %s%s%s", IFAVAILQ(GDCgetLinkPrefix(Config)));
VCFG("Lookaside: %s%s%s", IFAVAILQ(GDCgetLookAside(Config)));
VCFG("Restart: %s", IFAVAIL(GDCgetRestart(Config)));
GSsetType(gs,A_FILE);
if (Config->Securityon) {
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