/* misc.c */ #include "copyright.h" #include "config.h" #include <stdio.h> #include <sys/types.h> #include <ctype.h> #include <sys/time.h> #ifdef STRING_H #include <string.h> #else #include <strings.h> #endif /* STRING_H */ #include "teeny.h" #include "io.h" #include "case.h" char poll[36]; /* Poll for the @doing command */ /* The WHO list. Surprise. */ Iob *wholist = (Iob *) 0; /* Time last time timers() was called. */ static struct timeval last; /* Last time we did a dump */ static long lastdump; /* The time that the mud went up. */ static long startingtimeofmud; static void set_output_str(); static void log_create(); static void log_badconnect(); void init_timers() { (void) gettimeofday(&last, (struct timezone *) 0); lastdump = last.tv_sec; startingtimeofmud = 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. * */ void 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. * */ void dispatch(bp) Iob *bp; { char *buff, *cmd, *p; int count; int player; int fullbuff; int z; bp->lastcmd = last.tv_sec; if (bp->quota < 0) { bp->inputcnt = 0; if (bp->typ == INPUT_NEWCONN) { iobflush(bp); iobdrop(bp); log_disconnect(bp); } return; } 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; if ((bp->typ != INPUT_NEWCONN && !istemple(bp->player)) || bp->typ == INPUT_NEWCONN) (bp->quota)--; if (bp->quota < 0) { /* Fuck this guy */ (bp->blown)++; buff = cmd; /* Fake an empty buffer */ break; } fullbuff = 0; *buff++ = '\0'; count--; /* change all non-printing characters to whitespace */ for (z = 0; cmd[z]; z++) { if (!isprint(cmd[z])) cmd[z] = ' '; } /* strip leading and trailing whitespace */ for (z--; isspace(cmd[z]); z--); cmd[z + 1] = '\0'; for (; isspace(cmd[0]); cmd++); if (!cmd[0]) continue; /* Check special commands. */ #ifdef WHO_CI if (!strncasecmp(cmd, WHO_COMMAND, strlen(WHO_COMMAND))) { #else if (!strncmp(cmd, WHO_COMMAND, strlen(WHO_COMMAND))) { #endif /* WHO_CI */ if ((bp->typ != INPUT_NEWCONN) && bp->outputprefix) { iobput(bp, bp->outputprefix); iobput(bp, "\r\n"); } do_wholist(bp, cmd + strlen(WHO_COMMAND)); if ((bp->typ != INPUT_NEWCONN) && bp->outputsuffix) { iobput(bp, bp->outputsuffix); iobput(bp, "\r\n"); } continue; } else if (!strncasecmp(cmd, "@doing", strlen("@doing"))) { if ((bp->typ != INPUT_NEWCONN) && bp->outputprefix) { iobput(bp, bp->outputprefix); iobput(bp, "\r\n"); } do_doing(bp, cmd + strlen(FINGER_COMMAND)); if ((bp->typ != INPUT_NEWCONN) && bp->outputsuffix) { iobput(bp, bp->outputsuffix); iobput(bp, "\r\n"); } continue; } else #ifdef QUIT_CI if (!strcasecmp(cmd, QUIT_COMMAND)) #else if (!strcmp(cmd, QUIT_COMMAND)) #endif /* QUIT_CI */ { if ((bp->typ != INPUT_NEWCONN) && bp->outputprefix) { iobput(bp, bp->outputprefix); iobput(bp, "\r\n"); } if (bp->typ != INPUT_NEWCONN) iobput(bp, GOODBYE_MSG); if ((bp->typ != INPUT_NEWCONN) && bp->outputsuffix) { iobput(bp, bp->outputsuffix); iobput(bp, "\r\n"); } iobflush(bp); iobdrop(bp); log_disconnect(bp); if (bp->typ != INPUT_NEWCONN) { disconnect_player(bp->player); autotoadcheck(bp->player); } continue; } else if (!strncmp(cmd, PREFIX_COMMAND, strlen(PREFIX_COMMAND))) { #ifndef RESTRICT_BOT set_output_str(bp, cmd + strlen(PREFIX_COMMAND), PREFIX_CODE); #else /* RESTRICT_BOT */ if (!istemple(bp->player)) { iobput(bp, RESTRICT_BOT_MSG); } else { set_output_str(bp, cmd + strlen(PREFIX_COMMAND), PREFIX_CODE); } #endif /* RESTRICT_BOT */ continue; } else if (!strncmp(cmd, SUFFIX_COMMAND, strlen(SUFFIX_COMMAND))) { #ifndef RESTRICT_BOT set_output_str(bp, cmd + strlen(SUFFIX_COMMAND), SUFFIX_CODE); #else /* RESTRICT_BOT */ if (!istemple(bp->player)) { iobput(bp, RESTRICT_BOT_MSG); } else { set_output_str(bp, cmd + strlen(SUFFIX_COMMAND), SUFFIX_CODE); } #endif /* RESTRICT_BOT */ 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 (stringprefix(cmd, "connect")) { player = connect_player(p); if (player == -1) { iobput(bp, BAD_CONNECT); log_badconnect(p, bp); } else { bp->typ = INPUT_PLAY; bp->player = player; if (set_int_elt(player, SITE, bp->site) == -1) { iobput(bp, "Couldn't set SITE, something horrid has truly happened.\r\n"); warning("dispatch", "could not set SITE elt"); } log_connect(bp); iob_spit_file(bp, MOTD_FILE); if (iswiz(player)) iob_spit_file(bp, WIZN_FILE); #ifdef RESTRICT_BOT if (!istemple(player) && (bp->outputprefix || bp->outputsuffix)) { iobput(bp, "Your OUTPUTPREFIX and OUTPUTSUFFIX strings have been cleared.\r\n"); if (bp->outputprefix) { ty_free(bp->outputprefix); bp->outputprefix = (char *) 0; } if (bp->outputsuffix) { ty_free(bp->outputsuffix); bp->outputsuffix = (char *) 0; } } #endif /* RESTRICT_BOT */ do_look(player, (char *) 0); newwho(bp); } } else if (stringprefix(cmd, "create")) { #ifndef REGISTRATION #ifdef SITE_REGISTRATION if (check_lockout_list('R',bp->site)) { if (iob_spit_file(bp, SITELOCKOUT_FILE) == -1) { iobput(bp, SITE_REGISTER_MSG); } iobflush(bp); iobdrop(bp); log_disconnect(bp); } else { #endif /* SITE_REGISTRATION */ player = create_player(p, -1); if (player == -1) { iobput(bp, BAD_CREATE); } else { bp->typ = INPUT_PLAY; bp->player = player; if (set_int_elt(player, SITE, bp->site) == -1) { iobput(bp, "Couldn't set SITE, something horrid has truly happened.\r\n"); warning("dispatch", "could not set SITE elt"); } log_create(bp); iob_spit_file(bp, MOTD_FILE); #ifdef RESTRICT_BOT if (!istemple(player) && (bp->outputprefix || bp->outputsuffix)) { iobput(bp, "Your OUTPUTPREFIX and OUTPUTSUFFIX strings have been cleared.\r\n"); if (bp->outputprefix) { ty_free(bp->outputprefix); bp->outputprefix = (char *) 0; } if (bp->outputsuffix) { ty_free(bp->outputsuffix); bp->outputsuffix = (char *) 0; } } #endif /* RESTRICT_BOT */ do_look(player, (char *) 0); newwho(bp); } #ifdef SITE_REGISTRATION } #endif /* SITE_REGISTRATION */ #else /* REGISTRATION */ if (iob_spit_file(bp, REGISTER_FILE) == -1) { iobput(bp, REGISTER_MSG); } #endif /* REGISTRATION */ } else { /* Re-greet this idiot. */ greet(bp); } break; case INPUT_PLAY: if (bp->outputprefix) { iobput(bp, bp->outputprefix); iobput(bp, "\r\n"); } handle_cmd(bp->player, cmd); if (bp->outputsuffix) { iobput(bp, bp->outputsuffix); iobput(bp, "\r\n"); } 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); } else { bp->inputcnt = 0; } } static void set_output_str(bp, string, code) Iob *bp; char *string; int code; { while (*string && isspace(*string) && isascii(*string)) string++; if (code == PREFIX_CODE) { if (!string || !*string) { ty_free(bp->outputprefix); bp->outputprefix = 0; } else { ty_free(bp->outputprefix); bp->outputprefix = (char *) ty_malloc(strlen(string) + 1, "set_output_str"); if (bp->outputprefix) strcpy(bp->outputprefix, string); } } if (code == SUFFIX_CODE) { if (!string || !*string) { ty_free(bp->outputsuffix); bp->outputsuffix = 0; } else { ty_free(bp->outputsuffix); bp->outputsuffix = (char *) ty_malloc(strlen(string) + 1, "set_output_str"); if (bp->outputsuffix) strcpy(bp->outputsuffix, string); } } } void 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; } } void dropwho(bp) Iob *bp; { if (bp->whofwd == bp) { wholist = (Iob *) 0; } else { if (wholist == bp) { wholist = bp->whoback; } (bp->whoback)->whofwd = bp->whofwd; (bp->whofwd)->whoback = bp->whoback; } } void greet(bp) Iob *bp; { if (iob_spit_file(bp, GREET_FILE) == -1) { iobput(bp, DEFAULT_GREET); } } int iob_spit_file(bp, filename) Iob *bp; char *filename; { FILE *in; char filebuff[130]; int i; if ((in = fopen(filename, "r")) == NULL) { return (-1); } while (fgets(filebuff, 128, in) != NULL) { /* Replace the \n\0 with a \r\n\0, if present. */ i = strlen(filebuff); if(filebuff[i-1] == '\n') { filebuff[i-1] = '\r'; filebuff[i] = '\n'; filebuff[i+1] = '\0'; } iobput(bp, filebuff); } (void) fclose(in); return (1); } /* * 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. */ void do_wholist(bp, arg) Iob *bp; char *arg; { Iob *who; char *whonm, *p, idletype; char work2[82]; char work3[14]; char line[82]; int g, h, i, j, k, total = 0; int where, wizard = 0; #ifdef REVERSED_WHO Iob *first; #endif /* REVERSED_WHO */ if(arg != NULL) while (arg[0] == ' ') arg++; if ((bp->typ != INPUT_NEWCONN) && iswiz(bp->player)) wizard = 1; iobput(bp, "Player Name On For Idle "); iobput(bp, poll); iobput(bp, "\r\n"); if ((who = wholist) == (Iob *) 0) { iobput(bp, "No users are connected. "); goto uptime; } #ifdef REVERSED_WHO first = who = who->whofwd; #endif /* REVERSED_WHO */ do { total++; p = work2; if (get_str_elt(who->player, NAME, &whonm) != -1) { while (*whonm && !isspace(*whonm)) *p++ = *whonm++; *p = '\0'; } else (void) strcpy(work2, "???"); if ((arg != NULL) && !stringprefix(arg, work2)) goto skipthisline; if (wizard) { sprintf(work3, "(#%d)", who->player); strcat(work2, work3); } g = (int) (last.tv_sec - who->connect); h = g / 86400; g %= 86400; i = g / 3600; j = g / 60 % 60; k = (int) (last.tv_sec - who->lastcmd); idletype = 's'; if (k > 59) { idletype = 'm'; k /= 60; if (k > 59) { idletype = 'h'; k /= 60; if (k > 23) { idletype = 'd'; k /= 24; } } } if (h) sprintf(line, "%-19s %dd %02d:%02d %2d%c ", work2, h, i, j, k, idletype); else sprintf(line, "%-22s %02d:%02d %2d%c ", work2, i, j, k, idletype); strcat(line, who->doing); strcat(line, "\r\n"); iobput(bp, line); skipthisline: #ifdef REVERSED_WHO who = who->whofwd; } while (who != first); #else /* REVERSED_WHO */ who = who->whoback; } while (who != wholist); #endif /* REVERSED_WHO */ sprintf(line, "%d user%s %s connected. ", total, (total == 1) ? "" : "s", (total == 1) ? "is" : "are"); iobput(bp, line); uptime: h = last.tv_sec - startingtimeofmud; j = h / 3600 % 24; k = h / 60 % 60; i = h / 86400; sprintf(work3,"%dd, ",i); sprintf(line, "Uptime: %s%02d:%02d. %s\r\n", i ? work3 : "", j, k, total < 3 ? "Kinda lonely here." : total < 4 ? "Have a fish." : total < 5 ? "Who is John Galt?" : total < 6 ? "Yay." : total < 7 ? "TinySex is Not Allowed." : total < 8 ? "Let's have a party!" : total < 12 ? "Want a cookie?" : total < 16 ? "Reminder: AIX sux" : total < 20 ? "Thanks, it was delicious." : total < 25 ? "Space Madness down, or what?" : total < 33 ? "(EVIL!)Mud rocks, d00d!" : "fuckin'-A! A new record."); iobput(bp, line); } void do_doing(bp, arg) Iob *bp; char *arg; { int len; if(arg == NULL) { iobput(bp, "Set. Have fun doing it.\r\n"); strcpy(bp->doing,""); return; } while(arg[0] == ' ') arg++; len = strlen(arg); if(len > 35) { arg[35] = '\0'; iobput(bp, "Too long -- Clipped.\r\n"); } else { iobput(bp, "Set. Have fun doing it.\r\n"); } strcpy(bp->doing,arg); } /* do_doing */ void log_disconnect(bp) Iob *bp; { char *name, *p, ch; if (bp->typ != INPUT_NEWCONN) { if (get_str_elt(bp->player, NAME, &name) != -1) { for (p = name; p && *p && *p != ' '; p++); ch = *p; *p = '\0'; log_status("DISCONNECT: %s(#%d) on fd %d.\n", name, bp->player, bp->fd); *p = ch; } else log_status("DISCONNECT: ???(#%d) on fd %d.\n", bp->player, bp->fd); } else log_status("DISCONNECT: fd %d never connected.\n", bp->fd); } void log_connect(bp) Iob *bp; { char *name, *p, ch; if (bp->typ != INPUT_NEWCONN) { if (get_str_elt(bp->player, NAME, &name) != -1) { for (p = name; p && *p && *p != ' '; p++); ch = *p; *p = '\0'; log_status("CONNECTED: %s(#%d) on fd %d.\n", name, bp->player, bp->fd); *p = ch; } else log_status("CONNECTED: ???(#%d) on fd %d.\n", bp->player, bp->fd); } else log_status("CONNECTION: fd %d connected from [%s].\n", bp->fd, bp->hostname); } static void log_create(bp) Iob *bp; { char *name, *p, ch; if (get_str_elt(bp->player, NAME, &name) != -1) { for (p = name; *p && p && *p != ' '; p++); ch = *p; *p = '\0'; log_status("CREATED: %s(#%d) on fd %d.\n", name, bp->player, bp->fd); *p = ch; } else log_status("CREATED: ???(#%d) on fd %d.\n", bp->player, bp->fd); } static void log_badconnect(s, bp) char *s; Iob *bp; { char buf[65]; char *p, *q; for (p = s, q = buf; p && *p && *p != ' ' && (q - buf) < 64; *q++ = *p++); *q = '\0'; log_status("FAILED CONNECT: fd %d failed connection to \"%s\".\n", bp->fd, buf); } int match_active_player(arg) char *arg; { Iob *who; Iob *first; int number = 0; int player; char *name, work[40], *p; who = wholist; first = who = who->whofwd; do { p = work; if (get_str_elt(who->player, NAME, &name) != -1) { while (*name && !isspace(*name)) *p++ = *name++; *p = '\0'; } else { warning("match_active_player", "bad player name"); return(-1); } if ((arg != NULL) && stringprefix(arg, work)) { if (strlen(arg) == strlen(work)) return (who->player); number++; if(number == 1) { player = who->player; } else { if (who->player != player) return (-2); else number = 1; } } who = who->whofwd; } while (who != first); if (number) return (player); else return (-1); } void do_finger(player, arg) int player; char *arg; { Iob *who; char *whonm, *p, idletype; char work2[82]; char work3[14]; char line[82]; int where, wizard = 0; #ifdef REVERSED_WHO Iob *first; #endif /* REVERSED_WHO */ if(arg != NULL) while (arg[0] == ' ') arg++; #ifdef WIZWHOALL wizard = 1; #else /* WIZWHOALL */ if (iswiz(player)) wizard = 1; #endif /* WIZWHOALL */ notify_player(player, "Player Name Location "); notify_player(player, wizard ? "Site\r\n" : "\r\n"); if ((who = wholist) == (Iob *) 0) { notify_player(player, "No users are connected.\r\n"); return; } #ifdef REVERSED_WHO first = who = who->whofwd; #endif /* REVERSED_WHO */ do { p = work2; if (get_str_elt(who->player, NAME, &whonm) != -1) { while (*whonm && !isspace(*whonm)) *p++ = *whonm++; *p = '\0'; } else (void) strcpy(work2, "???"); if ((arg != NULL) && !stringprefix(arg, work2)) goto skipthisline2; if (wizard) { sprintf(work3, "(#%d)", who->player); strcat(work2, work3); } if (wizard) { if (get_int_elt(who->player, LOC, &where) == -1) where = -1; if(iswiz(player) || isjumpok(where)) sprintf(line, "%-19s (#%d)", work2, where); else sprintf(line, "%-19s private", work2); sprintf(work2, "%-30s %-30s", line, who->hostname); } strcat(work2, "\r\n"); notify_player(player, work2); skipthisline2: #ifdef REVERSED_WHO who = who->whofwd; } while (who != first); #else /* REVERSED_WHO */ who = who->whoback; } while (who != wholist); #endif /* REVERSED_WHO */ } int check_lockout_list(type,site) char type; long site; { FILE *file; int a,b,c,d; long lockedsite; char locktype; int lockedout = FALSE; char buf[200]; char *p; if ((file = fopen(LOCKOUT_FILE, "r")) == NULL) { warning ("check_lockout_list", "LOCKOUT_FILE does not exist"); return (lockedout); } while (!lockedout && fgets(buf, 200, file) != NULL) { a = b = c = d = 0; p = buf; while (*p && *p != '#') p++; *p = '\0'; p = buf; locktype = toupper(*p); /* We currently use 'L' and 'R' */ p+=2; a = atoi(p); while (*p != '.') p++; p++; b = atoi(p); while (*p != '.') p++; p++; c = atoi(p); while (*p != '.') p++; p++; d = atoi(p); lockedsite = ((a & 0xff) << 24) + ((b & 0xff) << 16) + ((c & 0xff) << 8) + (d & 0xff); if (lockedsite == site && locktype == type) lockedout = TRUE; } fclose(file); return (lockedout); }