/* 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