/*Last Modified: 8-MAR-1993 10:46:18.40, By: MARK */
/* Derived from an
* Example of server using TCP protocol
* pp 284-5 Stevens UNIX Network Programming
*/
#include "vmsgopherd.h"
void LOGGopher();
char Zehostname[128];
int GopherPort = GOPHER_PORT;
extern int vmserrno;
extern int socket_errno;
main(argc, argv)
int argc;
char *argv[];
{
int sockfd;
int newsockfd;
int clilen;
int childpid;
int i, argcounter;
char *vms_errno_string();
int ret_status, write_len, equiv_len, lnm_index;
unsigned int lnm_attrib;
unsigned char acmode;
char *LOGFile, *SecurityFile, *equiv_string, *datadir_def;
lnm_index = 0;
equiv_len = 0;
/*
* Translate the logical name for the log file if it exists
*/
ret_status = sys$trnlnm( 0, &d_stable, &d_logfile, &acmode, &lnmlst );
strncpy( equiv_string, "\0", 255 );
equiv_len = 0;
/*
* Translate the logical name for the data directory if it exists
*/
ret_status = sys$trnlnm( 0, &d_stable, &d_datadir, &acmode, &lnmlst );
strncpy( equiv_string, "\0", 255 );
equiv_len = 0;
/*
* Translate the logical name for the tcpport to use if it exists
*/
ret_status = sys$trnlnm( 0, &d_stable, &d_tcpport, &acmode, &lnmlst );
strncpy( equiv_string, "\0", 255 );
equiv_len = 0;
/*
* Translate the logical name to create the logical name for the root
* directory of the gopher data
*/
ret_status = sys$trnlnm( 0, &d_stable, &d_datadef, &acmode, &lnmlst );
/*** weird.. with this thing here our gethostaddrs work.
without it, it fails..... why?
***/
if (newsockfd < 0)
err_dump("server: accept error");
while(do_command(newsockfd)!=0);{} /* process the request */
#ifdef WOLLONGONG
netclose(newsockfd); /* parent process */
#endif
#ifdef MULTINET
socket_close(newsockfd); /* parent process */
#endif
#ifdef UCX
close(newsockfd); /* parent process */
#endif
}
}
/*
*
* Code stolen from nntp.....
*
* inet_netnames -- return the network, subnet, and host names of
* our peer process for the Internet domain.
*
* Parameters: "sock" is our socket, which we don't need.
* "sin" is a pointer to the result of
* a getpeername() call.
* "host_name"
* is filled in by this routine with the
* corresponding ASCII names of our peer.
* Returns: Nothing.
* Side effects: None.
*/
inet_netnames(sock, sin, host_name)
int sock;
struct sockaddr_in *sin;
char *host_name;
{
u_long net_addr;
struct hostent *hp;
struct netent *np;
net_addr = inet_netof(sin->sin_addr); /* net_addr in host order */
np = getnetbyaddr(net_addr, AF_INET);
hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
sizeof (sin->sin_addr.s_addr), AF_INET);
/*
* This finds the current peer and the time and jams it into the
* logfile (if any) and adds the message at the end
*/
void
LOGGopher(sockfd, message)
int sockfd;
char *message;
{
struct sockaddr sa;
int length;
static char host_name[256];
time_t Now;
char *cp;
fseek(SECFileHandle, 0, 0); /** Go to beginning of Security File **/
while (fgets(inputline, MAXLINE, SECFileHandle) != NULL) {
ZapCRLF(inputline);
MatchReturn = TRUE;
cp = inputline;
if (*cp == '!') {
MatchReturn = FALSE;
cp++;
}
if (isdigit(*cp)) {
/** Internet address x.x.x.x ..***/
/** Check for a match from the beginning **/
if (strstr(host_name,cp) == host_name)
return(MatchReturn);
}
else if (*cp == '*') {
return(MatchReturn);
}
else if (*cp != '#') {
/*** Not a comment, must be a host name **/
if ((strstr(host_name, cp) + strlen(cp)) == (host_name + strlen(host_name))) {
return(MatchReturn);
}
}
}
/*** Hmmm, didn't find a match... Let em have it***/
return(TRUE);
}
int
do_command(sockfd)
int sockfd;
{
char inputline[MAXLINE];
int length; /* Length of the command line */
char logline[MAXLINE];
/*** Reopen the security file ***/
if (*SecurityFile != '\0') {
SECFileHandle = fopen(SecurityFile, "r");
case 'm':
/*** This is an internal identifier ***/
/*** The m paired with an Objtype of 1 makes a mail spool file
into a directory.
***/
process_mailfile(sockfd, inputline + 1);
break;
case 'R':
/*** This is an internal identifier ***/
/*** The R defines a range ****/
/*** The format is R<startbyte>-<endbyte>-<filename> **/
{
int startbyte, endbyte;
char *cp, *oldcp;
/*
* This function tries to find out what type of file a pathname is.
* It then fills in the VAR type variables ObjType & ServerPath with
* corresponding info.
*/
char
Getfiletypes(newpath, ObjType, ServerPath)
char *newpath;
char **ObjType;
char **ServerPath;
{
boolean dirresult;
int Zefilefd;
static char Zebuf[64];
char *cp;
static char Selstr[256];
if (ServerPath != NULL) /* Don't overwrite existing path if any */
*ServerPath = Selstr;
dirresult = isadir(newpath);
if (dirresult == -1) /** Symlink or Special **/
return('3');
if (dirresult == 1) {
*ObjType = "1";
*Selstr = '1';
strcpy(Selstr +1, newpath);
return;
}
else if (dirresult == 0) { /** Some kind of data file.... */
if ((Zefilefd = open(newpath, O_RDONLY)) < 0) {
return('3');
}
*ObjType = "0";
*Selstr = '0';
strcpy(Selstr + 1, newpath);
return;
}
return('3'); /*** we shouldn't be able to get here..... ***/
}
/*
** This function lists out what is in a particular directory.
** it also outputs the contents of link files.
**
** Ack is this ugly.
*/
void
listdir(sockfd, pathname)
int sockfd;
char *pathname;
{
struct FAB wild_fab; /* Used in wildcard search */
struct NAM wild_nam; /* Used in conjunction with wild_fab */
char template[] = "*.*;*"; /* default template */
char fullname[256]; /* Input file spec given by user */
char expanded[256]; /* filespec after logical expansion */
char result[256]; /* result from search */
char *pointer1, *pointer2, *pointer3, *pathp2, *sidep1;
char *lbracketp, *rbracketp;
int result2_len, side_len;
register status;
if (chdir(pathname)<0) {
/* fprintf(stderr, "error: %d %s\n",vmserrno,vms_errno_string()); */
writestring(sockfd, "- Cannot access that directory\r\n.\r\n");
return;
}
sprintf(portnum, "%d", GopherPort);
for ( ; ; ) {
if ((( status = SYS$SEARCH(&wild_fab)) &1) != 1) {
if ( (status == RMS$_NMF) || (status == RMS$_FNF) )
break;
else {
fprintf(stderr, "Error %d on search\n",status);
writestring(sockfd, "- There were no files, or we had some other error on the search\r\n.\r\n");
return;
}
}
/*
* This processes a file containing any subset of
* Type, Name, Path, Port or Host, and returns pointers to the
* overriding data that it finds.
*
* The caller may choose to initialise the pointers - so we don't
* touch them unless we find an over-ride.
*/
Process_Side(sidefile, Gopherp)
FILE *sidefile;
GopherStruct *Gopherp;
{
char inputline[MAXLINE];
static char ItemType[3];
static char ItemName[255];
static char Path[255];
static char Host[64];
static char Port[10];
char *cp;
inputline[0] = '\0';
for (;;) {
for (;;) {
cp = fgets(inputline, 1024, sidefile);
if (inputline[0] != '#' || cp == NULL)
break;
}
/*** Test for EOF ***/
if (cp==NULL)
break;
ZapCRLF(inputline); /* should zap tabs as well! */
/*** Test for the various field values. **/
if (strncmp(inputline, "Type=", 5)==0) {
GSsetType(Gopherp, inputline[5]);
}
else if (strncmp(inputline, "Host=", 5)==0) {
GSsetHost(Gopherp, inputline+5);
}
else if (strncmp(inputline, "Port=", 5)==0) {
GSsetPort(Gopherp, atoi(inputline+5));
}
else if (strncmp(inputline, "Path=", 5)==0) {
GSsetPath(Gopherp, inputline+5);
}
/*
** This function opens the specified file, starts a zcat if needed,
** and barfs the file across the socket.
**
** It now also checks and sees if access is allowed
**
**
*/
void
printfile(sockfd, pathname, startbyte, endbyte)
int sockfd;
char *pathname;
int startbyte, endbyte;
{
FILE *ZeFile;
char inputline[512];
int i, rmtmpfile;
char Zcatcommand[256];
char *cp, *pointer1;
if ( (ZeFile = fopen(pathname, "r")) == NULL) {
/*
* The specified file does not exist
*/
writestring(sockfd, "- File does not exist!!!!!\r\n");
writestring(sockfd, ".\r\n");
return;
}