/************************************************************************** ** Module: uaf.c ** Author: Various Aber coders ** Description: This module holds all the functions to handle the database ** which holds the players data. (uaf_rand). **************************************************************************/ #define UAF_C #include <sys/file.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include "kernel.h" #include <errno.h> #include <gdbm.h> #include "machines.h" #include "pflags.h" #include "sflags.h" #include "uaf.h" #include "bprintf.h" #include "log.h" #include "mobile.h" #include "mud.h" #include "wizlist.h" #include "flags.h" #include "bootstrap.h" #include "commands.h" #include "sendsys.h" #include "rooms.h" GDBM_FILE dbf; extern int errno; extern char *WizLevels[]; void get_gender (char *gen); time_t time (time_t * v); void pers2player (PERSONA * d, int plx) { setpstr (plx, d->p_strength); setpdam (plx, d->p_damage); setphome (plx, d->p_home[0] == '\0' ? 0 : findroomnum(d->p_home)); setpscore (plx, d->p_score); setparmor (plx, d->p_armor); setsflags (plx, d->p_sflags); setpflags (plx, d->p_pflags); setpmask (plx, d->p_mask); qflags(plx) = d->p_quests; qpoints(plx) = d->p_questpoints; setpvis (plx, ptstflg (plx, PFL_STARTINVIS) ? d->p_vlevel : 0); setplev (plx, d->p_level); setpkilled(plx, d->p_killed); setpdied(plx,d->p_died); /* Fix score for people who died */ if (d->p_strength < 0) setpstr(plx, pmaxstrength(d->p_level)); setpwimpy (plx, d->p_wimpy); mob_id (plx) = d->p_id; if (plx < max_players) { setptitle (plx, d->p_title); players[plx].last_cmd = players[plx].last_command = global_clock; (void) strcpy(players[plx].email, d->p_email); (void) strcpy (players[plx].passwd, d->p_passwd); (void) strcpy (players[plx].prompt, d->p_prompt); (void) strcpy (players[plx].cprompt, d->p_prompt); setppager (plx,d->p_pager); } } void player2pers (PERSONA * d, time_t * last_on, int plx) { d->p_strength = pstr (plx); d->p_damage = pdam (plx); d->p_score = pscore (plx); d->p_armor = parmor (plx); d->p_sflags = sflags (plx); d->p_quests = qflags(plx); d->p_questpoints = qpoints(plx); d->p_vlevel = pvis (plx); d->p_level = plev (plx); d->p_damage = pdam (plx); d->p_armor = parmor (plx); d->p_wimpy = pwimpy (plx); d->p_id = mob_id (plx); /* clear spare fields */ d->spareint5 = 0; d->p_killed = pkilled(plx); d->p_died = pdied(plx); if (plx < max_players) { (void) strcpy (d->p_title, ptitle (plx)); (void) strcpy (d->p_passwd, players[plx].passwd); (void) strcpy (d->p_email, pemail(plx)); (void) strcpy (d->p_prompt, players[plx].prompt); d->p_pager = ppager(plx); d->p_pager = ppager(plx); d->p_pflags = (players[plx].defrob != NULL) ? players[plx].defrob->real_pflags : pflags (plx); d->p_mask = (players[plx].defrob != NULL) ? players[plx].defrob->real_mask : pmask (plx); d->p_level = (players[plx].defrob != NULL) ? players[plx].defrob->real_level : plev (plx); (void) strcpy (d->p_idname, pname(plx)); (void) strcpy (d->p_lasthost, players[plx].realhostname); } else { d->p_pflags = pflags(plx); d->p_mask = pmask(plx); d->p_level = plev(plx); } (void) strcpy (d->p_home, phome(plx) >= 0 ? "" : showname(phome(plx))); (void) strcpy (d->p_name, pname (plx)); if (last_on != NULL) d->p_last_on = *last_on; } void get_gender (char *gen) { Boolean ok = False; Boolean female = False; PERSONA d; if (gen == NULL) { replace_input_handler (get_gender); } else if (*gen == 'M' || *gen == 'm') { sclrflg (mynum, SFL_FEMALE); ok = True; } else if (*gen == 'F' || *gen == 'f') { ssetflg (mynum, SFL_FEMALE); ok = female = True; } else { bprintf ("M or F"); } if (ok) { /* initialize a very new user */ if (OPERATOR (pname (mynum))) { /* We make him a god */ bprintf("\nWelcome MasterUser %s!\n",pname(mynum)); sprintf (ptitle (mynum), "%%s the %s", WizLevels[LEV_GOD]); setplev (mynum, LVL_MASTER); setpstr (mynum, pmaxstrength (LVL_MASTER)); setpscore (mynum, levels[LVL_APPREN]); update_wizlist (pname (mynum), LEV_MASTER); strcpy(cur_player->cprompt,"&+wAdmin&+w>&* "); } else { sprintf(ptitle(mynum), "%%s the %s", (female ? FLevels: MLevels)[LVL_ONE]); setplev(mynum, LVL_ONE); setpstr(mynum, 40); setpscore(mynum, 0); strcpy(cur_player->prompt, cur_player->cprompt); } setpwimpy (mynum, 0); cur_player->defrob = False; mob_id (mynum) = id_counter++; setphome (mynum, 0); setpdam (mynum, 8); setparmor (mynum, 0); setpvis (mynum, 0); sflags(mynum).b3 = sflags(mynum).b2 = sflags(mynum).b1 = 0; ssetflg(mynum,SFL_AUTOEXIT); ssetflg(mynum,SFL_SAYBACK); setppager(mynum,24); setpkilled(mynum,0); setpdied(mynum,0); if (female) ssetflg (mynum, SFL_FEMALE); qflags(mynum).l = qflags(mynum).h = 0; qpoints(mynum) = 0; pflags(mynum).b1 = pflags(mynum).b2 = pflags(mynum).b3 = 0; set_xpflags (plev (mynum), &(pflags (mynum)), &(pmask (mynum))); /* Reset the prompt before saving */ strcpy(cur_player->prompt, cur_player->cprompt); player2pers (&d, &global_clock, mynum); putuaf (&d); save_id_counter (); give_options (NULL); } else { bprintf ("\n"); bprintf (strcpy (cur_player->prompt, "Sex (M/F) : >")); } } /* Utilizing the save_player routine now */ A_COMMAND(saveme) { if (cur_player->aliased || cur_player->polymorphed >= 0) { bprintf ("Not while aliased.\n"); return; } save_player(mynum,False); bflush(); } void save_player(int plx,Boolean UnAlias) { PERSONA d; if (plx <0) return; if (plx >= max_players || plx < 0) { mudlog("ERROR: save_player() with invalid parameter."); return; } if (players[plx].aliased || players->polymorphed >= 0) { if (UnAlias) { unalias(plx); unpolymorph(plx); setup_globals(plx); } } player2pers(&d,&global_clock, plx); sendf(plx,"\n&+w[&+wSaving %s&+w]&*\n",pname(plx)); putuaf(&d); } /* -------------------------------------------------------------------------*/ /* * Initialize userfile and keep it open */ void init_userfile() { /* void (*mudlog)();*/ if (dbf) return; /* already open */ #ifdef SAFE_USERFILE if ((dbf = gdbm_open(UAF_RAND,/*sizeof(PERSONA)*/ 1024,GDBM_WRCREAT,S_IRUSR|S_IWUSR,(void *)mudlog)) == NULL) { #else if ((dbf = gdbm_open(UAF_RAND,/*sizeof(PERSONA)*/ 1024,GDBM_WRCREAT|GDBM_FAST,S_IRUSR|S_IWUSR,mudlog)) == NULL) { #endif mudlog ("GDBM failed to access user file (%s)",UAF_RAND); exit (1); } return; } /* * sync userfile (safety for GDBM_FAST writes) */ void sync_userfile() { #ifndef SAFE_USERFILE /* no need if SAFE is on */ if (dbf) gdbm_sync(dbf); #endif return; } /* * reorganize userfile (at startup usually) */ int reorg_userfile() { return(gdbm_reorganize(dbf)); } void close_userfile() { if (dbf) gdbm_close(dbf); dbf = NULL; } Boolean getuaf (char *name, PERSONA * d) { datum in; datum key; datum data; char idname[PNAME_LEN+1]; /* Lowercase version of the name */ if (name == NULL || strlen(name) > PNAME_LEN) return False; strncpy(idname,name,PNAME_LEN); /* Potential crash bug if one tries * to copy more than 16 letters */ idname[strlen(name)] = '\0'; key.dptr = idname; lowercase(key.dptr); key.dptr[0]=toupper(key.dptr[0]); /* key.dsize = strlen(name) + 1;*/ key.dsize = strlen(idname) + 1; data.dptr = (char *)d; data.dsize = sizeof(PERSONA) +1; if (!dbf) init_userfile(); /* locate a user */ in = gdbm_fetch(dbf,key); if (in.dptr == NULL) return (False); /* no such entry */ /* copy it to our given pointer */ bcopy(in.dptr,d,sizeof(PERSONA)); /*setpname(mynum,d->p_name);*/ /* free the pointer */ if (in.dptr) free(in.dptr); return (True); } /* * opens the userfile and writes a record to it; if the record exists, * it will replace it */ void putuaf (PERSONA * d) { int ret; /* PERSONA x;*/ datum key; datum data; key.dptr = d->p_idname; lowercase(key.dptr); key.dptr[0]=toupper(key.dptr[0]); key.dsize = strlen(d->p_idname) + 1; data.dptr = (char *)d; data.dsize = sizeof(PERSONA) + 1; /* store the user */ ret = gdbm_store(dbf,key,data,GDBM_REPLACE); switch(ret) { case 1: mudlog("gdbm_store() - caller not official writer, or key or datum is null"); exit(1); break; case -1: mudlog("gdbm_store() - key exists and not allowed to replace."); exit(1); break; default:; } return; } void deluaf (char *name) { int ret; datum key; key.dptr = name; lowercase(key.dptr); key.dptr[0]=toupper(key.dptr[0]); key.dsize = strlen(name) + 1; ret = gdbm_delete(dbf,key); } /* * Load the user's name as it appears in the database */ Boolean getuafinfo (char *name) { PERSONA d; Boolean b; b = getuaf (name, &d); if (b) { pers2player (&d, mynum); setpname (mynum, d.p_name); } return b; } Boolean findsetins (char *name, SETIN_REC * s, int fd) { while (read (fd, s, sizeof (SETIN_REC)) == sizeof (SETIN_REC)) if (EQ (s->name, name)) { return True; } return False; } Boolean getsetins (char *name, SETIN_REC * s) { int fd; Boolean b; if ((fd = open (SETIN_FILE, O_RDONLY, 0)) < 0) return False; b = findsetins (name, s, fd); close (fd); return b; } void putsetins (char *name, SETIN_REC * s) { SETIN_REC v; int fd; Boolean b; if ((fd = open (SETIN_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { mudlog ("putsetins: Error in open for " SETIN_FILE); progerror ("open"); exit (1); } if ((b = findsetins (name, &v, fd))) { lseek (fd, (long) -sizeof (SETIN_REC), SEEK_CUR); } else { lseek (fd, 0L, SEEK_END); } if (write (fd, s, sizeof (SETIN_REC)) != sizeof (SETIN_REC)) { mudlog ("putsetins: Error in write for " SETIN_FILE); progerror ("write"); } lseek (fd, 0L, SEEK_END); close (fd); } void fetchprmpt (int plr) { SETIN_REC s; if (plr >= max_players || plr < 0) return; strcpy(players[plr].awaymsg,"Away Message lost in Reboot."); if (plev (plr) >= LVL_APPREN && getsetins (pname (plr), &s)) { /*strcpy (players[plr].prompt, s.prompt);*/ strcpy (players[plr].setin, s.setin); strcpy (players[plr].setout, s.setout); strcpy (players[plr].setmin, s.setmin); strcpy (players[plr].setmout, s.setmout); strcpy (players[plr].setvin, s.setvin); strcpy (players[plr].setvout, s.setvout); strcpy (players[plr].setqin, s.setqin); strcpy (players[plr].setqout, s.setqout); strcpy (players[plr].setsit, s.setsit); strcpy (players[plr].setstand, s.setstand); strcpy (players[plr].settrenter, s.settrenter); strcpy (players[plr].settrvict, s.settrvict); strcpy (players[plr].settrroom, s.settrroom); strcpy (players[plr].setsleep, s.setsleep); strcpy (players[plr].settrance, s.settrance); strcpy (players[plr].setaway, s.setaway); } else { strcpy (players[plr].setin, "%n has arrived."); strcpy (players[plr].setout, "%n has gone %d."); strcpy (players[plr].setmin, "%n appears with an ear-splitting bang."); strcpy (players[plr].setmout, "%n vanishes in a puff of smoke."); strcpy (players[plr].setvin, "%n suddenly appears!"); strcpy (players[plr].setvout, "%n has vanished!"); strcpy (players[plr].setqin, "%n has entered the game."); strcpy (players[plr].setqout, "%n has left the game."); strcpy (players[plr].setsit, "%n is sitting here."); strcpy (players[plr].setstand, "%n is standing here."); strcpy (players[plr].settrenter, "%n appears, looking bewildered."); strcpy (players[plr].settrvict, "You are summoned by %n."); strcpy (players[plr].settrroom, "%n evocates the summoning spell."); strcpy (players[plr].setsleep, "%n is sleeping here."); strcpy (players[plr].settrance, "%n is standing here deep in trance."); strcpy (players[plr].setaway, "%n is marked as being away, and might not answer immediately.\n"); } } char *build_setin (int plx, char *b, char *s, char *n, char *d) { char *p, *q, *r; for (p = b, q = s; *q != 0;) { if (*q != '%') *p++ = *q++; else { switch (*++q) { case 'n': for (r = n; *r != 0;) *p++ = *r++; break; case 'd': if (d == NULL) return NULL; for (r = d; *r != 0;) *p++ = *r++; break; case 'N': for (r = xname (n); *r != 0;) *p++ = *r++; break; case 'f': for (r = (psex (plx) ? "her" : "his"); *r != 0;) *p++ = *r++; break; case 'F': for (r = (psex (plx) ? "her" : "him"); *r != 0;) *p++ = *r++; break; case 0: --q; break; default: *p++ = *q; } ++q; } } if (p[-1] == '\n') --p; *p = 0; return b; }