#include <sys/types.h> #include <ctype.h> #include <sys/time.h> #include <strings.h> #include "teeny.h" #include "io.h" /* Copyright(C) 1990, Andrew Molitor, All Rights Reserved. This software may be freely used, modified, and redistributed, as long as this copyright message is left intact, and this software is not used to develop any commercial product, or used in any product that is provided on a pay-for-use basis. No warranties whatsoever. This is not guaranteed to compile, nor, in the event that it does compile to binaries, are these binaries guaranteed to perform any function whatsoever. */ /* #define IODEBUG */ /* The messages we write out when a create/connect attempt fails. */ #define BAD_CONNECT "Wrong password, or no such player.\n" #define BAD_CREATE "A player with that name already exists.\n" /* The WHO list. Surprise. */ Iob *wholist = (Iob *)0; /* Time last time timers() was called. */ struct timeval last; /* Last time we did a dump */ int lastdump; init_timers() { (void)gettimeofday(&last,(struct timezone *)0); lastdump = last.tv_sec; } /* This checks the current time and resets quotas if the current timeslice has elapsed, and does a dump if the current dump interval has elapsed. */ timers() { struct timeval now; int delta; Iob *curr; (void)gettimeofday(&now,(struct timezone *)0); /* How many tenths of seconds have elapsed since last time */ delta = (now.tv_sec - last.tv_sec) * 10 + (now.tv_usec - last.tv_usec) / 100000; if(delta >= TIME_SLICE){ /* Update all the quotas */ curr = wholist; if(curr != (Iob *)0){ do{ curr->quota = SLICE_QUOTA; curr = curr->whofwd; } while(curr != wholist); } last.tv_sec = now.tv_sec; last.tv_usec = now.tv_usec; } if(now.tv_sec - lastdump > DUMP_INTERVAL){ lastdump = now.tv_sec; /* Dump the DB */ dump_db(); } } /* The network code calls this with Iob's with pending goo to process. Process it. */ dispatch(bp) Iob *bp; { char *buff,*cmd,*p; int count; int player; int fullbuff; bp->lastcmd = last.tv_sec; if(bp->quota < 0){ bp->inputcnt = 0; if(bp->typ == INPUT_NEWCONN){ iobflush(bp); iobdrop(bp); } return(0); } buff = bp->inputbuf; count = bp->inputcnt; /* Slide along, chopping it up into commands. */ fullbuff = (count == (MUDBUFSIZ-1)); /* One for terminating \0 */ while(1){ cmd = buff; while(*buff != '\n' && count > 0 && *buff != '\r'){ buff++; count--; } if(count <= 0 && !fullbuff) break; (bp->quota)--; if(bp->quota < 0){ /* Fuck this guy */ (bp->blown)++; buff = cmd; /* Fake an empty buffer */ break; } fullbuff = 0; *buff++ = '\0'; count--; while(isspace(*cmd) && *cmd) cmd++; if(*cmd == '\0') continue; /* Check special commands. */ if(strcmp(cmd,"WHO") == 0){ do_wholist(bp); continue; } else if(strcmp(cmd,"QUIT") == 0){ iobput(bp,"Bye!\n"); iobflush(bp); iobdrop(bp); if(bp->typ != INPUT_NEWCONN){ disconnect_player(bp->player); } continue; } switch(bp->typ){ case INPUT_NEWCONN: /* We grok two commands, create and connect. */ for(p = cmd ; !isspace(*p) && *p ; p++); if(*p == '\0'){ greet(bp); break; } *p++ = '\0'; if(strcmp(cmd,"connect") == 0){ player = connect_player(p); if(player == -1){ iobput(bp,BAD_CONNECT); } else { bp->typ = INPUT_PLAY; bp->player = player; spit_file(player,"motd.txt"); do_look(player,(char *)0); newwho(bp); } } else if(strcmp(cmd,"create") == 0){ player = create_player(p); if(player == -1){ iobput(bp,BAD_CREATE); } else { bp->typ = INPUT_PLAY; bp->player = player; do_look(player,(char *)0); newwho(bp); } } else { /* Re-greet this idiot. */ greet(bp); } break; case INPUT_PLAY: handle_cmd(bp->player,cmd); break; } } /* OK We banged into the end of the buffer. */ if(cmd != buff){ /* Is there anything left in the buffer? */ bp->inputcnt = buff - cmd; bcopy(cmd,bp->inputbuf,bp->inputcnt); #ifdef IODEBUG printf("Read buffer ends with partial line of %d chars.\n" ,bp->inputcnt); #endif } else { bp->inputcnt = 0; #ifdef IODEBUG printf("Read buffer ended cleanly.\n"); #endif } return(0); /* We always succeed, being Way Studly. */ } newwho(bp) Iob *bp; { if(wholist == (Iob *)0){ wholist = bp->whofwd = bp->whoback = bp; } else { bp->whoback = wholist; bp->whofwd = wholist->whofwd; (wholist->whofwd)->whoback = bp; wholist->whofwd = bp; } } dropwho(bp) Iob *bp; { #ifdef IODEBUG printf("Dropping Iob for fd %d from the WHO list\n",bp->fd); #endif if(bp->whofwd == bp){ wholist = (Iob *)0; } else { if(wholist == bp){ wholist = bp->whoback; } (bp->whoback)->whofwd = bp->whofwd; (bp->whofwd)->whoback = bp->whoback; } } greet(bp) Iob *bp; { /* Yeah. I know I should open a file. Tough, I'm stingy w/my fds */ iobput(bp,"Welcome to TeenyMUD alpha-test.\n\n"); iobput(bp,"Use create <name> <password> or connect <name> <password>\n"); iobput(bp,"If you find a bug, don't whine. Report it well and without\n"); iobput(bp,"whining or I *will* hunt you down and break your fingers.\n\n"); } /* Matches against the list of active players. returns -1 if no match, -2 if ambiguous, or the object number. This lives here, 'cause it needs to screw around with the network's notion of the who list. */ int match_who(name) char *name; { Iob *curr; char *player_name,*p; int matched; matched = -1; curr = wholist; do { if(get_str_elt(curr->player,NAME,&player_name) == -1){ warning("match_who","bad name reference on WHO list"); return(-1); } if(player_name == (char *)0){ warning("match_who","active player with NULL name"); curr=curr->whofwd; continue; } for(p = name; DOWNCASE(*p) == DOWNCASE(*player_name) && *p && !isspace(*player_name) && *player_name;p++) player_name++; if(isspace(*player_name)){ return(curr->player); } curr = curr->whofwd;; } while(curr != wholist); return(matched); } /* Display the WHO list to a bp. */ /* 25 spaces */ char spaces[] = " "; do_wholist(bp) Iob *bp; { Iob *who; char *whonm,*p,ch; char work[16]; int len; iobput(bp,"Players Idle Connected\n"); if((who = wholist) == (Iob *)0) return; do { if(get_str_elt(who->player,NAME,&whonm) != -1){ for(p = whonm, len = 0;!isspace(*p) && *p;len++) p++; ch = *p; *p = '\0'; iobput(bp,whonm); *p = ch; if(len > 24) len = 24; p = ty_itoa(work,(int)(last.tv_sec - who->lastcmd)); *p = '\0'; iobput(bp,spaces+len+(p - work)+1); iobput(bp,work); p = ty_itoa(work,(int)(last.tv_sec - who->connect)); *p++ = '\n';*p = '\0'; iobput(bp,spaces+(p - work)+10); iobput(bp,work); } who = who->whoback; } while(who != wholist); } /* Writes a console WHO list out. To stdout. */ #define CONS_WHO "Name Idle Connected Blown Quotas\n" console_wholist() { Iob *who; char *whonm,*p; char work[16]; int len,len2; write(1,CONS_WHO,sizeof(CONS_WHO)-1); if((who = wholist) == (Iob *)0) return; do { /* Player number and name. */ work[0] = '#'; p = ty_itoa(work+1,who->player); *p++ = ' '; len2 = p-work; write(1,work,len2); if(get_str_elt(who->player,NAME,&whonm) != -1){ for(p = whonm, len = 0;!isspace(*p) && *p;len++) p++; write(1,whonm,len); } else { write(1,"<bad name>",10); len = 10; } len += len2; /* Idle time */ p = ty_itoa(work,(int)(last.tv_sec - who->lastcmd)); len = len + (p-work) + 1; if(len > 24) len = 24; write(1,spaces+len,25-len); write(1,work,p-work); /* Connect time */ p = ty_itoa(work,(int)(last.tv_sec - who->connect)); len = (p-work) + 9; write(1,spaces+len,25-len); write(1,work,p-work); /* Number of quotas blown. */ p = ty_itoa(work,who->blown); len = (p-work) + 9; *p++ = '\n'; write(1,spaces+len,25-len); write(1,work,p-work); who = who->whoback; } while(who != wholist); }