/* Copyright (c) 1993 Stephen F. White */ #include "cool.h" #include "proto.h" #include "netio.h" #include "execute.h" int promiscuous = 0; int corefile = 0; int compiler = 0; int registration = 0; int verify_servers = 0; Objid sys_obj; /* shortcut, d00d */ static int read_welcome (const char *fname); Playerid find_player (const char *name); void panic (const char *s) { writelog (); fprintf (stderr, "PANIC: %s\n", s); shutdown_server (); } /* * init() * * Initializes the database and dumpfile, loads and connects to * remote servers (if possible). Also calls SYSOBJ.boot_server() in * the newly-loaded database. */ int init (const char *dbfilename, int send_boot, int db_must_exist) { char buf[MAX_PATH_LEN]; /* sys_obj is a global to save shoving SYS_OBJ in a local var each time */ sys_obj.server = 0; sys_obj.id = SYS_OBJ; /* read config file */ sprintf (buf, "%s.cfg", dbfilename); writelog (); fprintf (stderr, "Reading config file from %s\n", buf); if (read_config (buf)) { writelog (); fprintf (stderr, "Couldn't read config file\n"); return -2; } /* if */ sprintf (buf, "%s.welcome", dbfilename); if (read_welcome (buf)) { return -3; } /* if */ /* initialize db and cache */ writelog (); fprintf (stderr, "Initializing db\n"); dddb_setfile (dbfilename); if (dddb_init (db_must_exist)) { return -4; } writelog (); fprintf (stderr, "Initializing cache\n"); if (cache_init ()) { return -5; } /* initialize system symbol table */ sym_init_sys (); /* initialize random number generator */ SRAND ((int) time ((time_t *) 0)); /* initialize opcode table */ opcode_init (); /* call SYS_OBJ.boot_server() */ if (send_boot) { send_message (-1, 0, 0, sys_obj, sys_obj, sys_obj, sym_sys (BOOT_SERVER), list_dup (empty_list), 0, sys_obj); } return 0; } static int read_welcome (const char *fname) { FILE *f; String *str; int c; if (!(f = fopen (fname, "rb"))) { writelog (); perror (fname); return -1; } str = string_new (0); while ((c = getc (f)) != EOF) { str = string_catc (str, c); } fclose (f); welcome = str_dup (str->str); string_free (str); return 0; } void shutdown_server (void) { writelog (); fprintf (stderr, "Syncing cache\n"); cache_sync (); writelog (); fprintf (stderr, "Closing database\n"); dddb_close (); } Error sys_get_global (const char *var, Var * r) { Object *sys; if (!(sys = retrieve (sys_obj))) { writelog (); fprintf (stderr, "SYS_OBJ: #%d not found\n", SYS_OBJ); return E_OBJNF; } else if (var_get_global (sys, var, r) == E_VARNF) { writelog (); fprintf (stderr, "SYS_OBJ: #%d.%s missing\n", SYS_OBJ, var); return E_VARNF; } else { return E_NONE; } } Error sys_assign_global (const char *var, Var value) { Object *sys; String *name = string_cpy (var); Error r; if (!(sys = retrieve (sys_obj))) { writelog (); fprintf (stderr, "SYS_OBJ: #%d not found\n", SYS_OBJ); r = E_OBJNF; } else if (var_assign_global (sys, name, value) == E_TYPE) { writelog (); fprintf (stderr, "SYS_OBJ: #%d.%s assignment: type mismatch\n", SYS_OBJ, var); r = E_TYPE; } else { r = E_NONE; } string_free (name); return r; } Playerid find_player (const char *name) { Object *p; Var players, pname; int i; Playerid player = NOTHING; if (sys_get_global ("players", &players) != E_NONE) { return NOTHING; } else if (players.type != LIST) { writelog (); fprintf (stderr, "SYS_OBJ: #%d.players is not a list\n", SYS_OBJ); return NOTHING; } else { players = var_dup (players); /* in case sysobj gets swapped out (!) */ for (i = 0; i < players.v.list->len; i++) { if (players.v.list->el[i].type == OBJ && (p = retrieve (players.v.list->el[i].v.obj)) && var_get_global (p, "name", &pname) == E_NONE && pname.type == STR && !strcasecmp (pname.v.str->str, name)) { player = p->id.id; break; } cache_reset (); } var_free (players); } return player; } static void do_connect (Objid player) { List *args = list_new (1); args->el[0].type = OBJ; args->el[0].v.obj = player; send_message (-1, 0, 0, player, sys_obj, sys_obj, sym_sys (CONNECT_PLAYER), args, 0, sys_obj); } Playerid connect_player (const char *name, const char *password) { Objid player; Var ppassword; Object *p; char salt[3]; player.server = 0; if (!name || !*name || !password) { return NOTHING; } else if ((player.id = find_player (name)) == NOTHING) { return NOTHING; } else if (!(p = retrieve (player))) { return NOTHING; } else if (var_get_global (p, "password", &ppassword) == E_VARNF || ppassword.type != STR || !ppassword.v.str->str[0]) { do_connect (player); cache_reset (); return player.id; } salt[0] = ppassword.v.str->str[0]; salt[1] = ppassword.v.str->str[1]; salt[2] = '\0'; if (!strcmp (crypt (password, salt), ppassword.v.str->str)) { do_connect (player); cache_reset (); return player.id; } else { return NOTHING; } } Playerid create_player (const char *name, const char *password) { Var strv, pclass; Object *p; char salt[3]; static char saltstuff[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./"; List *args; struct timeval cur_time; salt[0] = saltstuff[RAND () % strlen (saltstuff)]; salt[1] = saltstuff[RAND () % strlen (saltstuff)]; salt[2] = '\0'; if (!name || !*name || !password || !*password) { return NOTHING; } else if (sys_get_global ("player_class", &pclass) != E_NONE) { return NOTHING; } else if (pclass.type != OBJ) { writelog (); fprintf (stderr, "SYS_OBJ: #%d.player_class is not an obj\n", SYS_OBJ); return NOTHING; } if (find_player (name) != NOTHING) { return NOTHING; } p = clone (pclass.v.obj); if (!p) { writelog (); fprintf (stderr, "SYS_OBJ: couldn't clone #%d\n", pclass.v.obj.id); return NOTHING; } (void) send_message (-1, 0, 0, sys_obj, sys_obj, p->id, sym_sys (INIT), list_dup (empty_list), 0, p->id); gettimeofday (&cur_time, 0); process_queues (cur_time, &cur_time); /* do player init */ strv.type = STR; strv.v.str = string_cpy (name); (void) var_assign_global (p, sym_sys (NAME), strv); strv.v.str = string_cpy (crypt (password, salt)); (void) var_assign_global (p, sym_sys (PASSWORD), strv); args = list_new (1); args->el[0].type = OBJ; args->el[0].v.obj = p->id; send_message (-1, 0, 0, p->id, sys_obj, sys_obj, sym_sys (CREATE_PLAYER), args, 0, sys_obj); return p->id.id; } void disconnect_player (Playerid who) { List *args; Objid player; player.id = who; player.server = 0; args = list_new (1); args->el[0].type = OBJ; args->el[0].v.obj = player; send_message (-1, 0, 0, player, sys_obj, sys_obj, sym_sys (DISCONNECT_PLAYER), args, 0, sys_obj); } void connect_server (Serverid server) { List *args; args = list_new (1); args->el[0].type = OBJ; args->el[0].v.obj.id = 0; args->el[0].v.obj.server = server; (void) send_message (-1, 0, 0, sys_obj, sys_obj, sys_obj, sym_sys (CONNECT_SERVER), args, 0, sys_obj); } void disconnect_server (Serverid server) { List *args; args = list_new (1); args->el[0].type = OBJ; args->el[0].v.obj.id = 0; args->el[0].v.obj.server = server; (void) send_message (-1, 0, 0, sys_obj, sys_obj, sys_obj, sym_sys (DISCONNECT_SERVER), args, 0, sys_obj); } static Playerid progr; /* programmer */ int prog_getc (void); void prog_ungetc (int c); void prog_error (const char *s); /* error function */ static FILE *progfile; int prog_getc (void) { return getc (progfile); } void prog_ungetc (int c) { ungetc (c, progfile); } void prog_error (const char *s) { tell (progr, s); } void do_compile (Playerid player, FILE * pf, void *progwhat) { int *data = (int *) progwhat; Objid obj; String *method; int nerrors; Object *new; obj.server = 0; obj.id = data[0]; method = (String *) data[1]; progr = player; progfile = pf; if (obj.id < 0) { /* multiple objects */ nerrors = compile (player, prog_getc, prog_ungetc, prog_error, 0, 0, 0, 0, 0); } else { /* single method */ if (!(new = retrieve (obj))) { tell (player, "Object no longer exists!"); } else { nerrors = compile (player, prog_getc, prog_ungetc, prog_error, 1, new, method, 0, 0); } string_free (method); } cache_reset (); FREE (progwhat); }