#include <string.h> #include <unistd.h> #include "db.h" #include "config.h" #include "externs.h" static void destroy_player P((OBJ *)); OBJ *create_guest(char *name, char *alias, char *password) { OBJ *player; /* Make sure that old guest id's don't hang around! */ player = match_player(NULL, name); if(player) { if(Guest(player)) destroy_player(player); else return(NULL); } /* Make new player */ player = create_player(name, password, CLASS_GUEST, find_object(config.guest_start)); if(!player) { log_error("Failed in create_player"); return(NULL); } player->creator = root_obj; /* Lock guest to him/her-self */ atr_add(player, "LOCK", tprintf("#%d", player->dbref)); /* Set guest's description */ atr_add(player, "DESC", config.guest_description); /* Set guest's alias */ if(!match_player(NULL, alias)) atr_add(player, "ALIAS", alias); /* Zero their quota */ atr_clr(player, "QUOTA"); return(player); } void destroy_guest(OBJ *guest) { if(!Guest(guest)) return; destroy_player(guest); } OBJ *create_player(char *name, char *password, int class, OBJ *start) { OBJ *player; if(!start) { log_error("Default starting room doesn't exist!"); return(NULL); } if(!ok_player_name(NULL, strip_color(name), "") || !ok_password(password) || strchr(name, ' ')) { log_error("failed in name check"); return(NULL); } player = new_object(TYPE_PLAYER, 1); /* Initialize everything */ SET(player->name, strip_color(name)); atr_add(player, "RAINBOW", name); player->location = start; player->link = start; player->owner = player; player->pows = (int *)stack_alloc(sizeof(int)*NUM_POWS, 1, 0); player->flags = TYPE_PLAYER|PLAYER_NEWBIE|INHERIT_POWERS; player->class = CLASS_GUEST; atr_add(player, "PASSWORD", crypt(password, "XX")); giveto(player, config.initial_wealth); atr_add(player, "QUOTA", tprintf("%d", config.default_quota)); atr_add(player, "MOTD", "1"); atr_add(player, "CQUOTA", tprintf("%d", config.default_channel_quota)); player->next_con = start->contents; start->contents = player; do_class(root_obj, tprintf("#%d", player->dbref), class_to_name(class)); if(class != CLASS_GUEST) do_join_channel(player, "public"); return(player); } static void destroy_player(OBJ *player) { OBJ *thing; if(Typeof(player) != TYPE_PLAYER) return; /* Destroy everything the player owns */ for(thing = thing_list;thing;thing = thing->next) if(thing->owner == player) destroy_obj(thing); for(thing = room_list;thing;thing = thing->next) if(thing->owner == player) destroy_obj(thing); for(thing = exit_list;thing;thing = thing->next) if(thing->owner == player) destroy_obj(thing); while(boot_off(player)); do_halt(player, ""); rem_from_channels(player); remove_from_mlists(player); /* remove player from mailing lists */ destroy_obj(player); } char *create_random_password() { char passwd[4096], list[4096]; char c; int i, ctr = 0; for(c = 'A';c <= 'Z';++c) list[ctr++] = c; for(c = 'a';c <= 'z';++c) list[ctr++] = c; for(c = '0';c <= '9';++c) list[ctr++] = c; for(i = 0;i < 8;++i) passwd[i] = list[my_rand()%ctr]; passwd[i] = '\0'; return(stack_string_alloc(passwd, 0)); } void do_pcreate(OBJ *creator, char *player_name, char *player_password) { OBJ *player, *p; OBJ **plist; int i, j, ctr; char player_email[4096], *e; if(!*player_name) { ctr = 0; for(p = player_list;p;p = p->next) ctr++; plist = (OBJ **)stack_alloc(sizeof(OBJ *)*ctr, 0, 0); ctr = 0; for(p = player_list;p;p = p->next) plist[ctr++] = p; for(i = 0;i < ctr;++i) for(j = i+1;j < ctr;++j) if(plist[i]->create_time > plist[j]->create_time) { player = plist[i]; plist[i] = plist[j]; plist[j] = player; } for(i = 0;i < ctr;++i) notify(creator, tprintf("%s |+W|- %s |+W|- |+C|%s", my_ljust(unparse_object(creator, plist[i]), 25), my_ljust(name(plist[i]->creator), 15), mktm(plist[i]->create_time, "D", creator))); return; } if(!power(creator, POW_PCREATE)) { notify(creator, perm_denied()); return; } if(!*player_name) { notify(creator, "You must specify a name."); return; } if((player = match_player(NULL, player_name))) { notify(creator, tprintf("There is already a player named %s.", unparse_object(creator, player))); return; } if(!ok_player_name(NULL, strip_color(player_name), "")) { notify(creator, tprintf("Illegal player name '%s'", player_name)); return; } if(!*player_password) { notify(creator, "You must specify the new player's email address."); return; } if((e = strchr(player_password, ','))) { strcpy(player_email, e+1); *e = '\0'; } else { strcpy(player_email, player_password); player_password = create_random_password(); } player = create_player(player_name, player_password, CLASS_CITIZEN, player_start_obj); if(!player) { notify(creator, tprintf("Failure creating '%s'", player_name)); return; } notify(creator, tprintf("New player '%s' created with password '%s'", unparse_object(creator, player), player_password)); log_sensitive(tprintf("%s pcreated %s", unparse_object(creator, creator), unparse_object(player, player))); player->creator = creator; atr_add(player, "EMAIL", player_email); } void do_password(OBJ *player, char *old, char *newobj) { if(!*Pass(player) || (strcmp(old, Pass(player)) && strcmp(crypt(old,"XX"), Pass(player)))) { notify(player, "You must match your old password."); return; } if(!ok_password(newobj)) { notify(player, "Bad new password."); return; } atr_add(player, "PASSWORD", crypt(newobj, "XX")); notify(player, "Password changed."); } int owns_stuff(OBJ *player) { OBJ *o; int num = 0; for(o = thing_list;o;o = o->next) if(o->owner == player) num++; for(o = room_list;o;o = o->next) if(o->owner == player) num++; for(o = exit_list;o;o = o->next) if(o->owner == player) num++; return(num); } void do_nuke(OBJ *player, char *arg, char *reason) { OBJ *victim; if(!power(player, POW_NUKE)) { notify(player, perm_denied()); return; } victim = match_object(player, arg, TYPE_PLAYER); if(!victim) { notify(player, no_match(arg)); return; } if(!controls(player, victim, POW_NUKE)) { notify(player, perm_denied()); return; } if(owns_stuff(victim)) { notify(player, "You must @wipeout their junk first."); return; } if(!*reason) { notify(player, "You must specify a reason for nuking someone."); return; } notify(player, tprintf("%s - nuked.", name(victim))); notify_all(tprintf("|+W|-- |+R|%s has been nuked, " "toasted, destroyed, put to death, removed from %s by %s.", name(victim), config.maze_name, name(player)), NULL); log_sensitive(tprintf("%s(#%d) executed: @nuke %s(#%d). Reason: %s", name(player), player->dbref, name(victim), victim->dbref, reason)); destroy_player(victim); } void do_class(OBJ *player, char *arg1, char *class) { int i, newlevel; OBJ *who; if(!*arg1) who = player; else { who = match_object(player, arg1, TYPE_PLAYER); if(!who) { notify(player, no_match(arg1)); return; } } if(!*class) { class = class_to_name(get_class(who)); notify(player, tprintf("%s is %s %s.", name(who), (my_is_vowel(*class))?"an":"a", class)); return; } if(is_root(who)) { notify(player, "Root may not be reclassified!"); return; } i = name_to_class(class); if(i == -1) { notify(player, tprintf("'%s': no such classification", class)); return; } newlevel = i; log_sensitive(tprintf("%s tried to: @class %s=%s", unparse_object(player, player), name(who), class)); if(!controls(player, who, POW_CLASS) || (newlevel >= get_class(player) && !is_root(player))) { notify(player, perm_denied()); return; } log_sensitive(tprintf("%s executed: @class %s=%s", unparse_object(player, player), name(who), class)); notify(player, tprintf("%s is now reclassified as: %s", name(who), class_to_name(newlevel))); notify(who, tprintf("You have been reclassified as: %s", class_to_name(newlevel))); who->class = newlevel; for(i = 0;i < NUM_POWS;i++) set_pow(who, i, powers[i].init[class_to_list_pos(newlevel)]); } void do_empower(OBJ *player, char *whostr, char *powstr) { int pow; int powval; OBJ *who; char *i, *p; if(!power(player, POW_SETPOW)) { notify(player, perm_denied()); return; } i = strchr(powstr, ':'); if(!i) { notify(player, "Badly formed power specification. need powertype:powerval"); return; } *i++ = '\0'; if(!string_compare(i, "yes")) powval = PW_YES; else if(!string_compare(i, "no")) powval = PW_NO; else if(!string_compare(i, "yeseq")) powval = PW_YESEQ; else if(!string_compare(i, "yeslt")) powval = PW_YESLT; else { notify(player, "The power value must be one of yes, no, yeseq, or yeslt"); return; } if((pow = name_to_pow(powstr)) == -1) { notify(player, tprintf("Unknown power: %s", powstr)); return; } if(!(who = match_object(player, whostr, TYPE_PLAYER))) { notify(player, no_match(whostr)); return; } if(!controls(player, who, POW_SETPOW)) { notify(player, perm_denied()); return; } if(get_pow(player, pow) < powval && !is_root(player)) { notify(player, "But you yourself don't have that power!"); return; } if(powers[pow].max[class_to_list_pos(get_class(who))] < powval) { p = ""; switch(powers[pow].max[class_to_list_pos(get_class(who))]) { case PW_NO: p = "NO"; break; case PW_YES: p = "YES"; break; case PW_YESLT: p = "YESLT"; break; case PW_YESEQ: p = "YESEQ"; break; } notify(player, tprintf("Maximum value for that power for that class is: %s", p)); return; } set_pow(who, pow, powval); log_sensitive(tprintf("%s(%d) granted %s(%d) power %s, level %s", name(player), player->dbref, name(who), who->dbref, powstr, i)); if(powval != PW_NO) { notify(who, tprintf("You have been given the power of %s.", pow_to_name(pow))); notify(player, tprintf("%s has been given the power of %s.", name(who), pow_to_name(pow))); } switch(powval) { case PW_YES: notify(who, "You can use it on anyone."); break; case PW_YESEQ: notify(who, "You can use it on people your class and under."); break; case PW_YESLT: notify(who, "You can use it on people under your class."); break; case PW_NO: notify(who, tprintf("Your power of %s has been removed.", pow_to_name(pow))); notify(player, tprintf("%s power of %s has been removed.", poss(who), pow_to_name(pow))); break; } } void do_quota(OBJ *player, char *arg1, char *arg2) { OBJ *who; int owned, limit; if(*arg2) if(!power(player, POW_SETQUOTA)) { notify(player, perm_denied()); return; } if(!*arg1) who = player; else { who = match_object(player, arg1, TYPE_PLAYER); if(!who) { notify(player, no_match(arg1)); return; } } if(!controls(player, who, POW_SETQUOTA)) { notify(player, perm_denied()); return; } owned = owns_stuff(who); if(!*arg2) limit = atoi(atr_get(who, "QUOTA")); else { limit = atoi(arg2); if(limit < 0) { notify(player, "New limit cannot be a negative number!"); return; } atr_add(who, "QUOTA", tprintf("%d", limit)); } notify(player, tprintf("|+B|Objects|+W|: |+C|%d |+B|Limit|+W|: |+C|%s", owned, (power(who, POW_NOQUOTA))?"UNLIMITED":tprintf("%d", limit))); } void do_inactive(OBJ *player) { OBJ *i; int k, l; int ctr = 0; time_t last_on; float days_old; char buf[4096]; struct plist_struct { OBJ *player; float days; int objs; } *plist = NULL; if(!power(player, POW_DB)) { notify(player, perm_denied()); return; } for(i = player_list;i;i = i->next) { if(is_root(i) || get_class(i) != CLASS_CITIZEN) continue; last_on = atol(atr_get(i, "LASTCONN")); if(!last_on) last_on = i->create_time; if(now-last_on > 15552000) /* 180 days (believe it or not) */ { days_old = (float)(now-last_on)/(60*60*24); if(!ctr) plist = (struct plist_struct *)stack_alloc(sizeof(struct plist_struct), 0, 0); else plist = (struct plist_struct *)stack_realloc_tmp(plist, sizeof(struct plist_struct)*(ctr+1)); plist[ctr].player = i; plist[ctr].days = days_old; plist[ctr].objs = owns_stuff(i); ctr++; } } if(!ctr) notify(player, "No players have been inactive for more than 180 days."); else { struct plist_struct ptemp; for(k = 0;k < ctr;++k) for(l = k+1;l < ctr;++l) if(plist[k].days < plist[l].days) { ptemp.player = plist[k].player; ptemp.days = plist[k].days; ptemp.objs = plist[k].objs; plist[k].player = plist[l].player; plist[k].days = plist[l].days; plist[k].objs = plist[l].objs; plist[l].player = ptemp.player; plist[l].days = ptemp.days; plist[l].objs = ptemp.objs; } for(k = 0;k < ctr;++k) { if(plist[k].objs) sprintf(buf, " |+R|%d object%s", plist[k].objs, check_plural(plist[k].objs, "", "s")); else *buf = '\0'; notify(player, tprintf("%s |+W|(%.0f days inactive)%s", unparse_object(player, plist[k].player), plist[k].days, buf)); } notify(player, tprintf("\n|+W|%d |B|inactive players found.", ctr)); } } void do_complain(OBJ *player, char *arg1, char *arg2) { OBJ *obj; if(!(obj = match_player(NULL, arg1))) { notify(player, no_match(arg1)); return; } if(!*arg2) { notify(player, "You must specify a reason for this complaint."); return; } log_complaint(tprintf("%s(#%d) complains about %s(#%d) because: %s", name(player), player->dbref, name(obj), obj->dbref, arg2)); notify(player, "Your complaint has been logged."); }