/* dbmcmds.c */ #include "copyright.h" #include "config.h" #include <stdio.h> #include <ctype.h> #include "teeny.h" #include "dbm.h" void text_dump2(); void putlock2(); #ifdef COMPRESS extern char *uncompress(); #endif extern int atoi(); /* * Implements the other db manager commands. */ struct nuked { int obj; struct nuked *next; }; int lists_handle(z, ex, req) char *z; char *ex; char *req; { register int i; int loc; int flags; /* first we nuke all the lists in the db. what fun.. */ printf("Spamming...\n"); for (i = 0; i < db_top(); i++) { if (!exists_object(i)) continue; if (set_int_elt(i, EXITS, -1) == -1) printf("Object #%d has a bad exits pointer.\n", i); if (set_int_elt(i, CONTENTS, -1) == -1) printf("Object #%d has a bad contents pointer.\n", i); if (set_int_elt(i, NEXT, -1) == -1) printf("Object #%d has a bad next pointer.\n", i); } /* now we rebuild everything. loc had better have been correct... */ printf("Rebuilding...\n"); for (i = 0; i < db_top(); i++) { if (!exists_object(i)) continue; if (get_int_elt(i, LOC, &loc) == -1) { printf("Object #%d has a bad location reference. Destroy it.\n", i); continue; } if (get_int_elt(i, FLAGS, &flags) == -1) { printf("Object #%d has a bad flags reference. Destroy it.\n", i); continue; } switch (flags & TYPE_MASK) { case TYP_THING: case TYP_PLAYER: list_add(i, loc, CONTENTS_LIST); break; case TYP_EXIT: list_add(i, loc, EXITS_LIST); break; case TYP_ROOM: list_add(i, loc, ROOMS_LIST); break; default: printf("Object #%d has a bad type. Destroy it.\n", i); } } printf("Done.\n"); } int pur_handle(p, ex, req) char *p; atom *ex; int *req; { int i; int flags; int ptr; /* home, dest or dropto */ struct nuked *nuked_list = NULL; struct nuked *tmp, *nuked_this; printf("Purging.\n"); /* Make one pass over the db killing stuff, and keeping track */ /* of what's been killed so far. */ for (i = 0; i < db_top(); i++) { if (exists_object(i) && eval_expr(i, ex, *req)) { recycle_obj(i, &nuked_list); nuked_this = (struct nuked *) ty_malloc(sizeof(struct nuked), "purge"); nuked_this->next = nuked_list; nuked_this->obj = i; nuked_list = nuked_this; } } /* Another pass over the DB, checking destinations, and */ /* Handling them as best we can. Reset homes to 0 and */ /* simply unlink exits/rooms pointed at nuked things. */ for (i = 0; i < db_top(); i++) { if (!exists_object(i)) continue; /* This depends heavily on the fact that */ /* Destination, Home, and DropTo are all */ /* The same element of an object. */ if (get_int_elt(i, DESTINATION, &ptr) == -1) goto dropthru; /* See if the destination has been nuked. */ for (tmp = nuked_list; tmp != NULL; tmp = tmp->next) { if (tmp->obj == ptr) break; } if (tmp == NULL) continue; /* If we get here, the dest HAS been nuked. */ if (get_int_elt(i, FLAGS, &flags) == -1) goto dropthru; switch (flags & TYPE_MASK) { case TYP_PLAYER: if (set_int_elt(i, DESTINATION, STARTING_LOC) == -1) goto dropthru; break; case TYP_THING: { int home, owner; if (get_int_elt(i, OWNER, &owner) == -1) goto dropthru; if (get_int_elt(owner, HOME, &home) == -1) goto dropthru; if (set_int_elt(i, HOME, home) == -1) goto dropthru; } break; case TYP_ROOM: case TYP_EXIT: if (set_int_elt(i, DESTINATION, -1) == -1) goto dropthru; break; } } free_nuked_list(nuked_list); return (0); dropthru: printf("Bad DB reference in 2nd pass at object %d\n", i); free_nuked_list(nuked_list); return (-1); } free_nuked_list(nk) struct nuked *nk; { struct nuked *tmp; if (nk == NULL) { return; } do { tmp = nk->next; free((char *) nk); nk = tmp; } while (tmp != NULL); } int cho_handle(p, ex, req) char *p; atom *ex; int *req; { int i, newowner; while (isspace(*p)) p++; if (*p++ != '#') { printf("Invalid object number for new owner.\n"); return (0); } newowner = atoi(p); printf("Chowning selected objects to #%d\n", newowner); for (i = 0; i < db_top(); i++) { if (exists_object(i) && eval_expr(i, ex, *req)) { if (set_int_elt(i, OWNER, newowner) == -1) { printf("Bad object ref at %d\n", i); return (-1); } } } return (0); } int sum_handle(p, ex, req) char *p; atom *ex; int *req; { int i; char *name; int owner; char *ownername; int flags; char *q, ch = '\0', work[BUFFSIZ]; for (i = 0; i < db_top(); i++) { if (exists_object(i) && eval_expr(i, ex, *req)) { /* Summarize the data for this guy */ if (get_str_elt(i, NAME, &name) == -1) { printf("DB error at object #%d\n", i); continue; } if (get_int_elt(i, OWNER, &owner) == -1) { printf("DB error at object #%d\n", i); continue; } if (get_str_elt(owner, NAME, &ownername) == -1) { printf("DB error at object #%d\n", owner); continue; } if (get_int_elt(i, FLAGS, &flags) == -1) { printf("DB error at object #%d\n", i); continue; } /* We've got the data. Write it out. */ if (isplayer(i)) { for (q = name; *q && *q != ' '; q++); ch = *q; *q = '\0'; } printf("(#%d) Name: %s\n", i, name); if (ch) *q = ch; if (isplayer(owner)) { for (q = ownername; *q && *q != ' '; q++); ch = *q; *q = '\0'; } switch (flags & TYPE_MASK) { case TYP_EXIT: strcpy(work, "E/"); break; case TYP_ROOM: strcpy(work, "R/"); break; case TYP_PLAYER: strcpy(work, "P/"); break; case TYP_THING: strcpy(work, "T/"); break; default: strcpy(work, "U/"); } if (flags & GOD) strcat(work, "G"); if (flags & WIZARD) strcat(work, "W"); if (flags & ROBOT) strcat(work, "R"); if (flags & LINK_OK) strcat(work, "L"); if (flags & JUMP_OK) strcat(work, "J"); if (flags & ABODE) strcat(work, "A"); if (flags & HAVEN) strcat(work, "H"); if (flags & DARK) strcat(work, "D"); printf("Flags: %s(%d) Owner: %s\n", work, flags, ownername); if (ch) *q = ch; } } } /* * First pass of recycling. This does one object. */ recycle_obj(obj, nuke_list) int obj; struct nuked **nuke_list; /* So we can add things to it. */ { int loc, flags, next, list; struct nuked *tmp; if (obj == 0) { printf("Cannot recycle object Zero.\n"); return; } #if STARTING_LOC != 0 if (obj == STARTING_LOC) { printf("Cannot recycle player start.\n"); return; } #endif /* STARTING_LOC != 0 */ if (get_int_elt(obj, FLAGS, &flags) == -1) goto bomb; if (get_int_elt(obj, LOC, &loc) == -1) goto bomb; switch (flags & TYPE_MASK) { case TYP_PLAYER: /* Get the player off the contents list. */ /* Otherwise it's just like a room. */ list_drop(obj, loc, 1); case TYP_ROOM: /* Destroy all the exits in room/carried by player */ if (get_int_elt(obj, EXITS, &list) == -1) goto bomb; while (list != -1) { if (get_int_elt(list, NEXT, &next) == -1) goto bomb; tmp = (struct nuked *) ty_malloc(sizeof(struct nuked), "recycle_obj"); tmp->next = *nuke_list; *nuke_list = tmp; tmp->obj = list; destroy_obj(list); list = next; } /* Try to send room contents/player inventory home. */ if (get_int_elt(obj, CONTENTS, &list) == -1) goto bomb; while (list != -1) { if (get_int_elt(list, NEXT, &next) == -1) goto bomb; send_home(list, obj); list = next; } /* Now nuke everything left -- i.e. stuff homed here */ if (get_int_elt(obj, CONTENTS, &list) == -1) goto bomb; while (list != -1) { if (get_int_elt(list, NEXT, &next) == -1) goto bomb; tmp = (struct nuked *) ty_malloc(sizeof(struct nuked), "recycle_obj"); tmp->next = *nuke_list; *nuke_list = tmp; tmp->obj = list; destroy_obj(list); list = next; } /* nuke the room/player itself. */ destroy_obj(obj); break; case TYP_EXIT: list_drop(obj, loc, 0); destroy_obj(obj); break; case TYP_THING: list_drop(obj, loc, 1); destroy_obj(obj); break; default: printf("Eeek! Unknown object type!\n"); return; } return; bomb: printf("Something bad happened. Good luck.\n"); return; } int fix_handle() { int i, list, loc, flags; int total = 0; printf("Scanning the database...\n"); for (i = 0; i < db_top(); i++) { if (!exists_object(i)) continue; /* loop through the exits list first.. */ if (get_int_elt(i, EXITS, &list) == -1) goto bomb; while (list != -1) { if (get_int_elt(list, LOC, &loc) == -1) goto bomb; if (loc != i) { if (set_int_elt(list, LOC, i) == -1) goto bomb; total++; } if (get_int_elt(list, NEXT, &list) == -1) goto bomb; } /* now do the contents list. this is slightly more complex.. */ if (get_int_elt(i, CONTENTS, &list) == -1) goto bomb; while (list != -1) { int next; if (get_int_elt(list, NEXT, &next) == -1) goto bomb; if (get_int_elt(list, FLAGS, &flags) == -1) goto bomb; if ((flags & TYPE_MASK) == TYP_EXIT) { if (get_int_elt(list, LOC, &loc) == -1) goto bomb; if (loc != i) { if (set_int_elt(list, LOC, i) == -1) goto bomb; } total++; list_drop(list, i, 1); list_add(list, i, 0); if (set_int_elt(list, DESTINATION, -1) == -1) goto bomb; } list = next; } /* all done with that sucker... */ } printf("Scan done. %d exits fixed.\n", total); return (0); bomb: printf("Database corrupt. Scan aborted.\n"); return (-1); } /* * Utility funtions. * */ /* Sends an object home */ send_home(obj, loc) int obj; int loc; { int home; if (get_int_elt(obj, HOME, &home) == -1) { printf("Object #%d has a bad home reference.\n", obj); return; } list_drop(obj, loc, CONTENTS_LIST); /* Drop it from contents list here */ if (!exists_object(home)) { home = STARTING_LOC; /* Fake it, eh? */ } if (set_int_elt(obj, LOC, home) == -1) { printf("Could not set location for object #%d.\n", obj); return; } list_add(obj, home, CONTENTS_LIST); }