From bacchus.pa.dec.com!decwrl!wuarchive!cs.utexas.edu!uunet!ogicse!zephyr.ens.tek.com!tekred!saab!billr Mon Jul 30 17:54:09 PDT 1990 Article 1046 of comp.sources.games: Path: bacchus.pa.dec.com!decwrl!wuarchive!cs.utexas.edu!uunet!ogicse!zephyr.ens.tek.com!tekred!saab!billr From: billr@saab.CNA.TEK.COM (Bill Randle) Newsgroups: comp.sources.games Subject: v11i009: tinymud2 - user-extendible multi-user adventure (v1.5.4), Part05/10 Message-ID: <6054@tekred.CNA.TEK.COM> Date: 30 Jul 90 16:45:30 GMT Sender: news@tekred.CNA.TEK.COM Lines: 2211 Approved: billr@saab.CNA.TEK.COM Submitted-by: James Aspnes Posting-number: Volume 11, Issue 9 Archive-name: tinymud2/Part05 Supersedes: tinymud: Volume 8, Issue 80-83 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'interface.c' <<'END_OF_FILE' X/* Concentrator upgraded June 1990 Robert Hood */ X X/* modifed Concentrator to match Fuzzy & Randoms 1.5.4 changes = 6/90 Fuzzy */ X X/* modified interface.c to support LOTS of people, using a concentrator */ X/* May 1990, Robert Hood */ X X/* #define CHECKC /* consistency checking */ X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#include "config.h" X#include "db.h" X#include "interface.h" X X#define BUFSIZE 0xFFFF X Xstruct text_block X{ X int nchars; X struct text_block *nxt; X char *start; X char *buf; X}; X Xstruct text_queue X{ X struct text_block *head; X struct text_block **tail; X}; X Xstruct descriptor_data X{ X int descriptor; X int num; X int connected; X dbref player; X char *output_prefix; X char *output_suffix; X int output_size; X struct text_queue output; X struct text_queue input; X char *raw_input; X char *raw_input_at; X long connected_at; X long last_time; X int quota; X struct sockaddr_in address; /* added 3/6/90 SCG */ X char *hostname; /* 5/18/90 - Fuzzy */ X struct descriptor_data *next; X}; X X#define MALLOC(result, type, number) do { \ X if (!((result) = (type *) malloc ((number) * sizeof (type)))) \ X panic("Out of memory"); \ X } while (0) X X#define FREE(x) (free((void *) x)) X Xstruct message X{ X char *data; X short len; X struct message *next; X}; X Xstruct conc_list X{ X struct conc_list *next; X int sock, current, status; X struct descriptor_data *firstd; X struct message *first, *last; X char *incoming, *outgoing; X int ilen, olen; X} *firstc = 0; X Xvoid queue_message(struct conc_list * c, char *data, int len); Xvoid start_log(); Xstruct timeval timeval_sub(struct timeval now, struct timeval then); Xstruct timeval msec_add(struct timeval t, int x); Xstruct timeval update_quotas(struct timeval last, struct timeval current); Xvoid main_loop(); Xint notify(dbref player, const char *msg); Xvoid process_output(struct conc_list * c); Xint process_input(struct descriptor_data * d, char *buf, int got); Xvoid process_commands(); Xvoid dump_users(struct descriptor_data * e, char *user); Xvoid free_text_block(struct text_block * t); Xvoid main(int argc, char **argv); Xvoid set_signals(); Xint msec_diff(struct timeval now, struct timeval then); Xvoid clearstrings(struct descriptor_data * d); Xvoid shutdownsock(struct descriptor_data * d); Xstruct descriptor_data *initializesock(struct sockaddr_in * a); Xstruct text_block *make_text_block(const char *s, int n); Xvoid add_to_queue(struct text_queue * q, const char *b, int n); Xint flush_queue(struct text_queue * q, int n); Xint queue_write(struct descriptor_data * d, const char *b, int n); Xint queue_string(struct descriptor_data * d, const char *s); Xvoid freeqs(struct descriptor_data * d); Xvoid welcome_user(struct descriptor_data * d); Xvoid do_motd(dbref); Xchar *strsave(const char *s); Xvoid save_command(struct descriptor_data * d, const char *command); Xvoid set_userstring(char **userstring, const char *command); Xint do_command(struct descriptor_data * d, char *command); Xvoid check_connect(struct descriptor_data * d, const char *msg); Xvoid parse_connect(const char *msg, char *command, char *user, char *pass); Xvoid close_sockets(); Xvoid emergency_shutdown(void); Xvoid boot_off(dbref player); Xint bailout(int sig, int code, struct sigcontext * scp); Xchar *time_format_1(long dt); Xchar *time_format_2(long dt); X#ifdef CONNECT_MESSAGES Xvoid announce_connect(dbref); Xvoid announce_disconnect(dbref); X#endif /* CONNECT_MESSAGES */ Xint sigshutdown(int, int, struct sigcontext *); X Xint logsynch(); Xchar *logfile = LOG_FILE; X Xint debug; Xvoid chg_userid(); Xvoid file_date(struct descriptor_data * d, const char *file); X Xstatic const char *connect_fail = "Either that player does not exist, or has a different password.\n"; X#ifndef REGISTRATION Xstatic const char *create_fail = "Either there is already a player with that name, or that name is illegal.\n"; X#endif /* REGISTRATION */ Xstatic const char *flushed_message = "\n"; Xstatic const char *shutdown_message = "Going down - Bye\n"; X Xint sock; Xint shutdown_flag = 0; X Xint port = TINYPORT; Xint intport = INTERNAL_PORT; X X Xstart_port() X{ X int temp; X struct sockaddr_in sin; X X sock = socket(AF_INET, SOCK_STREAM, 0); X if (sock < 1) X { X perror("socket"); X exit(-1); X } X temp = 1; X setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&temp, sizeof(temp)); X sin.sin_family = AF_INET; X sin.sin_port = htons(intport); X sin.sin_addr.s_addr = htonl(INADDR_ANY); X X temp = bind(sock, (struct sockaddr *) & sin, sizeof(sin)); X if (temp < 0) X { X perror("bind"); X exit(-1); X } X temp = listen(sock, 5); X if (temp < 0) X { X perror("listen"); X exit(-1); X } X} X Xstruct timeval X timeval_sub(struct timeval now, struct timeval then) X{ X now.tv_sec -= then.tv_sec; X now.tv_usec -= then.tv_usec; X if (now.tv_usec < 0) X { X now.tv_usec += 1000000; X now.tv_sec--; X } X return now; X} X Xstruct timeval X msec_add(struct timeval t, int x) X{ X t.tv_sec += x / 1000; X t.tv_usec += (x % 1000) * 1000; X if (t.tv_usec >= 1000000) X { X t.tv_sec += t.tv_usec / 1000000; X t.tv_usec = t.tv_usec % 1000000; X } X return t; X} X Xstruct timeval X update_quotas(struct timeval last, struct timeval current) X{ X int nslices; X struct descriptor_data *d; X struct conc_list *c; X X nslices = msec_diff(current, last) / COMMAND_TIME_MSEC; X X if (nslices > 0) X { X for (c = firstc; c; c = c->next) X for (d = c->firstd; d; d = d->next) X { X d->quota += COMMANDS_PER_TIME * nslices; X if (d->quota > COMMAND_BURST_SIZE) X d->quota = COMMAND_BURST_SIZE; X } X } X return msec_add(last, nslices * COMMAND_TIME_MSEC); X} X Xint X notify(dbref player2, const char *msg) X{ X struct descriptor_data *d; X struct conc_list *c; X int retval = 0; X X#ifdef COMPRESS X extern const char *uncompress(const char *); X X msg = uncompress(msg); X#endif /* COMPRESS */ X for (c = firstc; c; c = c->next) X for (d = c->firstd; d; d = d->next) X { X if (d->connected && d->player == player2) X { X queue_string(d, msg); X queue_write(d, "\n", 1); X retval++; X } X } X return (retval); X} X Xint X process_input(d, buf, got) X struct descriptor_data *d; X char *buf; X int got; X{ X char *p, *pend, *q, *qend; X X d->last_time = time(0); X if (!d->raw_input) X { X MALLOC(d->raw_input, char, MAX_COMMAND_LEN); X d->raw_input_at = d->raw_input; X } X p = d->raw_input_at; X pend = d->raw_input + MAX_COMMAND_LEN - 1; X for (q = buf, qend = buf + got; q < qend; q++) X { X if (*q == '\n') X { X *p = '\0'; X if (p > d->raw_input) X save_command(d, d->raw_input); X p = d->raw_input; X } else X if (p < pend && isascii(*q) && isprint(*q)) X { X *p++ = *q; X } X } X if (p > d->raw_input) X { X d->raw_input_at = p; X } else X { X FREE(d->raw_input); X d->raw_input = 0; X d->raw_input_at = 0; X } X return 1; X} X Xvoid process_commands() X{ X int nprocessed; X struct descriptor_data *d, *dnext, *dlast; X struct conc_list *c; X struct text_block *t; X char header[4]; X X do X { X nprocessed = 0; X for (c = firstc; c; c = c->next) X { X dlast = 0; X for (d = c->firstd; d; d = dnext) X { X dnext = d->next; X if (d->quota > 0 && (t = d->input.head)) X { X d->quota--; X nprocessed++; X if (!do_command(d, t->start)) X { X header[0] = 0; X header[1] = 2; X header[2] = d->num; X queue_message(c, header, 3); X if (dlast) X dlast->next = dnext; X else X c->firstd = dnext; X shutdownsock(d); X FREE(d); X break; X } else X { X d->input.head = t->nxt; X if (!d->input.head) X d->input.tail = &d->input.head; X free_text_block(t); X } X } X dlast = d; X } X } X } while (nprocessed > 0); X} X Xvoid dump_users(struct descriptor_data * e, char *user) X{ X static struct conc_list *rwclist[NOFILE]; X static struct descriptor_data *rwdlist[NOFILE]; X int ccount, dcount, dloop, cloop; X X struct descriptor_data *d; X struct conc_list *c; X long now; X int counter = 0; X static int maxcounter = 0; X int wizard, reversed, tabular; X char buf[1024]; X X X# ifdef DO_WHOCHECK X writelog("WHO CHECK %d\n", sizeof(rwclist)); X writelog("WHO CHECK %d\n", sizeof(rwdlist)); X# endif X X while (*user && isspace(*user)) X user++; X if (!*user) X user = NULL; X X reversed = e->connected && Flag(e->player, REVERSED_WHO); X tabular = e->connected && Flag(e->player, TABULAR_WHO); X X time(&now); X X queue_string(e, tabular ? "Player Name On For Idle\n" : X "Current Players:\n"); X#ifdef GOD_MODE X wizard = e->connected && God(e->player); X#else GOD_MODE X wizard = e->connected && Wizard(e->player); X#endif GOD_MODE X X if (reversed) X { X ccount = 0; X for (c = firstc; c; c = c->next) X rwclist[ccount++] = c; X for (cloop = ccount - 1; cloop >= 0; --cloop) X { X dcount = 0; X for (d = rwclist[cloop]->firstd; d; d = d->next) X rwdlist[dcount++] = d; X for (dloop = dcount - 1; dloop >= 0; --dloop) X { X d = rwdlist[dloop]; X if (d->connected && X ++counter && /* Count everyone connected */ X (!user || string_prefix(db[d->player].name, user))) X { X if (tabular) X { X sprintf(buf, "%-16s %10s %4s", X db[d->player].name, X time_format_1(now - d->connected_at), X time_format_2(now - d->last_time)); X X if (wizard) X sprintf(buf, "%s %s", buf, d->hostname); X } else X { X sprintf(buf, "%s idle %d seconds", X db[d->player].name, now - d->last_time); X if (wizard) X sprintf(buf, "%s from host %s", buf, d->hostname); X } X strcat(buf, "\n"); X queue_string(e, buf); X } X } X } X } else X { X for (c = firstc; c; c = c->next) X { X for (d = c->firstd; d; d = d->next) X { X if (d->connected && X ++counter && /* Count everyone connected */ X (!user || string_prefix(db[d->player].name, user))) X { X if (tabular) X { X sprintf(buf, "%-16s %10s %4s", X db[d->player].name, X time_format_1(now - d->connected_at), X time_format_2(now - d->last_time)); X X if (wizard) X sprintf(buf, "%s %s", buf, d->hostname); X } else X { X sprintf(buf, "%s idle %d seconds", X db[d->player].name, now - d->last_time); X if (wizard) X sprintf(buf, "%s from host %s", buf, d->hostname); X } X strcat(buf, "\n"); X queue_string(e, buf); X } X } X } X } X X if (counter > maxcounter) X { maxcounter = counter; X if (counter > 30) X { writelog ("%d users logged in\n", counter); } X } X X sprintf(buf, "%d user%s connected\n", counter, X counter == 1 ? " is" : "s are"); X queue_string(e, buf); X} X Xvoid free_text_block(struct text_block * t) X{ X FREE(t->buf); X FREE((char *)t); X} X X#ifndef BOOLEXP_DEBUGGING Xvoid main(int argc, char **argv) X{ X int pid; X X if (argc < 3) X { X fprintf(stderr, "Usage: %s infile dumpfile [port iport logfile]\n", *argv); X exit(1); X X } X if (argc > 3) X port = atoi(argv[3]); X if (argc > 4) X intport = atoi(argv[4]); X if (argc > 5) X logfile = argv[5]; X X start_log(); X X if (init_game(argv[1], argv[2]) < 0) X { X writelog("INIT: Couldn't load %s\n", argv[1]); X exit(2); X } X pid = vfork(); X if (pid < 0) X { X perror("fork"); X exit(-1); X } X if (pid == 0) X { X char pstr[32], istr[32], clvl[32]; X X /* Add port argument to concentrator */ X sprintf(pstr, "%d", port); X sprintf(istr, "%d", intport); X sprintf(clvl, "%d", 1); X execl("concentrate", "conc", pstr, istr, clvl, 0); X } X set_signals(); X start_port(port); X main_loop(); X close_sockets(); X dump_database(); X exit(0); X} X X#endif X Xvoid start_log() X{ X#ifdef DETACH X if (!debug) X { X int i; X X if (fork() != 0) X exit(0); X X i = open("/dev/tty", O_RDWR, 0); X if (i != -1) X { X ioctl(i, TIOCNOTTY, 0); X close(i); X } X } X freopen(logfile, "a", stderr); X setbuf(stderr, NULL); X#endif /* DETACH */ X} X Xvoid set_signals(void) X{ X int dump_status(void); X signal(SIGPIPE, SIG_IGN); X X signal(SIGINT, (void *)sigshutdown); X signal(SIGTERM, (void *)sigshutdown); X X#ifdef DETACH X signal(SIGUSR2, (void *)logsynch); X#else /* DETACH */ X signal(SIGUSR2, (void *)bailout); X#endif /* DETACH */ X X if (debug) X return; X X# ifdef NOCOREDUMP X signal(SIGQUIT, (void *)bailout); X signal(SIGILL, (void *)bailout); X signal(SIGTRAP, (void *)bailout); X signal(SIGIOT, (void *)bailout); X signal(SIGEMT, (void *)bailout); X signal(SIGFPE, (void *)bailout); X signal(SIGBUS, (void *)bailout); X signal(SIGSEGV, (void *)bailout); X signal(SIGSYS, (void *)bailout); X signal(SIGTERM, (void *)bailout); X signal(SIGXCPU, (void *)bailout); X signal(SIGXFSZ, (void *)bailout); X signal(SIGVTALRM, (void *)bailout); X# endif X} X Xint X msec_diff(struct timeval now, struct timeval then) X{ X return ((now.tv_sec - then.tv_sec) * 1000 X + (now.tv_usec - then.tv_usec) / 1000); X} X Xvoid X clearstrings(struct descriptor_data * d) X{ X if (d->output_prefix) X { X FREE(d->output_prefix); X d->output_prefix = 0; X } X if (d->output_suffix) X { X FREE(d->output_suffix); X d->output_suffix = 0; X } X} X Xvoid X shutdownsock(struct descriptor_data * d) X{ X if (d->connected) X { X writelog("DISCONNECT descriptor %d,%d player %s(%d)\n", d->descriptor, d->num, db[d->player].name, d->player); X#ifdef CONNECT_MESSAGES X announce_disconnect(d->player); X#endif /* CONNECT_MESSAGES */ X } else X { X writelog("DISCONNECT descriptor %d,%d never connected\n", d->descriptor, d->num); X } X clearstrings(d); X freeqs(d); X} X Xstruct descriptor_data * X initializesock(struct sockaddr_in * a) X{ X struct descriptor_data *d; X X MALLOC(d, struct descriptor_data, 1); X d->connected = 0; X d->output_prefix = 0; X d->output_suffix = 0; X d->output_size = 0; X d->output.head = 0; X d->output.tail = &d->output.head; X d->input.head = 0; X d->input.tail = &d->input.head; X d->raw_input = 0; X d->raw_input_at = 0; X d->quota = COMMAND_BURST_SIZE; X d->last_time = 0; X d->address = *a; /* This will be the address of the X * concentrator */ X d->hostname = ""; /* This will be set during connect */ X X welcome_user(d); X return d; X} X Xstruct text_block * X make_text_block(const char *s, int n) X{ X struct text_block *p; X X MALLOC(p, struct text_block, 1); X MALLOC(p->buf, char, n); X bcopy(s, p->buf, n); X p->nchars = n; X p->start = p->buf; X p->nxt = 0; X return p; X} X Xvoid X add_to_queue(struct text_queue * q, const char *b, int n) X{ X struct text_block *p; X X if (n == 0) X return; X X p = make_text_block(b, n); X p->nxt = 0; X *q->tail = p; X q->tail = &p->nxt; X} X Xint X flush_queue(struct text_queue * q, int n) X{ X struct text_block *p; X int really_flushed = 0; X X n += strlen(flushed_message); X X while (n > 0 && (p = q->head)) X { X n -= p->nchars; X really_flushed += p->nchars; X q->head = p->nxt; X free_text_block(p); X } X p = make_text_block(flushed_message, strlen(flushed_message)); X p->nxt = q->head; X q->head = p; X if (!p->nxt) X q->tail = &p->nxt; X really_flushed -= p->nchars; X return really_flushed; X} X Xint X queue_write(struct descriptor_data * d, const char *b, int n) X{ X int space; X X space = MAX_OUTPUT - d->output_size - n; X if (space < 0) X d->output_size -= flush_queue(&d->output, -space); X add_to_queue(&d->output, b, n); X d->output_size += n; X return n; X} X Xint X queue_string(struct descriptor_data * d, const char *s) X{ X return queue_write(d, s, strlen(s)); X} X Xvoid X freeqs(struct descriptor_data * d) X{ X struct text_block *cur, *next; X X cur = d->output.head; X while (cur) X { X next = cur->nxt; X free_text_block(cur); X cur = next; X } X d->output.head = 0; X d->output.tail = &d->output.head; X X cur = d->input.head; X while (cur) X { X next = cur->nxt; X free_text_block(cur); X cur = next; X } X d->input.head = 0; X d->input.tail = &d->input.head; X X if (d->raw_input) X FREE(d->raw_input); X d->raw_input = 0; X d->raw_input_at = 0; X} X Xvoid X welcome_user(struct descriptor_data * d) X{ X queue_string(d, WELCOME_MESSAGE); X file_date(d, NEWS_FILE); X# ifdef CONNECT_FILE X do_connect_msg(d, CONNECT_FILE); X# endif X} X Xvoid X goodbye_user(struct descriptor_data * d) X{ X queue_string(d, LEAVE_MESSAGE); X} X Xchar * X strsave(const char *s) X{ X char *p; X X MALLOC(p, char, strlen(s) + 1); X X if (p) X strcpy(p, s); X return p; X} X Xvoid X save_command(struct descriptor_data * d, const char *command) X{ X add_to_queue(&d->input, command, strlen(command) + 1); X} X Xvoid X set_userstring(char **userstring, const char *command) X{ X if (*userstring) X { X FREE(*userstring); X *userstring = 0; X } X while (*command && isascii(*command) && isspace(*command)) X command++; X if (*command) X *userstring = strsave(command); X} X Xint X do_command(struct descriptor_data * d, char *command) X{ X if (!strcmp(command, QUIT_COMMAND)) X { X goodbye_user(d); X return 0; X } else X if (!strncmp(command, WHO_COMMAND, strlen(WHO_COMMAND))) X { X if (d->output_prefix) X { X queue_string(d, d->output_prefix); X queue_write(d, "\n", 1); X } X dump_users(d, command + strlen(WHO_COMMAND)); X if (d->output_suffix) X { X queue_string(d, d->output_suffix); X queue_write(d, "\n", 1); X } X } else X if (d->connected && X !strncmp(command, PREFIX_COMMAND, strlen(PREFIX_COMMAND))) X { X#ifdef ROBOT_MODE X if (!Robot(d->player)) X { X#ifndef TINKER X notify(d->player, X "Only robots can use OUTPUTPREFIX; contact a Wizard."); X#else TINKER X notify(d->player, X "Only robots can use OUTPUTPREFIX; contact a Tinker."); X#endif TINKER X return 1; X } X if (!d->connected) X return 1; X#endif ROBOT_MODE X set_userstring(&d->output_prefix, command + strlen(PREFIX_COMMAND)); X } else X if (d->connected && X !strncmp(command, SUFFIX_COMMAND, strlen(SUFFIX_COMMAND))) X { X#ifdef ROBOT_MODE X if (!Robot(d->player)) X { X#ifndef TINKER X notify(d->player, X "Only robots can use OUTPUTSUFFIX; contact a Wizard."); X#else TINKER X notify(d->player, X "Only robots can use OUTPUTSUFFIX; contact a Tinker."); X#endif TINKER X return 1; X } X#endif ROBOT_MODE X set_userstring(&d->output_suffix, command + strlen(SUFFIX_COMMAND)); X } else X { X if (d->connected) X { X if (d->output_prefix) X { X queue_string(d, d->output_prefix); X queue_write(d, "\n", 1); X } X process_command(d->player, command); X if (d->output_suffix) X { X queue_string(d, d->output_suffix); X queue_write(d, "\n", 1); X } X } else X { X check_connect(d, command); X } X } X return 1; X} X Xvoid X check_connect(struct descriptor_data * d, const char *msg) X{ X char command[MAX_COMMAND_LEN]; X char user[MAX_COMMAND_LEN]; X char password[MAX_COMMAND_LEN]; X dbref player; X X parse_connect(msg, command, user, password); X X if (!strncmp(command, "co", 2)) X { X player = connect_player(user, password); X if (player == NOTHING) X { X queue_string(d, connect_fail); X writelog("FAILED CONNECT %s on descriptor %d,%d\n", user, d->descriptor, d->num); X } else X { X writelog("CONNECTED %s(%d) on descriptor %d,%d %s\n", X db[player].name, player, d->descriptor, d->num, d->hostname); X d->connected = 1; X d->connected_at = time(NULL); X d->player = player; X do_motd(player); X do_look_around(player); X#ifdef CONNECT_MESSAGES X announce_connect(player); X#endif /* CONNECT_MESSAGES */ X } X } else X if (!strncmp(command, "cr", 2)) X { X#ifndef REGISTRATION X player = create_player(user, password); X if (player == NOTHING) X { X queue_string(d, create_fail); X writelog("FAILED CREATE %s on descriptor %d,%d %s\n", X user, d->descriptor, d->num, d->hostname); X } else X { X writelog("CREATED %s(%d) on descriptor %d,%d %s\n", X db[player].name, player, d->descriptor, d->num, d->hostname); X d->connected = 1; X d->connected_at = time(0); X d->player = player; X do_motd(player); X do_look_around(player); X#ifdef CONNECT_MESSAGES X announce_connect(player); X#endif /* CONNECT_MESSAGES */ X } X#else X queue_string(d, REGISTER_MESSAGE); X#endif /* REGISTRATION */ X } else X { X welcome_user(d); X } X} X Xvoid X parse_connect(const char *msg, char *command, char *user, char *pass) X{ X char *p; X X while (*msg && isascii(*msg) && isspace(*msg)) X msg++; X p = command; X while (*msg && isascii(*msg) && !isspace(*msg)) X *p++ = *msg++; X *p = '\0'; X while (*msg && isascii(*msg) && isspace(*msg)) X msg++; X p = user; X while (*msg && isascii(*msg) && !isspace(*msg)) X *p++ = *msg++; X *p = '\0'; X while (*msg && isascii(*msg) && isspace(*msg)) X msg++; X p = pass; X while (*msg && isascii(*msg) && !isspace(*msg)) X *p++ = *msg++; X *p = '\0'; X} X Xvoid X close_sockets(void) X{ X struct descriptor_data *d, *dnext; X struct conc_list *c; X char header[4]; X X for (c = firstc; c; c = c->next) X { X /* conc.c now handles printing the Going Down - Bye message */ X shutdown(c->sock, 0); X close(c->sock); X } X close(sock); X} X Xvoid X emergency_shutdown(void) X{ X close_sockets(); X} X Xint X bailout(int sig, int code, struct sigcontext * scp) X{ X long *ptr; X int i; X X writelog("BAILOUT: caught signal %d code %d", sig, code); X ptr = (long *)scp; X for (i = 0; i < sizeof(struct sigcontext); i++) X writelog(" %08lx\n", *ptr); X panic("PANIC on spurious signal"); X _exit(7); X return 0; X} X Xchar * X time_format_1(long dt) X{ X register struct tm *delta; X static char buf[64]; X X delta = gmtime(&dt); X if (delta->tm_yday > 0) X { X sprintf(buf, "%dd %02d:%02d", X delta->tm_yday, delta->tm_hour, delta->tm_min); X } else X { X sprintf(buf, "%02d:%02d", X delta->tm_hour, delta->tm_min); X } X return buf; X} X Xchar * X time_format_2(long dt) X{ X register struct tm *delta; X static char buf[64]; X X delta = gmtime(&dt); X if (delta->tm_yday > 0) X { X sprintf(buf, "%dd", delta->tm_yday); X } else X if (delta->tm_hour > 0) X { X sprintf(buf, "%dh", delta->tm_hour); X } else X if (delta->tm_min > 0) X { X sprintf(buf, "%dm", delta->tm_min); X } else X { X sprintf(buf, "%ds", delta->tm_sec); X } X return buf; X} X X#ifdef CONNECT_MESSAGES Xvoid X announce_connect(dbref player) X{ X dbref loc; X char buf[BUFFER_LEN]; X X if ((loc = getloc(player)) == NOTHING) X return; X if (Dark(player) || Dark(loc)) X return; X X sprintf(buf, "%s has connected.", db[player].name); X X notify_except(db[loc].contents, player, buf); X} X Xvoid X announce_disconnect(dbref player) X{ X dbref loc; X char buf[BUFFER_LEN]; X X if ((loc = getloc(player)) == NOTHING) X return; X if (Dark(player) || Dark(loc)) X return; X X sprintf(buf, "%s has disconnected.", db[player].name); X X notify_except(db[loc].contents, player, buf); X} X X#endif /* CONNECT_MESSAGES */ X Xint X sigshutdown(int sig, int code, struct sigcontext * scp) X{ X writelog("SHUTDOWN: on signal %d code %d\n", sig, code); X shutdown_flag = 1; X return 0; X} X X#ifdef DETACH Xint X logsynch() X{ X freopen(logfile, "a", stderr); X setbuf(stderr, NULL); X writelog("log file reopened\n"); X return 0; X} X X#endif /* DETACH */ X X#include X Xvoid X file_date(struct descriptor_data * d, char *file) X{ X static char buf[80]; X extern char *ctime(long *clock); X struct stat statb; X char *tstring; X char *cp; X X if (stat(file, &statb) == -1) X return; X X tstring = ctime(&statb.st_mtime); X if ((cp = (char *)index(tstring, '\n')) != NULL) X *cp = '\0'; X X strcpy(buf, "News last updated "); X strcat(buf, tstring); X strcat(buf, "\n\n"); X X queue_string(d, (char *)buf); X} X Xvoid main_loop() X{ X struct message *ptr; X int found, newsock, lastsock, len, loop; X int accepting; X struct timeval tv; X struct sockaddr_in sin; X fd_set in, out; X char data[1025], *p1, *p2, buffer[1025], header[4]; X struct conc_list *c, *tempc, *nextc, *lastc; X struct descriptor_data *d, *tempd, *nextd; X struct timeval last_slice, current_time; X struct timeval next_slice; X struct timeval slice_timeout; X short templen; X X accepting = 1; X lastsock = sock + 1; X while (!shutdown_flag) X { X gettimeofday(¤t_time, (struct timezone *) 0); X last_slice = update_quotas(last_slice, current_time); X X process_commands(); X X if (shutdown_flag) X break; X X next_slice = msec_add(last_slice, COMMAND_TIME_MSEC); X slice_timeout = timeval_sub(next_slice, current_time); X X FD_ZERO(&in); X FD_ZERO(&out); X X FD_SET(sock, &in); X for (c = firstc; c; c = c->next) X process_output(c); X for (c = firstc; c; c = c->next) X if (c->sock) X { X if (c->ilen < BUFSIZE) X FD_SET(c->sock, &in); X len = c->first ? c->first->len : 0; X while (c->first && ((c->olen + len + 2) < BUFSIZE)) X { X templen = c->first->len; X bcopy(&templen, c->outgoing + c->olen, 2); X bcopy(c->first->data, c->outgoing + c->olen + 2, len); X c->olen += len + 2; X ptr = c->first; X c->first = ptr->next; X FREE(ptr->data); X FREE(ptr); X if (c->last == ptr) X c->last = 0; X len = c->first ? c->first->len : 0; X } X if (c->olen) X FD_SET(c->sock, &out); X } X tv.tv_sec = 1000; X tv.tv_usec = 0; X X found = select(lastsock, &in, &out, (fd_set *) 0, &tv); X if (found < 0) X continue; X if (accepting && FD_ISSET(sock, &in)) X { X len = sizeof(sin); X newsock = accept(sock, (struct sockaddr *) & sin, &len); X if (newsock >= 0) X { X if (newsock >= lastsock) X lastsock = newsock + 1; X if (fcntl(newsock, F_SETFL, FNDELAY) == -1) X { X perror("make_nonblocking: fcntl"); X } X MALLOC(tempc, struct conc_list, 1); X tempc->next = firstc; X tempc->firstd = 0; X tempc->first = 0; X tempc->last = 0; X tempc->status = 0; X /* Imcomming and outgoing I/O buffers */ X MALLOC(tempc->incoming, char, BUFSIZE); X tempc->ilen = 0; X MALLOC(tempc->outgoing, char, BUFSIZE); X tempc->olen = 0; X firstc = tempc; X firstc->sock = newsock; X writelog("CONCENTRATOR CONNECT: sock %d, addr %x\n", newsock, sin.sin_addr.s_addr); X } X } X for (c = firstc; c; c = nextc) X { X nextc = c->next; X#ifdef CHECKC X if (!(c->sock)) X writelog("CONSISTENCY CHECK: Concentrator found with null socket #\n"); X#endif X if ((FD_ISSET(c->sock, &in)) && (c->ilen < BUFSIZE)) X { X int i; X len = recv(c->sock, c->incoming + c->ilen, X BUFSIZE - c->ilen, 0); X if (len == 0) X { X struct message *mptr, *tempm; X writelog("CONCENTRATOR DISCONNECT: %d\n", c->sock); X close(c->sock); X d = c->firstd; X while (d) X { X shutdownsock(d); X tempd = d; X d = d->next; X FREE(tempd); X } X if (firstc == c) X firstc = firstc->next; X else X lastc->next = c->next; X FREE(c->incoming); X FREE(c->outgoing); X mptr = c->first; X while (mptr) X { X tempm = mptr; X mptr = mptr->next; X FREE(mptr->data); X FREE(mptr); X } X FREE(c); X break; X } else X if (len < 0) X { X writelog("recv: %s\n", strerror(errno)); X } else X { X int num; X X c->ilen += len; X while (c->ilen > 2) X { X bcopy(c->incoming, &templen, 2); X#ifdef CHECKC X if (templen < 1) X writelog("CONSISTENCY CHECK: Message recived with lenght < 1\n"); X#endif X if (c->ilen >= (templen + 2)) X { X num = *(c->incoming + 2); X /* Is it coming from the command user #? */ X if (num == 0) X { X /* Proccess commands */ X switch (*(c->incoming + 3)) X { X case 1: /* connect */ X d = initializesock(&sin); X d->descriptor = c->sock; X d->next = c->firstd; X c->firstd = d; X d->num = *(c->incoming + 4); X MALLOC(d->hostname, char, X templen - 5); X bcopy(c->incoming + 9, d->hostname, X templen - 6); X *(d->hostname + templen - 7) = 0; X#ifdef DEBUG X writelog("USER CONNECT %d,%d from host %s\n", c->sock, d->num, d->hostname); X#endif X break; X case 2: /* disconnect */ X tempd = 0; X d = c->firstd; X num = *(c->incoming + 4); X while (d) X { X if (d->num == num) X { X writelog("USER ABORTED CONNECTION %d,%d\n", c->sock, d->num); X shutdownsock(d); X if (c->firstd == d) X c->firstd = d->next; X else X tempd->next = d->next; X FREE(d); X break; X } X tempd = d; X d = d->next; X } X#ifdef CHECKC X if (!d) X writelog("CONSISTENCY CHECK: Disconnect Received for unknown user %d,%d\n", c->sock, num); X#endif X break; X X /* X * This take a message from a concentrator, and logs it in X * the log file X */ X case 4: X { X char buffer[2048]; X bcopy(c->incoming + 4, buffer, X templen - 2); X *(buffer + templen - 1) = 0; X writelog(buffer); X break; X } X#ifdef CHECKC X default: X writelog("CONSISTENCY CHECK: Received unknown command from concentrator\n"); X#endif X } X } else X { X d = c->firstd; X while (d) X { X if (d->num == num) X { X process_input(d, c->incoming + 3, X templen - 1); X break; X } X d = d->next; X } X#ifdef CHECKC X if (!d) X writelog("CONSISTENCY CHECK: Message received for unknown user %d,%d\n", c->sock, num); X#endif X } X bcopy(c->incoming + templen + 2, c->incoming, X (c->ilen - templen - 2)); X c->ilen = c->ilen - templen - 2; X } else X break; X } X } X } X lastc = c; X } X /* Send data loop */ X for (c = firstc; c; c = c->next) X { X if (FD_ISSET(c->sock, &out)) X { X if (c->olen) X { X len = send(c->sock, c->outgoing, c->olen, 0); X if (len > 0) X { X c->olen -= len; X bcopy(c->outgoing + len, c->outgoing, c->olen); X } X } X } X } X } X} X Xvoid process_output(struct conc_list * c) X{ X struct descriptor_data *d; X struct text_block **qp, *cur; X short templen; X X for (d = c->firstd; d; d = d->next) X { X qp = &d->output.head; X cur = *qp; X if (cur) X { X if (cur->nchars < 512) X { X if ((c->olen + cur->nchars + 3) < BUFSIZE) X { X templen = cur->nchars + 1; X bcopy(&templen, c->outgoing + c->olen, 2); X *(c->outgoing + c->olen + 2) = d->num; X strncpy(c->outgoing + c->olen + 3, cur->start, cur->nchars); X d->output_size -= cur->nchars; X c->olen += cur->nchars + 3; X if (!cur->nxt) X d->output.tail = qp; X *qp = cur->nxt; X free_text_block(cur); X } X } else X { X if ((c->olen + 512 + 3) < BUFSIZE) X { X templen = 512 + 1; X bcopy(&templen, c->outgoing + c->olen, 2); X *(c->outgoing + c->olen + 2) = d->num; X strncpy(c->outgoing + c->olen + 3, cur->start, 512); X d->output_size -= 512; X c->olen += 512 + 3; X cur->nchars -= 512; X cur->start += 512; X } X } X } X } X} X Xvoid boot_off(dbref player) X{ X struct conc_list *c; X struct descriptor_data *d, *lastd; X char header[4]; X X for (c = firstc; c; c = c->next) X { X lastd = 0; X for (d = c->firstd; d; d = d->next) X { X if (d->connected && d->player == player) X { X header[0] = 0; X header[1] = 2; X header[2] = d->num; X queue_message(c, header, 3); X process_output(c); X if (lastd) X lastd->next = d->next; X else X c->firstd = d->next; X shutdownsock(d); X FREE(d); X return; X } X lastd = d; X } X } X} X Xvoid queue_message(struct conc_list * c, char *data, int len) X{ X struct message *ptr; X X MALLOC(ptr, struct message, 1); X MALLOC(ptr->data, char, len); X ptr->len = len; X bcopy(data, ptr->data, len); X ptr->next = 0; X if (c->last == 0) X c->first = ptr; X else X c->last->next = ptr; X c->last = ptr; X} X Xint do_connect_msg(struct descriptor_data * d, const char *filename) X{ X FILE *f; X char buf[BUFFER_LEN]; X char *p; X X if ((f = fopen(filename, "r")) == NULL) X { X return (0); X } else X { X while (fgets(buf, sizeof buf, f)) X { X queue_string(d, (char *)buf); X X } X fclose(f); X return (1); X } X} END_OF_FILE if test 33958 -ne `wc -c <'interface.c'`; then echo shar: \"'interface.c'\" unpacked with wrong size! fi # end of 'interface.c' fi if test -f 'joinspl.sh' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'joinspl.sh'\" else echo shar: Extracting \"'joinspl.sh'\" \(333 characters\) sed "s/^X//" >'joinspl.sh' <<'END_OF_FILE' X#! /bin/sh X# X# join split lines in the config.h and small.db files X# Xecho creating config.h Xsed -f comb.sed config_h.spl >config.h Xecho creating small.db Xsed -f comb.sed smalldb.spl >small.db Xrm config_h.spl smalldb.spl X# X# build tinymud.ps from its three parts X# Xcreating tinymud.ps Xcat tinymud.ps.xa? >tinymud.ps Xrm tinymud.ps.xa? END_OF_FILE if test 333 -ne `wc -c <'joinspl.sh'`; then echo shar: \"'joinspl.sh'\" unpacked with wrong size! fi chmod +x 'joinspl.sh' # end of 'joinspl.sh' fi if test -f 'wiz.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'wiz.c'\" else echo shar: Extracting \"'wiz.c'\" \(16849 characters\) sed "s/^X//" >'wiz.c' <<'END_OF_FILE' X#include "copyright.h" X X/* Wizard-only commands */ X X X#include "db.h" X#include "config.h" X#include "interface.h" X#include "match.h" X#include "externs.h" X Xvoid do_teleport(dbref player, const char *arg1, const char *arg2) X{ X dbref victim; X dbref destination; X const char *to; X X#ifdef RESTRICTED_TELEPORT X if(!Wizard(player)) { X#ifndef TINKER X notify(player, "Only a Wizard may teleport at will."); X#else TINKER X notify(player, "Only a Tinker may teleport at will."); X#endif TINKER X return; X } X#endif /* RESTRICTED_TELEPORT */ X X /* get victim, destination */ X if(*arg2 == '\0') { X victim = player; X to = arg1; X } else { X init_match(player, arg1, NOTYPE); X match_neighbor(); X match_possession(); X match_me(); X match_absolute(); X match_player(); X X if((victim = noisy_match_result()) == NOTHING) { X return; X } X to = arg2; X } X X /* get destination */ X init_match(player, to, TYPE_PLAYER); X match_here(); X match_absolute(); X if(Wizard(player)) { X match_neighbor(); X match_me(); X match_player(); X } X X switch(destination = match_result()) { X case NOTHING: X notify(player, "Send it where?"); X break; X case AMBIGUOUS: X notify(player, "I don't know which destination you mean!"); X break; X default: X /* check victim, destination types, teleport if ok */ X if(Typeof(destination) == TYPE_EXIT X || Typeof(destination) == TYPE_THING X || Typeof(victim) == TYPE_EXIT X || Typeof(victim) == TYPE_ROOM X || (Typeof(victim) == TYPE_PLAYER X && Typeof(destination) != TYPE_ROOM)) { X notify(player, "Bad destination."); X#ifndef RESTRICTED_TELEPORT X } else if(!Wizard(player) X && !(Typeof(victim) == TYPE_THING X && Typeof(destination) == TYPE_ROOM X && (controls(player, victim) X || (Typeof(db[victim].location) == TYPE_ROOM X && controls(player, db[victim].location))) X && (can_link_to(player, TYPE_PLAYER, destination)))) { X notify(player, "Permission denied."); X#endif /* RESTRICTED_TELEPORT */ X } else if(Typeof(victim) == TYPE_PLAYER) { X notify(victim, "You feel a wrenching sensation..."); X enter_room(victim, destination); X notify(player, "Teleported."); X } else { X /* check for non-sticky dropto */ X if(Typeof(destination) == TYPE_ROOM X && db[destination].location != NOTHING X && !(db[destination].flags & STICKY)) { X /* destination has immediate dropto */ X destination = db[destination].location; X } X X /* do the move */ X moveto(victim, destination); X notify(player, "Teleported."); X } X } X} X Xvoid do_mass_teleport(dbref player, const char *arg1) X{ X dbref victim; X dbref destination; X char buf[BUFFER_LEN]; X int moved = 0; X X if(!God(player)) { X#ifndef TINKER X notify(player, "Only God can do a mass teleport."); X#else TINKER X notify(player, "Only the Master Tinker can do a mass teleport."); X#endif TINKER X return; X } X X /* get destination */ X init_match(player, arg1, TYPE_ROOM); X match_here(); X match_absolute(); X X if ((destination = match_result()) == NOTHING) { X notify(player, "Please specify a destination to send everyone to."); X return; X } X X switch (Typeof(destination)) { X case NOTHING: X notify(player, "Send them where?"); X break; X X case TYPE_ROOM: X for (victim = 0; victim < db_top; victim++) { X if (victim != player && Typeof(victim) == TYPE_PLAYER) { X notify(victim, X "You and everyone around you feels a wrenching sensation..."); X moveto(victim, destination); X look_room(victim, destination); X moved++; X } X } X sprintf (buf, "Teleported %d players to %s.", X moved, unparse_object (player, destination)); X notify(player, "Teleported."); X break; X X default: X notify(player, "Mass teleports are legal to rooms only."); X } X} X Xvoid do_force(dbref player, const char *what, char *command) X{ X dbref victim; X X if(!Wizard(player)) { X writelog ("FORCE: failed, priv, player %s(%d), who '%s', what '%s'\n", X db[player].name, player, what, command); X#ifndef TINKER X notify(player, "Only Wizards may use this command."); X#else TINKER X notify(player, "Only Tinkers may use this command."); X#endif TINKER X return; X } X X /* get victim */ X if((victim = lookup_player(what)) == NOTHING) { X writelog ("FORCE: failed, victim, player %s(%d), who '%s', what '%s'\n", X db[player].name, player, what, command); X notify(player, "That player does not exist."); X return; X } X X#ifdef GOD_PRIV X if(God(victim)) { X#ifndef TINKER X writelog ("FORCE: failed, wizard, player %s(%d), who '%s', what '%s'\n", X#else TINKER X writelog ("FORCE: failed, tinker, player %s(%d), who '%s', what '%s'\n", X#endif TINKER X db[player].name, player, what, command); X#ifndef TINKER X notify(player, "You can't force God."); X#else TINKER X notify(player, "You can't force the Master Tinker."); X#endif TINKER X return; X } X#endif GOD_PRIV X X /* force victim to do command */ X writelog ("FORCE: success, player %s(%d), who '%s', what '%s'\n", X db[player].name, player, what, command); X X process_command(victim, command); X} X Xvoid do_stats(dbref player, const char *name) X{ X dbref rooms; X dbref exits; X dbref things; X dbref players; X dbref total; X dbref i; X dbref owner; X char buf[BUFFER_LEN]; X X if(!Wizard(player)) { X sprintf(buf, "The universe contains %d objects.", db_top); X notify(player, buf); X } else { X owner = lookup_player(name); X total = rooms = exits = things = players = 0; X for(i = 0; i < db_top; i++) { X if(owner == NOTHING || owner == db[i].owner) { X total++; X switch(Typeof(i)) { X case TYPE_ROOM: X rooms++; X break; X case TYPE_EXIT: X exits++; X break; X case TYPE_THING: X things++; X break; X case TYPE_PLAYER: X players++; X break; X default: X abort(); X break; X } X } X } X sprintf(buf, X "%d objects = %d rooms, %d exits, %d things, %d players.", X total, rooms, exits, things, players); X notify(player, buf); X#ifdef TEST_MALLOC X sprintf(buf, "Malloc count = %d.", malloc_count); X notify(player, buf); X#endif /* TEST_MALLOC */ X } X} X Xvoid do_bobble(dbref player, const char *name, const char *rname) X{ X dbref victim, recip, i; X char buf[BUFFER_LEN]; X int newflags = 0; X X if(!Wizard(player)) { X#ifndef TINKER X writelog("TOAD: failed, priv %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "Only a Wizard can turn a person into a toad."); X#else TINKER X writelog("BOBBLE: failed, priv %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "Only a Tinker can bobble a person."); X#endif TINKER X return; X } X X if (!name || !*name) { X#ifndef TINKER X writelog("TOAD: failed, syntax %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("BOBBLE: failed, syntax %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X notify(player, "You must specify a victim."); X return; X } X X init_match(player, name, TYPE_PLAYER); X match_neighbor(); X match_absolute(); X match_player(); X if((victim = noisy_match_result()) == NOTHING) { X#ifndef TINKER X writelog("TOAD: failed, victim %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("BOBBLE: failed, victim %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X notify(player, "Please specify another victim."); X return; X } X X#ifdef RECYCLE X /* Default the recipient to RECYCLER */ X if (!rname || !*rname || string_compare (rname, RECYCLER) == 0) { X recip = lookup_player(RECYCLER); X newflags = UNWANTED; /* Can be gotten by other players */ X } else { X recip = lookup_player(rname); X } X#else X recip = lookup_player(rname); X#endif X X if(recip == NOTHING || recip == victim) { X#ifndef TINKER X writelog("TOAD: failed, recip %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("BOBBLE: failed, recip %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X notify(player, "Please specify another player to own the victim's effects."); X return; X } X X if(Typeof(victim) != TYPE_PLAYER) { X#ifndef TINKER X writelog("TOAD: failed, type %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "You can only turn players into toads!"); X#else TINKER X writelog("BOBBLE: failed, type %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "You can only bobble players!"); X#endif TINKER X } else if(Wizard(victim)) { X#ifndef TINKER X writelog("TOAD: failed, wizard %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "You can't turn a Wizard into a toad."); X#else TINKER X writelog("BOBBLE: failed, tinker %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "You can't bobble a Tinker."); X#endif TINKER X } else if(db[victim].contents != NOTHING) { X#ifndef TINKER X writelog("TOAD: failed, contents %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("BOBBLE: failed, contents %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X X notify(player, "What about what they are carrying?"); X } else { X#ifndef TINKER X writelog("TOAD: success %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("BOBBLE: success %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X X /* we are ok */ X /* do it */ X if(db[victim].password) { X free((void *) db[victim].password); X db[victim].password = 0; X } X db[victim].flags = TYPE_THING; X X /* Give the sphere and all old belongings to recipient */ X db[victim].owner = recip; X for (i=0; i = "); X#else TINKER X writelog("UNBOBBLE: failed, syntax %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, X "You must specify a new name: @unbobble = "); X#endif TINKER X return; X } X X init_match(player, name, TYPE_THING); X match_neighbor(); X match_absolute(); X match_player(); X if((victim = noisy_match_result()) == NOTHING) { X#ifndef TINKER X writelog("UNTOAD: failed, victim %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("UNBOBBLE: failed, victim %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X notify(player, "Please specify another thing."); X return; X } X X if(Typeof(victim) != TYPE_THING) { X#ifndef TINKER X writelog("UNTOAD: failed, type %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "You can only turn players into toads!"); X#else TINKER X writelog("UNBOBBLE: failed, type %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "You can only bobble players!"); X#endif TINKER X } else if (!ok_player_name(newname)) { X#ifndef TINKER X writelog("UNTOAD: failed, name %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("UNBOBBLE: failed, name %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X notify(player, "You can't give a player that name!"); X } else { X#ifndef TINKER X writelog("UNTOAD: success %s(%d) who '%s'\n", X db[player].name, player, name); X#else TINKER X writelog("UNBOBBLE: success %s(%d) who '%s'\n", X db[player].name, player, name); X#endif TINKER X X /* we are ok */ X /* do it */ X db[victim].flags = TYPE_PLAYER; X db[victim].owner = victim; X db[victim].pennies = KILL_BONUS; X X /* reset name */ X free((void *) db[victim].name); X db[victim].name = alloc_string(newname); X X#ifndef TINKER X sprintf(buf, "You turned the toad back into %s!", db[victim].name); X#else TINKER X sprintf(buf, "You unbobbled %s!", db[victim].name); X#endif TINKER X notify(player, buf); X X sprintf(buf, "Use @newpassword to give %s a password", X db[victim].name); X notify(player, buf); X X#ifdef PLAYER_LIST X add_player(victim); X#endif PLAYER_LIST X } X} X Xvoid do_newpassword(dbref player, const char *name, const char *password) X{ X dbref victim; X char buf[BUFFER_LEN]; X X if(!Wizard(player)) { X writelog("PASSWORD: failed, priv %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "Your delusions of grandeur have been duly noted."); X return; X } else if((victim = lookup_player(name)) == NOTHING) { X writelog("PASSWORD: failed, victim %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "No such player."); X } else if(*password != '\0' && !ok_password(password)) { X /* Wiz can set null passwords, but not bad passwords */ X writelog("PASSWORD: failed, password %s(%d) who '%s'\n", X db[player].name, player, name); X notify(player, "Bad password"); X#ifdef GOD_PRIV X } else if (God(victim) && !God(player)) { X#ifndef TINKER X writelog("PASSWORD: failed, wizard %s(%d) who '%s'\n", X#else TINKER X writelog("PASSWORD: failed, tinker %s(%d) who '%s'\n", X#endif TINKER X db[player].name, player, name); X notify(player, "You cannot change that player's password."); X#endif GOD_PRIV X } else { X writelog("PASSWORD: success %s(%d) who '%s'\n", X db[player].name, player, name); X /* it's ok, do it */ X if(db[victim].password) free((void *) db[victim].password); X db[victim].password = alloc_string(password); X notify(player, "Password changed."); X sprintf(buf, "Your password has been changed by %s.", db[player].name); X notify(victim, buf); X } X} X Xvoid do_boot(dbref player, const char *name) X{ X dbref victim; X char buf[BUFFER_LEN]; X X if(!Wizard(player)) { X writelog ("BOOT: failed, priv player %s(%d), who '%s'\n", X db[player].name, player, name); X X#ifndef TINKER X notify(player, "Only a Wizard can boot another player off!"); X#else TINKER X notify(player, "Only a Tinker can boot another player off!"); X#endif TINKER X return; X } X X init_match(player, name, TYPE_PLAYER); X match_neighbor(); X match_absolute(); X match_player(); X if((victim = noisy_match_result()) == NOTHING) return; X X#ifdef GOD_PRIV X if(God(victim)) { X#ifndef TINKER X writelog ("BOOT: failed, wizard, player %s(%d), who '%s'\n", X#else TINKER X writelog ("BOOT: failed, tinker, player %s(%d), who '%s'\n", X#endif TINKER X db[player].name, player, name); X X notify(player, "You can't boot that player!"); X return; X } X#endif GOD_PRIV X X if(Typeof(victim) != TYPE_PLAYER) { X writelog ("BOOT: failed, victim, player %s(%d), who '%s'\n", X db[player].name, player, name); X X notify(player, "You can only boot off other players!"); X } else { X writelog ("BOOT: success, player %s(%d), who '%s'\n", X db[player].name, player, name); X X /* we are ok */ X /* do it */ X /* notify people */ X sprintf(buf, "You have been booted off the game by %s.", X db[player].name); X notify(victim, buf); X sprintf(buf, "You booted %s off!", db[victim].name); X notify(player, buf); X boot_off(victim); X /* reset name */ X } X} END_OF_FILE if test 16849 -ne `wc -c <'wiz.c'`; then echo shar: \"'wiz.c'\" unpacked with wrong size! fi # end of 'wiz.c' fi echo shar: End of archive 5 \(of 10\). cp /dev/null ark5isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 10 archives. echo ">>> now type 'sh joinspl.sh'" rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0