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; }
struct svalue * debug_command(char *debcmd, int argc, struct svalue *argv) { static struct svalue retval; int dbnum, dbi, il; char buff[200]; for (dbi = -1, dbnum = 0; debc[dbnum]; dbnum++) { if (strcmp(debcmd, debc[dbnum]) == 0) dbi = dbnum; } if (dbi < 0) { retval.type = T_NUMBER; retval.u.number = 0; return &retval; } switch (dbi) { case 0: /* index */ retval.type = T_POINTER; retval.u.vec = allocate_array(dbnum); for (il = 0; il < dbnum; il++) { retval.u.vec->item[il].type = T_STRING; retval.u.vec->item[il].string_type = STRING_CSTRING; retval.u.vec->item[il].u.string = debc[il]; } return &retval; case 1: /* malloc */ retval.type = T_STRING; retval.string_type = STRING_MSTRING; retval.u.string = make_mstring((char *)dump_malloc_data()); return &retval; case 2: /* status */ case 3: /* status tables */ retval.type = T_STRING; retval.string_type = STRING_MSTRING; retval.u.string = (char *)get_gamedriver_info(debc[dbi]); return &retval; case 4: /* mudstatus on/off eval_lim time_lim */ if (argc < 3 || argv[0].type != T_STRING || argv[1].type != T_NUMBER || argv[2].type != T_NUMBER) break; if (strcmp(argv[0].u.string, "on") == 0) mudstatus_set(1, argv[1].u.number, argv[2].u.number); else if (strcmp(argv[0].u.string, "off") == 0) mudstatus_set(0, argv[1].u.number, argv[2].u.number); else break; retval.type = T_NUMBER; retval.u.number = 1; return &retval; case 5: /* functionlist object */ if (argc < 1 || argv[0].type != T_OBJECT) break; retval.type = T_POINTER; retval.u.vec = allocate_array(argv[0].u.ob->prog->num_functions); for (il = 0; il < (int)argv[0].u.ob->prog->num_functions; il++) { retval.u.vec->item[il].type = T_STRING; retval.u.vec->item[il].string_type = STRING_SSTRING; retval.u.vec->item[il].u.string = reference_sstring(argv[0].u.ob->prog->functions[il].name); } return &retval; case 6: /* rusage */ { #ifdef RUSAGE /* Only defined if we compile GD with RUSAGE */ char buff[500]; struct rusage rus; long utime, stime; long maxrss; if (getrusage(RUSAGE_SELF, &rus) < 0) buff[0] = 0; else { utime = rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000; stime = rus.ru_stime.tv_sec * 1000 + rus.ru_stime.tv_usec / 1000; maxrss = rus.ru_maxrss; (void)sprintf(buff, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld", utime, stime, maxrss, rus.ru_ixrss, rus.ru_idrss, rus.ru_isrss, rus.ru_minflt, rus.ru_majflt, rus.ru_nswap, rus.ru_inblock, rus.ru_oublock, rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); } retval.type = T_STRING; retval.string_type = STRING_MSTRING; retval.u.string = make_mstring(buff); return &retval; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with RUSAGE flag.\n"; return &retval; #endif } #if defined(PROFILE_LPC) case 7: /* top_ten_cpu */ { #define NUMBER_OF_TOP_TEN 100 struct program *p[NUMBER_OF_TOP_TEN]; struct vector *v; struct program *prog; int i, j; for(i = 0; i < NUMBER_OF_TOP_TEN; i++) p[i] = (struct program *)0L; prog = prog_list; do { for(i = NUMBER_OF_TOP_TEN-1; i >= 0; i--) { if ( p[i] && (prog->cpu <= p[i]->cpu)) break; } if (i < (NUMBER_OF_TOP_TEN - 1)) for (j = 0; j <= i; j++) if (strcmp(p[j]->name,prog->name) == 0) { i = NUMBER_OF_TOP_TEN-1; break; } if (i < (NUMBER_OF_TOP_TEN - 1)) { j = NUMBER_OF_TOP_TEN - 2; while(j > i) { p[j + 1] = p[j]; j--; } p[i + 1] = prog; } } while (prog_list != (prog = prog->next_all)); v = make_cpu_array(NUMBER_OF_TOP_TEN, p); if (v) { retval.type = T_POINTER; retval.u.vec = v; return &retval; } break; #undef NUMBER_OF_TOP_TEN } #else case 7: retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC flag.\n"; return &retval; #endif case 8: /* object_cpu object */ { long long c_num; if (argc && (argv[0].type == T_OBJECT)) { #if defined(PROFILE_LPC) c_num = argv[0].u.ob->prog->cpu * 1e6; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC flag.\n"; return &retval; #endif } else { #ifdef RUSAGE struct rusage rus; if (getrusage(RUSAGE_SELF, &rus) < 0) { c_num = -1; } else { c_num = (long long)rus.ru_utime.tv_sec * 1000000 + rus.ru_utime.tv_usec + (long long)rus.ru_stime.tv_sec * 1000000 + rus.ru_stime.tv_usec; } #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with RUSAGE flag.\n"; return &retval; #endif } retval.type = T_NUMBER; retval.u.number = c_num; return &retval; } case 9: /* swap, object */ #if 0 /* can not swap while executing */ if (argc && (argv[0].type == T_OBJECT)) (void)swap(argv[0].u.ob); #endif retval = const1; return &retval; case 10: /* version, */ { char buff[64]; (void)snprintf(buff, sizeof(buff), "%6.6s%02d %s %s", GAME_VERSION, PATCH_LEVEL, __DATE__, __TIME__); retval.type = T_STRING; retval.string_type = STRING_MSTRING; retval.u.string = make_mstring(buff); return &retval; } case 11: /* wizlist, wizname */ /* * Prints information, will be changed */ retval = const1; return &retval; case 12: /* trace, bitmask */ { int ot = -1; extern struct object *current_interactive; if (current_interactive && current_interactive->interactive) { if (argc && (argv[0].type == T_NUMBER)) { ot = current_interactive->interactive->trace_level; current_interactive->interactive->trace_level = argv[0].u.number; } } retval.type = T_NUMBER; retval.u.number = ot; return &retval; } case 13: /* traceprefix, pathstart */ { char *old = 0; extern struct object *current_interactive; if (current_interactive && current_interactive->interactive) { if (argc) { old = current_interactive->interactive->trace_prefix; if (argv[0].type == T_STRING) { current_interactive->interactive->trace_prefix = make_sstring(argv[0].u.string); } else current_interactive->interactive->trace_prefix = 0; } } if (old) { retval.type = T_STRING; retval.string_type = STRING_SSTRING; retval.u.string = old; } else retval = const0; return &retval; } case 14: /* call_out_info, */ { extern struct vector *get_calls(struct object *); if (argv[0].type != T_OBJECT) break; retval.type = T_POINTER; retval.u.vec = get_calls(argv[0].u.ob); return &retval; } case 15: /* inherit_list, object */ if (argc && (argv[0].type == T_OBJECT)) { retval.type = T_POINTER; retval.u.vec = inherit_list(argv[0].u.ob); return &retval; } else { retval = const0; return &retval; } case 16: /* load_average, */ retval.type = T_STRING; retval.string_type = STRING_MSTRING; retval.u.string = make_mstring(query_load_av()); return &retval; case 17: /* shutdown, */ startshutdowngame(0); retval = const1; return &retval; case 18: /* "object_info", num object */ { struct object *ob; char db_buff[1024], tdb[200]; int i; if (argc < 2 || argv[0].type != T_NUMBER || argv[1].type != T_OBJECT) break; if (argv[0].u.number == 0) { int flags; struct object *obj2; if ( argv[1].type != T_OBJECT) break; ob = argv[1].u.ob; flags = ob->flags; (void)sprintf(db_buff,"O_ENABLE_COMMANDS : %s\nO_CLONE : %s\nO_DESTRUCTED : %s\nO_SWAPPED : %s\nO_ONCE_INTERACTIVE: %s\nO_CREATED : %s\n", flags&O_ENABLE_COMMANDS ?"TRUE":"FALSE", flags&O_CLONE ?"TRUE":"FALSE", flags&O_DESTRUCTED ?"TRUE":"FALSE", flags&O_SWAPPED ?"TRUE":"FALSE", flags&O_ONCE_INTERACTIVE?"TRUE":"FALSE", flags&O_CREATED ?"TRUE":"FALSE"); (void)sprintf(tdb,"time_of_ref : %d\n", ob->time_of_ref); (void)strcat(db_buff, tdb); (void)sprintf(tdb,"ref : %d\n", ob->ref); (void)strcat(db_buff, tdb); #ifdef DEBUG (void)sprintf(tdb,"extra_ref : %d\n", ob->extra_ref); (void)strcat(db_buff, tdb); #endif (void)sprintf(tdb,"swap_num : %d\n", ob->swap_num); (void)strcat(db_buff, tdb); (void)snprintf(tdb, sizeof(tdb), "name : '%s'\n", ob->name); (void)strcat(db_buff, tdb); (void)snprintf(tdb, sizeof(tdb), "next_all : OBJ(%s)\n", ob->next_all?ob->next_all->name: "NULL"); (void)strcat(db_buff, tdb); if (obj_list == ob) { (void)strcat(db_buff, "This object is the head of the object list.\n"); } obj2 = obj_list; i = 1; do if (obj2->next_all == ob) { (void)snprintf(tdb, sizeof(tdb), "Previous object in object list: OBJ(%s)\n", obj2->name); (void)strcat(db_buff, tdb); (void)sprintf(tdb, "position in object list:%d\n",i); (void)strcat(db_buff, tdb); } while (obj_list != (obj2 = obj2->next_all)); } else if (argv[0].u.number == 1) { if (argv[1].type != T_OBJECT) break; ob = argv[1].u.ob; (void)sprintf(db_buff,"program ref's %d\n", ob->prog->ref); (void)snprintf(tdb, sizeof(tdb), "Name %s\n", ob->prog->name); (void)strcat(db_buff, tdb); (void)sprintf(tdb,"program size %d\n", ob->prog->program_size); (void)strcat(db_buff, tdb); (void)sprintf(tdb, "num func's %u (%u) \n", ob->prog->num_functions ,ob->prog->num_functions * (unsigned) sizeof(struct function)); (void)strcat(db_buff, tdb); (void)sprintf(tdb,"sizeof rodata %d\n", ob->prog->rodata_size); (void)strcat(db_buff, tdb); (void)sprintf(tdb,"num vars %u (%u)\n", ob->prog->num_variables ,ob->prog->num_variables * (unsigned) sizeof(struct variable)); (void)strcat(db_buff, tdb); (void)sprintf(tdb,"num inherits %u (%u)\n", ob->prog->num_inherited ,ob->prog->num_inherited * (unsigned) sizeof(struct inherit)); (void)strcat(db_buff, tdb); (void)sprintf(tdb,"total size %d\n", ob->prog->total_size); (void)strcat(db_buff, tdb); } else { (void)sprintf(db_buff, "Bad number argument to object_info: %lld\n", argv[0].u.number); } retval.type = T_STRING; retval.string_type = STRING_MSTRING; retval.u.string = make_mstring(db_buff); return &retval; } case 19: /* opcdump, 19 */ { #ifdef OPCPROF opcdump(); retval = const1; return &retval; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with OPCPROF flag.\n"; return &retval; #endif } case 20: /* send_udp, 20 host, port, msg */ { #ifdef CATCH_UDP_PORT extern udpsvc_t *udpsvc; #endif if (argc < 3 || argv[0].type != T_STRING || argv[1].type != T_NUMBER || argv[2].type != T_STRING) break; #ifdef CATCH_UDP_PORT tmp = udpsvc_send(udpsvc, argv[0].u.string, argv[1].u.number, argv[2].u.string); if (tmp) retval = const1; else #endif retval = const0; return &retval; } case 21: /* mud_port, 21 */ { extern int port_number; retval.type = T_NUMBER; retval.u.number = port_number; return &retval; } case 22: /* udp_port, 22 */ { #ifdef CATCH_UDP_PORT extern int udp_port; retval.u.number = udp_port; #else retval.u.number = -1; #endif retval.type = T_NUMBER; return &retval; } case 23: /* set_wizard, object */ if (argc && (argv[0].type == T_OBJECT)) { retval = const1; return &retval; } else { retval = const0; return &retval; } case 24: /* ob_flags, 24 ob */ { if (argc && (argv[0].type == T_OBJECT)) { retval.type = T_NUMBER; retval.u.number = argv[0].u.ob->flags; return &retval; } retval = const0; return &retval; } case 25: /* get_variables, 25 object NULL/string */ { struct svalue get_variables(struct object *); struct svalue get_variable(struct object *, char *); switch (argc) { case 1: if ( argv[0].type != T_OBJECT) { retval = const0; return &retval; } retval = get_variables(argv[0].u.ob); return &retval; case 2: if ( argv[0].type != T_OBJECT || argv[1].type != T_STRING) { retval = const0; return &retval; } retval = get_variable(argv[0].u.ob, argv[1].u.string); return &retval; case 3: if ( argv[0].type == T_OBJECT && argv[1].type == T_STRING) { retval = get_variable(argv[0].u.ob, argv[1].u.string); return &retval; } if ( argv[0].type == T_OBJECT) { retval = get_variables(argv[0].u.ob); return &retval; } retval = const0; return &retval; default: retval = const0; return &retval; } } case 26: /* get_eval_cost, 26 */ { extern int eval_cost; retval.type = T_NUMBER; retval.u.number = eval_cost; return &retval; } case 27: /* debug malloc, 27 */ { retval = const1; return &retval; } case 28: /* getprofile, 28 object */ { int format = 0; #ifndef PROFILE_LPC retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC flag.\n"; return &retval; #else if (argc < 1 || argv[0].type != T_OBJECT) break; if (argc >= 2 && argv[1].type == T_NUMBER) format = argv[1].u.number; if (format == 0) { retval.type = T_POINTER; retval.u.vec = allocate_array(argv[0].u.ob->prog->num_functions); for (il = 0; il < (int)argv[0].u.ob->prog->num_functions; il++) { (void)snprintf(buff, sizeof(buff), "%016lld:%020lld: %s", (long long)argv[0].u.ob->prog->functions[il].num_calls, (long long)(argv[0].u.ob->prog->functions[il].time_spent * 1e6), argv[0].u.ob->prog->functions[il].name); retval.u.vec->item[il].type = T_STRING; retval.u.vec->item[il].string_type = STRING_MSTRING; retval.u.vec->item[il].u.string = make_mstring(buff); } } else if (format == 1) { retval.type = T_POINTER; retval.u.vec = allocate_array(argv[0].u.ob->prog->num_functions); double now = current_cpu(); struct program *prog = argv[0].u.ob->prog; for (il = 0; il < (int)prog->num_functions; il++) { struct function *func = prog->functions + il; struct vector *res = allocate_array(7); update_func_profile(func, now, 0.0, 0.0, 0); res->item[0].type = T_STRING; res->item[0].string_type = STRING_MSTRING; res->item[0].u.string = make_mstring(func->name); res->item[1].type = T_FLOAT; res->item[1].u.real = func->time_spent * 1e6; res->item[2].type = T_FLOAT; res->item[2].u.real = func->tot_time_spent * 1e6; res->item[3].type = T_FLOAT; res->item[3].u.real = func->num_calls; res->item[4].type = T_FLOAT; res->item[4].u.real = func->avg_time * 1e6; res->item[5].type = T_FLOAT; res->item[5].u.real = func->avg_tot_time * 1e6; res->item[6].type = T_FLOAT; res->item[6].u.real = func->avg_calls; retval.u.vec->item[il].type = T_POINTER; retval.u.vec->item[il].u.vec = res; } } else { retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Unknown format.\n"; } return &retval; #endif } case 29: /* get_avg_response, 29 */ { extern int get_msecs_response(int); extern int msr_point; int sum, num, tmp; if (msr_point >=0) { sum = 0; num = 0; for (il = 0; il < 100; il++) { if ((tmp = get_msecs_response(il)) >=0) { sum += tmp; num++; } } retval.type = T_NUMBER; retval.u.number = (num > 0) ? sum / num : 0; return &retval; } break; } case 30: /* destruct, 30 */ case 31: /* destroy, 31 */ { extern void destruct_object(struct object *); if (argc && argv[0].type == T_OBJECT && !(argv[0].u.ob->flags & O_DESTRUCTED)) destruct_object(argv[0].u.ob); break; } case 32: /* update snoops, 31 */ #ifdef SUPER_SNOOP update_snoop_file(); #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with SUPER_SNOOP flag.\n"; #endif break; case 33: /* call_warnings, int 0 = off, 1 = on */ if (argc && (argv[0].type == T_STRING)) { if (strcmp(argv[0].u.string, "on") == 0) call_warnings++; else call_warnings = call_warnings > 0 ? call_warnings - 1 : 0; retval.type = T_NUMBER; retval.u.number = call_warnings; return &retval; } else { retval.type = T_NUMBER; retval.u.number = -1; return &retval; } case 34: /* dump objects */ { FILE *ufile; struct object *ob; if ((ufile = fopen(OBJECT_DUMP_FILE, "w")) == NULL) { retval.type = T_NUMBER; retval.u.number = -1; return &retval; } fputs("Array (size), Mapping (size), String (size), Objs, Ints, Floats, Inventory, Callouts, Environment, Name\n", ufile); ob = obj_list; do { mem_variables(ufile, ob); } while (obj_list != (ob = ob->next_all)); (void)fclose(ufile); break; } case 35: /* query_debug_ob */ if (!argc || argv[0].type != T_OBJECT) break; retval.type = T_NUMBER; retval.u.number = argv[0].u.ob->debug_flags; return &retval; case 36: /* set_debug_ob */ if (!argc || argv[0].type != T_OBJECT || argv[1].type != T_NUMBER) break; retval.type = T_NUMBER; retval.u.number = argv[0].u.ob->debug_flags; argv[0].u.ob->debug_flags = argv[1].u.number; return &retval; case 37: /* set_swap */ retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Obsolete function.\n"; return &retval; case 38: /* query_swap */ retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Obsolete function.\n"; return &retval; case 39: /* query_debug_prog */ if (!argc || argv[0].type != T_OBJECT) break; retval.type = T_NUMBER; retval.u.number = argv[0].u.ob->prog->debug_flags; return &retval; case 40: /* set_debug_prog */ if (argc < 2 || argv[0].type != T_OBJECT || argv[1].type != T_NUMBER) break; retval.type = T_NUMBER; retval.u.number = argv[0].u.ob->prog->debug_flags; argv[0].u.ob->prog->debug_flags = argv[1].u.number; return &retval; #ifdef FUNCDEBUG case 41: dumpfuncs(); retval = const0; return &retval; #endif case 42: /* inhibitcallouts */ if (argc && (argv[0].type == T_STRING)) { extern int inhibitcallouts; int old; old = inhibitcallouts; if (strcmp(argv[0].u.string, "on") == 0) inhibitcallouts = 1; else inhibitcallouts = 0; retval.type = T_NUMBER; retval.u.number = old; return &retval; } else { retval.type = T_NUMBER; retval.u.number = -1; return &retval; } case 43: /* inhibitcallouts */ if (argc && (argv[0].type == T_STRING)) { extern int warnobsoleteflag; int old; old = warnobsoleteflag; if (strcmp(argv[0].u.string, "on") == 0) warnobsoleteflag = 1; else warnobsoleteflag = 0; retval.type = T_NUMBER; retval.u.number = old; return &retval; } else { retval.type = T_NUMBER; retval.u.number = -1; return &retval; } case 44: /* shared_strings */ #ifdef DEBUG dump_sstrings(); retval = const0; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with DEBUG flag.\n"; #endif return &retval; case 45: /* dump_alarms */ { int c; FILE *ufile; if ((ufile = fopen(ALARM_DUMP_FILE, "w")) == NULL) { retval.type = T_NUMBER; retval.u.number = -1; return &retval; } c = dump_callouts(ufile); fclose(ufile); retval.type = T_NUMBER; retval.u.number = c; return &retval; } #ifdef PROFILE_LPC case 46: /* top_ten_cpu */ { #define NUMBER_OF_TOP_TEN 100 struct program *p[NUMBER_OF_TOP_TEN]; struct program *prog; struct vector *v; int i, j; double now = current_cpu(); for(i = 0; i < NUMBER_OF_TOP_TEN; i++) p[i] = (struct program *)0L; prog = prog_list; do { update_prog_profile(prog, now, 0.0, 0.0); for(i = NUMBER_OF_TOP_TEN-1; i >= 0; i--) { if ( p[i] && (prog->cpu_avg <= p[i]->cpu_avg)) break; } if (i < (NUMBER_OF_TOP_TEN - 1)) for (j = 0; j <= i; j++) if (strcmp(p[j]->name,prog->name) == 0) { i = NUMBER_OF_TOP_TEN-1; break; } if (i < (NUMBER_OF_TOP_TEN - 1)) { j = NUMBER_OF_TOP_TEN - 2; while(j > i) { p[j + 1] = p[j]; j--; } p[i + 1] = prog; } } while (prog_list != (prog = prog->next_all)); v = make_cpu_array2(NUMBER_OF_TOP_TEN, p); if (v) { retval.type = T_POINTER; retval.u.vec = v; return &retval; } break; #undef NUMBER_OF_TOP_TEN } #else case 46: retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC flag.\n"; return &retval; #endif case 47: /* object_cpu_avg object */ { #if defined(PROFILE_LPC) if (argc < 1 || (argv[0].type != T_OBJECT)) break; update_prog_profile(argv[0].u.ob->prog, current_cpu(), 0.0, 0.0); retval.type = T_FLOAT; retval.u.number =argv[0].u.ob->prog->cpu_avg * 1e6; return &retval; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC flag.\n"; return &retval; #endif } case 48: /* getprofile_avg, 28 object */ { #if defined(PROFILE_LPC) if (argc < 1 || argv[0].type != T_OBJECT) break; retval.type = T_POINTER; retval.u.vec = allocate_array(argv[0].u.ob->prog->num_functions); double now = current_cpu(); struct program *prog = argv[0].u.ob->prog; for (il = 0; il < (int)prog->num_functions; il++) { struct function *func = prog->functions + il; struct vector *res = allocate_array(3); update_func_profile(func, now, 0.0, 0.0, 0); res->item[0].type = T_STRING; res->item[0].string_type = STRING_MSTRING; res->item[0].u.string = make_mstring(func->name); res->item[1].type = T_FLOAT; res->item[1].u.real = func->avg_time * 1e6; res->item[2].type = T_FLOAT; res->item[2].u.real = func->avg_calls; retval.u.vec->item[il].type = T_POINTER; retval.u.vec->item[il].u.vec = res; } return &retval; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC flag.\n"; return &retval; #endif } case 49: /* profile_timebase */ { #if defined(PROFILE_LPC) if (argc < 1) { /* Return current value */ retval.type = T_FLOAT; retval.u.real = get_profile_timebase(); return &retval; } /* Update using old timebase */ double now = current_cpu(); struct program *prog = prog_list; do { update_prog_profile(prog, now, 0.0, 0.0); for (int i = 0; i < prog->num_functions; i++) { struct function *func = prog->functions + i; update_func_profile(func, now, 0.0, 0.0, 0); } } while (prog_list != (prog = prog->next_all)); /* Set the new value */ if (argv[0].type == T_NUMBER && argv[0].u.number > 0) set_profile_timebase(argv[0].u.number); else if (argv[0].type == T_FLOAT && argv[0].u.real > 1e-3) set_profile_timebase(argv[0].u.real); else break; retval = const1; return &retval; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC flag.\n"; return &retval; #endif } case 50: { #ifdef PROFILE_LPC extern int trace_calls; extern FILE *trace_calls_file; if (argc < 1 || argv[0].type != T_NUMBER) break; if (!trace_calls && argv[0].u.number) { if ((trace_calls_file = fopen(TRACE_CALLS_FILE, "w")) == 0) break; setvbuf(trace_calls_file, 0, _IOFBF, 1<<20); /* Set a 1MB buffer */ trace_calls = 1; } else if (trace_calls && !argv[0].u.number) { fclose(trace_calls_file); trace_calls_file = 0; trace_calls = 0; } retval = const1; return &retval; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC.\n"; return &retval; #endif } case 51: { #if defined(PROFILE_LPC) long long num_top, criteria, num_items = 0; double now = current_cpu(), crit_val; struct program *prog; struct { struct program *prog; double crit_val; unsigned short func_index; } *result; if (argc < 2 || argv[0].type != T_NUMBER || argv[1].type != T_NUMBER) break; num_top = argv[0].u.number; criteria = argv[1].u.number; if (num_top < 0 || num_top > 1000) { retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "The number of itmes must be >= 0 and <= 1000."; break; } if (criteria < 0 || criteria > 9) { retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "The criteria must be >= 0 and <= 9."; break; } if (num_top == 0) { retval.type = T_POINTER; retval.u.vec = allocate_array(0); return &retval; } result = xalloc(sizeof(*result) * (num_top + 1)); memset(result, 0, sizeof(*result) * (num_top + 1)); prog = prog_list; do { update_prog_profile(prog, now, 0.0, 0.0); for (int i = 0; i < prog->num_functions; i++) { struct function *func = prog->functions + i; update_func_profile(func, now, 0.0, 0.0, 0); crit_val = get_top_func_criteria(func, criteria); if (num_items == num_top && result[num_items - 1].crit_val >= crit_val) continue; if (num_items == 0 || (num_items < num_top && result[num_items - 1].crit_val >= crit_val)) { result[num_items].prog = prog; result[num_items].func_index = i; result[num_items].crit_val = crit_val; num_items++; } else { int insert = num_items; while (insert > 0 && result[insert - 1].crit_val < crit_val) insert--; memmove(&result[insert + 1], &result[insert], sizeof(*result) * (num_items - insert)); result[insert].prog = prog; result[insert].func_index = i; result[insert].crit_val = crit_val; if (num_items < num_top) num_items++; } } } while ((prog = prog->next_all) != prog_list); retval.type = T_POINTER; retval.u.vec = allocate_array(num_items); for (int i = 0; i < num_items; i++) { struct vector *val = allocate_array(9); prog = result[i].prog; struct function *func = &prog->functions[result[i].func_index]; crit_val = result[i].crit_val; val->item[0].type = T_STRING; val->item[0].string_type = STRING_MSTRING; val->item[0].u.string = make_mstring(prog->name); val->item[1].type = T_STRING; val->item[1].string_type = STRING_SSTRING; val->item[1].u.string = func->name; reference_sstring(func->name); val->item[2].type = T_FLOAT; val->item[2].u.real = crit_val; val->item[3].type = T_FLOAT; val->item[3].u.real = func->time_spent; val->item[4].type = T_FLOAT; val->item[4].u.real = func->avg_time; val->item[5].type = T_FLOAT; val->item[5].u.real = func->tot_time_spent; val->item[6].type = T_FLOAT; val->item[6].u.real = func->avg_tot_time; val->item[7].type = T_FLOAT; val->item[7].u.real = func->num_calls; val->item[8].type = T_FLOAT; val->item[8].u.real = func->avg_calls; retval.u.vec->item[i].type = T_POINTER; retval.u.vec->item[i].u.vec = val; } free(result); return &retval; #else retval.type = T_STRING; retval.string_type = STRING_CSTRING; retval.u.string = "Only valid if GD compiled with PROFILE_LPC.\n"; return &retval; #endif } } retval = const0; return &retval; }
void parse_args(int argc, char **argv) { int ch; while ((ch = getopt(argc, argv, "h?m:p:t:u:f:d:D:OeclNSy")) != -1) { switch (ch) { case 'm': mudlib_path = strdup(optarg); break; case 't': port_number = atoi(optarg); break; case 'u': #ifdef CATCH_UDP_PORT udp_port = atoi(optarg); #endif break; case 'p': #ifdef SERVICE_PORT service_port = atoi(optarg); #endif break; case 'f': flag = strdup(optarg); continue; case 'e': e_flag++; continue; case 'D': add_pre_define(optarg); continue; case 'O': warnobsoleteflag++; continue; case 'd': d_flag = atoi(optarg); continue; case 'c': comp_flag++; continue; case 'l': unlimited++; continue; case 'N': no_ip_demon++; continue; case 'S': s_flag++; mudstatus_set(1, -1, -1); /* Statistics, default limits */ continue; case 'y': #ifdef YYDEBUG yydebug = 1; #endif default: case '?': usage(argc, argv); break; } } }