/* TCP/IP based server for HyperText TCPServer.c
** ---------------------------------
**
** History:
** 2 Oct 90 Written TBL. Include filenames for VM from RTB.
*/
/* Module parameters:
** -----------------
**
** These may be undefined and redefined by syspec.h
*/
#define LISTEN_BACKLOG 2 /* Number of pending connect requests (TCP)*/
#define MAX_CHANNELS 20 /* Number of channels we will keep open */
#define BUFFER_SIZE 4096 /* Arbitrary size for efficiency */
#define WILDCARD '*' /* Wildcard used in addressing */
#define NETCLOSE close /* Routine to close a TCP-IP socket */
#define NETREAD read /* Routine to read from a TCP-IP socket */
#define NETWRITE write /* Routine to write to a TCP-IP socket */
#define FIRST_TCP_PORT 5000 /* When using dynamic allocation */
#define LAST_TCP_PORT 5999
#ifdef NeXT
#define SELECT /* Handle >1 channel if we can. */
#include Use a keyword search to get documents, help files, etc. \n");
return 0;
}
strcpy(system_command,"EXEC NICFIND1 ");
strcat(system_command, keywords);
if (*filename) {
strcat(system_command, " ( ");
strcat(system_command, filename);
}
} else {
strcpy(system_command,"EXEC NICFOUN1 ");
strcat(system_command, filename);
}
lines = system(system_command);
if (TRACE) printf("Command `%s' returned %i lines.\n",
system_command, lines);
if (lines")==0) break; */
for(p=buffer; *p; p++) *p = TOASCII(*p);
write(soc, buffer, p-buffer);
}
return 0;
} /* if FIND */
#else
fd = open(arg, O_RDONLY, 0 ); /* un*x open @@ */
if (fdSmall network access test v1.01\n");
write_ascii(soc, "\n\nThe (unrecognised) command used was `");
write_ascii(soc, command);
write_ascii(soc, "'.\n\n");
if (TRACE) printf("Return test string written back'\n");
return 0; /* End of file - please close socket */
} /* for */
} /* handle */
/*_____________________________________________________________________________________
*/
/* Encode INET status (as in sys/errno.h) inet_status()
** ------------------
**
** On entry,
** where gives a description of what caused the error
** global errno gives the error number in the unix way.
**
** On return,
** returns a negative status in the unix way.
*/
#ifdef vms
extern int uerrno; /* Deposit of error info (as perr errno.h) */
extern int vmserrno; /* Deposit of VMS error info */
extern volatile noshare int errno; /* noshare to avoid PSECT conflict */
#else
#ifndef errno
extern int errno;
#endif
#endif
PRIVATE int inet_status(where)
char *where;
{
CTRACE(tfp, "TCP: Error %d in `errno' after call to %s() failed.\n",
errno, where);
#ifdef vms
CTRACE(tfp, " Unix error number (uerrno) = %ld dec\n", uerrno);
CTRACE(tfp, " VMS error (vmserrno) = %lx hex\n", vmserrno);
#endif
return -errno;
}
/* Parse a cardinal value parse_cardinal()
** ----------------------
**
** On entry,
** *pp points to first character to be interpreted, terminated by
** non 0:9 character.
** *pstatus points to status already valid
** maxvalue gives the largest allowable value.
**
** On exit,
** *pp points to first unread character
** *pstatus points to status updated iff bad
*/
PRIVATE unsigned int parse_cardinal(pstatus, pp, max_value)
int *pstatus;
char **pp;
unsigned int max_value;
{
int n;
if ( (**pp'9')) { /* Null string is error */
*pstatus = -3; /* No number where one expeceted */
return 0;
}
n=0;
while ((**pp>='0') && (**ppmax_value) {
*pstatus = -4; /* Cardinal outside range */
return 0;
}
return n;
}
/* Bind to a TCP port
** ------------------
**
** On entry,
** tsap is a string explaining where to take data from.
** "" means data is taken from stdin.
** "*:1729" means "listen to anyone on port 1729"
**
** On exit,
** returns Negative value if error.
*/
int do_bind(const char * tsap)
{
FD_ZERO(&open_sockets); /* Clear our record of open sockets */
num_sockets = 0;
/* Deal with PASSIVE socket:
**
** A passive TSAP is one which has been created by the inet daemon.
** It is indicated by a void TSAP name. In this case, the inet
** daemon has started this process and given it, as stdin, the connection
** which it is to use.
*/
if (*tsap == 0) { /* void tsap => passive */
dynamic_allocation = FALSE; /* not dynamically allocated */
role = passive; /* Passive: started by daemon */
#ifdef vms
{ unsigned short channel; /* VMS I/O channel */
struct string_descriptor { /* This is NOT a proper descriptor*/
int size; /* but it will work. */
char *ptr; /* Should be word,byte,byte,long */
} sys_input = {10, "SYS$INPUT:"};
int status; /* Returned status of assign */
extern int sys$assign();
status = sys$assign(&sys_input, &channel, 0, 0);
com_soc = channel; /* The channel is stdin */
CTRACE(tfp, "IP: Opened PASSIVE socket %d\n", channel);
return -BAD(status);
}
#else
com_soc = 0; /* The channel is stdin */
CTRACE(tfp, "IP: PASSIVE socket 0 assumed from inet daemon\n");
return 0; /* Good */
#endif
/* Parse the name (if not PASSIVE)
*/
} else { /* Non-void TSAP */
char *p; /* pointer to string */
char *q;
struct hostent *phost; /* Pointer to host - See netdb.h */
char buffer[256]; /* One we can play with */
register struct sockaddr_in* sin = &soc_address;
strcpy(buffer, tsap);
p = buffer;
/* Set up defaults:
*/
sin->sin_family = AF_INET; /* Family = internet, host order */
sin->sin_port = 0; /* Default: new port, */
dynamic_allocation = TRUE; /* dynamically allocated */
role = passive; /* by default */
/* Check for special characters:
*/
if (*p == WILDCARD) { /* Any node */
role = master;
p++;
}
/* Strip off trailing port number if any:
*/
for(q=p; *q; q++)
if (*q==':') {
int status;
*q++ = 0; /* Terminate node string */
sin->sin_port = htons((unsigned short)parse_cardinal(
&status, &q, (unsigned int)65535));
if (statussin_addr.s_addr = INADDR_ANY; /* Default: any address */
} else if (*p>='0' && *psin_addr.s_addr = inet_addr(p); /* See arpa/inet.h */
} else { /* Alphanumeric node name: */
phost=gethostbyname(p); /* See netdb.h */
if (!phost) {
CTRACE(tfp, "IP: Can't find internet node name `%s'.\n",p);
return inet_status("gethostbyname"); /* Fail? */
}
memcpy(&sin->sin_addr, phost->h_addr, phost->h_length);
}
CTRACE(tfp,
"TCP: Parsed address as port %4x, inet %d.%d.%d.%d\n",
(unsigned int)ntohs(sin->sin_port),
(int)*((unsigned char *)(&sin->sin_addr)+0),
(int)*((unsigned char *)(&sin->sin_addr)+1),
(int)*((unsigned char *)(&sin->sin_addr)+2),
(int)*((unsigned char *)(&sin->sin_addr)+3));
} /* scope of p */
/* Master socket for server:
*/
if (role == master) {
/* Create internet socket
*/
master_soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (master_soc num_sockets) num_sockets=master_soc+1;
return master_soc;
} /* if master */
return -1; /* unimplemented role */
} /* do_bind */
/* Handle incomming messages do_action()
** -------------------------
**
** On entry:
**
** timeout -1 for infinite, 0 for poll, else in units of 10ms
**
** On exit,
** returns The status of the operation, =0) {
max_wait.tv_sec = timeout/100;
max_wait.tv_usec = (timeout%100)*10000;
}
for (com_soc=-1; com_soc= 0 ? &max_wait : 0);
if (nfound num_sockets) num_sockets=tcp_status+1;
nfound--;
} /* end if new connection */
/* If a message has arrived on one of the channels, take that channel:
*/
if(nfound) {
int i;
for(i=0;;i++)
if(FD_ISSET(i, &read_chans)) {
if (TRACE) printf("Got new socket %i\n", i);
com_soc = i; /* Got one! */
break;
}
break; /* Found input socket com_soc */
} /* if message waiting */
} /* loop on event */
#else /* SELECT not supported */
if (com_socmdp.soc_tcp.soc_address,
&rsoc->mdp.soc_tcp.soc_addrlen);
if (tcp_status