#include #include #include #include #include #include extern const char *__progname; static const char *dbfile; static int ndbrefs; static int *dbrefs; static int dbfd; static FILE *dbf; static const char *linetags[] = { " dbref", " @name", " @desc", " location", " contents", " next", " nextowned", " owner", " key", " @fail", " @succ", " @drop", " @ofail", " @osucc", " @odrop", "Fflags", " ctime", " mtime", " utime", "P", "T" }; static const char *room_lines[] = { "Hdbref is a room", " dropto", " exits", " useval", " stamp", 0 }; static const char *thing_lines[] = { "Hdbref is a thing", " home", " actions", " value", 0 }; static const char *exit_lines[] = { "Hdbref is an exit", "Nlinkcount", "Rlink-to", 0 }; static const char *player_lines[] = { "Hdbref is a player", " home", " actions", " pennies", " password", 0 }; static const char *program_lines[] = { "Hdbref is a program", 0 }; #define FLAGTYPEMASK 7 static const char **typelines[] = { &room_lines[0], &thing_lines[0], &exit_lines[0], &player_lines[0], &program_lines[0], 0, 0, 0 }; static char typechars[] = "RTEPFD??"; static struct { unsigned long int bit; char c; const char *s; } flagbits[] = { { 0x00000008, 'c', 0 }, { 0x00000010, 'w', 0 }, { 0x00000020, 'l', 0 }, { 0x00000040, 'd', 0 }, { 0x00000100, 's', 0 }, { 0x00000200, 'b', 0 }, { 0x00000400, 'o', 0 }, { 0x00000800, 'j', 0 }, { 0x00001000, 'e', 0 }, { 0x00002000, 'k', 0 }, { 0x00004000, 'n', 0 }, { 0x00008000, 'f', 0 }, { 0x00010000, 'h', 0 }, { 0x00020000, 'a', 0 }, { 0x00040000, 'm', 0 }, { 0x00080000, 'u', 0 }, { 0x00200000, 'i', 0 }, { 0x00400000, 't', 0 }, { 0x00800000, 'p', 0 }, { 0x01000000, 'g', 0 }, { 0x02000000, 'q', 0 }, { 0x04000000, 'v', 0 }, { 0x08000000, 'r', 0 }, { 0x10000000, 'x', 0 }, { 0x20000000, 'y', 0 }, { 0x40000000, 'z', 0 }, { 0x00000080, 0, "ILineNum" }, { 0x00100000, 0, "oldSwapout" }, { 0x80000000, 0, "0x80000000" }, { 0 } }; static void usage(void) { fprintf(stderr,"Usage: %s dbfile dbref [dbref...]\n",__progname); } static void set_dbfile(const char *s) { dbfile = s; } static void set_dbref(const char *s) { if (*s == '#') s ++; ndbrefs ++; dbrefs = realloc(dbrefs,ndbrefs*sizeof(*dbrefs)); dbrefs[ndbrefs-1] = atoi(s); } static void handleargs(int ac, char **av) { int skip; int errs; dbfile = 0; ndbrefs = 0; dbrefs = 0; skip = 0; errs = 0; for (ac--,av++;ac;ac--,av++) { if (skip > 0) { skip --; continue; } if (**av != '-') { if (dbfile == 0) { set_dbfile(*av); } else { set_dbref(*av); } continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); errs ++; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-dbfile")) { WANTARG(); set_dbfile(av[skip]); continue; } if (!strcmp(*av,"-dbref")) { WANTARG(); set_dbref(av[skip]); continue; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",__progname,*av); errs ++; } if (errs) exit(1); } static void open_dbfile(void) { dbfd = open(dbfile,O_RDONLY,0); if (dbfd < 0) { fprintf(stderr,"%s: %s: %s\n",__progname,dbfile,strerror(errno)); exit(1); } dbf = fdopen(dbfd,"r"); } static void check_args(void) { if (! dbfile) { fprintf(stderr,"%s: need a database file\n",__progname); usage(); exit(1); } if (ndbrefs < 1) { fprintf(stderr,"%s: need at least one dbref\n",__progname); usage(); exit(1); } } static int skip_to_dbref(void) { int c; long int nloff; int state; int dbref; state = 0; while (1) { c = getc(dbf); if (c == EOF) return(-1); switch (state) { case 0: if (c == '\n') { nloff = ftell(dbf); state = 1; } break; case 1: state = (c == '#') ? 2 : 0; dbref = 0; break; case 2: if (c == '\n') { fseek(dbf,nloff,0); return(dbref); } if (! isdigit(c)) state = 0; dbref = (dbref * 10) + (c - '0'); break; } } } static int find_dbref(int dbr) { int maxdbr; int lastd; int d; long int l; long int m; long int h; rewind(dbf); maxdbr = skip_to_dbref(); if (maxdbr < 0) { fprintf(stderr,"%s: no dbrefs in db file\n",__progname); exit(1); } if (dbr > maxdbr) { printf("#%d not in file (too large)\n",dbr); return(0); } if (dbr == maxdbr) return(1); lastd = maxdbr; l = ftell(dbf); fseek(dbf,0,2); h = ftell(dbf); while (h-l > 65536) { m = (h + l) / 2; fseek(dbf,m,0); d = skip_to_dbref(); if (d < 0) { h = m; continue; } if (d == dbr) return(1); if (d < dbr) { h = m; } else { l = m; lastd = d; } } fseek(dbf,l,0); while (1) { d = skip_to_dbref(); if (d < 0) { printf("#%d not in file (not found - EOF while searching)\n",dbr); return(0); } if (d < dbr) { printf("#%d not in file (not found - #%d to #%d)\n",dbr,lastd,d); return(0); } if (d == dbr) return(1); lastd = d; } } static void dump_dbref(void) { int i; int s; unsigned long int f; unsigned long int v; int n; const char **tags; int c; if (0) { unexeof:; printf("*** unexpected EOF\n"); return; } tags = &linetags[0]; for (i=0;tags[i];i++) { switch (tags[i][0]) { case ' ': case 'F': case 'N': case 'R': break; case 'H': printf(" [%s]\n",tags[i]+1); continue; break; case 'T': tags = typelines[f&FLAGTYPEMASK]; if (tags == 0) { printf("*** Bad type %d\n",(int)(f&FLAGTYPEMASK)); return; } i = -1; continue; break; case 'P': s = 0; while (s < 3) { c = getc(dbf); if (c == EOF) goto unexeof; putchar(c); switch (s) { case 0: if (c == '\n') s = 1; break; case 1: s = (c == '*') ? 2 : (c == '\n') ? 1 : 0; break; case 2: s = (c == '\n') ? 3 : 0; break; } } continue; break; default: fprintf(stderr,"%s: impossible tag tag character\n",__progname); abort(); break; } printf("(%s) ",tags[i]+1); v = 0; while (1) { c = getc(dbf); if (c == EOF) goto unexeof; putchar(c); if (isdigit(c)) v = (10 * v) + (c - '0'); if (c == '\n') break; } switch (tags[i][0]) { case ' ': break; case 'F': f = v; printf(" [flags = %c",typechars[v&FLAGTYPEMASK]); for (s=0;flagbits[s].bit;s++) { if (v & flagbits[s].bit) { if (flagbits[s].c) putchar(flagbits[s].c); if (flagbits[s].s) printf(" %s",flagbits[s].s); } } printf("]\n"); break; case 'N': n = v; break; case 'R': if (--n > 0) i --; break; } } } static void find_dbrefs(void) { int i; int any; any = 0; for (i=0;i