/* * Check that a path to a file is valid for read or write. * This is done by functions in the master object. * The path is always treated as an absolute path, and is returned without * a leading '/'. * If the path was '/', then '.' is returned. * Otherwise, the returned path is temporarily allocated by apply(), which * means it will be deallocated at next apply(). */ const char *check_valid_path (const char * path, object_t * call_object, const char * const call_fun, int writeflg) { svalue_t *v; if(!master_ob && !call_object){ //early startup, ignore security extern svalue_t apply_ret_value; free_svalue(&apply_ret_value, "check_valid_path"); apply_ret_value.type = T_STRING; apply_ret_value.subtype = STRING_MALLOC; path = apply_ret_value.u.string = string_copy(path, "check_valid_path"); return path; } if (call_object == 0 || call_object->flags & O_DESTRUCTED) return 0; #ifdef WIN32 { char *p; for(p=path; *p; p++) if (*p == '\\') *p='/'; } #endif copy_and_push_string(path); push_object(call_object); push_constant_string(call_fun); if (writeflg) v = apply_master_ob(APPLY_VALID_WRITE, 3); else v = apply_master_ob(APPLY_VALID_READ, 3); if (v == (svalue_t *)-1) v = 0; if (v && v->type == T_NUMBER && v->u.number == 0) return 0; if (v && v->type == T_STRING) { path = v->u.string; } else { extern svalue_t apply_ret_value; free_svalue(&apply_ret_value, "check_valid_path"); apply_ret_value.type = T_STRING; apply_ret_value.subtype = STRING_MALLOC; path = apply_ret_value.u.string = string_copy(path, "check_valid_path"); } if (path[0] == '/') path++; if (path[0] == '\0') path = "."; if (legal_path(path)) return path; return 0; }
/* 将ob设置为master对象 */ void set_master(object_t * ob) { #if defined(PACKAGE_UIDS) || defined(PACKAGE_MUDLIB_STATS) int first_load = (!master_ob); #endif #ifdef PACKAGE_UIDS svalue_t *ret; #endif get_master_applies(ob); /* master load好之后,要apply一下? */ master_ob = ob; /* Make sure master_ob is never made a dangling pointer. */ add_ref(master_ob, "set_master"); #ifndef PACKAGE_UIDS # ifdef PACKAGE_MUDLIB_STATS if (first_load) { set_backbone_domain("BACKBONE"); set_master_author("NONAME"); } # endif #else ret = apply_master_ob(APPLY_GET_ROOT_UID, 0); /* can't be -1 or we wouldn't be here */ if (!ret) { debug_message("No function %s() in master object; possibly the mudlib doesn't want PACKAGE_UIDS to be defined.\n", applies_table[APPLY_GET_ROOT_UID]); exit(-1); } if (ret->type != T_STRING) { debug_message("%s() in master object does not work.\n", applies_table[APPLY_GET_ROOT_UID]); exit(-1); } if (first_load) { /* 第一次load master? */ master_ob->uid = set_root_uid(ret->u.string); master_ob->euid = master_ob->uid; # ifdef PACKAGE_MUDLIB_STATS set_master_author(ret->u.string); # endif ret = apply_master_ob(APPLY_GET_BACKBONE_UID, 0); if (ret == 0 || ret->type != T_STRING) { debug_message("%s() in the master file does not work\n", applies_table[APPLY_GET_BACKBONE_UID]); /* apply有多个,装table */ exit(-1); } set_backbone_uid(ret->u.string); # ifdef PACKAGE_MUDLIB_STATS set_backbone_domain(ret->u.string); # endif } else { master_ob->uid = add_uid(ret->u.string); master_ob->euid = master_ob->uid; } #endif }
static void udpsvc_process(udpsvc_t *svc) { int addrlen, cc; struct sockaddr_in addr; struct gdexception exception_frame; update_udp_av(); exception_frame.e_exception = exception; exception_frame.e_catch = 0; exception = &exception_frame; if (setjmp(exception_frame.e_context) == 0) { push_string(inet_ntoa(addr.sin_addr), STRING_MSTRING); push_string((char *)nq_rptr(svc->nq), STRING_MSTRING); (void)apply_master_ob(M_INCOMING_UDP, 2); } exception = exception->e_exception; addrlen = sizeof (addr); if (!read_datagram(svc)) { nd_enable(svc->nd, ND_R); svc->task = 0; return; } reschedule_task(svc->task); }
static void slow_shut_down(void *v) { shutdown_task = 0; push_number(slow_shut_down_to_do); slow_shut_down_to_do = 0; apply_master_ob(M_MEMORY_FAILURE, 1); }
static void PSIG(sig_usr1) { push_string("Host machine shutting down", STRING_CONSTANT); push_undefined(); push_undefined(); apply_master_ob(APPLY_CRASH, 3); debug_message("Received SIGUSR1, calling exit(-1)\n"); exit(-1); }
/* New version used when not in -o mode. The epilog() in master.c is * supposed to return an array of files (castles in 2.4.5) to load. The array * returned by apply() will be freed at next call of apply(), which means that * the ref count has to be incremented to protect against deallocation. * * The master object is asked to do the actual loading. */ void preload_objects (int eflag) { VOLATILE array_t *prefiles; svalue_t *ret; VOLATILE int ix; error_context_t econ; save_context(&econ); if (SETJMP(econ.context)) { restore_context(&econ); pop_context(&econ); return; } push_number(eflag); ret = apply_master_ob(APPLY_EPILOG, 1); pop_context(&econ); if ((ret == 0) || (ret == (svalue_t *)-1) || (ret->type != T_ARRAY)) return; else prefiles = ret->u.arr; if ((prefiles == 0) || (prefiles->size < 1)) return; debug_message("\nLoading preloaded files ...\n"); prefiles->ref++; ix = 0; /* in case of an error, effectively do a 'continue' */ save_context(&econ); if (SETJMP(econ.context)) { restore_context(&econ); ix++; } for ( ; ix < prefiles->size; ix++) { if (prefiles->item[ix].type != T_STRING) continue; set_eval(max_cost); push_svalue(((array_t *)prefiles)->item + ix); (void) apply_master_ob(APPLY_PRELOAD, 1); } free_array((array_t *)prefiles); pop_context(&econ); } /* preload_objects() */
static void init_domain_for_ob (object_t * ob) { svalue_t *ret; const char *domain_name; if (!current_object #ifdef PACKAGE_UIDS || !current_object->uid #endif ) { /* * Only for the master and void object. Note that you can't ask for * the backbone or root domain here since we're in the process of * loading the master object. */ ob->stats.domain = add_stat_entry("NONAME", &domains); return; } /* * Ask master object who the creator of this object is. */ push_malloced_string(add_slash(ob->obname)); if (master_ob) ret = apply_master_ob(APPLY_DOMAIN_FILE, 1); else ret = apply(applies_table[APPLY_DOMAIN_FILE], ob, 1, ORIGIN_DRIVER); if (IS_ZERO(ret)) { ob->stats.domain = current_object->stats.domain; return; } if (ret->type != T_STRING) error("'domain_file' in the master object must return a string!\n"); domain_name = ret->u.string; if (strcmp(current_object->stats.domain->name, domain_name) == 0) { ob->stats.domain = current_object->stats.domain; return; } if (strcmp(backbone_domain->name, domain_name) == 0) { /* * The object is loaded from backbone. We give domain ownership to * the creator rather than backbone. */ ob->stats.domain = current_object->stats.domain; return; } /* * The object isn't loaded from backbone or from the same domain as the * creator, so we need to lookup the domain, and add it if it isnt * present. */ ob->stats.domain = add_stat_entry(domain_name, &domains); return; }
/* * Argument is a file name, which we want to get the domain of. * Ask the master object. */ static const char *domain_for_file (const char * file) { svalue_t *ret; static char buff[512]; share_and_push_string(file); ret = apply_master_ob(APPLY_DOMAIN_FILE, 1); if (ret == 0 || ret == (svalue_t*)-1 || ret->type != T_STRING) return 0; strcpy(buff, ret->u.string); return buff; }
INLINE int valid_hide P1(struct object *, obj) { struct svalue *ret; if (!obj) { return 0; } push_object(obj); ret = apply_master_ob(APPLY_VALID_HIDE, 1); return (!IS_ZERO(ret)); }
static const char *author_for_file (const char * file) { svalue_t *ret; static char buff[50]; copy_and_push_string(file); ret = apply_master_ob(APPLY_AUTHOR_FILE, 1); if (ret == 0 || ret == (svalue_t*)-1 || ret->type != T_STRING) return 0; strcpy(buff, ret->u.string); return buff; }
static void init_author_for_ob (object_t * ob) { svalue_t *ret; push_malloced_string(add_slash(ob->obname)); ret = apply_master_ob(APPLY_AUTHOR_FILE, 1); if (ret == (svalue_t *)-1) { ob->stats.author = master_author; } else if (!ret || ret->type != T_STRING) { ob->stats.author = NULL; } else { ob->stats.author = add_stat_entry(ret->u.string, &authors); } }
/* valid_database * * Calls APPLY_VALID_DATABASE in the master object to provide some * security on which objects can tweak your database (we don't want * people doing "DELETE * FROM *" or equivalent for us) */ svalue_t *valid_database (const char * action, array_t * info) { svalue_t *ret; /* * Call valid_database(object ob, string action, mixed *info) * * Return: string - password for access * int - 1 for no password, accept, 0 deny */ push_object(current_object); push_constant_string(action); push_refed_array(info); ret = apply_master_ob(APPLY_VALID_DATABASE, 3); if (ret && (ret == (svalue_t *)-1 || (ret->type == T_STRING || (ret->type == T_NUMBER && ret->u.number)))) return ret; error("Database security violation attempted\n"); }
/* * Read and process a UDP datagram. */ static void udpsvc_read(ndesc_t *nd, nqueue_t *nq) { int addrlen, cc; struct sockaddr_in addr; addrlen = sizeof (addr); cc = recvfrom(nd_fd(nd), nq_wptr(nq), nq_size(nq) - 1, 0, (struct sockaddr *)&addr, &addrlen); if (cc == -1) return; nq_wptr(nq)[cc] = '\0'; /* XXX We need a safe master apply XXX */ push_string(inet_ntoa(addr.sin_addr), STRING_MSTRING); push_string((char *)nq_rptr(nq), STRING_MSTRING); (void)apply_master_ob(M_INCOMING_UDP, 2); }
static void send_signals(void *x) { int i; sigprocmask(SIG_BLOCK, &sigs_to_block, NULL); for (i = 0; i < MAX_SIGNALS; i++) if (pending_signals & (1 << i)) break; pending_signals &= ~(1 << i); sigprocmask(SIG_UNBLOCK, &sigs_to_block, NULL); if (pending_signals) reschedule_task(signal_task); else signal_task = 0; if (i < MAX_SIGNALS) push_string(disp[i].name, STRING_CSTRING); (void)apply_master_ob(M_EXTERNAL_SIGNAL, 1); }
static void handle_exception(int action, char *message) { char buf[1024]; (void)strcpy(buf, "\""); if (strlen(message) < 2) (void)strcat(buf, "Unspecified condition"); else (void)strcat(buf, message); (void)strcat(buf, "\""); push_number(action); push_string(buf, STRING_MSTRING); push_number(current_line); push_string(current_file, STRING_MSTRING); (void)apply_master_ob(M_PARSE_EXCEPTION, 4); if (action == ERROR) lexerror("Parse aborted on #error statement,"); }
/* * check permission */ int check_valid_socket (const char * const what, int fd, object_t * owner, const char * const addr, int port) { array_t *info; svalue_t *mret; info = allocate_empty_array(4); info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], owner); info->item[2].type = T_STRING; info->item[2].subtype = STRING_SHARED; info->item[2].u.string = make_shared_string(addr); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_constant_string(what); push_refed_array(info); mret = apply_master_ob(APPLY_VALID_SOCKET, 3); return MASTER_APPROVED(mret); }
/* Make sure the path does not have any ".." elements. */ char * check_valid_compile_path(char *path, char *file_name, char *calling_function) { #if 0 struct svalue *ret; #endif char *p = path; while (*p) { if (p[0] == '.' && p[1] == '.') return NULL; p++; } #if 0 push_string(path, STRING_MSTRING); push_string(file_name, STRING_MSTRING); push_string(calling_function, STRING_MSTRING); ret = apply_master_ob(M_VALID_COMPILE_PATH, 3); if (ret) path = tmpstring_copy(ret->u.string); #endif return path; }
int main (int argc, char ** argv) { time_t tm; int i, new_mudlib = 0, got_defaults = 0; char *p; char version_buf[80]; #if 0 int dtablesize; #endif error_context_t econ; #ifdef PROTO_TZSET void tzset(); #endif #ifdef INCL_LOCALE_H setlocale(LC_ALL, "C"); #endif #if !defined(__SASC) && (defined(AMITCP) || defined(AS225)) amiga_sockinit(); atexit(amiga_sockexit); #endif #ifdef WRAPPEDMALLOC wrappedmalloc_init(); #endif /* WRAPPEDMALLOC */ #ifdef DEBUGMALLOC MDinit(); #endif #if (defined(PROFILING) && !defined(PROFILE_ON) && defined(HAS_MONCONTROL)) moncontrol(0); #endif #ifdef USE_TZSET tzset(); #endif boot_time = get_current_time(); const0.type = T_NUMBER; const0.u.number = 0; const1.type = T_NUMBER; const1.u.number = 1; /* const0u used by undefinedp() */ const0u.type = T_NUMBER; const0u.subtype = T_UNDEFINED; const0u.u.number = 0; //fake_prog.program_size = 0; //0 anyway /* * Check that the definition of EXTRACT_UCHAR() is correct. */ p = (char *) &i; *p = -10; if (EXTRACT_UCHAR(p) != 0x100 - 10) { fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in interpret.h.\n"); exit(-1); } /* * An added test: can we do EXTRACT_UCHAR(x++)? * (read_number, etc uses it) */ p = (char *) &i; (void) EXTRACT_UCHAR(p++); if ((p - (char *) &i) != 1) { fprintf(stderr, "EXTRACT_UCHAR() in interpret.h evaluates its argument more than once.\n"); exit(-1); } /* * Check the living hash table size */ if (CFG_LIVING_HASH_SIZE != 4 && CFG_LIVING_HASH_SIZE != 16 && CFG_LIVING_HASH_SIZE != 64 && CFG_LIVING_HASH_SIZE != 256 && CFG_LIVING_HASH_SIZE != 1024 && CFG_LIVING_HASH_SIZE != 4096) { fprintf(stderr, "CFG_LIVING_HASH_SIZE in options.h must be one of 4, 16, 64, 256, 1024, 4096, ...\n"); exit(-1); } #ifdef RAND srand(get_current_time()); #else # ifdef DRAND48 srand48(get_current_time()); # else # ifdef RANDOM srandom(get_current_time()); # else fprintf(stderr, "Warning: no random number generator specified!\n"); # endif # endif #endif current_time = get_current_time(); /* * Initialize the microsecond clock. */ init_usec_clock(); /* read in the configuration file */ got_defaults = 0; for (i = 1; (i < argc) && !got_defaults; i++) { if (argv[i][0] != '-') { set_defaults(argv[i]); got_defaults = 1; } } get_version(version_buf); if (!got_defaults) { fprintf(stderr, "%s for %s.\n", version_buf, ARCH); fprintf(stderr, "You must specify the configuration filename as an argument.\n"); exit(-1); } printf("Initializing internal tables....\n"); init_strings(); /* in stralloc.c */ init_otable(); /* in otable.c */ init_identifiers(); /* in lex.c */ init_locals(); /* in compiler.c */ /* * If our estimate is larger than FD_SETSIZE, then we need more file * descriptors than the operating system can handle. This is a problem * that can be resolved by decreasing MAX_USERS, MAX_EFUN_SOCKS, or both. * * Unfortunately, since neither MAX_USERS or MAX_EFUN_SOCKS exist any more, * we have no clue how many we will need. This code really should be * moved to places where ENFILE/EMFILE is returned. */ #if 0 if (dtablesize > FD_SETSIZE) { fprintf(stderr, "Warning: File descriptor requirements exceed system capacity!\n"); fprintf(stderr, " Configuration exceeds system capacity by %d descriptor(s).\n", dtablesize - FD_SETSIZE); } #ifdef HAS_SETDTABLESIZE /* * If the operating system supports setdtablesize() then we can request * the number of file descriptors we really need. First check to see if * wee already have enough. If so dont bother the OS. If not, attempt to * allocate the number we estimated above. There are system imposed * limits on file descriptors, so we may not get as many as we asked for. * Check to make sure we get enough. */ if (getdtablesize() < dtablesize) if (setdtablesize(dtablesize) < dtablesize) { fprintf(stderr, "Warning: Could not allocate enough file descriptors!\n"); fprintf(stderr, " setdtablesize() could not allocate %d descriptor(s).\n", getdtablesize() - dtablesize); } /* * Just be polite and tell the administrator how many he has. */ fprintf(stderr, "%d file descriptors were allocated, (%d were requested).\n", getdtablesize(), dtablesize); #endif #endif time_to_clean_up = TIME_TO_CLEAN_UP; max_cost = MAX_COST; reserved_size = RESERVED_SIZE; max_array_size = MAX_ARRAY_SIZE; if(max_array_size > 65535){ fprintf(stderr, "Maximum array size can not exceed 65535"); max_array_size = 65535; } max_buffer_size = MAX_BUFFER_SIZE; max_string_length = MAX_STRING_LENGTH; mud_lib = (char *) MUD_LIB; set_inc_list(INCLUDE_DIRS); if (reserved_size > 0) reserved_area = (char *) DMALLOC(reserved_size, TAG_RESERVED, "main.c: reserved_area"); for (i = 0; i < sizeof consts / sizeof consts[0]; i++) consts[i] = exp(-i / 900.0); reset_machine(1); /* * The flags are parsed twice ! The first time, we only search for the -m * flag, which specifies another mudlib, and the D-flags, so that they * will be available when compiling master.c. */ for (i = 1; i < argc; i++) { if (argv[i][0] != '-') continue; switch (argv[i][1]) { case 'D': if (argv[i][2]) { lpc_predef_t *tmp = ALLOCATE(lpc_predef_t, TAG_PREDEFINES, "predef"); tmp->flag = argv[i] + 2; tmp->next = lpc_predefs; lpc_predefs = tmp; continue; } fprintf(stderr, "Illegal flag syntax: %s\n", argv[i]); exit(-1); case 'N': no_ip_demon++; continue; #ifdef HAS_CONSOLE case 'C': has_console = 1; continue; #endif #ifdef YYDEBUG case 'y': yydebug = 1; continue; #endif /* YYDEBUG */ case 'm': mud_lib = alloc_cstring(argv[i] + 2, "mudlib dir"); if (chdir(mud_lib) == -1) { fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib); exit(-1); } new_mudlib = 1; break; } } if (!new_mudlib && chdir(mud_lib) == -1) { fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib); exit(-1); } time(&tm); debug_message("----------------------------------------------------------------------------\n%s (%s) starting up on %s - %s\n\n", MUD_NAME, version_buf, ARCH, ctime(&tm)); add_predefines(); #ifdef WIN32 _tzset(); #endif #ifndef NO_IP_DEMON if (!no_ip_demon && ADDR_SERVER_IP) init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT); #endif /* NO_IP_DEMON */ set_eval(max_cost); save_context(&econ); if (SETJMP(econ.context)) { debug_message("The simul_efun (%s) and master (%s) objects must be loadable.\n", SIMUL_EFUN, MASTER_FILE); exit(-1); } else { init_simul_efun(SIMUL_EFUN); init_master(); } pop_context(&econ); for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { continue; } else { /* * Look at flags. -m and -o has already been tested. */ switch (argv[i][1]) { case 'D': case 'N': case 'm': case 'y': case 'C': continue; case 'f': save_context(&econ); if (SETJMP(econ.context)) { debug_message("Error while calling master::flag(\"%s\"), aborting ...\n", argv[i] + 2); exit(-1); } push_constant_string(argv[i] + 2); apply_master_ob(APPLY_FLAG, 1); if (MudOS_is_being_shut_down) { debug_message("Shutdown by master object.\n"); exit(0); } pop_context(&econ); continue; case 'e': e_flag++; continue; case 'p': external_port[0].port = atoi(argv[i] + 2); continue; case 'd': #ifdef DEBUG_MACRO if (argv[i][2]) debug_level_set(&argv[i][2]); else debug_level |= DBG_d_flag; #else debug_message("Driver must be compiled with DEBUG_MACRO on to use -d.\n"); #endif break; case 'c': comp_flag++; continue; case 't': t_flag++; continue; default: debug_message("Unknown flag: %s\n", argv[i]); exit(-1); } } } if (MudOS_is_being_shut_down) exit(1); if (*(DEFAULT_FAIL_MESSAGE)) { char buf[8192]; strcpy(buf, DEFAULT_FAIL_MESSAGE); strcat(buf, "\n"); default_fail_message = make_shared_string(buf); } else default_fail_message = "What?\n"; #ifdef PACKAGE_MUDLIB_STATS restore_stat_files(); #endif preload_objects(e_flag); #ifdef SIGFPE signal(SIGFPE, sig_fpe); #endif #ifdef TRAP_CRASHES #ifdef SIGUSR1 signal(SIGUSR1, sig_usr1); #endif #ifdef SIGUSR2 signal(SIGUSR2, sig_usr2); #endif signal(SIGTERM, sig_term); signal(SIGINT, sig_int); #ifndef DEBUG #if defined(SIGABRT) signal(SIGABRT, sig_abrt); #endif #ifdef SIGIOT signal(SIGIOT, sig_iot); #endif #ifdef SIGHUP signal(SIGHUP, sig_hup); #endif #ifdef SIGBUS signal(SIGBUS, sig_bus); #endif signal(SIGSEGV, sig_segv); signal(SIGILL, sig_ill); #endif /* DEBUG */ #endif #ifndef WIN32 #ifdef USE_BSD_SIGNALS signal(SIGCHLD, sig_cld); #else signal(SIGCLD, sig_cld); #endif #endif #ifdef HAS_CONSOLE if(has_console >= 0) signal(SIGTTIN, sig_ttin); signal(SIGTTOU, SIG_IGN); #endif backend(); return 0; }
int main P2(int, argc, char **, argv) { time_t tm; int i, new_mudlib = 0, got_defaults = 0; int no_ip_demon = 0; char *p; char version_buf[80]; #if 0 int dtablesize; #endif error_context_t econ; #if !defined(LATTICE) && !defined(OLD_ULTRIX) && !defined(sequent) && \ !defined(sgi) void tzset(); #endif struct lpc_predef_s predefs; #if !defined(__SASC) && (defined(AMITCP) || defined(AS225)) amiga_sockinit(); atexit(amiga_sockexit); #endif #ifdef WRAPPEDMALLOC wrappedmalloc_init(); #endif /* WRAPPEDMALLOC */ #ifdef DEBUGMALLOC MDinit(); #endif #if (defined(PROFILING) && !defined(PROFILE_ON) && defined(HAS_MONCONTROL)) moncontrol(0); #endif #if !defined(OLD_ULTRIX) && !defined(LATTICE) && !defined(sequent) tzset(); #endif boot_time = get_current_time(); const0.type = T_NUMBER; const0.u.number = 0; const1.type = T_NUMBER; const1.u.number = 1; /* const0u used by undefinedp() */ const0u.type = T_NUMBER; const0u.subtype = T_UNDEFINED; const0u.u.number = 0; /* const0n used by nullp() */ const0n.type = T_NUMBER; const0n.subtype = T_NULLVALUE; const0n.u.number = 0; fake_prog.program_size = 0; /* * Check that the definition of EXTRACT_UCHAR() is correct. */ p = (char *) &i; *p = -10; if (EXTRACT_UCHAR(p) != 0x100 - 10) { fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in interpret.h.\n"); exit(-1); } /* * An added test: can we do EXTRACT_UCHAR(x++)? * (read_number, etc uses it) */ p = (char *) &i; (void) EXTRACT_UCHAR(p++); if ((p - (char *) &i) != 1) { fprintf(stderr, "EXTRACT_UCHAR() in interpret.h evaluates its argument more than once.\n"); exit(-1); } /* * Check the living hash table size */ if (CFG_LIVING_HASH_SIZE != 4 && CFG_LIVING_HASH_SIZE != 16 && CFG_LIVING_HASH_SIZE != 64 && CFG_LIVING_HASH_SIZE != 256 && CFG_LIVING_HASH_SIZE != 1024 && CFG_LIVING_HASH_SIZE != 4096) { fprintf(stderr, "CFG_LIVING_HASH_SIZE in options.h must be one of 4, 16, 64, 256, 1024, 4096, ...\n"); exit(-1); } #ifdef RAND srand(get_current_time()); #else # ifdef DRAND48 srand48(get_current_time()); # else # ifdef RANDOM srandom(get_current_time()); # else fprintf(stderr, "Warning: no random number generator specified!\n"); # endif # endif #endif current_time = get_current_time(); /* * Initialize the microsecond clock. */ init_usec_clock(); /* read in the configuration file */ got_defaults = 0; for (i = 1; (i < argc) && !got_defaults; i++) { if (argv[i][0] != '-') { set_defaults(argv[i]); got_defaults = 1; } } if (!got_defaults) { fprintf(stderr, "You must specify the configuration filename as an argument.\n"); exit(-1); } printf("Initializing internal tables....\n"); init_strings(); /* in stralloc.c */ init_otable(); /* in otable.c */ init_identifiers(); /* in lex.c */ init_locals(); /* in compiler.c */ /* disable this for now */ #if 0 /* * We estimate that we will need MAX_USERS + MAX_EFUN_SOCKS + 10 file * descriptors if the maximum number of users were to log in and all LPC * sockets were in use. This is a pretty close estimate. */ #ifndef LATTICE dtablesize = MAX_USERS + MAX_EFUN_SOCKS + 10; #else /* * Amiga sockets separate from file descriptors */ dtablesize = MAX_USERS + MAX_EFUN_SOCKS; #endif /* * If our estimate is larger than FD_SETSIZE, then we need more file * descriptors than the operating system can handle. This is a problem * that can be resolved by decreasing MAX_USERS, MAX_EFUN_SOCKS, or both. */ if (dtablesize > FD_SETSIZE) { fprintf(stderr, "Warning: File descriptor requirements exceed system capacity!\n"); fprintf(stderr, " Configuration exceeds system capacity by %d descriptor(s).\n", dtablesize - FD_SETSIZE); } #ifdef HAS_SETDTABLESIZE /* * If the operating system supports setdtablesize() then we can request * the number of file descriptors we really need. First check to see if * wee already have enough. If so dont bother the OS. If not, attempt to * allocate the number we estimated above. There are system imposed * limits on file descriptors, so we may not get as many as we asked for. * Check to make sure we get enough. */ if (getdtablesize() < dtablesize) if (setdtablesize(dtablesize) < dtablesize) { fprintf(stderr, "Warning: Could not allocate enough file descriptors!\n"); fprintf(stderr, " setdtablesize() could not allocate %d descriptor(s).\n", getdtablesize() - dtablesize); } /* * Just be polite and tell the administrator how many he has. */ fprintf(stderr, "%d file descriptors were allocated, (%d were requested).\n", getdtablesize(), dtablesize); #endif #endif time_to_clean_up = TIME_TO_CLEAN_UP; time_to_swap = TIME_TO_SWAP; max_cost = MAX_COST; reserved_size = RESERVED_SIZE; max_array_size = MAX_ARRAY_SIZE; max_buffer_size = MAX_BUFFER_SIZE; max_string_length = MAX_STRING_LENGTH; master_file_name = (char *) MASTER_FILE; /* fix the filename */ while (*master_file_name == '/') master_file_name++; p = master_file_name; while (*p++); if (p[-2]=='c' && p[-3]=='.') p[-3]=0; mud_lib = (char *) MUD_LIB; set_inc_list(INCLUDE_DIRS); if (reserved_size > 0) reserved_area = (char *) DMALLOC(reserved_size, TAG_RESERVED, "main.c: reserved_area"); for (i = 0; i < sizeof consts / sizeof consts[0]; i++) consts[i] = exp(-i / 900.0); init_num_args(); reset_machine(1); /* * The flags are parsed twice ! The first time, we only search for the -m * flag, which specifies another mudlib, and the D-flags, so that they * will be available when compiling master.c. */ for (i = 1; i < argc; i++) { if (argv[i][0] != '-') continue; switch (argv[i][1]) { case 'D': if (argv[i][2]) { /* Amylaar : allow flags to be passed down to * the LPC preprocessor */ struct lpc_predef_s *tmp; tmp = &predefs; tmp->flag = argv[i] + 2; tmp->next = lpc_predefs; lpc_predefs = tmp; continue; } fprintf(stderr, "Illegal flag syntax: %s\n", argv[i]); exit(-1); case 'N': no_ip_demon++; continue; #ifdef YYDEBUG case 'y': yydebug = 1; continue; #endif /* YYDEBUG */ case 'm': mud_lib = alloc_cstring(argv[i] + 2, "mudlib dir"); if (chdir(mud_lib) == -1) { fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib); exit(-1); } new_mudlib = 1; break; } } if (!new_mudlib && chdir(mud_lib) == -1) { fprintf(stderr, "Bad mudlib directory: %s\n", mud_lib); exit(-1); } get_version(version_buf); time(&tm); debug_message("----------------------------------------------------------------------------\n%s (%s) starting up on %s - %s\n\n", MUD_NAME, version_buf, ARCH, ctime(&tm)); #ifdef BINARIES init_binaries(argc, argv); #endif #ifdef LPC_TO_C init_lpc_to_c(); #endif add_predefines(); #ifndef NO_IP_DEMON if (!no_ip_demon && ADDR_SERVER_IP) init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT); #endif /* NO_IP_DEMON */ eval_cost = max_cost; /* needed for create() functions */ save_context(&econ); if (SETJMP(econ.context)) { debug_message("The simul_efun (%s) and master (%s) objects must be loadable.\n", SIMUL_EFUN, MASTER_FILE); exit(-1); } else { init_simul_efun(SIMUL_EFUN); init_master(MASTER_FILE); } pop_context(&econ); for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { continue; } else { /* * Look at flags. -m and -o has already been tested. */ switch (argv[i][1]) { case 'D': case 'N': case 'm': case 'y': continue; case 'f': save_context(&econ); if (SETJMP(econ.context)) { debug_message("Error while calling master::flag(\"%s\"), aborting ...", argv[i] + 2); exit(-1); } push_constant_string(argv[i] + 2); (void) apply_master_ob(APPLY_FLAG, 1); if (MudOS_is_being_shut_down) { debug_message("Shutdown by master object.\n"); exit(0); } pop_context(&econ); continue; case 'e': e_flag++; continue; case 'p': external_port[0].port = atoi(argv[i] + 2); continue; case 'd': #ifdef DEBUG d_flag++; #else debug_message("Driver must be compiled with DEBUG on to use -d.\n"); #endif case 'c': comp_flag++; continue; case 't': t_flag++; continue; default: debug_message("Unknown flag: %s\n", argv[i]); exit(-1); } } } if (MudOS_is_being_shut_down) exit(1); if (strlen(DEFAULT_FAIL_MESSAGE)) default_fail_message = DEFAULT_FAIL_MESSAGE; else default_fail_message = "What?"; #ifdef PACKAGE_MUDLIB_STATS restore_stat_files(); #endif #ifdef PACKAGE_SOCKETS init_sockets(); /* initialize efun sockets */ #endif preload_objects(e_flag); #ifdef SIGFPE signal(SIGFPE, sig_fpe); #endif #ifdef TRAP_CRASHES #ifdef SIGUSR1 signal(SIGUSR1, sig_usr1); #endif signal(SIGTERM, sig_term); signal(SIGINT, sig_int); #ifndef DEBUG #if defined(SIGABRT) && !defined(LATTICE) signal(SIGABRT, sig_abrt); #endif #ifdef SIGIOT signal(SIGIOT, sig_iot); #endif #ifdef SIGHUP signal(SIGHUP, sig_hup); #endif #ifdef SIGBUS signal(SIGBUS, sig_bus); #endif #ifndef LATTICE signal(SIGSEGV, sig_segv); signal(SIGILL, sig_ill); #endif #endif /* DEBUG */ #endif backend(); return 0; }
/* * The start_boot() in master.c is supposed to return an array of files to load. * The array returned by apply() will be freed at next call of apply(), * which means that the ref count has to be incremented to protect against * deallocation. * * The master object is asked to do the actual loading. */ void preload_objects(int eflag) { struct gdexception exception_frame; struct vector *prefiles; struct svalue *ret = NULL; volatile int ix; set_current_time(); if (setjmp(exception_frame.e_context)) { clear_state(); (void)add_message("Error in start_boot() in master_ob.\n"); exception = NULL; return; } else { exception_frame.e_exception = NULL; exception_frame.e_catch = 0; exception = &exception_frame; push_number(eflag); ret = apply_master_ob(M_START_BOOT, 1); } if ((ret == 0) || (ret->type != T_POINTER)) return; else prefiles = ret->u.vec; if ((prefiles == 0) || (prefiles->size < 1)) return; INCREF(prefiles->ref); /* Otherwise it will be freed next sapply */ ix = -1; if (setjmp(exception_frame.e_context)) { clear_state(); (void)add_message("Anomaly in the fabric of world space.\n"); } while (++ix < prefiles->size) { set_current_time(); if (s_flag) reset_mudstatus(); eval_cost = 0; push_svalue(&(prefiles->item[ix])); (void)apply_master_ob(M_PRELOAD_BOOT, 1); if (s_flag) print_mudstatus(prefiles->item[ix].u.string, eval_cost, get_millitime(), get_processtime()); tmpclean(); } free_vector(prefiles); exception = NULL; set_current_time(); }
int main(int argc, char **argv) { extern int game_is_being_shut_down; char *p; int i = 0; struct svalue *ret; extern struct svalue catch_value; extern void init_cfuns(void); struct gdexception exception_frame; (void)setlinebuf(stdout); parse_args(argc, argv); const0.type = T_NUMBER; const0.u.number = 0; const1.type = T_NUMBER; const1.u.number = 1; constempty.type = T_FUNCTION; constempty.u.func = &funcempty; funcempty.funtype = FUN_EMPTY; catch_value = const0; /* * Check that the definition of EXTRACT_UCHAR() is correct. */ p = (char *)&i; *p = -10; if (EXTRACT_UCHAR(p) != 0x100 - 10) { (void)fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in config.h.\n"); exit(1); } set_current_time(); #ifdef PROFILE_LPC set_profile_timebase(60.0); /* One minute */ #endif #if RESERVED_SIZE > 0 reserved_area = malloc(RESERVED_SIZE); #endif init_random(); init_tasks(); query_load_av(); init_num_args(); init_machine(); init_cfuns(); init_hash(); /* * Set up the signal handling. */ init_signals(); if (chdir(mudlib_path) == -1) { (void)fprintf(stderr, "Bad mudlib directory: %s\n", MUD_LIB); exit(1); } if (setjmp(exception_frame.e_context)) { clear_state(); add_message("Anomaly in the fabric of world space.\n"); } else { exception_frame.e_exception = NULL; exception_frame.e_catch = 0; exception = &exception_frame; auto_ob = 0; master_ob = 0; if ((auto_ob = load_object("secure/auto", 1, 0, 0)) != NULL) { add_ref(auto_ob, "main"); auto_ob->prog->flags |= PRAGMA_RESIDENT; } get_simul_efun(); master_ob = load_object("secure/master", 1, 0, 0); if (master_ob) { /* * Make sure master_ob is never made a dangling pointer. * Look at apply_master_ob() for more details. */ add_ref(master_ob, "main"); master_ob->prog->flags |= PRAGMA_RESIDENT; resolve_master_fkntab(); create_object(master_ob); load_parse_information(); clear_state(); } } exception = NULL; if (auto_ob == 0) { (void)fprintf(stderr, "The file secure/auto must be loadable.\n"); exit(1); } if (master_ob == 0) { (void)fprintf(stderr, "The file secure/master must be loadable.\n"); exit(1); } set_inc_list(apply_master_ob(M_DEFINE_INCLUDE_DIRS, 0)); { struct svalue* ret1; ret1 = apply_master_ob(M_PREDEF_DEFINES, 0); if (ret1 && ret1->type == T_POINTER) { int ii; for (ii = 0; ii < ret1->u.vec->size; ii++) if (ret1->u.vec->item[ii].type == T_STRING) { add_pre_define(ret1->u.vec->item[ii].u.string); } } } if (flag != NULL) { printf("Applying driver flag: %s\n", flag); push_string(flag, STRING_MSTRING); (void)apply_master_ob(M_FLAG, 1); if (game_is_being_shut_down) { (void)fprintf(stderr, "Shutdown by master object.\n"); exit(0); } } /* * See to it that the mud name is always defined in compiled files */ ret = apply_master_ob(M_GET_MUD_NAME, 0); if (ret && ret->type == T_STRING) { struct lpc_predef_s *tmp; tmp = (struct lpc_predef_s *) xalloc(sizeof(struct lpc_predef_s)); if (!tmp) fatal("xalloc failed\n"); tmp->flag = string_copy(ret->u.string); tmp->next = lpc_predefs; lpc_predefs = tmp; } ret = apply_master_ob(M_GET_VBFC_OBJECT, 0); if (ret && ret->type == T_OBJECT) { vbfc_object = ret->u.ob; INCREF(vbfc_object->ref); } else vbfc_object = 0; if (game_is_being_shut_down) exit(1); init_call_out(); preload_objects(e_flag); (void)apply_master_ob(M_FINAL_BOOT, 0); mainloop(); return 0; }
/* * Remove an interactive player immediately. */ void remove_interactive(struct interactive *ip, int link_dead) { struct object *save = command_giver; struct object *ob = ip->ob; int i; if (!ob || !(ob->interactive)) return; for (i = 0; i < MAX_PLAYERS; i++) { if (all_players[i] != ob->interactive) continue; if (ob->interactive->closing) fatal("Double call to remove_interactive()\n"); command_giver = ob; if (ob->interactive->ed_buffer) { extern void save_ed_buffer(void); /* This will call 'get_ed_buffer_save_file_name' in master_ob * If that fails(error in LPC) the closing IP will hang and * on the next read a 'fatal read on closing socket will occur' * unless we do this here before ip->closing = 1 */ (void)add_message("Saving editor buffer.\n"); save_ed_buffer(); } if (ob->interactive == NULL) return; ob->interactive->closing = 1; if (ob->interactive->snoop_by) { ob->interactive->snoop_by->snoop_on = 0; ob->interactive->snoop_by = 0; } if (ob->interactive->snoop_on) { ob->interactive->snoop_on->snoop_by = 0; ob->interactive->snoop_on = 0; } write_socket("Closing down.\n", ob); telnet_detach(ob->interactive->tp); #ifdef SUPER_SNOOP if (ob->interactive->snoop_fd >= 0) { (void)close(ob->interactive->snoop_fd); ob->interactive->snoop_fd = -1; } #endif num_player--; if (ob->interactive->input_to) { free_sentence(ob->interactive->input_to); ob->interactive->input_to = 0; } if(ob->interactive->rname) free(ob->interactive->rname); if (current_interactive == ob) current_interactive = 0; free((char *)ob->interactive); ob->interactive = 0; all_players[i] = 0; free_object(ob, "remove_interactive"); push_object(ob); push_number(link_dead); (void)apply_master_ob(M_REMOVE_INTERACTIVE,2); command_giver = save; return; } fatal("Could not find and remove player %s\n", ob->name); }
int main(int argc, char **argv) { extern int game_is_being_shut_down; int i, new_mudlib = 0; char *p; struct svalue *ret; extern struct svalue catch_value; extern void init_cfuns(void); struct gdexception exception_frame; (void)setlinebuf(stdout); const0.type = T_NUMBER; const0.u.number = 0; const1.type = T_NUMBER; const1.u.number = 1; constempty.type = T_FUNCTION; constempty.u.func = &funcempty; funcempty.funtype = FUN_EMPTY; catch_value = const0; /* * Check that the definition of EXTRACT_UCHAR() is correct. */ p = (char *)&i; *p = -10; if (EXTRACT_UCHAR(p) != 0x100 - 10) { (void)fprintf(stderr, "Bad definition of EXTRACT_UCHAR() in config.h.\n"); exit(1); } set_current_time(); #ifdef PROFILE_LPC set_profile_timebase(60.0); /* One minute */ #endif #ifdef DRAND48 srand48((long)current_time); #else #ifdef RANDOM srandom(current_time); #else #error No random generator specified!\n #endif /* RANDOM */ #endif /* DRAND48 */ #if RESERVED_SIZE > 0 reserved_area = malloc(RESERVED_SIZE); #endif init_tasks(); query_load_av(); init_num_args(); init_machine(); init_cfuns(); /* * Set up the signal handling. */ init_signals(); /* * The flags are parsed twice ! * The first time, we only search for the -m flag, which specifies * another mudlib, and the D-flags, so that they will be available * when compiling master.c. */ for (i = 1; i < argc; i++) { if (atoi(argv[i])) port_number = atoi(argv[i]); else if (argv[i][0] != '-') continue; switch(argv[i][1]) { case 'D': if (argv[i][2]) { /* Amylaar : allow flags to be passed down to the LPC preprocessor */ struct lpc_predef_s *tmp; tmp = (struct lpc_predef_s *) xalloc(sizeof(struct lpc_predef_s)); if (!tmp) fatal("xalloc failed\n"); tmp->flag = string_copy(argv[i]+2); tmp->next = lpc_predefs; lpc_predefs = tmp; continue; } (void)fprintf(stderr, "Illegal flag syntax: %s\n", argv[i]); exit(1); /* NOTREACHED */ case 'N': no_ip_demon++; continue; case 'm': if (chdir(argv[i]+2) == -1) { (void)fprintf(stderr, "Bad mudlib directory: %s\n", argv[i]+2); exit(1); } new_mudlib = 1; break; } } if (!new_mudlib && chdir(MUD_LIB) == -1) { (void)fprintf(stderr, "Bad mudlib directory: %s\n", MUD_LIB); exit(1); } if (setjmp(exception_frame.e_context)) { clear_state(); add_message("Anomaly in the fabric of world space.\n"); } else { exception_frame.e_exception = NULL; exception_frame.e_catch = 0; exception = &exception_frame; auto_ob = 0; master_ob = 0; if ((auto_ob = load_object("secure/auto", 1, 0, 0)) != NULL) { add_ref(auto_ob, "main"); auto_ob->prog->flags |= PRAGMA_RESIDENT; } get_simul_efun(); master_ob = load_object("secure/master", 1, 0, 0); if (master_ob) { /* * Make sure master_ob is never made a dangling pointer. * Look at apply_master_ob() for more details. */ add_ref(master_ob, "main"); master_ob->prog->flags |= PRAGMA_RESIDENT; resolve_master_fkntab(); create_object(master_ob); load_parse_information(); clear_state(); } } exception = NULL; if (auto_ob == 0) { (void)fprintf(stderr, "The file secure/auto must be loadable.\n"); exit(1); } if (master_ob == 0) { (void)fprintf(stderr, "The file secure/master must be loadable.\n"); exit(1); } set_inc_list(apply_master_ob(M_DEFINE_INCLUDE_DIRS, 0)); { struct svalue* ret1; ret1 = apply_master_ob(M_PREDEF_DEFINES, 0); if (ret1 && ret1->type == T_POINTER) { int ii; struct lpc_predef_s *tmp; for (ii = 0; ii < ret1->u.vec->size; ii++) if (ret1->u.vec->item[ii].type == T_STRING) { tmp = (struct lpc_predef_s *) xalloc(sizeof(struct lpc_predef_s)); tmp->flag = string_copy(ret1->u.vec->item[ii].u.string); tmp->next = lpc_predefs; lpc_predefs = tmp; } } } for (i = 1; i < argc; i++) { if (atoi(argv[i])) ; else if (argv[i][0] != '-') { (void)fprintf(stderr, "Bad argument %s\n", argv[i]); exit(1); } else { /* * Look at flags. -m has already been tested. */ switch(argv[i][1]) { case 'f': push_string(argv[i]+2, STRING_MSTRING); (void)apply_master_ob(M_FLAG, 1); if (game_is_being_shut_down) { (void)fprintf(stderr, "Shutdown by master object.\n"); exit(0); } continue; case 'e': e_flag++; continue; case 'O': warnobsoleteflag++; continue; case 'D': continue; case 'N': continue; case 'm': continue; case 'd': d_flag = atoi(argv[i] + 2); continue; case 'c': comp_flag++; continue; case 'l': unlimited++; continue; case 't': t_flag++; continue; case 'S': s_flag++; mudstatus_set(1, -1, -1); /* Statistics, default limits */ continue; case 'u': #ifdef CATCH_UDP_PORT udp_port = atoi (&argv[i][2]); #endif continue; case 'p': #ifdef SERVICE_PORT service_port = atoi (&argv[i][2]); #endif continue; case 'y': #ifdef YYDEBUG yydebug = 1; #endif continue; default: (void)fprintf(stderr, "Unknown flag: %s\n", argv[i]); exit(1); } } } /* * See to it that the mud name is always defined in compiled files */ ret = apply_master_ob(M_GET_MUD_NAME, 0); if (ret && ret->type == T_STRING) { struct lpc_predef_s *tmp; tmp = (struct lpc_predef_s *) xalloc(sizeof(struct lpc_predef_s)); if (!tmp) fatal("xalloc failed\n"); tmp->flag = string_copy(ret->u.string); tmp->next = lpc_predefs; lpc_predefs = tmp; } ret = apply_master_ob(M_GET_VBFC_OBJECT, 0); if (ret && ret->type == T_OBJECT) { vbfc_object = ret->u.ob; INCREF(vbfc_object->ref); } else vbfc_object = 0; if (game_is_being_shut_down) exit(1); if (!t_flag) init_call_out(); preload_objects(e_flag); (void)apply_master_ob(M_FINAL_BOOT, 0); mainloop(); /* backend(); */ return 0; }