/*
Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
VMS port by Andrew Molitor.
*/
#ifndef lint
static char RCSid[] = "$Header: /usr/users/mjr/hacks/umud/RCS/xmit_bsd.c,v 1.1 91/06/17 14:37:48 mjr Exp $";
#endif
/* configure all options BEFORE including system stuff. */
#include "config.h"
#include <stdio.h>
#include "multinet_root:[multinet.include.sys]types.h"
#include "multinet_root:[multinet.include]netdb.h"
#include "multinet_root:[multinet.include.sys]socket.h"
#include "multinet_root:[multinet.include.netinet]in.h"
#include "multinet_root:[multinet.include.vms]inetiodef.h"
#include <ctype.h>
#include <varargs.h>
#include <ssdef.h>
#include <libdtdef.h>
#include "mud.h"
#include "xact.h"
#include "sbuf.h"
/*
We use event flags 62 and 63 here -- one on a timeout timer, one to
synchronize actual network events. We never have more than one event
outstanding here.
Flags 32, 33, and 34 are used by net_vms.c
We use timer reqidt 1, for the hell of it. Since we're cancelling this
a lot, you'd best not go using that ID for anything else, eh?
*/
/*
#define XMITVMS_DEBUG
*/
/* don't bother being too big - this is a TCP */
#define XMBUFSIZ 1024
/* default timeout for I/O or connections */
#define DEFAULT_TIMEOUT 2
/* mud database entry */
typedef struct mudent {
int flg;
char *name;
char *plyport;
char *host;
char *symhost;
char *rempw;
char *locpw;
struct sockaddr_in addr;
int timot;
struct mudent *next;
} Mudent;
/* buffered connection */
typedef struct {
int fd;
short int iosb[4];
char ibuf[XMBUFSIZ];
char *ibp;
int ibc;
char obuf[XMBUFSIZ];
char *obp;
Mudent *curmp;
} Cnxt;
static Mudent *getmudent();
static Mudent *mud_list;
static Cnxt xbuf;
static Mudent *lastmud = (Mudent *)0;
/* Look up the remote MUD and set the context up right */
set_remmud(nam)
char *nam;
{
Mudent *mp;
if((mp = getmudent(nam)) == (Mudent *)0)
return(1);
lastmud = xbuf.curmp = mp;
return(0);
}
xc_open(mud)
char *mud;
{
Mudent *mp;
long timo[2];
int op;
if((mp = getmudent(mud)) == (Mudent *)0) {
logf("unknown mud ",mud,"\n",(char *)0);
return(-1);
}
if((xbuf.fd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
perror("socket");
return(-1);
}
/* Get a connect to the specified MUD. Time out reasonably fast */
/* Return -1 on error, 0 on success */
/* Set up a timer */
op = LIB$K_DELTA_SECONDS;
lib$cvt_to_internal_time(&op,&(mp->timot),timo);
sys$setimr(62L,timo,0,1,0);
/* Queue up the connect request */
sys$qio(63L,xbuf.fd,IO$_CONNECT,&(xbuf.iosb),0,0,
&(mp->addr),sizeof(struct sockaddr_in),0,0,0,0);
/* Wait around for something to happen */
sys$wflor(32L,0xC0000000L); /* Top two events flags, 62, 63 */
sys$cantim(1,0); /* Kill timer now, just in case */
/* *what* happened? */
if(xbuf.iosb[0] != SS$_NORMAL){
/* connect didn't work out. Bag. */
sys$cancel(xbuf.fd);
return(-1);
}
/* Connect succeeded, cool. */
#ifdef XMITVMS_DEBUG
(void)printf("<<<connected>>>\n");
#endif
logf("connection to ",mud,"\n",(char *)0);
xbuf.ibp = xbuf.ibuf;
xbuf.ibc = 0;
xbuf.obp = xbuf.obuf;
*xbuf.ibp = *xbuf.obp = '\0';
lastmud = xbuf.curmp = mp;
return(0);
}
xc_initfd(fd)
int fd;
{
xbuf.fd = fd;
xbuf.ibp = xbuf.ibuf;
xbuf.ibc = 0;
xbuf.obp = xbuf.obuf;
*xbuf.ibp = *xbuf.obp = '\0';
return(0);
}
/* Send out an OIF Level 2 greet string to the current mud */
xmit_greet()
{
/* Firewall. This should NEVER happen. */
if(xbuf.curmp == (Mudent *)0)
return(-1);
if(xc_write("UnterMUD ",mud_getname()," ",version," "
,(xbuf.curmp)->locpw,"\n",(char *)0))
return(-1);
if(xc_flush())
return(-1);
return(0);
}
/* Return 0 if pwd is OK */
check_rempwd(pwd)
char *pwd;
{
/* NEVER happen. */
if(xbuf.curmp == (Mudent *)0)
return(1);
return(strcmp(pwd,(xbuf.curmp)->rempw));
}
/* These grub data out of the LAST Mud contacted. */
char *
xc_getips()
{
extern char *inet_ntoa();
if(lastmud == (Mudent *)0)
return("");
return( inet_ntoa(lastmud->addr.sin_addr) );
}
char *
xc_getmudname()
{
if(lastmud == (Mudent *)0){
return("");
}
return(lastmud->name);
}
char *
xc_gethostname()
{
if(lastmud == (Mudent *)0)
return("");
return(lastmud->symhost);
}
char *
xc_getport()
{
if(lastmud == (Mudent *)0)
return("");
return(lastmud->plyport);
}
static Mudent *
getmudent(mud)
char *mud;
{
Mudent *mp = mud_list;
while(mp != (Mudent *)0) {
if(!strcmp(mud,mp->name))
return(mp);
mp = mp->next;
}
return((Mudent *)0);
}
/*
define a MUD entry. One semi-sensible thing done here is to
pre-resolve the addresses and just stash those. this way
we shouldn't have to hit our resolver a whole lot once the
MUD is up, if at all. also accept "dot" notation.
*/
xmit_def_mudent(name,host,symhost,rempw,locpw,port,plyport,timot)
char *name;
char *host;
char *symhost;
char *rempw;
char *locpw;
char *port;
char *plyport;
char *timot;
{
Mudent *np;
#ifndef NO_HUGE_RESOLVER_CODE
struct hostent *hp;
#endif
struct sockaddr_in tmpa;
char *p;
p = host;
while(*p != '\0' && (*p == '.' || isdigit(*p)))
p++;
if(*p != '\0') {
#ifndef NO_HUGE_RESOLVER_CODE
if((hp = gethostbyname(host)) == (struct hostent *)0) {
logf("unknown host ",host,"\n",(char *)0);
return(1);
}
(void)bcopy(hp->h_addr,(char *)&tmpa.sin_addr,hp->h_length);
#else
logf("must use 'dot' notation to define host ",host,"\n",(char *)0);
return(1);
#endif
} else {
unsigned long f;
if((f = inet_addr(host)) == -1L)
return(1);
(void)bcopy((char *)&f,(char *)&tmpa.sin_addr,sizeof(f));
}
if((np = (Mudent *)malloc(sizeof(Mudent))) == (Mudent *)0) {
logf("cannot allocate remote mud map\n",(char *)0);
return(1);
}
(void)bcopy((char *)&tmpa.sin_addr,&(np->addr.sin_addr),sizeof(tmpa.sin_addr));
np->addr.sin_port = htons(atoi(port));
np->addr.sin_family = AF_INET;
if(timot != (char *)0)
np->timot = atoi(timot);
else
np->timot = DEFAULT_TIMEOUT;
np->name = malloc((unsigned)(strlen(name) + 1));
np->rempw = malloc((unsigned)(strlen(rempw) + 1));
np->locpw = malloc((unsigned)(strlen(locpw) + 1));
np->plyport = mallo] != SS$_NORMAL){
/* read didn't work out. Bag. */
#ifdef XMITVMS_DEBUG
printf("Read failed. iosb[0]=%d, iosb[1]=%d\n",
xbuf.iosb[0],xbuf.iosb[1]);
printf("Buffer contains: %s\n",xbuf.ibuf);
socket_perror("hep!");
#endif
sys$cancel(xbuf.fd);
return(0);
}
#ifdef XMITVMS_DEBUG
printf("Read succeeded, read %d chars\n",xbuf.iosb[1]);
#endif
xbuf.ibc = xbuf.iosb[1];
if(xbuf.ibc <= 0)
return(0);
xbuf.ibp = xbuf.ibuf;
}
/* end of line? */
if(*xbuf.ibp == '\n') {
sbuf_put('\0',sb);
xbuf.ibp++;
xbuf.ibc--;
return(1);
}
/* put. */
sbuf_put(*xbuf.ibp,sb);
xbuf.ibp++;
xbuf.ibc--;
}
}
xc_flush()
{
long timo[2];
int op,sec;
op = LIB$K_DELTA_SECONDS;
if(xbuf.curmp != (Mudent *)0)
sec = xbuf.curmp->timot;
else
sec = DEFAULT_TIMEOUT;
/* Start the timer */
lib$cvt_to_internal_time(&op,&sec,timo);
sys$setimr(62L,timo,0,1,0);
/* Queue up the write request */
sys$qio(63L,xbuf.fd,IO$_WRITEVBLK,&(xbuf.iosb),0,0,
xbuf.obuf,xbuf.obp - xbuf.obuf,0,0,0,0);
/* Wait around for something to happen */
sys$wflor(32L,0xC0000000L); /* Top two events flags, 62, 63 */
sys$cantim(1,0); /* Kill timer now, just in case */
/* *what* happened? */
if(xbuf.iosb[0] != SS$_NORMAL){
/* write didn't work out. Bag. */
sys$cancel(xbuf.fd);
return(1);
} else {
xbuf.obp = xbuf.obuf;
}
return(0);
}
/* VARARGS */
xc_write(va_alist)
va_dcl
{
char *s;
va_list ap;
#ifdef XMITVMS_DEBUG
printf("xc_write: ");
#endif
va_start(ap);
while((s = va_arg(ap,char *)) != (char *)0) {
#ifdef XMITVMS_DEBUG
printf("%s ",s);
#endif
while(*s) {
if((xbuf.obp - xbuf.obuf) >= sizeof(xbuf.obuf))
if(xc_flush())
return(1);
*xbuf.obp++ = *s++;
}
}
va_end(ap);
#ifdef XMITVMS_DEBUG
printf("\n");
#endif
return(0);
}
/* Maintain a list of MUD-names we've heard about. */
static Mudent *known_muds = 0;
static int restrict_known = 0; /* Don't restrict to just known
MUDs. */
static Mudent *
isknownmud(mud)
char *mud;
{
Mudent *temp, *pos;
temp = getmudent(mud);
if (temp != NULL)
return temp;
pos = known_muds;
while (pos != NULL) {
if (!strcmp(pos->name, mud))
return pos;
pos = pos->next;
}
return (Mudent *) 0;
}
int
xmit_def_knownmud(mud)
char *mud;
{
Mudent *mp;
restrict_known = 1;
mp = isknownmud(mud);
if (mp != 0)
return 0;
mp = (Mudent *) malloc(sizeof(Mudent));
if (mp == 0) {
logf("couldn't alloc memory for knownmud mudent\n", (char *)0);
return 1;
}
mp->name = malloc((unsigned)(strlen(mud) + 1));
if (mp->name == 0) {
free(mp);
logf("couldn't alloc memory for knownmud name\n", (char *)0);
return 1;
}
(void)strcpy(mp->name, mud);
mp->next = known_muds;
known_muds = mp;
return 0;
}
/* A given MUD name is okay if:
- we don't have MUD security enabled (we have specified no defknownmuds)
- it's a MUD we connect to
- it's a MUD listed in a _mudconfig defknownmud
or - it's us.
*/
int
xmit_okay_remote(name)
char *name;
{
if (!restrict_known)
return 1;
if (isknownmud(name) != 0)
return 1;
if (!strcmp(name, mud_getname()))
return 1;
return 0;
}
(sb)
Sbuf *sb;
{
unsigned long eflags;
if(xbuf.fd == -1 || sb == (Sbuf *)0)
return(0);
sbuf_reset(sb);
while(1) {
/* buffer empty ? fill. */
if(xbuf.ibc <= 0) {
int op,sec;
long timo[2];
op = LIB$K_DELTA_SECONDS;
if(xbuf.curmp != (Mudent *)0)
sec = xbuf.curmp->timot;
else
sec = DEFAULT_TIMEOUT;
/* Start the timer */
lib$cvt_to_internal_time(&op,&sec,timo);
sys$setimr(62L,timo,0,1,0);
/* Qumud/CHANGES 100400 000604 000012 00000004465 05103144527 007762 0 37777777777 1 0 V1.13 - minor nits. fixed rwho output spew. :)
V1.12 - added patch to correctly sync and shut down Iobs when someone
disconnects. 'build dropto' command removed. 'build exit' demands
a destination. 'build exit' also understands 'here' as dest. 'set'
degenerates to a mass of special cases. rooms can also teleport
players in them home. random exit matching fixed. fix so things
like (T|T)&F work. eats whitespace before a command. added support
for 'local' flag. rewrote attribute expansion code. fix buffer
overrun in xact code.
V1.11 - cleaned up some error messages and diagnostics. added WHO
list sorting code.
# numbering scheme changes
V1.10 - added patch to prevent null attribute names. patched whisper
to only match players. patched matching some more. patched log
formatting. added automatic disconnect for players at login
prompt for more than 80 seconds. fixed teeny weeny buffer
overrun that rarely occurred in booleans. added latent support
for public/private attributes in vars.c (support not added to
vlookup()). added '$#' environment variable, which gives th