/* * Plists.c */ #include <stdlib.h> #include <ctype.h> #include <time.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <memory.h> #include <signal.h> #include <setjmp.h> #include "fix.h" #include "config.h" #include "player.h" #include "compaction.c" /* externs */ extern player *find_player_absolute_quiet(char *); extern char *gstring(player *); extern void do_inform(player *, char *); extern void do_prompt(player *, char *); extern void quit(player *, char *); extern void finish_edit(player *); extern int restore_player_title(player *, char *, char *); extern void decompress_list(saved_player *); extern void decompress_alias(saved_player *); extern void decompress_item(saved_player *); #if !defined(linux) extern char *crypt(char *, char *); #endif /* LINUX */ extern void player_flags(player *), player_flags_verbose(player *, char *); extern file load_file(); extern char *end_string(), *convert_time(), *retrieve_room_data(), *retrieve_list_data(), *bit_string(), *retrieve_mail_data(), *retrieve_alias_data(), *retrieve_item_data(); extern room *create_room(), *convert_room(); extern void password_mode_on(), password_mode_off(), trans_to(); extern void construct_room_save(), construct_list_save(), construct_mail_save(); extern void decompress_room(room *), construct_alias_save(), construct_item_save(); extern void log(char *, char *), handle_error(char *), free_room_data(saved_player *); extern void tell_player(player *, char *), tell_room(room *, char *); extern void swho(player *, char *), pager(player *, char *, int); extern int possible_move(player *, room *, int), true_count_su(), ishcadmin(); extern time_t shutdown_count; extern char *word_time(); extern file full_msg, under18_msg; extern void look(player *, char *), pg_version(player *, char *); extern void match_commands(); extern char *do_alias_match(); extern player *p_sess; /* interns */ void error_on_load(), hcadmin_check_password(); int bad_player_load = 0; char player_loading[MAX_NAME + 2]; jmp_buf jmp_env; file motd_msg, connect_msg, newban_msg, banned_msg, nonewbies_msg, newbie_msg, newpage1_msg, newpage2_msg, disclaimer_msg, splat_msg, sumotd_msg, version_msg, spodlist_msg, hitells_msg, fingerpaint_msg, connect2_msg, connect3_msg, noressies_msg; saved_player **saved_hash[26]; int update[26]; void save_player(), newbie_check_name(), link_to_program(); int restore_player(); saved_player **birthday_list = 0; /* update functions .. a complete database traversal */ /* crypts the password */ char *update_password(char *oldpass) { char key[9]; strncpy(key, oldpass, 8); return crypt(key, "SP"); } void players_update_function(player * p) { char em[MAX_EMAIL]; if (p->email[0] == ' ') strcpy(em, " <VALIDATED AS SET>"); else strcpy(em, p->email); if (p->residency & ADMIN) printf("%-18s -- %-40s >(ADMIN)\n", p->name, em); else if (p->residency & SU) printf("%-18s -- %-40s >(SU)\n", p->name, em); else if (p->residency & PSU) printf("%-18s -- %-40s >(PSEUDO)\n", p->name, em); else printf("%-18s -- %s\n", p->name, em); } void update_spodlist_fxn(player * p) { float ass; ass = (((float) p->total_login)/(((float) (time(0) - p->first_login_date)))) * 1000; if ((p->total_login - p->total_idle_time) > SPODLIST_MINIMUM) printf("%d %.0f %s\n", (p->total_login - p->total_idle_time), ass, p->name); } void interesting_data_function(player * p) { printf("%-17s -- %-3d %-3d -- %d\n", p->name, p->max_list, p->max_rooms, p->pennies); } void update_url_links_function(player * p) { if(p->alt_email[0]) printf("<A HREF = \"%s\"> %s </A>\n", p->alt_email, p->name); } void flags_update_function(player * p) { printf("%-18s -- %-40s\n", p->name, bit_string(p->residency)); } void rooms_update_function(player * p) { room *r; saved_player *sp; sp = p->saved; r = sp->rooms; while (r) { if (r->flags & OPEN) { decompress_room(r); printf("-=> %s.%s (%s)\n", r->owner->lower_name, r->id, r->name); if (r->exits.where) printf(r->exits.where); } r = r->next; } } void do_update(int rooms) { player *p; saved_player *scan, **hash; int i, j, fd; fd = open("/dev/null", O_WRONLY); p = (player *) MALLOC(sizeof(player)); for (j = 0; j < 26; j++) { /* printf("Updating %c\n",j+'a'); */ hash = saved_hash[j]; for (i = 0; i < HASH_SIZE; i++, hash++) { for (scan = *hash; scan; scan = scan->next) { if (scan->residency != STANDARD_ROOMS && scan->residency != SYSTEM_ROOM &&(scan->residency != BANISHED) && (scan->residency != BANISHD)) { memset((char *) p, 0, sizeof(player)); p->fd = fd; p->script = 0; p->location = (room *) - 1; restore_player(p, scan->lower_name); if (rooms == 2) update_spodlist_fxn(p); else if (rooms == 3) update_url_links_function(p); else if (rooms == 4) interesting_data_function(p); else if (rooms) rooms_update_function(p); else if (sys_flags & UPDATE) players_update_function(p); else flags_update_function(p); save_player(p); } } } } close(fd); if (rooms == 2) printf("0 0 noone\n"); } /* return the top player in a hash list */ saved_player *find_top_player(char c, int h) { if ((c < 0) || (c > 25)) return 0; if ((h < 0) || (h > HASH_SIZE)) return 0; return (*(saved_hash[c] + h)); } /* birthdays !!! */ void do_birthdays() { player *p; saved_player *scan, **hash, **list; int i, j, fd; time_t t; struct tm *date, *bday; char *oldstack; fd = open("/dev/null", O_WRONLY); oldstack = stack; align(stack); list = (saved_player **) stack; t = time(0); date = localtime(&t); p = (player *) MALLOC(sizeof(player)); for (j = 0; j < 26; j++) { hash = saved_hash[j]; for (i = 0; i < HASH_SIZE; i++, hash++) for (scan = *hash; scan; scan = scan->next) if (scan->residency != STANDARD_ROOMS && scan->residency != SYSTEM_ROOM && (scan->residency != BANISHED) && (!(scan->residency & BANISHD))) { memset((char *) p, 0, sizeof(player *)); restore_player(p, scan->lower_name); bday = localtime((time_t *)&(p->birthday)); if ((bday->tm_mon == date->tm_mon) && (bday->tm_mday == date->tm_mday)) { *((saved_player **) stack) = scan; stack += sizeof(saved_player *); p->age++; save_player(p); } } } *((saved_player **) stack) = 0; stack += sizeof(saved_player *); if (birthday_list) FREE(birthday_list); i = (int) stack - (int) list; if (i > 4) { birthday_list = (saved_player **) MALLOC(i); memcpy(birthday_list, list, i); } else birthday_list = 0; close(fd); } /* saved player stuff */ /* see if a saved player exists (given lower case name) */ saved_player *find_saved_player(char *name) { saved_player **hash, *list; int sum = 0,h; char *c; if (!isalpha(*name)) return 0; hash = saved_hash[((int) (tolower(*name)) - (int) 'a')]; for (c = name; *c; c++) { if (isalpha(*c)) sum += (int) (tolower(*c)) - 'a'; else return 0; } list = *(hash + (sum % HASH_SIZE)); for (; list; list = list->next) if (!strcmp(name, list->lower_name)) return list; return 0; } /* hard load and save stuff (ie to disk and back) */ /* extract one player */ void extract_player(char *where, int length) { int len, sum; char *oldstack, *c; saved_player *old, *sp, **hash; oldstack = stack; where = get_int(&len, where); where = get_string(oldstack, where); stack = end_string(oldstack); old = find_saved_player(oldstack); sp = old; if (!old) { sp = (saved_player *) MALLOC(sizeof(saved_player)); memset((char *) sp, 0, sizeof(saved_player)); strncpy(sp->lower_name, oldstack, MAX_NAME); strncpy(player_loading, sp->lower_name, MAX_NAME); sp->rooms = 0; sp->mail_sent = 0; sp->mail_received = 0; sp->list_top = 0; hash = saved_hash[((int) sp->lower_name[0] - (int) 'a')]; for (sum = 0, c = sp->lower_name; *c; c++) sum += (int) (*c) - 'a'; hash = (hash + (sum % HASH_SIZE)); sp->next = *hash; *hash = sp; } where = get_int(&sp->last_on, where); where = get_int(&sp->system_flags, where); where = get_int(&sp->tag_flags, where); where = get_int(&sp->custom_flags, where); where = get_int(&sp->misc_flags, where); where = get_int(&sp->pennies, where); where = get_int(&sp->residency, where); if (sp->residency == BANISHED) sp->residency = BANISHD; if (sp->residency == BANISHD) { sp->last_host[0] = 0; sp->email[0] = 0; sp->data.where = 0; sp->data.length = 0; stack = oldstack; return; } /* * This bit controls when idle players get wiped. After summer hols, this * bit MUST be uncommented */ if ( ((time(0)-(sp->last_on)) > PLAYER_TIMEOUT) && !(sp->residency&NO_TIMEOUT)) { log("timeouts", sp->lower_name); remove_player_file(sp->lower_name); stack=oldstack; return; } /* PUT ANYTHING TO CHANGE RESIDENCY OR OTHER FLAGS HERE */ where = get_string(sp->last_host, where); where = get_string(sp->email, where); where = get_int(&sp->data.length, where); sp->data.where = (char *) MALLOC(sp->data.length); memcpy(sp->data.where, where, sp->data.length); where += sp->data.length; where = retrieve_room_data(sp, where); where = retrieve_list_data(sp, where); where = retrieve_alias_data(sp, where); where = retrieve_item_data(sp, where); where = retrieve_mail_data(sp, where); stack = oldstack; } /* hard load in on player file */ void hard_load_one_file(char c) { char *oldstack, *where, *scan; int fd, length, len2, i, fromjmp; oldstack = stack; if (sys_flags & VERBOSE) { sprintf(oldstack, "Loading player file '%c'.", c); stack = end_string(oldstack); log("boot", oldstack); stack = oldstack; } #ifdef PC sprintf(oldstack, "files\\players\\%c", c); fd = open(oldstack, O_RDONLY | O_BINARY); #else sprintf(oldstack, "files/players/%c", c); fd = open(oldstack, O_RDONLY | O_NDELAY); #endif if (fd < 0) { sprintf(oldstack, "Failed to load player file '%c'", c); stack = end_string(oldstack); log("error", oldstack); } else { length = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); if (length) { where = (char *) MALLOC(length); if (read(fd, where, length) < 0) handle_error("Can't read player file."); for (i = 0, scan = where; i < length;) { get_int(&len2, scan); fromjmp = setjmp(jmp_env); if (!fromjmp && !bad_player_load) { extract_player(scan, len2); } else { sprintf(oldstack, "Bad Player \'%s\' deleted on load. (oh fuck)", player_loading); stack = end_string(oldstack); log("boot", oldstack); stack = oldstack; remove_player_file(player_loading); bad_player_load = 0; } i += len2; scan += len2; } FREE(where); } close(fd); } stack = oldstack; } /* load in all the player files */ void hard_load_files() { char c; int i, hash_length; char *oldstack; #if defined(hpux) | defined(linux) struct sigaction sa; sa.sa_handler = error_on_load; sa.sa_mask = 0; sa.sa_flags = 0; sigaction(SIGSEGV, &sa, 0); sigaction(SIGSEGV, &sa, 0); #else /* hpux | linux */ signal(SIGSEGV, error_on_load); signal(SIGBUS, error_on_load); #endif /* hpux | linux */ oldstack = stack; hash_length = HASH_SIZE * sizeof(saved_player *); for (i = 0; i < 26; i++) { saved_hash[i] = (saved_player **) MALLOC(hash_length); memset((void *) saved_hash[i], 0, hash_length); } for (c = 'a'; c <= 'z'; c++) hard_load_one_file(c); } /* write one player file out */ void write_to_file(saved_player * sp) { char *oldstack; int length; oldstack = stack; if (sys_flags & VERBOSE && sys_flags & PANIC) { sprintf(oldstack, "Attempting to write player '%s'.", sp->lower_name); stack = end_string(oldstack); log("sync", oldstack); stack = oldstack; } stack += 4; stack = store_string(stack, sp->lower_name); stack = store_int(stack, sp->last_on); stack = store_int(stack, sp->system_flags); stack = store_int(stack, sp->tag_flags); stack = store_int(stack, sp->custom_flags); stack = store_int(stack, sp->misc_flags); stack = store_int(stack, sp->pennies); stack = store_int(stack, sp->residency); if ((sp->residency != BANISHED) ) { stack = store_string(stack, sp->last_host); stack = store_string(stack, sp->email); stack = store_int(stack, sp->data.length); memcpy(stack, sp->data.where, sp->data.length); stack += sp->data.length; construct_room_save(sp); construct_list_save(sp); construct_alias_save(sp); construct_item_save(sp); construct_mail_save(sp); } length = (int) stack - (int) oldstack; (void) store_int(oldstack, length); } /* sync player files corresponding to one letter */ void sync_to_file(char c, int background) { saved_player *scan, **hash; char *oldstack; int fd, i, length; if (background && fork()) return; oldstack = stack; if (sys_flags & VERBOSE) { sprintf(oldstack, "Syncing File '%c'.", c); stack = end_string(oldstack); log("sync", oldstack); stack = oldstack; } hash = saved_hash[((int) c - (int) 'a')]; for (i = 0; i < HASH_SIZE; i++, hash++) for (scan = *hash; scan; scan = scan->next) if (scan->residency != STANDARD_ROOMS && scan->residency != SYSTEM_ROOM && (!(scan->residency & NO_SYNC) || scan->residency == BANISHED)) write_to_file(scan); length = (int) stack - (int) oldstack; /* test that you can write out a file ok */ strcpy(stack, "files/players/backup_write"); fd = open(stack, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) handle_error("Primary open failed (player back)"); if (write(fd, oldstack, length) < 0) handle_error("Primary write failed " "(playerback)"); close(fd); #ifdef PC sprintf(stack, "files\\players\\%c", c); fd = open(stack, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY); #else sprintf(stack, "files/players/%c", c); fd = open(stack, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, S_IRUSR | S_IWUSR); #endif if (fd < 0) handle_error("Failed to open player file."); if (write(fd, oldstack, length) < 0) handle_error("Failed to write player file."); close(fd); update[(int) c - (int) 'a'] = 0; stack = oldstack; if (background) exit(0); } /* sync everything to disk */ void sync_all() { char c, *oldstack; oldstack = stack; for (c = 'a'; c <= 'z'; c++) sync_to_file(c, 0); log("sync", "Full Sync Completed."); } /* fork and sync the playerfiles */ void fork_the_thing_and_sync_the_playerfiles(void) { int fl; char c, *oldstack; fl = fork(); if (fl == -1) { log("error", "Forked up!"); return; } if (fl > 0) return; sync_all(); exit(0); } /* flicks on the update flag for a particular player hash */ void set_update(char c) { update[(int) c - (int) 'a'] = 1; } /* removes an entry from the saved player lists */ int remove_player_file(char *name) { saved_player *previous = 0, **hash, *list; char *c; int sum = 0; if (!isalpha(*name)) { log("error", "Tried to remove non-player from save files."); return 0; } strcpy(stack, name); lower_case(stack); hash = saved_hash[((int) (*stack) - (int) 'a')]; for (c = stack; *c; c++) { if (isalpha(*c)) sum += (int) (*c) - 'a'; else { log("error", "Remove bad name from save files"); return 0; } } hash += (sum % HASH_SIZE); list = *hash; for (; list; previous = list, list = list->next) { if (!strcmp(stack, list->lower_name)) { if (previous) previous->next = list->next; else *hash = list->next; if (list->data.where) FREE(list->data.where); if (list->mail_received) FREE(list->mail_received); free_room_data(list); FREE((void *) list); set_update(*stack); return 1; } } return 0; } /* remove an entire hash of players */ void remove_entire_list(char c) { saved_player **hash, *sp, *next; int i; if (!isalpha(c)) return; hash = saved_hash[((int) (c) - (int) 'a')]; for (i = 0; i < HASH_SIZE; i++, hash++) { sp = *hash; while (sp) { next = sp->next; if (sp->data.where) FREE(sp->data.where); free_room_data(sp); FREE((void *) sp); sp = next; } *hash = 0; } set_update(c); } /* routines to save a player to the save files */ /* makes the save data onto the stack */ file construct_save_data(player * p) { file d; d.where = stack; stack = store_string(stack, p->name); stack = store_string(stack, p->prompt); stack = store_string(stack, p->converse_prompt); stack = store_string(stack, p->email); if (p->password[0] == -1) p->password[0] = 0; stack = store_string(stack, p->password); stack = store_string(stack, p->title); stack = store_string(stack, p->plan); stack = store_string(stack, p->description); stack = store_string(stack, p->enter_msg); stack = store_string(stack, p->pretitle); stack = store_string(stack, p->ignore_msg); stack = store_string(stack, p->room_connect); stack = store_int(stack, p->term_width); stack = store_int(stack, p->word_wrap); stack = store_int(stack, p->max_rooms); stack = store_int(stack, p->max_exits); stack = store_int(stack, p->max_autos); stack = store_int(stack, p->max_list); stack = store_int(stack, p->max_mail); stack = store_int(stack, p->gender); stack = store_int(stack, p->no_shout); stack = store_int(stack, p->total_login); stack = store_int(stack, p->term); stack = store_int(stack, p->birthday); stack = store_int(stack, p->age); /* Here goes with adding to the playerfiles */ stack = store_int(stack, p->jetlag); stack = store_int(stack, p->sneezed); /* now the mother load of trap's spooning........ */ stack = store_string(stack, p->logonmsg); stack = store_string(stack, p->logoffmsg); stack = store_string(stack, p->blockmsg); stack = store_string(stack, p->exitmsg); stack = store_int(stack, p->time_in_main); stack = store_int(stack, p->no_sing); stack = store_string(stack, p->married_to); stack = store_string(stack, p->irl_name); stack = store_string(stack, p->alt_email); stack = store_string(stack, p->hometown); stack = store_string(stack, p->spod_class); stack = store_string(stack, p->favorite1); stack = store_string(stack, p->favorite2); stack = store_string(stack, p->favorite3); stack = store_int(stack, p->total_idle_time); stack = store_int(stack, p->max_alias); stack = store_string(stack, p->colorset); stack = store_string(stack, p->ressied_by); stack = store_string(stack, p->git_string); stack = store_string(stack, p->git_by); stack = store_int(stack, p->warn_count); stack = store_int(stack, p->eject_count); stack = store_int(stack, p->idled_out_count); stack = store_int(stack, p->booted_count); stack = store_int(stack, p->num_ressied); stack = store_int(stack, p->num_warned); stack = store_int(stack, p->num_ejected); stack = store_int(stack, p->num_rmd); stack = store_int(stack, p->num_booted); stack = store_int(stack, p->first_login_date); stack = store_int(stack, p->max_items); stack = store_int(stack, p->prs_record); stack = store_string(stack, p->ingredients); /* end of my spooning... (well, not the end of me spooning, but the end of this mega-batch) */ d.length = (int) stack - (int) d.where; stack = d.where; return d; } /* the routine that sets everything up for the save */ void save_player(player * p) { saved_player *old, **hash, *sp; int sum; file data; char *c, *oldstack; int verb = 1; oldstack = stack; if (!(p->location) || !(p->name[0]) || p->residency == NON_RESIDENT) return; if (sys_flags & PANIC) { c = stack; sprintf(c, "Attempting to save player %s.", p->name); stack = end_string(c); log("boot", c); stack = c; } if (!(isalpha(p->lower_name[0]))) { log("error", "Tried to save non-player."); return; } if (p->residency & SYSTEM_ROOM) verb = 0; if (p != current_player) verb = 0; if (verb) { if (!(p->password[0] && p->password[0] != -1)) { tell_current(" Tried to save this character but failed ...\n" " Your character will not save until you set a password.\n" " Simply type 'password' whilst in command mode to set one.\n"); p->residency |= NO_SYNC; tell_current(" NOT saved.\n"); stack = oldstack; return; } if (p->email[0] == 2) { tell_current(" Tried to save this character but failed ...\n" " Your character will not save until you set an email address.\n" " To set this just type 'email <whatever>', where <whatever> is your\n" " email address.\n" " If you do not have an email, please speak to one of the superusers.\n"); p->residency |= NO_SYNC; tell_player(p, "NOT saved.\n"); stack = oldstack; return; } } p->residency &= ~NO_SYNC; p->saved_residency = p->residency; old = p->saved; sp = old; if (!old) { sp = (saved_player *) MALLOC(sizeof(saved_player)); memset((char *) sp, 0, sizeof(saved_player)); strncpy(sp->lower_name, p->lower_name, MAX_NAME); sp->rooms = 0; sp->mail_sent = 0; sp->mail_received = 0; sp->list_top = 0; hash = saved_hash[((int) p->lower_name[0] - (int) 'a')]; for (sum = 0, c = p->lower_name; *c; c++) { if (isalpha(*c)) sum += (int) (*c) - 'a'; else { tell_player(p, " Eeek, trying to save bad player name !!\n"); FREE(sp); return; } } hash = (hash + (sum % HASH_SIZE)); sp->next = *hash; *hash = sp; p->saved = sp; sp->system_flags = p->system_flags; sp->tag_flags = p->tag_flags; sp->custom_flags = p->custom_flags; sp->misc_flags = p->misc_flags; sp->pennies = p->pennies; create_room(p); } data = construct_save_data(p); if (!data.length) { log("error", "Bad construct save."); return; } if (old && sp->data.where) FREE((void *) sp->data.where); sp->data.where = (char *) MALLOC(data.length); sp->data.length = data.length; memcpy(sp->data.where, data.where, data.length); sp->residency = p->saved_residency; sp->system_flags = p->system_flags; sp->tag_flags = p->tag_flags; sp->custom_flags = p->custom_flags; sp->misc_flags = p->misc_flags; sp->pennies = p->pennies; strncpy(sp->last_host, p->inet_addr, MAX_INET_ADDR - 2); strncpy(sp->email, p->email, MAX_EMAIL - 3); set_update(*(sp->lower_name)); p->saved = sp; sp->last_on = time(0); if (verb) tell_current(" Character Saved ...\n"); } /* the routine that sets everything up for the save */ void create_banish_file(char *str) { saved_player **hash, *sp, *scan; int sum; char *c, name[20]; strncpy(name, str, MAX_NAME - 3); sp = (saved_player *) MALLOC(sizeof(saved_player)); memset((char *) sp, 0, sizeof(saved_player)); strcpy(stack, name); lower_case(stack); strncpy(sp->lower_name, stack, MAX_NAME - 3); sp->rooms = 0; sp->mail_sent = 0; sp->mail_received = 0; hash = saved_hash[((int) name[0] - (int) 'a')]; for (sum = 0, c = name; *c; c++) if (isalpha(*c)) sum += (int) (*c) - 'a'; else { log("error", "Tried to banish bad player"); FREE(sp); return; } hash = (hash + (sum % HASH_SIZE)); scan = *hash; while (scan) { hash = &(scan->next); scan = scan->next; } *hash = sp; sp->residency = BANISHD; sp->system_flags = 0; sp->tag_flags = 0; sp->custom_flags = 0; sp->misc_flags = 0; sp->pennies = 50; sp->last_host[0] = 0; sp->email[0] = 0; sp->last_on = time(0); sp->next = 0; set_update(tolower(*(sp->lower_name))); } /* load from a saved player into a current player */ /* actually do load */ int load_player(player * p) { saved_player *sp; char *r; lower_case(p->lower_name); sp = find_saved_player(p->lower_name); p->saved = sp; if (!sp) return 0; p->residency = sp->residency; p->saved_residency = p->residency; p->system_flags = sp->system_flags; p->tag_flags = sp->tag_flags; p->custom_flags = sp->custom_flags; p->misc_flags = sp->misc_flags; p->pennies = sp->pennies; if (sp->residency == BANISHED || sp->residency == STANDARD_ROOMS || sp->residency == SYSTEM_ROOM || sp->residency == BANISHD) return 1; r = sp->data.where; r = get_string(p->name, r); r = get_string(p->prompt, r); r = get_string(p->converse_prompt, r); r = get_string(p->email, r); r = get_string(p->password, r); r = get_string(p->title, r); r = get_string(p->plan, r); r = get_string(p->description, r); r = get_string(p->enter_msg, r); r = get_string(p->pretitle, r); r = get_string(p->ignore_msg, r); r = get_string(p->room_connect, r); r = get_int(&p->term_width, r); r = get_int(&p->word_wrap, r); r = get_int(&p->max_rooms, r); r = get_int(&p->max_exits, r); r = get_int(&p->max_autos, r); r = get_int(&p->max_list, r); r = get_int(&p->max_mail, r); r = get_int(&p->gender, r); r = get_int(&p->no_shout, r); r = get_int(&p->total_login, r); r = get_int(&p->term, r); r = get_int(&p->birthday, r); r = get_int(&p->age, r); r = get_int(&p->jetlag, r); r = get_int(&p->sneezed, r); /* ok the first time through, these won't be in... instead we just do blanks. */ /* i commented this out when I did the evil deed... */ r = get_string(p->logonmsg, r); r = get_string(p->logoffmsg, r); r = get_string(p->blockmsg, r); r = get_string(p->exitmsg, r); r = get_int(&p->time_in_main, r); r = get_int(&p->no_sing, r); r = get_string(p->married_to, r); r = get_string(p->irl_name, r); r = get_string(p->alt_email, r); r = get_string(p->hometown, r); r = get_string(p->spod_class, r); r = get_string(p->favorite1, r); r = get_string(p->favorite2, r); r = get_string(p->favorite3, r); r = get_int(&p->total_idle_time, r); r = get_int(&p->max_alias, r); r = get_string(p->colorset, r); r = get_string(p->ressied_by, r); r = get_string(p->git_string, r); r = get_string(p->git_by, r); r = get_int(&p->warn_count, r); r = get_int(&p->eject_count, r); r = get_int(&p->idled_out_count, r); r = get_int(&p->booted_count, r); r = get_int(&p->num_ressied, r); r = get_int(&p->num_warned, r); r = get_int(&p->num_ejected, r); r = get_int(&p->num_rmd, r); r = get_int(&p->num_booted, r); r = get_int(&p->first_login_date, r); r = get_int(&p->max_items, r); r = get_int(&p->prs_record, r); r = get_string(p->ingredients, r); /* end of trap's shit - the loaded version. */ if (((p->term_width) >> 1) <= (p->word_wrap)) p->word_wrap = (p->term_width) >> 1; decompress_list(sp); decompress_alias(sp); decompress_item(sp); p->system_flags = sp->system_flags; p->tag_flags = sp->tag_flags; p->custom_flags = sp->custom_flags; p->misc_flags = sp->misc_flags; p->pennies = sp->pennies; return 1; } /* load and do linking */ int restore_player(player * p, char *name) { return restore_player_title(p, name, 0); } int restore_player_title(player * p, char *name, char *title) { int did_load, i; int found_lower; char *n; strncpy(p->name, name, MAX_NAME - 3); strncpy(p->lower_name, name, MAX_NAME - 3); lower_case(p->lower_name); if (!strcmp(p->name, p->lower_name)) p->name[0] = toupper(p->name[0]); found_lower = 0; n = p->name; while (*n) { if (*n >= 'a' && *n <= 'z') { found_lower = 1; } *n++; } if (!found_lower) { n = p->name; *n++; while (*n) { *n = *n - ('A' - 'a'); *n++; } } /* Set up a default player structure, methinks */ strncpy(p->prompt, "PG ->", MAX_PROMPT); strncpy(p->converse_prompt, "(Con)->", MAX_PROMPT); strcpy(p->enter_msg, "enters in a standard kind of way."); strcpy(p->colorset, "HYBGAaCPN"); p->term_width = 79; p->column = 0; p->word_wrap = 10; p->total_login = 0; p->first_login_date = time(0); p->gender = VOID_GENDER; p->no_shout = 180; p->tag_flags = TAG_ECHO | SEEECHO | TAG_PERSONAL | TAG_SHOUT; p->custom_flags = PRIVATE_EMAIL | MAIL_INFORM | NOEPREFIX | NOPREFIX; p->system_flags = IAC_GA_ON; p->misc_flags = NOCOLOR; p->pennies = 50; strncpy(p->title, "is new to the Program.", MAX_TITLE); strncpy(p->description, "I'll write a description someday...", MAX_DESC); strncpy(p->plan, "Plan? What Plan?" , MAX_PLAN); p->max_rooms = 2; p->max_exits = 5; p->max_autos = 5; p->max_list = 25; p->max_mail = 10; p->max_alias = 10; p->birthday = 0; p->age = 0; p->jail_timeout = 0; for (i=0;i<8;i++) strcpy(p->rev[i].review,""); p->script = 0; strcpy(p->script_file, "dummy.log"); p->assisted_by[0] = 0; p->residency = 0; strcpy(p->ignore_msg, ""); p->jetlag = 0; /* gonna need these now.... */ strcpy(p->logonmsg, ""); strcpy(p->logoffmsg, ""); strcpy(p->blockmsg, ""); strcpy(p->exitmsg, ""); strcpy(p->married_to, ""); strcpy(p->irl_name, ""); strcpy(p->alt_email, ""); strcpy(p->hometown, ""); strcpy(p->spod_class, ""); strcpy(p->favorite1, ""); strcpy(p->favorite2, ""); strcpy(p->favorite3, ""); strcpy(p->ingredients, ""); strcpy(p->ressied_by, ""); strcpy(p->git_string, ""); strcpy(p->git_by, ""); /* and set the ints up too =) */ p->no_sing = 180; p->time_in_main = 0; p->total_idle_time = 0; p->warn_count = 0; p->eject_count = 0; p->idled_out_count = 0; p->booted_count = 0; p->num_ressied = 0; p->num_warned = 0; p->num_ejected = 0; p->num_rmd = 0; p->num_booted = 0; p->prs = 0; p->prs_record = 0; p->max_items = 10; p->gag_top = 0; did_load = load_player(p); if (did_load && !strcmp(p->lower_name, "guest")) did_load = 0; strcpy(p->assisted_by, ""); if (title && *title) { strncpy(p->title, title, MAX_TITLE); p->title[MAX_TITLE] = 0; } if ((p->system_flags & IAC_GA_ON) && (!(p->flags & EOR_ON))) p->flags |= IAC_GA_DO; else p->flags &= ~IAC_GA_DO; if (p->residency == 0 && did_load == 1) p->residency = SYSTEM_ROOM; /* blank the repeat stuff, just in case... */ p->last_remote_command = -1; /* will give error to user =) */ strcpy(p->last_remote_msg, ""); if (p->system_flags & SAVEDFROGGED) p->flags |= FROGGED; /* got to have someone here I'm afraid.. */ if (ishcadmin(p->lower_name)) { p->residency = HCADMIN_INIT; p->residency |= (REGULAR_STYLE_CHAN | CODER | ASU); /* I don't wanna recompile all :P */ strcpy(p->ressied_by, "Hard Coded"); } /* this is just an example of how one can "mask" a site for a test char */ if ( !strcmp("cassius", p->lower_name)) { strcpy(p->num_addr, "133.99.18.6"); strcpy(p->inet_addr, "zork.infocom.com"); } if ( !strcmp("rock", p->lower_name)) { strcpy(p->num_addr, "138.25.9.2"); /*forgive the implication on this site *giggle* */ strcpy(p->inet_addr, "charlie.progsoc.uts.edu.au"); } if (p->residency & PSU) p->no_shout = 0; /* integrity .. sigh */ p->saved_residency = p->residency; /* * if (p->max_rooms>50 || p->max_rooms<0) p->max_rooms=3; if * (p->max_exits>50 || p->max_exits<0) p->max_exits=10; if (p->max_autos>50 * || p->max_autos<0) p->max_autos=10; if (p->max_list>100 || * p->max_list<0) p->max_list=20; if (p->max_mail>100 || p->max_mail<0) * p->max_mail=10; if (p->term_width>200 || p->term_width<0) * p->term_width=79; */ if ((p->word_wrap) > ((p->term_width) >> 1) || p->word_wrap < 0) p->word_wrap = (p->term_width) >> 1; if (p->term > 9) p->term = 0; return did_load; } /* current player stuff */ /* create an abstract player into the void hash list */ player *create_player() { player *p; p = (player *) MALLOC(sizeof(player)); memset((char *) p, 0, sizeof(player)); if (flatlist_start) flatlist_start->flat_previous = p; p->flat_next = flatlist_start; flatlist_start = p; p->hash_next = hashlist[0]; hashlist[0] = p; p->hash_top = 0; p->timer_fn = 0; p->timer_count = -1; p->edit_info = 0; p->logged_in = 0; return p; } /* unlink p from all the lists */ void punlink(player * p) { player *previous, *scan; /* reset the session p */ p_sess = 0; /* first remove from the hash list */ scan = hashlist[p->hash_top]; previous = 0; while (scan && scan != p) { previous = scan; scan = scan->hash_next; } if (!scan) log("error", "Bad hash list"); else if (!previous) hashlist[p->hash_top] = p->hash_next; else previous->hash_next = p->hash_next; /* then remove from the flat list */ if (p->flat_previous) p->flat_previous->flat_next = p->flat_next; else flatlist_start = p->flat_next; if (p->flat_next) p->flat_next->flat_previous = p->flat_previous; /* finally remove from the location list */ if (p->location) { previous = 0; scan = p->location->players_top; while (scan && scan != p) { previous = scan; scan = scan->room_next; } if (!scan) log("error", "Bad Location list"); else if (!previous) p->location->players_top = p->room_next; else previous->room_next = p->room_next; } } /* remove a player from the current hash lists */ void destroy_player(player * p) { #ifndef PC if ((p->fd) > 0) { shutdown(p->fd, 0); close(p->fd); } #endif if (p->name[0] && p->location) current_players--; punlink(p); if (p->edit_info) finish_edit(p); FREE(p); #ifdef PC if (p == input_player) { input_player = flatlist_start; if (!input_player) sys_flags |= SHUTDOWN; } #endif } /* get person to agree to disclaimer */ void agree_disclaimer(player * p, char *str) { p->input_to_fn = 0; if (!strcasecmp(str, "continue")) { p->system_flags |= AGREED_DISCLAIMER; if (p->saved) p->saved->system_flags |= AGREED_DISCLAIMER; if (!ishcadmin(p->name)) link_to_program(p); else hcadmin_check_password(p); return; } else if (!strcasecmp(str, "end")) { tell_player(p, "\n Disconnecting from program.\n\n"); quit(p, ""); } else { do_prompt(p, "Enter 'continue' or 'end':"); p->input_to_fn = agree_disclaimer; } } /* check if the motd is a new one */ /* HOPE that this works right ;) */ /* the function will check motd or sumotd, or any other ones we add. If the motd was written since the last time the player was seen, the function returns 1, and that player will see the appropriate motd */ int motd_is_new(player *p, char *filename) { struct stat statblk; char motdfile[20]; /* fuck the magic number rules :P */ if (!(p->saved)) /* hcadmin new login */ return 1; sprintf(motdfile,"files/%s.msg",filename); stat(motdfile,&statblk); /* Get the stats on the file */ if(statblk.st_mtime >= p->saved->last_on) { /* check mod file vs player last login */ return 1; } else return 0; } /* links a person into the program properly (several fxns) */ void finish_player_login_2(player *p, char *str) { char *oldstack, *hello; saved_player *sp; room *r, *rm; int i; oldstack = stack; if (p->residency && p->custom_flags & CONVERSE) p->mode |= CONV; current_players++; p->on_since = time(0); logins++; if (!(p->flags & RECONNECTION)) p->shout_index = 50; if (p->residency != NON_RESIDENT) player_flags(p); if (p->system_flags & SAVEDJAIL) { p->jail_timeout = -1; trans_to(p, "system.prison"); } else if (p->custom_flags & TRANS_TO_HOME || *p->room_connect && !(p->flags & RECONNECTION)) { sp = p->saved; if (!sp) tell_player(p, " Double Eeek (room_connect)!\n"); else { if (p->custom_flags & TRANS_TO_HOME) { for (r = sp->rooms; r; r = r->next) if (r->flags & HOME_ROOM) { sprintf(oldstack, "%s.%s", r->owner->lower_name, r->id); stack = end_string(oldstack); trans_to(p, oldstack); break; } } else { rm = convert_room(p, p->room_connect); if (rm && rm->flags & CONFERENCE && possible_move(p, rm, 1)) trans_to(p, p->room_connect); } if (!(p->location)) tell_player(p, " -=> Tried to connect you to a room, but failed" " !!\n\n"); } } if (!(p->location)) { trans_to(p, ENTRANCE_ROOM); } if (p->flags & RECONNECTION) { do_inform(p, "[%s reconnects] %s"); sprintf(oldstack, "%s appears momentarily frozen as %s reconnects.\n", p->name, gstring(p)); stack = end_string(oldstack); command_type |= RECON_TAG; tell_room(p->location, oldstack); command_type &= ~RECON_TAG; /* I still need to know this for a sec or 3 p->flags &= ~RECONNECTION; */ } else { if (p->gender==PLURAL) do_inform(p, "[%s join us] %s"); else do_inform(p, "[%s joins us] %s"); if (strlen(p->logonmsg) < 1) { if (p->gender==PLURAL) sprintf(oldstack, "%s enter the program.\n", p->name); else sprintf(oldstack, "%s enters the program.\n", p->name); } else { if (*p->logonmsg == 39 || *p->logonmsg == ',') sprintf(oldstack, "%s%s\n", p->name, p->logonmsg); else sprintf(oldstack, "%s %s\n", p->name, p->logonmsg); } stack = end_string(oldstack); command_type |= LOGIN_TAG; tell_room(p->location, oldstack); command_type &= ~LOGIN_TAG; } if (p->saved) { decompress_list(p->saved); decompress_alias(p->saved); decompress_item(p->saved); /* here is the bug */ p->system_flags = p->saved->system_flags; p->tag_flags = p->saved->tag_flags; p->custom_flags = p->saved->custom_flags; p->misc_flags = p->saved->misc_flags; if (!(p->pennies) && !(p->flags & RECONNECTION)) p->pennies = p->saved->pennies; /* wibble plink? =) */ if (p->flags & RECONNECTION) look(p, 0); if (p->custom_flags & YES_QWHO_LOGIN) qwho(p, 0); if (p->flags & RECONNECTION) { hello = do_alias_match(p, "_recon"); if (strcmp(hello, "\n")) match_commands(p, "_recon"); } else { hello = do_alias_match(p, "_logon"); if (strcmp(hello, "\n")) match_commands(p, "_logon"); } } /* clear the chanflags, just in case... */ if (p->flags & RECONNECTION) { p->flags &= ~RECONNECTION; } else { p->chanflags = 0; p->opflags = 0; p->c_invites = 0; } stack = oldstack; for (i=0;i<8;i++) strcpy(p->rev[i].review,""); if (p->system_flags & SAVED_RM_MOVE) p->no_move = 100; p->input_to_fn = 0; return; } void finish_player_login(player * p, char *str) { finish_player_login_2(p, ""); } void show_sumotd_login(player * p, char *str) { tell_player(p, sumotd_msg.where); do_prompt(p, "Hit <RETURN> to continue:"); p->input_to_fn = finish_player_login; return; } void show_reg_motd_login(player * p, char *str) { tell_player(p, motd_msg.where); do_prompt(p, "Hit <RETURN> to continue:"); p->input_to_fn = finish_player_login; return; } void show_new_motd_login(player * p, char *str) { tell_player(p, newbie_msg.where); do_prompt(p, "Hit <RETURN> to continue:"); p->input_to_fn = show_reg_motd_login; } void set_term_hitells_asty(player *p, char *str) { if (!*str) hitells(p,"vt100"); else hitells(p, str); do_prompt(p, "Hit <RETURN> to continue:"); p->input_to_fn = show_new_motd_login; return; } void in_sulog(player *p) { char *oldstack; int csu; csu = true_count_su(); oldstack = stack; if (p->residency & ADMIN) sprintf(stack, "%s login (admin) - %d sus now on.", p->name, csu + 1); else sprintf(stack, "%s login (su) - %d sus now on.", p->name, csu + 1); stack = end_string(stack); log ("su", oldstack); stack = oldstack; } void link_to_program(player * p) { char *oldstack; saved_player *sp; player *search, *previous, *scan; int hash; time_t t; struct tm *log_time; oldstack = stack; search = hashlist[((int) (p->lower_name[0])) - (int) 'a' + 1]; for (; search; search = search->hash_next) { if (!strcmp(p->lower_name, search->lower_name)) { if (p->residency == NON_RESIDENT) { tell_player(p, "\n Sorry there is already someone on the " "program with that name.\n Please try again, " "but use a different name.\n\n"); quit(p, ""); return; } else { tell_player(p, "\n You were already on the program !!\n\n" " Closing other connection.\n\n"); p->total_login = search->total_login; search->flags |= RECONNECTION; p->flags |= RECONNECTION; if (search->location) { previous = 0; scan = search->location->players_top; while (scan && scan != search) { previous = scan; scan = scan->room_next; } if (!scan) log("error", "Bad Location list"); else if (!previous) search->location->players_top = p; else previous->room_next = p; p->room_next = search->room_next; } /* lets try this -- we'll copy some of the info over on reconnect */ /* search->location = 0; quit(search, 0); */ p->chanflags = search->chanflags; p->opflags = search->opflags; p->location = search->location; p->flags = search->flags; strncpy(p->comment, search->comment, MAX_COMMENT - 3); p->no_shout = search->no_shout; p->shout_index = search->shout_index; p->jail_timeout = search->jail_timeout; p->lagged = search->lagged; p->no_move = search->no_move; p->pennies = search->pennies; strncpy(p->reply, search->reply, MAX_REPLY - 3); p->no_sing = search->no_sing; p->c_invites = search->c_invites; /* now get rid of mr. search */ search->location = 0; quit(search, 0); } } } /* do the disclaimer biz */ if (!(p->system_flags & AGREED_DISCLAIMER)) { if (!(p->saved && p->password[0] == 0)) { tell_player(p, disclaimer_msg.where); do_prompt(p, "Enter 'continue' or 'end':"); p->input_to_fn = agree_disclaimer; return; } } /* remove player from non name hash list */ previous = 0; scan = hashlist[0]; while (scan && scan != p) { previous = scan; scan = scan->hash_next; } if (!scan) log("error", "Bad non-name hash list"); else if (!previous) hashlist[0] = p->hash_next; else previous->hash_next = p->hash_next; /* now place into named hashed lists */ hash = (int) (p->lower_name[0]) - (int) 'a' + 1; p->hash_next = hashlist[hash]; hashlist[hash] = p; p->hash_top = hash; if (p->flags & SITE_LOG) { sprintf(oldstack,"%s - %s",p->name,p->inet_addr); stack=end_string(oldstack); log("site", oldstack); } t = time(0); log_time = localtime(&t); p->flags |= PROMPT; p->timer_fn = 0; p->timer_count = -1; p->system_flags &= ~NEW_SITE; p->mode = NONE; if (p->residency != NON_RESIDENT) { if (p->residency & SU && true_count_su() <= 1) in_sulog(p); p->logged_in = 1; sp = p->saved; if (motd_is_new(p, "motd")) { tell_player(p, motd_msg.where); do_prompt(p, "Hit <RETURN> to continue:"); if (p->residency & PSU && motd_is_new(p, "sumotd")) p->input_to_fn = show_sumotd_login; else p->input_to_fn = finish_player_login; } else if (p->residency & PSU && motd_is_new(p, "sumotd")) show_sumotd_login(p, ""); else { finish_player_login(p, ""); return; } } else { tell_player(p, hitells_msg.where); do_prompt(p, "Enter your termtype [vt100]:"); p->input_to_fn = set_term_hitells_asty; } return; } /* get new gender */ void enter_gender(player * p, char *str) { switch (tolower(*str)) { case 'm': p->gender = MALE; tell_player(p, " Gender set to Male.\n"); break; case 'f': p->gender = FEMALE; tell_player(p, " Gender set to Female.\n"); break; case 'p': p->gender = PLURAL; strncpy(p->title, "are new to the Program.", MAX_TITLE); strncpy(p->description, "We'll write our description someday.. maybe.", MAX_DESC); strncpy(p->plan, "Plans? We don't need no steeeenkin plans!", MAX_PLAN); /* blank the repeat stuff, just in case... */ p->last_remote_command = -1; /* will give error to user =) */ strcpy(p->last_remote_msg, ""); strcpy(p->enter_msg, "enter in a standard kind of way."); tell_player(p, " Gender set to Plural.\n"); break; case 'n': p->gender = OTHER; tell_player(p, " Gender set to well, erm, something.\n"); break; default: tell_player(p, " No gender set.\n"); break; } p->input_to_fn = 0; link_to_program(p); } /* time out */ void login_timeout(player * p) { tell_player(p, "\n\n Connection Timed Out ...\n\n"); quit(p, 0); } /* newbie stuff */ void newbie_get_gender(player * p, char *str) { tell_player(p, "\n\n The program requires that you enter your gender.\n" " This is used solely for the purposes of correct english and grammer.\n" " If you object to this, then simply type 'n' for not applicable.\n\n"); do_prompt(p, "Enter (M)ale, (F)emale, (P)lural, or (N)ot applicable:\n"); p->input_to_fn = enter_gender; } void got_new_name(player * p, char *str) { char *oldstack, *cpy; int length = 0; player *search; oldstack = stack; for (cpy = str; *cpy; cpy++) if (isalpha(*cpy)) { *stack++ = *cpy; length++; } *stack++ = 0; length++; if (length > (MAX_NAME - 3)) { tell_player(p, " Sorry, that name is too long, please enter something " "shorter.\n\n"); do_prompt(p, "Please enter another name:"); p->input_to_fn = got_new_name; if (sys_flags & VERBOSE) { cpy = stack; sprintf(cpy, "Name too long : %s\n", str); stack = end_string(cpy); log("connection", cpy); stack = cpy; } stack = oldstack; return; } if (length < 3) { tell_player(p, " Thats a bit short, try something longer.\n\n"); do_prompt(p, "Please enter another name:"); p->input_to_fn = got_new_name; stack = oldstack; return; } if (!strcasecmp(oldstack, "guest")) { TELLPLAYER(p, " Sorry, but the names containing \"guest\" are reserved" " for new users to logon with and cannot be used" " beyond this point.\n\n"); TELLPLAYER(p, " In selecting a name, we suggest that you use a name" " choose something that shows your interests or your" " hobbies or your personality. Choosing your real" " name here is probably not a good idea, because you" " will be telling many total strangers (at this point)" " what your real name is.\n\n"); TELLPLAYER(p, " Remember that, once you" " have a name, it can be difficult or impossible to" " change it later, so choose carefully. If you get an" " error message that the name you picked cannot be used" " then simply choose another -- it means that someone" " else has already reserved that name and you cannot use" " it.\n\n"); do_prompt(p, "Please enter another name:"); p->input_to_fn = got_new_name; stack = oldstack; return; } if (restore_player_title(p, oldstack, 0)) { tell_player(p, " Sorry, there is already someone who uses the " "program with that name.\n\n"); do_prompt(p, "Please enter another name:"); p->input_to_fn = got_new_name; stack = oldstack; return; } search = hashlist[((int) (p->lower_name[0])) - (int) 'a' + 1]; for (; search; search = search->hash_next) if (!strcmp(p->lower_name, search->lower_name)) { tell_player(p, "\n Sorry there is already someone on the program " "with that name.\nPlease try again, but use a " "different name.\n\n"); stack = oldstack; do_prompt(p, "Please enter another name:"); p->input_to_fn = got_new_name; return; } newbie_get_gender(p, str); stack = oldstack; } void newbie_got_name_answer(player * p, char *str) { switch (tolower(*str)) { case 'y': newbie_get_gender(p, str); break; case 'n': tell_player(p, "\n\n Ok, then, please enter a new name ...\n\n"); do_prompt(p, "Please enter the name you want:"); p->input_to_fn = got_new_name; break; default: tell_player(p, " Please answer with Y or N.\n"); newbie_check_name(p, str); break; } } void check_hcadmin_pw(player * p, char *str) { p->input_to_fn = 0; password_mode_off(p); if (strcmp(str, HC_PASSWORD)) { TELLPLAYER(p, "\n\n ILLEGAL ACCESS!! Bye!! \n\n"); /* alert the sus and admins on */ SUWALL(" -=*> An attempt to login as %s was just made!!\n", p->name); LOGF("sufailpass", "someone failed to login as hcadmin %s from %s", p->name, p->inet_addr); quit(p, 0); } else { TELLPLAYER(p, "\nAccess accepted.\n"); link_to_program(p); } } void hcadmin_check_password(player * p) { /* this is a security measure against newbie hcadmins */ TELLPLAYER(p, " You are attempting to login as a hard coded admin.\n" " To continue, you must enter the HCADMIN access password.\n"); do_prompt(p, "Enter the HCADMIN ACCESS PASSWORD:"); password_mode_on(p); p->input_to_fn = check_hcadmin_pw; } void newbie_check_name(player * p, char *str) { char *oldstack; oldstack = stack; if (strcasecmp(p->name, "guest")) { sprintf(stack, "\n\n You entered the name '%s' when you first logged in.\n" " Is this the name that you wish to be known as on the program ?\n\n", p->name); stack = end_string(stack); tell_player(p, oldstack); do_prompt(p, "Answer Y or N:"); p->input_to_fn = newbie_got_name_answer; stack = oldstack; } else { TELLPLAYER(p, " At this point, I am going to ask you to choose a name\n" " to use on this program. Some of the names may\n" " already be taken by someone else, if that happens, \n" " just try a different name\n\n\n"); do_prompt(p, "Please enter the name you want:"); p->input_to_fn = got_new_name; } } void newbie_start(player * p, char *str) { tell_player(p, newpage2_msg.where); do_prompt(p, "Hit return to continue:"); p->input_to_fn = newbie_check_name; } /* test password */ int check_password(char *password, char *entered, player * p) { char key[9]; strncpy(key, entered, 8); return (!strncmp(crypt(key, p->lower_name), password, 11)); } void got_password(player * p, char *str) { char *oldstack; oldstack = stack; p->input_to_fn = 0; password_mode_off(p); if (!check_password(p->password, str, p)) { tell_player(p, "\n\n Hey !! that ain't right !\n" " Wrong password .... closing connection.\n\n"); sprintf(stack, "Password fail: %s - %s", p->inet_addr, p->name); stack = end_string(stack); if (p->residency & SU) { log("sufailpass", oldstack); } else { log("connection", oldstack); } stack = oldstack; p->flags |= NO_SAVE_LAST_ON; quit(p, ""); return; } if (p->gender < 0) { p->input_to_fn = enter_gender; tell_player(p, "\n You have no gender set.\n"); do_prompt(p, "Please choose M(ale), F(female) or N(ot applicable):"); return; } stack = oldstack; link_to_program(p); } /* check for soft splats */ int site_soft_splat(player * p) { int no1 = 0, no2 = 0, no3 = 0, no4 = 0, out; out = time(0); sscanf(p->num_addr, "%d.%d.%d.%d", &no1, &no2, &no3, &no4); if (out <= soft_timeout && no1 == soft_splat1 && no2 == soft_splat2) return 1; else return 0; } /* calls here when the player has entered their name */ void got_name(player * p, char *str) { int t; char *oldstack, *cpy, *space; int length = 0, isspace = 0, nologin; player *search; oldstack = stack; for (cpy = str; *cpy && *cpy != ' '; cpy++) if (isalpha(*cpy)) { *stack++ = *cpy; length++; } if (*cpy == ' ') isspace = 1; *stack++ = 0; space = stack; length++; if (length > (MAX_NAME - 3)) { tell_player(p, " Sorry, that name is too long, please enter something " "shorter.\n\n"); do_prompt(p, "Please enter a name:"); p->input_to_fn = got_name; if (sys_flags & VERBOSE) { cpy = stack; sprintf(cpy, "Name too long : %s\n", str); stack = end_string(cpy); log("connection", cpy); stack = cpy; } stack = oldstack; return; } if (length < 3) { tell_player(p, " Thats a bit short, try something longer.\n\n"); do_prompt(p, "Please enter a name:"); p->input_to_fn = got_name; stack = oldstack; return; } if (!strcasecmp("who", oldstack)) { swho(p, 0); p->input_to_fn = got_name; do_prompt(p, "Please enter a name:"); stack = oldstack; return; } if (!strcasecmp("quit", oldstack)) { quit(p, ""); stack = oldstack; return; } if (isspace) while (*++cpy == ' '); if (restore_player_title(p, oldstack, isspace ? cpy : 0)) { if (p->residency & BANISHD && strcasecmp("guest", oldstack)) { tell_player(p, banned_msg.where); quit(p, ""); stack = oldstack; return; } if (!strcasecmp("guest", oldstack)) { if (p->flags & BAN18) { tell_player(p, under18_msg.where); quit(p, ""); stack = oldstack; return; } if (p->flags & CLOSED_TO_NEWBIES) { tell_player(p, newban_msg.where); quit(p, ""); stack = oldstack; return; } if (site_soft_splat(p)) { tell_player(p, newban_msg.where); quit(p, ""); stack = oldstack; return; } } if (p->residency == SYSTEM_ROOM) { tell_player(p, "\n Sorry but that name is reserved.\n" " Choose a different name ...\n\n"); do_prompt(p, "Please enter a name:"); p->input_to_fn = got_name; stack = oldstack; return; } t = time(0); if (p->sneezed > t) { nologin = p->sneezed - t; stack = oldstack; sprintf(stack, "\n Sorry, you have been prevented from logging on for " "another %d seconds (and counting ...)\n\n", nologin); stack = end_string(stack); tell_player(p, oldstack); quit(p, ""); stack = oldstack; return; } else p->sneezed = 0; /* login limits checks here */ if (!(p->residency & (SU | LOWER_ADMIN | ADMIN))) { if (current_players >= max_players) { tell_player(p, full_msg.where); quit(p, 0); stack = oldstack; return; } else if (shutdown_count < 180 && shutdown_count != -1) { TELLPLAYER(p, " We are sorry, but %s is currently rebooting for normal system\n" " maintenance. We will return in less than 3 minutes, so please try again\n" " in a couple minutes. Thank you =)\n", TALKER_NAME); quit(p, 0); stack = oldstack; return; } else if (sys_flags & CLOSED_TO_RESSIES) { tell_player(p, noressies_msg.where); quit(p, ""); stack = oldstack; return; } } sprintf(oldstack, "\n Character '%s' exists already.\n\n", p->name); stack = end_string(oldstack); tell_player(p, oldstack); stack = oldstack; if (p->password[0]) { password_mode_on(p); do_prompt(p, "Please enter your password:"); p->input_to_fn = got_password; p->timer_count = 60; p->timer_fn = login_timeout; stack = oldstack; return; } stack = oldstack; link_to_program(p); tell_player(p, "\n You have no password !!!\n" " Please set one as soon as possible with the 'password' command.\n" " If you don't your character will not save\n"); p->input_to_fn = 0; return; } p->input_to_fn = 0; if (p->flags & BAN18) { tell_player(p, under18_msg.where); quit(p, ""); stack = oldstack; return; } if (p->flags & CLOSED_TO_NEWBIES) { tell_player(p, newban_msg.where); quit(p, ""); stack = oldstack; return; } if (site_soft_splat(p)) { tell_player(p, newban_msg.where); quit(p, ""); stack = oldstack; return; } if (shutdown_count < 180 && shutdown_count != -1) { TELLPLAYER(p, " We are sorry, but %s is currently rebooting for normal system\n" " maintenance. We will return in less than 3 minutes, so please try again in\n" " a couple minutes. Thank you =)\n", TALKER_NAME); quit(p, 0); stack = oldstack; return; } if (sys_flags & CLOSED_TO_NEWBIES) { tell_player(p, nonewbies_msg.where); quit(p, ""); stack = oldstack; return; } search = hashlist[((int) (p->lower_name[0])) - (int) 'a' + 1]; for (; search; search = search->hash_next) if (!strcmp(p->lower_name, search->lower_name)) { tell_player(p, "\n Sorry there is already someone on the program " "with that name.\nPlease try again, but use a " "different name.\n\n"); stack = oldstack; do_prompt(p, "Please enter a name:"); p->input_to_fn = got_name; return; } tell_player(p, newpage1_msg.where); do_prompt(p, "Hit return to continue:"); p->input_to_fn = newbie_start; p->timer_count = 1800; stack = oldstack; } /* a new player has connected */ void connect_to_prog(player * p) { player *cp; int wcm; wcm = (rand() % 3); cp = current_player; current_player = p; tell_player(p, "\377\373\031"); /* send will EOR */ if (!wcm) tell_player(p, connect_msg.where); else if (wcm == 1) tell_player(p, connect2_msg.where); else tell_player(p, connect3_msg.where); do_prompt(p, "Please enter your name (new users use \"guest\"):"); p->input_to_fn = got_name; p->timer_count = 60; p->timer_fn = login_timeout; current_player = cp; } /* tell player motd */ void motd(player * p, char *str) { if (!p->residency) tell_player(p, newbie_msg.where); tell_player(p, motd_msg.where); } void fingerpaint(player * p, char *str) { int test = 0; if (!p->term) { tell_player(p, " You must have hitells set to see color.\n"); return; } if (p->misc_flags & NOCOLOR) { test = 1; p->misc_flags &= ~NOCOLOR; } tell_player(p, fingerpaint_msg.where); if (test) p->misc_flags |= NOCOLOR; } /* tell player sumotd */ void sumotd(player * p, char *str) { tell_player(p, sumotd_msg.where); } /* init everything needed for the plist file */ void init_plist() { char *oldstack; int i; oldstack = stack; #ifdef PC newban_msg = load_file("files\\newban.msg"); nonewbies_msg = load_file("files\\nonew.msg"); connect_msg = load_file("files\\connect.msg"); motd_msg = load_file("files\\motd.msg"); banned_msg = load_file("files\\banned.msg"); newbie_msg = load_file("files\\newbie.msg"); newpage1_msg = load_file("files\\newpage1.msg"); newpage2_msg = load_file("files\\newpage2.msg"); #else newban_msg = load_file("files/newban.msg"); nonewbies_msg = load_file("files/nonew.msg"); noressies_msg = load_file("files/nores.msg"); connect_msg = load_file("files/connect.msg"); connect2_msg = load_file("files/connect2.msg"); connect3_msg = load_file("files/connect3.msg"); motd_msg = load_file("files/motd.msg"); spodlist_msg = load_file("files/spodlist.msg"); banned_msg = load_file("files/banned.msg"); newbie_msg = load_file("files/newbie.msg"); newpage1_msg = load_file("files/newpage1.msg"); newpage2_msg = load_file("files/newpage2.msg"); disclaimer_msg = load_file("files/disclaimer.msg"); splat_msg = load_file("files/splat.msg"); sumotd_msg = load_file("files/sumotd.msg"); hitells_msg = load_file("files/hitells.msg"); fingerpaint_msg = load_file("files/color_test.msg"); #endif hard_load_files(); for (i = 0; i < 26; i++) update[i] = 0; stack = oldstack; } /* various associated routines */ /* find one player given a (partial) name */ /* little subroutinette */ int match_player(char *str1, char *str2) { for (; *str2; str1++, str2++) { if (*str1 != *str2 && *str2 != ' ') { if (!(*str1) && *str2 == '.' && !(*(str2 + 1))) return 1; return 0; } } if (*str1) return -1; return 1; } /* command to view res files */ void view_saved_lists(player * p, char *str) { saved_player *scan, **hash; int i, j; char *oldstack; oldstack = stack; if (!*str || !isalpha(*str)) { tell_player(p, " Argument is a letter.\n"); return; } strcpy(stack, "[HASH] [NAME] 12345678901234567890123456789012\n"); stack = strchr(stack, 0); hash = saved_hash[((int) (tolower(*str)) - (int) 'a')]; for (i = 0; i < HASH_SIZE; i++, hash++) for (scan = *hash; scan; scan = scan->next) { sprintf(stack, "[%d]", i); j = strlen(stack); stack = strchr(stack, 0); for (j = 7 - j; j; j--) *stack++ = ' '; strcpy(stack, scan->lower_name); j = strlen(stack); stack = strchr(stack, 0); for (j = 21 - j; j; j--) *stack++ = ' '; switch (scan->residency) { case STANDARD_ROOMS: strcpy(stack, "Standard room file."); break; case BANISHD: strcpy(stack, "BANISHED (Name Only)"); break; default: if (scan->residency & BANISHD) { strcpy(stack, "BANISHED"); } else { strcpy(stack, bit_string(scan->residency)); } break; } stack = strchr(stack, 0); *stack++ = '\n'; } *stack++ = 0; pager(p, oldstack, 1); stack = oldstack; } /* external routine to check updates */ void check_updates(player * p, char *str) { char *oldstack; int i; oldstack = stack; strcpy(stack, "abcdefghijklmnopqrstuvwxyz\n"); stack = strchr(stack, 0); for (i = 0; i < 26; i++) if (update[i]) *stack++ = '*'; else *stack++ = ' '; *stack++ = '\n'; *stack++ = 0; tell_player(p, oldstack); stack = oldstack; } void player_flags(player * p) { char *oldstack, *str; oldstack = stack; str = stack; if (p->residency == NON_RESIDENT) { log("error", "You've sponged Chris. Tried to player_flags a non-resi"); return; } if (!p->saved) tell_player(p, " Eeeeeeek ! No saved bits !\n"); else { /* don't touch this, or else... (violates agreement if this isn't in the login script) */ pg_version(p, 0); /* end untouchable segment */ sprintf(oldstack, "\n --\n Last logged in %s from %s.\n", convert_time(p->saved->last_on), p->saved->last_host); stack = strchr(stack, 0); strcpy(stack, " You are "); stack = strchr(stack, 0); if (p->custom_flags & HIDING) { strcpy(stack, "in hiding, "); stack = strchr(stack, 0); } if (p->tag_flags & BLOCK_SHOUT) { strcpy(stack, "ignoring shouts, "); stack = strchr(stack, 0); } if (p->tag_flags & BLOCK_TELLS) { strcpy(stack, "ignoring tells, "); stack = strchr(stack, 0); } if (p->tag_flags & SINGBLOCK) { strcpy(stack, "ignoring singing, "); stack = strchr(stack, 0); } if (p->custom_flags & CONVERSE) { strcpy(stack, "in converse mode, "); stack = strchr(stack, 0); } if (p->custom_flags & NOPREFIX) { strcpy(stack, "ignoring prefixes, "); stack = strchr(stack, 0); } if (str = strrchr(oldstack, ',')) { *str++ = '.'; *str++ = '\n'; *str++ = 0; stack = strchr(stack, 0); *stack++; tell_player(p, oldstack); } } if (p->system_flags & NEW_MAIL) { command_type |= HIGHLIGHT; tell_player(p, " You have unread mail\n"); p->system_flags &= ~NEW_MAIL; p->saved->system_flags &= ~NEW_MAIL; command_type &= ~HIGHLIGHT; } if (p->residency & SU && sys_flags & CLOSED_TO_NEWBIES) { command_type |= HIGHLIGHT; TELLPLAYER(p, " %s is closed to newbies\n", TALKER_NAME); command_type &= ~HIGHLIGHT; } tell_player(p, " --\n"); stack = oldstack; } void player_flags_verbose(player * p, char *str) { char *oldstack, *wibble, *argh; player *p2; oldstack = stack; if (*str && (p->residency & SU || p->residency & ADMIN)) { p2 = find_player_absolute_quiet(str); if (!p2) { tell_player(p, " No-one on of that name.\n"); return; } } else p2 = p; if (p2->residency == NON_RESIDENT) { tell_player(p, " You aren't a resident, so your character won't be " "saved when you log off.\n"); return; } strcpy(stack, "\n --\n"); stack = strchr(stack, 0); argh = stack; strcpy(stack, " You are "); stack = strchr(stack, 0); if (p2->custom_flags & HIDING) { strcpy(stack, "in hiding, "); stack = strchr(stack, 0); } if (p2->tag_flags & BLOCK_SHOUT) { strcpy(stack, "ignoring shouts, "); stack = strchr(stack, 0); } if (p2->tag_flags & BLOCK_TELLS) { strcpy(stack, "ignoring tells, "); stack = strchr(stack, 0); } if (p2->tag_flags & SINGBLOCK) { strcpy(stack, "ignoring singing, "); stack = strchr(stack, 0); } if (p2->custom_flags & CONVERSE) { strcpy(stack, "in converse mode, "); stack = strchr(stack, 0); } if (p2->custom_flags & NOPREFIX) { strcpy(stack, "ignoring prefixes, "); stack = strchr(stack, 0); } if (wibble = strrchr(oldstack, ',')) { *wibble++ = '.'; *wibble++ = '\n'; *wibble = 0; } else stack = argh; if (p2->custom_flags & PRIVATE_EMAIL) strcpy(stack, " Your email is private.\n"); else strcpy(stack, " Your email is public for all to see.\n"); stack = strchr(stack, 0); if (p2->custom_flags & TRANS_TO_HOME) { strcpy(stack, " You will be taken to your home when you log in.\n"); stack = strchr(stack, 0); } else if (*p2->room_connect) { sprintf(stack, " You will try to connect to room '%s' when you log" " in\n", p->room_connect); stack = strchr(stack, 0); } if (p2->tag_flags & NO_ANONYMOUS) strcpy(stack, " You won't receive anonymous mail.\n"); else strcpy(stack, " You are currently able to receive anonymous mail.\n"); stack = strchr(stack, 0); if (p2->system_flags & IAC_GA_ON) strcpy(stack, " Iacga prompting is turned on.\n"); else strcpy(stack, " Iacga prompting is turned off.\n"); stack = strchr(stack, 0); if (p2->custom_flags & NO_PAGER) strcpy(stack, " You are not recieving paged output.\n"); else strcpy(stack, " You are recieving paged output.\n"); stack = strchr(stack, 0); if (p2->flags & BLOCK_SU && p->residency & PSU) { strcpy(stack, " You are ignoring sus.\n"); stack = strchr(stack, 0); } /* will they be notified when people enter their rooms (ie have they room notify set) */ if (p2->custom_flags & ROOM_ENTER) strcpy(stack, " You will be informed when someone enters one of " "your rooms.\n"); else strcpy(stack, " You will not be informed when someone enters " "one of your rooms.\n"); stack = strchr(stack, 0); strcpy(stack, " --\n"); stack = end_string(stack); tell_player(p, oldstack); stack = oldstack; } /* Catch SEGV's and BUS's on load of players, hopefully... */ void error_on_load() { bad_player_load = 1; longjmp(jmp_env, 0); longjmp(jmp_env, 0); } /* Count number of ressies, give a small statistic - by Nogard */ /* spoon additions by trap =) */ void res_count(player * p, char *str) { int psu=0, bsu=0, asu = 0, banned=0; int ladmin=0, uadmin=0, hcadmin=0; int players=0, ressies=0, staff=0, builder=0; int spod=0, minister=0, married=0, engaged=0, flirt=0; saved_player *scanlist, **hashlist; int counter, charcounter; char *oldstack; oldstack = stack; for(charcounter = 0; charcounter < 26; charcounter++) { hashlist = saved_hash[charcounter]; for (counter = 0; counter < HASH_SIZE; counter++, hashlist++) for (scanlist = *hashlist; scanlist; scanlist = scanlist->next) { switch (scanlist->residency) { case STANDARD_ROOMS: break; case BANISHD: banned++; break; default: if(!(scanlist->residency & BANISHD)) { if(scanlist->residency & SPOD) spod++; if(scanlist->system_flags & MINISTER) minister++; if(scanlist->system_flags & BUILDER) builder++; if(scanlist->system_flags & MARRIED) married++; else if (scanlist->system_flags & ENGAGED) engaged++; else if (scanlist->system_flags & FLIRT_BACHELOR) flirt++; if(scanlist->residency & HCADMIN) hcadmin++; else if(scanlist->residency & ADMIN) uadmin++; else if(scanlist->residency & LOWER_ADMIN) ladmin++; else if(scanlist->residency & ASU) asu++; else if(scanlist->residency & SU) bsu++; else if(scanlist->residency & PSU) psu++; players++; } /* this if statement to weed out banishd players */ else banned++; break; } } } staff=psu+asu+bsu+ladmin+uadmin+hcadmin; ressies=players-staff; if (p->residency & PSU && (*str != '-')) { sprintf(stack, " *------- %s current resident and staff count ------*\n", TALKER_NAME); stack = strchr(stack, 0); sprintf(stack, " | Administrators : %-4d | Lower Admins : %-4d |\n" " | Super Users : %-4d | SU-in-training : %-4d |\n" " | Pseudo SUs : %-4d | <Banished> : %-4d |\n" " *------------------------------*---------------------------*\n" " | (Builders) : %-4d | (Spods) : %-4d |\n" " | Married : %-4d | Engaged : %-4d |\n" " | Flirt : %-4d | Ministers : %-4d |\n" " *------------------------------*---------------------------*\n" " | Normal Residents : %-4d | Total Players : %-4d |\n" " *------------------------------*---------------------------*\n", hcadmin+uadmin,ladmin,asu,bsu,psu,banned,builder,spod,married,engaged,flirt,minister,ressies,players); stack = end_string(stack); } /* else its just a resident - tell them the total # -- astyanax */ else { sprintf(stack, " ) %s resident count (up to the minute) : %-4d\n" " ) Of these, %d are on staff, %d are ministers, and %d are builders.\n", TALKER_NAME, players, staff-psu, minister, builder); stack = end_string(stack); } tell_player(p, oldstack); stack = oldstack; } /* Search for names that match a subset of a name - by Nogard 8-5-95 moved to plists.c -- maybe it'll work here :P -- traP */ void xref_name(player * p, char *str) { saved_player *scanlist, **hashlist; int counter, charcounter; char *oldstack; oldstack = stack; if (!*str) { tell_player(p, " Format: xref <string to search for> \n"); return; } strcpy(stack, " Names that match "); stack = strchr(stack, 0); sprintf(stack, " %s :\n",str); for(charcounter = 0; charcounter < 26; charcounter++) { hashlist = saved_hash[charcounter]; for (counter = 0; counter < HASH_SIZE; counter++, hashlist++) for (scanlist = *hashlist; scanlist; scanlist = scanlist->next) { switch (scanlist->residency) { case STANDARD_ROOMS: break; case BANISHD: break; default: if (strstr (scanlist->lower_name, str) || (strstr (str,scanlist->lower_name))) { stack = strchr(stack, 0); sprintf(stack, "%s, ",scanlist->lower_name); } break; } } } stack = strchr(stack, 0); stack -=2; *stack++ = '.'; *stack++ = '\n'; *stack++ = 0; tell_player(p, oldstack); stack = oldstack; } void spodlist_view(player * p, char *str) { if (p->custom_flags & NO_PAGER) tell_player(p, spodlist_msg.where); else pager(p, spodlist_msg.where, 1); } void xref_player_email(player * p, char *str) { saved_player *scanlist, **hashlist; int counter, charcounter; char *oldstack; char email[MAX_EMAIL + 2]; oldstack = stack; if (!*str) { tell_player(p, " Format: etrace <string to search for> \n"); return; } strcpy(stack, " Email addresses that match "); stack = strchr(stack, 0); sprintf(stack, " %s :\n",str); for(charcounter = 0; charcounter < 26; charcounter++) { hashlist = saved_hash[charcounter]; for (counter = 0; counter < HASH_SIZE; counter++, hashlist++) for (scanlist = *hashlist; scanlist; scanlist = scanlist->next) { switch (scanlist->residency) { case STANDARD_ROOMS: break; case BANISHD: break; default: strncpy(email, scanlist->email, MAX_EMAIL - 3); lower_case(email); if ((scanlist->email) && strstr(email, str)) { stack = strchr(stack, 0); sprintf(stack, "%-20s - %s\n",scanlist->lower_name, scanlist->email); } break; } } } stack = strchr(stack, 0); *stack++ = 0; tell_player(p, oldstack); stack = oldstack; }