mirror of
git://git.psyced.org/git/psyclpc
synced 2024-08-15 03:20:16 +00:00
832 lines
20 KiB
C
832 lines
20 KiB
C
/*
|
||
crasher: Standardversion (Menaures 07.12.01)
|
||
|
||
ANLEITUNG:
|
||
|
||
1. Bei dem Define DEBUGGER den eigenen Real-Namen angeben
|
||
|
||
2. Define VERBOSE auskommentieren, falls nicht bereits so.
|
||
VERBOSE kann genutzt werden, wenn gesicherte Dateien einen
|
||
Crash ausloesen und die genaue Zeile gesucht wird.
|
||
(VERBOSE gibt vor jedem einzelnen Aufruf momentane
|
||
Datei und Zeile per debug_message aus).
|
||
|
||
3. Wenn bereits aufgenommene Dateien existieren, das EFuns und
|
||
Values-Array NICHT modifizieren, bzw. nicht die Positionen
|
||
der einzelnen Elemente aendern - sonst werden die aufgezeichneten
|
||
Dateien unbrauchbar. Ebenso koennen nach solchen Modifikationen
|
||
aufgenommene Dateien nicht mehr von alten Versionen des Crashers
|
||
abgespielt werden.
|
||
|
||
Wer andere Values / Closures haben moechte, modifiziere die
|
||
entsprechenden Arrays, speichere den Crasher unter einem anderen
|
||
Filenamen und mache einen eindeutigen Eintrag im Header...
|
||
|
||
record:
|
||
|
||
record(file) speichert Ausfuehrungsablaeufe in Dateien namens
|
||
file_xxxx, wobei xxxx eine Durchlaufnummer ist. Das Objekt
|
||
braucht fuer diese Dateien logischerweise Schreibrecht.
|
||
|
||
Die aufgenommenen Dateien werden nach ihrer Erstellung automatisch
|
||
ausgefuehrt. Fuehrt dies zu einem Crash, kann man das ganze einfach
|
||
nochmals abspielen.
|
||
|
||
replay:
|
||
|
||
replay(file) spielt aufgenommene Dateien ab, fuehrt sie also aus.
|
||
Dies ist dazu da, um Crashes, die dieses Objekt erzeugt, zu
|
||
reproduzieren. Statt file wird file_xxxx eingelesen, wobei xxxx
|
||
eine Durchlaufnummer ist.
|
||
|
||
execute_file:
|
||
|
||
Mit execute_file(file) kann man eine Datei gezielt ausfuehren.
|
||
Dazu gibt man den echten Dateinamen der Datei an, inklusive
|
||
Durchlaufnummer.
|
||
|
||
debug_query:
|
||
|
||
Mit debug_query(file, line) kann man abfragen, was in der Datei
|
||
file in Zeile line ausgefuehrt werden wuerde - also welche
|
||
Closure mit welchen Argumenten.
|
||
|
||
Hierzu muss der eigene Name als DEBUGGER definiert sein.
|
||
|
||
debug_exec:
|
||
|
||
Mit debug_exec(file, line) wird die angegebene Zeile in der
|
||
Datei ausgefuehrt. Dadurch kann gezielt festgestellt werden,
|
||
ob der einzelne Aufruf den Crash ausgeloest hat.
|
||
|
||
|
||
Crash-Grund finden:
|
||
|
||
Bringt der Crasher den Driver zum Absturz, zunaechst den Driver
|
||
neu starten und mit execute_file das zuletzt aufgenommene File
|
||
abspielen.
|
||
|
||
Bringt das den Driver zum Crash, den gleichen Vorgang mit
|
||
aktiviertem VERBOSE wiederholen, um die Zeilennummer herauszufinden.
|
||
|
||
Hat man erst einmal die Zeilennummer, laesst sich per debug_query
|
||
herausfinden, was ausgefuehrt werden, und mit debug_exec pruefen,
|
||
ob es wirklich der Ausloeser war.
|
||
|
||
Kann der Crash auf diese Weise nicht reproduziert werden, kann man
|
||
einmal versuchen, alle aufgenommenen Dateien mit replay abzuspielen;
|
||
fuehrt das zu keinem Crash, wurde der Crash nicht durch einen
|
||
bestimmten Aufruf (oder eine bestimmte Folge selbiger) ausgeloest,
|
||
sondern hat einen anderen Grund, der genauer untersucht werden muss.
|
||
*/
|
||
|
||
|
||
|
||
#include <math.h>
|
||
|
||
#define DEBUGGER "menaures"
|
||
#include <debug.h>
|
||
|
||
// #define VERBOSE // Aktivieren, wenn man die crashausloesende Zeile sucht
|
||
|
||
#define MAX_ARGS 5
|
||
#define DELAY 4
|
||
#define ITERATIONS 1000
|
||
|
||
mixed execute;
|
||
mixed efuns;
|
||
mixed values;
|
||
mixed names;
|
||
|
||
void record(string file);
|
||
|
||
void reset_all()
|
||
{
|
||
catch(
|
||
|
||
execute = 0,
|
||
|
||
( efuns =
|
||
({
|
||
#'Name,
|
||
#'[,
|
||
#'abs,
|
||
#'abs_path,
|
||
#'acos,
|
||
#'add_action,
|
||
#'add_dot_to_msg,
|
||
// #'add_verb,
|
||
// #'add_xverb,
|
||
#'all_environment,
|
||
#'all_inventory,
|
||
#'allocate,
|
||
// #'allocate_mapping,
|
||
#'and_bits,
|
||
#'apply,
|
||
#'arr_delete,
|
||
#'asin,
|
||
// #'assoc,
|
||
#'atan,
|
||
#'atan2,
|
||
#'attach_erq_demon,
|
||
#'auto_owner_search,
|
||
#'binary_message,
|
||
#'bind_lambda,
|
||
// #'break_point,
|
||
#'call_other,
|
||
#'call_out,
|
||
#'call_out_info,
|
||
#'call_resolved,
|
||
#'caller_stack,
|
||
#'caller_stack_depth,
|
||
#'capitalize,
|
||
#'cat,
|
||
#'catch,
|
||
#'ceil,
|
||
#'center,
|
||
#'clear_bit,
|
||
#'clock,
|
||
#'clone_object,
|
||
#'clonep,
|
||
// #'clones,
|
||
#'closurep,
|
||
#'command,
|
||
#'command_stack,
|
||
#'command_stack_depth,
|
||
#'cond_present,
|
||
#'convert_message,
|
||
#'convert_umlaute,
|
||
#'copies,
|
||
#'copy,
|
||
#'copy_bits,
|
||
#'copy_file,
|
||
// #'copy_mapping,
|
||
#'cos,
|
||
#'count_bits,
|
||
#'crypt,
|
||
#'ctime,
|
||
// #'db_affected_rows,
|
||
// #'db_close,
|
||
// #'db_coldefs,
|
||
// #'db_connect,
|
||
// #'db_conv_string,
|
||
// #'db_error,
|
||
// #'db_exec,
|
||
// #'db_fetch,
|
||
// #'db_handles,
|
||
// #'db_insert_id,
|
||
#'debug_info,
|
||
#'debug_message,
|
||
#'deep_copy,
|
||
#'deep_inventory,
|
||
#'deep_present,
|
||
#'dein,
|
||
#'deinem,
|
||
#'deinen,
|
||
#'deines,
|
||
#'dem,
|
||
#'den,
|
||
#'der,
|
||
#'des,
|
||
#'destruct,
|
||
#'diesem,
|
||
#'diesen,
|
||
#'dieser,
|
||
#'dieses,
|
||
#'disable_commands,
|
||
#'domain2map,
|
||
#'ed,
|
||
// #'efun308,
|
||
#'ein,
|
||
#'einem,
|
||
#'einen,
|
||
#'eines,
|
||
#'enable_commands,
|
||
#'environment,
|
||
#'er,
|
||
#'exec,
|
||
#'execute_command,
|
||
#'exp,
|
||
#'expand_define,
|
||
#'explode,
|
||
#'export_uid,
|
||
#'extern_call,
|
||
// #'extract,
|
||
// #'file_name,
|
||
#'file_path,
|
||
#'file_size,
|
||
#'file_time,
|
||
#'filter,
|
||
// #'filter_array,
|
||
#'filter_indices,
|
||
// #'filter_mapping,
|
||
#'filter_objects,
|
||
#'find_call_out,
|
||
#'find_living,
|
||
#'find_object,
|
||
#'find_player,
|
||
#'first_inventory,
|
||
#'floatp,
|
||
#'floor,
|
||
#'format_seconds,
|
||
#'format_vseconds,
|
||
#'funcall,
|
||
#'function_exists,
|
||
#'functionlist,
|
||
#'garbage_collection,
|
||
#'get_align_string,
|
||
#'get_dir,
|
||
#'get_error_file,
|
||
#'get_eval_cost,
|
||
#'get_extra_wizinfo,
|
||
#'get_genitiv,
|
||
#'get_type_info,
|
||
#'get_unique_string,
|
||
#'geteuid,
|
||
#'getuid,
|
||
#'gmtime,
|
||
#'heart_beat_info,
|
||
#'ihm,
|
||
#'ihn,
|
||
#'ihr,
|
||
#'ihrem,
|
||
#'ihren,
|
||
#'ihres,
|
||
#'implode,
|
||
#'inherit_list,
|
||
#'input_to,
|
||
// #'insert_alist,
|
||
#'interactive,
|
||
// #'intersect_alist,
|
||
#'intp,
|
||
#'invert_bits,
|
||
#'ist,
|
||
#'lambda,
|
||
#'last_bit,
|
||
#'last_instructions,
|
||
#'left,
|
||
#'limited,
|
||
#'liste,
|
||
#'living,
|
||
#'load_name,
|
||
#'load_object,
|
||
#'localtime,
|
||
#'log,
|
||
#'log_file,
|
||
#'lower_case,
|
||
#'m_allocate,
|
||
#'m_contains,
|
||
#'m_delete,
|
||
#'m_indices,
|
||
#'m_reallocate,
|
||
// #'m_sizeof,
|
||
#'m_values,
|
||
#'make_shared_string,
|
||
#'map,
|
||
#'map2domain,
|
||
// #'map_array,
|
||
#'map_indices,
|
||
// #'map_mapping,
|
||
#'map_object,
|
||
#'map_objects,
|
||
// #'mapping_contains,
|
||
#'mappingp,
|
||
#'max,
|
||
#'md5,
|
||
#'member,
|
||
// #'member_array,
|
||
#'min,
|
||
#'mixed2str,
|
||
#'mixed_to_closure,
|
||
#'mkdir,
|
||
#'mkmapping,
|
||
#'move_object,
|
||
#'negate,
|
||
#'next_bit,
|
||
#'next_inventory,
|
||
#'not_alone,
|
||
#'notify_fail,
|
||
#'object_info,
|
||
#'object_name,
|
||
#'object_time,
|
||
#'objectp,
|
||
#'or_bits,
|
||
// #'order_alist,
|
||
#'parse_com,
|
||
#'parse_com_error,
|
||
#'parse_com_error_string,
|
||
#'player_exists,
|
||
#'player_present,
|
||
#'playerp,
|
||
#'plural,
|
||
#'pointerp,
|
||
#'pol2xy,
|
||
#'pow,
|
||
#'present,
|
||
#'present_clone,
|
||
#'previous_object,
|
||
#'printf,
|
||
#'process_string,
|
||
#'program_name,
|
||
#'program_time,
|
||
#'query_actions,
|
||
// #'query_akkusativ,
|
||
#'query_command,
|
||
// #'query_dativ,
|
||
#'query_deklin,
|
||
#'query_deklin_adjektiv,
|
||
#'query_deklin_ein_adjektiv,
|
||
#'query_deklin_name,
|
||
// #'query_dekliniert,
|
||
#'query_editing,
|
||
// #'query_genitiv,
|
||
#'query_idle,
|
||
// #'query_imp_port,
|
||
#'query_input_pending,
|
||
#'query_ip_name,
|
||
#'query_ip_number,
|
||
#'query_limits,
|
||
#'query_living_name,
|
||
#'query_livings,
|
||
#'query_load_average,
|
||
#'query_mud_port,
|
||
#'query_notify_fail,
|
||
#'query_once_interactive,
|
||
#'query_pronom,
|
||
#'query_real_player_level,
|
||
#'query_shadowing,
|
||
#'query_snoop,
|
||
#'query_udp_port,
|
||
#'query_up_time,
|
||
#'query_verb,
|
||
#'quote,
|
||
#'raise_error,
|
||
#'random,
|
||
#'read_bytes,
|
||
#'read_file,
|
||
#'real_time_diff,
|
||
#'referencep,
|
||
#'regexp,
|
||
#'regexplode,
|
||
#'regreplace,
|
||
#'remove_action,
|
||
#'remove_call_out,
|
||
#'remove_input_to,
|
||
#'remove_interactive,
|
||
#'rename,
|
||
#'rename_object,
|
||
#'replace_program,
|
||
#'restore_object,
|
||
#'restore_value,
|
||
#'right,
|
||
#'rm,
|
||
#'rmdir,
|
||
#'round,
|
||
#'rusage,
|
||
#'save_object,
|
||
#'save_value,
|
||
#'say,
|
||
#'search_object,
|
||
#'sein,
|
||
#'seinem,
|
||
#'seinen,
|
||
#'seines,
|
||
#'send_erq,
|
||
// #'send_imp,
|
||
#'send_udp,
|
||
// #'set_auto_include_string,
|
||
#'set_bit,
|
||
#'set_buffer_size,
|
||
#'set_combine_charset,
|
||
#'set_connection_charset,
|
||
#'set_driver_hook,
|
||
#'set_environment,
|
||
#'set_extra_wizinfo,
|
||
#'set_extra_wizinfo_size,
|
||
#'set_heart_beat,
|
||
#'set_is_wizard,
|
||
#'set_light,
|
||
#'set_limits,
|
||
#'set_living_name,
|
||
#'set_modify_command,
|
||
#'set_next_reset,
|
||
#'set_prompt,
|
||
#'set_this_object,
|
||
#'set_this_player,
|
||
#'seteuid,
|
||
#'sgn,
|
||
#'shadow,
|
||
#'short_format_seconds,
|
||
#'short_format_vseconds,
|
||
#'shorttimestr,
|
||
#'shortvtimestr,
|
||
#'shout,
|
||
#'shutdown,
|
||
#'sin,
|
||
#'sizeof,
|
||
// #'slice_array,
|
||
#'snoop,
|
||
#'sort_array,
|
||
#'space,
|
||
#'sprintf,
|
||
#'sqrt,
|
||
#'sscanf,
|
||
#'str2int,
|
||
#'string_parser,
|
||
#'stringp,
|
||
#'strip,
|
||
#'strlen,
|
||
#'strstr,
|
||
#'substr,
|
||
// #'swap,
|
||
#'symbol_function,
|
||
#'symbol_variable,
|
||
#'symbolp,
|
||
#'sys_log,
|
||
#'tail,
|
||
#'tan,
|
||
#'tell_object,
|
||
#'tell_room,
|
||
#'terminal_colour,
|
||
#'test_bit,
|
||
#'this_interactive,
|
||
#'this_object,
|
||
#'this_player,
|
||
#'throw,
|
||
#'time,
|
||
#'time_to_vtime,
|
||
#'timestr,
|
||
#'to_array,
|
||
#'to_float,
|
||
#'to_int,
|
||
#'to_object,
|
||
#'to_string,
|
||
#'touch,
|
||
#'trace,
|
||
#'traceprefix,
|
||
#'transpose_array,
|
||
#'trim,
|
||
#'typeof,
|
||
#'unbound_lambda,
|
||
#'unique_array,
|
||
#'unmkmapping,
|
||
#'unshadow,
|
||
#'upper_case,
|
||
#'users,
|
||
#'utime,
|
||
#'vclock,
|
||
#'vtime,
|
||
#'vtime_to_time,
|
||
#'vtimestr,
|
||
#'walk_mapping,
|
||
#'wem,
|
||
#'wen,
|
||
#'wer,
|
||
#'wessen,
|
||
#'widthof,
|
||
#'wizardshellp,
|
||
#'wizlist_info,
|
||
#'wrap,
|
||
#'wrap_say,
|
||
#'write,
|
||
#'write_bytes,
|
||
#'write_file,
|
||
#'xor_bits,
|
||
#'xy2pol,
|
||
|
||
#',,
|
||
#'=,
|
||
#'+=,
|
||
#'-=,
|
||
#'&=,
|
||
#'|=,
|
||
#'^=,
|
||
#'<<=,
|
||
#'>>=,
|
||
#'>>>=,
|
||
#'*=,
|
||
#'%=,
|
||
#'/=,
|
||
#'?,
|
||
#'||,
|
||
#'&&,
|
||
#'|,
|
||
#'^,
|
||
#'&,
|
||
#'==,
|
||
#'!=,
|
||
#'>,
|
||
#'>=,
|
||
#'<,
|
||
#'<=,
|
||
#'<<,
|
||
#'>>,
|
||
#'>>>,
|
||
#'+,
|
||
#'-,
|
||
#'*,
|
||
#'%,
|
||
#'/,
|
||
#'++,
|
||
#'--,
|
||
#'negate,
|
||
#'!,
|
||
#'~,
|
||
#'({,
|
||
#'([,
|
||
#'[,
|
||
#'[<,
|
||
#'[..],
|
||
#'[..<],
|
||
#'[<..],
|
||
#'[<..<],
|
||
#'[..,
|
||
#'[<..,
|
||
#'({,
|
||
#'([,
|
||
}) ),
|
||
|
||
( values =
|
||
({
|
||
/* --- Integers: --- */
|
||
0,
|
||
1,
|
||
-1,
|
||
32,
|
||
-32,
|
||
40,
|
||
-40,
|
||
29292929,
|
||
-5050211,
|
||
__INT_MAX__,
|
||
__INT_MIN__,
|
||
|
||
/* --- Floats: --- */
|
||
0.0,
|
||
0.5,
|
||
-0.5,
|
||
55.5,
|
||
-55.5,
|
||
999999999999999999999999999999999999999999999.99,
|
||
-999999999999999999999999999999999999999999999.99,
|
||
|
||
/* --- Strings: --- */
|
||
"",
|
||
"foo bar",
|
||
"%d %q %T",
|
||
"0",
|
||
"",
|
||
" ",
|
||
"_",
|
||
"^^^^^^",
|
||
"#^# #^#",
|
||
" ^",
|
||
"^ ",
|
||
" - - - - ",
|
||
"? ? ? ? ? ? ????? ???? ??",
|
||
"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",
|
||
"\\/ "*32,
|
||
" !"*42,
|
||
|
||
/* --- Objekte: --- */
|
||
touch("/obj/fackel"),
|
||
touch("/obj/rucksack"),
|
||
touch("/obj/rope"),
|
||
touch("/secure/master"),
|
||
clone_object("/obj/schiff"),
|
||
clone_object("/obj/player"),
|
||
clone_object("/obj/tisch"),
|
||
|
||
/* --- Closures: --- */
|
||
(: :),
|
||
(: (: 1 :) :),
|
||
#'sizeof,
|
||
#'garbage_collection,
|
||
symbol_function("query_long", touch("/i/item")),
|
||
lambda( ({'x, 'y}), ({#'?, ({#'>, 'x, 'y}), 'x, 'y}) ),
|
||
unbound_lambda( ({'x}), ({#'==, 0, 'x}) ),
|
||
|
||
/* --- Arrays: --- */
|
||
({ }),
|
||
({ 0 }),
|
||
({ "" }),
|
||
({ ({ }) }),
|
||
({ ([ ]) }),
|
||
allocate(3000),
|
||
|
||
/* --- Mappings: --- */
|
||
([ ]),
|
||
([ (: :) ]),
|
||
m_allocate(5,5),
|
||
mkmapping(allocate(30), allocate(30, ({})), allocate(30, (:1:))),
|
||
|
||
}) )
|
||
|
||
); // catch
|
||
|
||
if(pointerp(values)) {
|
||
values += ({0,0,0});
|
||
|
||
apply((: values[<3] = $1 :), &execute);
|
||
apply((: values[<2] = $1 :), &values);
|
||
apply((: values[<1] = $1 :), &efuns);
|
||
}
|
||
while(remove_call_out("execute_file") != -1);
|
||
while(remove_call_out("do_replay") != -1);
|
||
while(remove_call_out("do_record") != -1);
|
||
|
||
seteuid(getuid());
|
||
}
|
||
|
||
int execute_file(string file)
|
||
{
|
||
int line;
|
||
string str;
|
||
mixed restore;
|
||
|
||
if(!stringp(file) || file_size(file) <= 0)
|
||
{
|
||
DEBUG("ERROR: Cannot execute "+file+": Invalid file.");
|
||
return 0;
|
||
}
|
||
|
||
DEBUG("Executing: "+file);
|
||
|
||
for(line = 0; (str=read_file(file, line, 2)) && strlen(str); line += 2)
|
||
{
|
||
restore = restore_value(str);
|
||
|
||
rm("/save/crash/LAST_EXEC");
|
||
write_file("/save/crash/LAST_EXEC",
|
||
save_value( ({file, line}) ));
|
||
|
||
#ifdef VERBOSE
|
||
debug_message("File: "+file+" Line: "+line+"\n");
|
||
#endif
|
||
debug_message(sprintf("REPLAY: %O %O -> %O %O\n", restore[0], restore[1], efuns[ restore[0] ], map( restore[1], (: values[$1] :) )));
|
||
|
||
catch(
|
||
apply( efuns[ restore[0] ],
|
||
map( restore[1], (: values[$1] :) ) )
|
||
);
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
mixed query_values() { return values; }
|
||
|
||
int generate_file(string file)
|
||
{
|
||
int i, h, efun_index, * value_index;
|
||
|
||
if(!stringp(file) || !write_file(file, ""))
|
||
{
|
||
DEBUG("ERROR: Cannot write file: "+file);
|
||
debug_message(wrap("ERROR: Cannot write file: "+file));
|
||
|
||
seteuid(getuid());
|
||
|
||
record("/save/crash/"+(mixed2str(utime())-"({,})"));
|
||
|
||
return 0;
|
||
}
|
||
|
||
DEBUG("Recording: "+file);
|
||
|
||
for(i = ITERATIONS; i--; )
|
||
{
|
||
efun_index = random(sizeof(efuns));
|
||
value_index = ({});
|
||
|
||
for(h = random(MAX_ARGS+1); h--; )
|
||
{
|
||
value_index += ({ random(sizeof(values)) });
|
||
}
|
||
|
||
write_file(file, save_value( ({efun_index, value_index}) ));
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
void replay(string file)
|
||
{
|
||
if (!file)
|
||
{
|
||
file = names[0];
|
||
names = names[1..];
|
||
}
|
||
DEBUG("Stopping all actions and starting REPLAY for: "+file);
|
||
|
||
reset_all();
|
||
|
||
execute = ({ #'call_out, "do_replay", DELAY, file, 1 });
|
||
|
||
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
|
||
set_next_reset(DELAY);
|
||
}
|
||
|
||
static void do_replay(string file, int number)
|
||
{
|
||
if(execute_file(file + right(number, 5, "_0000")))
|
||
{
|
||
call_out("do_replay", DELAY, file, number+1);
|
||
}
|
||
else call_out("replay", DELAY, 0);
|
||
}
|
||
|
||
void record(string file)
|
||
{
|
||
DEBUG("Stopping all actions and starting RECORD for: "+file);
|
||
|
||
reset_all();
|
||
|
||
execute = ({ #'call_out, "do_record", DELAY, file, 1 });
|
||
|
||
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
|
||
set_next_reset(DELAY);
|
||
}
|
||
|
||
static void do_record(string file, int number)
|
||
{
|
||
if(generate_file(file+right(number, 5, "_0000")))
|
||
{
|
||
call_out("execute_file", DELAY, file+right(number, 5, "_0000"));
|
||
call_out("do_record", DELAY*2, file, number+1);
|
||
}
|
||
}
|
||
|
||
void reset()
|
||
{
|
||
// Um this_player etc. loszuwerden einen Reset-Hack ;o)
|
||
if(execute)
|
||
{
|
||
apply(execute[0], execute[1..]);
|
||
execute = 0;
|
||
}
|
||
}
|
||
|
||
void debug_query(string file, int line)
|
||
{
|
||
mixed restore;
|
||
|
||
restore = restore_value(read_file(file, line, 2));
|
||
|
||
rm("/save/crash/TEMP");
|
||
write_file("/save/crash/TEMP",
|
||
sprintf("apply( %Q, %Q )", efuns[ restore[0] ],
|
||
map(restore[1], (: values[$1] :))));
|
||
|
||
({this_player()})->more("/save/crash/TEMP");
|
||
}
|
||
|
||
void debug_exec(string file, int line)
|
||
{
|
||
mixed restore;
|
||
|
||
restore = restore_value(read_file(file, line, 2));
|
||
|
||
catch(
|
||
apply( efuns[ restore[0] ], map(restore[1], (: values[$1] :)))
|
||
);
|
||
}
|
||
|
||
void create()
|
||
{
|
||
string str;
|
||
mixed strs;
|
||
|
||
reset_all();
|
||
|
||
str = read_file("/save/crash/LAST_EXEC");
|
||
|
||
if(str)
|
||
{
|
||
catch( apply( #'debug_query, restore_value(str) ),
|
||
write_file("/save/crash/CRASHERS",
|
||
"-"*80 + "\n"
|
||
+ read_file("/save/crash/TEMP")+ "\n" ) );
|
||
}
|
||
|
||
#if 0
|
||
strs = get_dir("/save/crash/1*");
|
||
|
||
foreach(str : strs)
|
||
{
|
||
rm("/save/crash/"+str);
|
||
}
|
||
#endif
|
||
|
||
#if 1
|
||
call_out("record", 4, "/save/crash/"+(mixed2str(utime())-"({,})"));
|
||
#else
|
||
names = ({
|
||
"/save/crash/crash1"
|
||
});
|
||
call_out("replay", 4, 0);
|
||
#endif
|
||
}
|
||
|
||
/* --- End of file. --- */
|