void handle_read(struct request *req, int val){ aiob *aio = req->aio; close(aio->aio_fildes); if(val){ FREE(aio->aio_buf); push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); return; } val = aio_return(aio); if(val < 0){ FREE(aio->aio_buf); push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); return; } char *file = new_string(val, "read_file_async: str"); memcpy(file, (char *)(aio->aio_buf), val); file[val]=0; push_malloced_string(file); FREE(aio->aio_buf); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); }
void handle_write(struct request *req){ free_svalue(&req->tmp, "handle_write"); int val = req->ret; if(val < 0){ push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); return; } push_undefined(); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); }
void handle_getdir(struct request *req, int val){ aiob *aio = req->aio; close(aio->aio_fildes); val = aio_return(aio); array_t *ret = allocate_empty_array(val); int i; if(val > -1) { struct linux_dirent *de = (struct linux_dirent *)aio->aio_buf; for(i=0; ((char *)de) - (char *)(aio->aio_buf) < val; i++) { svalue_t *vp = &(ret->item[i]); vp->type = T_STRING; vp->subtype = STRING_MALLOC; //printf("%s ", de->d_name); vp->u.string = string_copy(de->d_name, "encode_stat"); de = (struct linux_dirent *)(((char *)de) + de->d_reclen); } } ret = RESIZE_ARRAY(ret, i); ret->size = i; push_refed_array(ret); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); }
void handle_getdir(struct request *req){ int val = req->ret; if(val>MAX_ARRAY_SIZE) val = MAX_ARRAY_SIZE; array_t *ret = allocate_empty_array(val); int i=0; if(val > 0) { struct linux_dirent *de = (struct linux_dirent *)req->buf; for(i=0; i<MAX_ARRAY_SIZE && ((char *)de) - (char *)(req->buf) < val; i++) { svalue_t *vp = &(ret->item[i]); vp->type = T_STRING; vp->subtype = STRING_MALLOC; vp->u.string = string_copy(de->d_name, "encode_stat"); de = (struct linux_dirent *)(((char *)de) + de->d_reclen); } } ret = resize_array(ret, i); ret->size = i; push_refed_array(ret); FREE((void *)req->buf); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); }
void handle_read(struct request *req){ int val = req->ret; if(val < 0){ FREE((void *)req->buf); push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); return; } char *file = new_string(val, "read_file_async: str"); memcpy(file, (char *)(req->buf), val); file[val]=0; push_malloced_string(file); FREE((void *)req->buf); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); }
orcaData parserParser::eval(orcaVM* vm, const string& src)/*{{{*/ { set_eval(true); //printf(">>> eval: %s\n", src.c_str()); curr_fp = fmemopen((void*)src.c_str(), src.size(), "r"); // init parserCode::init(); parserCode::push_code_stack((char*)"eval", NULL); code_top->init_current(); // parse int rv; try { init(); try { rv = yyparse(); } catch(const char* cp) { printf("%s\n", cp); rv = -1; } if (rv == 0) { code_top->push_char(OP_RETURN); code_top->eval(vm); } if (!is<TYPE_NIL>(g_last_pop_stack)) { parserCode::init(); set_eval(false); return g_last_pop_stack; } } catch(orcaException& e) { printf("uncaugted exception: %s %s\n", e.who(), e.what()); cout << e.m_stack_trace << endl; } parserCode::init(); set_eval(false); return NIL; }
void handle_db_exec(struct request *req){ free_svalue(&req->tmp, "handle_db_exec"); int val = req->ret; if(val == -1){ copy_and_push_string(req->path); } else push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); }
void handle_write(struct request *req, int val){ aiob *aio = req->aio; close(aio->aio_fildes); free_svalue(&req->tmp, "handle_write"); if(val){ push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); return; } val = aio_return(aio); if(val < 0){ push_number(val); set_eval(max_cost); safe_call_efun_callback(req->fun, 1); return; } push_undefined(); set_eval(max_cost); safe_call_efun_callback(req->fun, 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() */
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; }
void backend() { struct timeval timeout; int i, nb; volatile int first_call = 1; int there_is_a_port = 0; error_context_t econ; debug_message("Initializations complete.\n\n"); for (i = 0; i < 5; i++) { if (external_port[i].port) { debug_message("Accepting connections on port %d.\n", external_port[i].port); there_is_a_port = 1; } } if (!there_is_a_port) debug_message("No external ports specified.\n"); init_user_conn(); /* initialize user connection socket */ #ifdef SIGHUP signal(SIGHUP, startshutdownMudOS); #endif clear_state(); save_context(&econ); if (SETJMP(econ.context)) restore_context(&econ); if (!t_flag && first_call) { first_call = 0; call_heart_beat(); } while (1) { /* Has to be cleared if we jumped out of process_user_command() */ current_interactive = 0; set_eval(max_cost); if (obj_list_replace || obj_list_destruct) remove_destructed_objects(); /* * shut down MudOS if MudOS_is_being_shut_down is set. */ if (MudOS_is_being_shut_down) shutdownMudOS(0); if (slow_shut_down_to_do) { int tmp = slow_shut_down_to_do; slow_shut_down_to_do = 0; slow_shut_down(tmp); } /* * select */ make_selectmasks(); timeout.tv_sec = 1; timeout.tv_usec = 0; #ifndef hpux nb = select(FD_SETSIZE, &readmask, &writemask, (fd_set *) 0, &timeout); #else nb = select(FD_SETSIZE, (int *) &readmask, (int *) &writemask, (int *) 0, &timeout); #endif /* * process I/O if necessary. */ if (nb > 0) { process_io(); } /* * process user commands. */ for (i = 0; process_user_command() && i < max_users; i++) ; /* * call outs */ call_out(); #ifdef PACKAGE_ASYNC check_reqs(); #endif } } /* backend() */
void call_heart_beat() { object_t *ob; heart_beat_t *curr_hb; error_context_t econ; current_interactive = 0; if ((num_hb_to_do = num_hb_objs)) { num_hb_calls++; heart_beat_index = 0; save_context(&econ); while (1) { ob = (curr_hb = &heart_beats[heart_beat_index])->ob; DEBUG_CHECK(!(ob->flags & O_HEART_BEAT), "Heartbeat not set in object on heartbeat list!"); /* is it time to do a heart beat ? */ curr_hb->heart_beat_ticks--; if (ob->prog->heart_beat != 0) { if (curr_hb->heart_beat_ticks < 1) { object_t *new_command_giver; curr_hb->heart_beat_ticks = curr_hb->time_to_heart_beat; current_heart_beat = ob; new_command_giver = ob; #ifndef NO_SHADOWS while (new_command_giver->shadowing) new_command_giver = new_command_giver->shadowing; #endif #ifndef NO_ADD_ACTION if (!(new_command_giver->flags & O_ENABLE_COMMANDS)) new_command_giver = 0; #endif #ifdef PACKAGE_MUDLIB_STATS add_heart_beats(&ob->stats, 1); #endif set_eval(max_cost); if (SETJMP(econ.context)) { restore_context(&econ); } else { save_command_giver(new_command_giver); call_direct(ob, ob->prog->heart_beat - 1, ORIGIN_DRIVER, 0); pop_stack(); /* pop the return value */ restore_command_giver(); } current_object = 0; } } if (++heart_beat_index == num_hb_to_do) break; } pop_context(&econ); if (heart_beat_index < num_hb_to_do) perc_hb_probes = 100 * (float) heart_beat_index / num_hb_to_do; else perc_hb_probes = 100.0; heart_beat_index = num_hb_to_do = 0; } current_prog = 0; current_heart_beat = 0; look_for_objects_to_swap(); #ifdef PACKAGE_MUDLIB_STATS mudlib_stats_decay(); #endif } /* call_heart_beat() */
/* * Despite the name, this routine takes care of several things. * It will run once every 15 minutes. * * . It will attempt to reconnect to the address server if the connection has * been lost. * . It will loop through all objects. * * . If an object is found in a state of not having done reset, and the * delay to next reset has passed, then reset() will be done. * * . If the object has a existed more than the time limit given for swapping, * then 'clean_up' will first be called in the object * * There are some problems if the object self-destructs in clean_up, so * special care has to be taken of how the linked list is used. */ static void look_for_objects_to_swap() { static int next_time; #ifndef NO_IP_DEMON extern int no_ip_demon; static int next_server_time; #endif object_t *ob; VOLATILE object_t *next_ob; error_context_t econ; #ifndef NO_IP_DEMON if (current_time >= next_server_time) { /* initialize the address server. if it is already initialized, then * this is a nop. this will cause the driver to reattempt connecting * to the address server once every 15 minutes in the event that it * has gone down. */ if (!no_ip_demon && next_server_time) init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT); next_server_time = current_time + 15 * 60; } #endif if (current_time < next_time) return; /* Not time to look yet */ next_time = current_time + 5 * 60; /* Next time is in 5 minutes */ /* * Objects object can be destructed, which means that next object to * investigate is saved in next_ob. If very unlucky, that object can be * destructed too. In that case, the loop is simply restarted. */ next_ob = obj_list; save_context(&econ); if (SETJMP(econ.context)) restore_context(&econ); while ((ob = (object_t *)next_ob)) { int ready_for_clean_up = 0; if (ob->flags & O_DESTRUCTED) ob = obj_list; /* restart */ next_ob = ob->next_all; /* * Check reference time before reset() is called. */ if (current_time - ob->time_of_ref > time_to_clean_up) ready_for_clean_up = 1; #if !defined(NO_RESETS) && !defined(LAZY_RESETS) /* * Should this object have reset(1) called ? */ if ((ob->flags & O_WILL_RESET) && (ob->next_reset < current_time) && !(ob->flags & O_RESET_STATE)) { debug(d_flag, ("RESET /%s\n", ob->obname)); set_eval(max_cost); reset_object(ob); if(ob->flags & O_DESTRUCTED) continue; } #endif if (time_to_clean_up > 0) { /* * Has enough time passed, to give the object a chance to * self-destruct ? Save the O_RESET_STATE, which will be cleared. * * Only call clean_up in objects that has defined such a function. * * Only if the clean_up returns a non-zero value, will it be called * again. */ if (ready_for_clean_up && (ob->flags & O_WILL_CLEAN_UP)) { int save_reset_state = ob->flags & O_RESET_STATE; svalue_t *svp; debug(d_flag, ("clean up /%s\n", ob->obname)); /* * Supply a flag to the object that says if this program is * inherited by other objects. Cloned objects might as well * believe they are not inherited. Swapped objects will not * have a ref count > 1 (and will have an invalid ob->prog * pointer). * * Note that if it is in the apply_low cache, it will also * get a flag of 1, which may cause the mudlib not to clean * up the object. This isn't bad because: * (1) one expects it is rare for objects that have untouched * long enough to clean_up to still be in the cache, especially * on busy MUDs. * (2) the ones that are are the more heavily used ones, so * keeping them around seems justified. */ push_number(ob->flags & (O_CLONE) ? 0 : ob->prog->ref); set_eval(max_cost); svp = apply(APPLY_CLEAN_UP, ob, 1, ORIGIN_DRIVER); if (ob->flags & O_DESTRUCTED) continue; if (!svp || (svp->type == T_NUMBER && svp->u.number == 0)) ob->flags &= ~O_WILL_CLEAN_UP; ob->flags |= save_reset_state; } } } pop_context(&econ); } /* look_for_objects_to_swap() */