diff --git a/src/64bitmalloc.c b/src/64bitmalloc.c index 8941e7975..672eecbb6 100644 --- a/src/64bitmalloc.c +++ b/src/64bitmalloc.c @@ -51,7 +51,7 @@ void *malloc64(int size){ if(size < blocksize){ if(!freelist){ res = (unsigned long *)mmap(where, size+sizeof(long),MAP_FIXED|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); - if(res != where){ + if((char *)res != where){ perror("mmap failed! (55)"); printf("where = %lx\n", where); res = (unsigned long *)malloc(size+sizeof(long)); @@ -77,7 +77,7 @@ void *malloc64(int size){ int thissize = size / 4096; thissize++; res = (unsigned long *)mmap(where, size+sizeof(long),MAP_FIXED|PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); - if(res != where) + if((char *)res != where) perror("mmap failed! (72)"); where += (thissize*4096); } diff --git a/src/ChangeLog.fluffos-2.x b/src/ChangeLog.fluffos-2.x index ede6032e6..954ef9935 100644 --- a/src/ChangeLog.fluffos-2.x +++ b/src/ChangeLog.fluffos-2.x @@ -2,6 +2,72 @@ As MudOS is moving too slow to keep our driver hacks apart, we now call our own FluffOS :), note: where it says Cratylus, I got it from his version, usually someone else did the work, but I don't know how to find who did what there. +FluffOS 2.27 +Fixed Changelog name for 2.26 +fix incorrect sha1() hashes (Voltara ) +Fix db.c with PACKAGE_ASYNC. (mactorg@lpmuds.net) +allow floating point for heart beat interval +added extra file:linenumber result for call_stack(4) +fix call_other type errors as warnings and some timezone leaking bugs (driver timezone would be changed after efun/error in efun) +Fix a valgrind complain in posix_timer.c (Yucong Sun ) +Testsuit fixes. (Yucong Sun ) +compile with C99 (Yucong Sun ) +Unbreak DEBUG_MALLOC & CHECK_MEMORY, now everything is accounted for. (Yucong Sun ) +Crypto package multiple fixes and enhancements (Voltara ) +Code cleanup/fixes (Yucong Sun ) +LPC MIN_INT, MAX_FLOAT, MIN_FLOAT predefines. (Yucong Sun ) +Added POSIX_TIMERS alternative for eval timer (Voltara ) +IPV6 compile fix on unbuntu. (Yucong Sun ) + +FluffOS 2.26 +Compile warning fixes (sunyc@lpmuds.net) +add_action moved objects fix (vorpal@lpmuds.net) +Properly report 64 bit linux when starting (sunyc@lpmuds.net) +heart_beat() now sets current_interactive +Changes for C99 (sunyc@lpmuds.net) +GMCP telnet negotiation now following the correct protocol, probably +Websocket support, add a port in the config file with type websocket, when it + gets a connection on that it will ask the master object for a + connection as usual, this object will need to do the websocket + handshake, incoming data will go to process_input(), after finishing + the handshake call websocket_handshake_done(), after calling that it + will act like a normal user connection on the mud side, the other side + is a binary websocket. I suggest you change to the normal login object + after the handshake. +Added a break at the end of mssp activation to stop it from turning on mccp as + well +Stop skipping next user input when we get user input (no idea why that was + there) + (vorpal@lpmuds.net) +Several LPC stack fixes (sunyc@lpmuds.net) +Added several missing type checks (sunyc@lpmuds.net) +Fixed wrong int/long variable types, this includes fixing sha1, so if you used + that for passwords on 64bit, you'll need to figure out how to get + around sha1 results changing.(sunyc@lpmuds.net, me (with suggestions from + (vorpal@lpmuds.net))) +sizeof now returns an actual number (reported by vorpal@lpmuds.net) +Fixed crasher in local_time() (sunyc@lpmuds.net) +Overflow improvement on eval_cost calculation (sunyc@lpmuds.net) +Stop reading past the end of the read data in read_file() +Fixed possible crasher in using floats +Fixed crasher in call_other type warnings (sunyc@lpmuds.net) +Several testsuite improvements (sunyc@lpmuds.net) +Added GCmalloc (sunyc@lpmuds.net) +Mapping fix for 32bit +Fixed crasher in f_unique_mapping (reported by sunyc@lpmuds.net) +options.h fixes (sunyc@lpmuds.net, me) +Added placeholder for now missing old binary config (sunyc@lpmuds.net) +File closing fix for compressed files (sunyc@lpmuds.net) +Fixed zonetime crasher (sunyc@lpmuds.net) +Fixed is_daylight_savings_time crasher (sunyc@lpmuds.net) +Fixed remove_get_char crasher (reported by sunyc@lpmuds.net) + +FluffOS 2.25 +Fixed the defer() fix +Added new test_load() efun which will try to load a file, it will return 0 when + it failed, 1 when the file can load, and error if there was a compilation + error + FluffOS 2.24 LPC floats are now C doubles number of structs (or classes) allowed is now 127 diff --git a/src/GNUmakefile.in b/src/GNUmakefile.in index 35397ab9f..9c6a55a36 100644 --- a/src/GNUmakefile.in +++ b/src/GNUmakefile.in @@ -58,7 +58,8 @@ SRC=grammar.tab.c lex.c main.c rc.c interpret.c simulate.c file.c object.c \ socket_efuns.c socket_ctrl.c qsort.c eoperators.c socket_err.c md.c \ disassembler.c uvalarm.c $(STRFUNCS) \ replace_program.c master.c function.c \ - debug.c crypt.c applies_table.c add_action.c eval.c fliconv.c console.c + debug.c crypt.c applies_table.c add_action.c eval.c fliconv.c console.c \ + posix_timers.c all: $(OBJDIR) cc.h main_build main_build2: $(DRIVER_BIN) addr_server portbind diff --git a/src/Makefile.in b/src/Makefile.in index 49efed2ad..2b82d366c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -61,7 +61,8 @@ SRC=grammar.tab.c lex.c main.c rc.c interpret.c simulate.c file.c object.c \ socket_efuns.c socket_ctrl.c qsort.c eoperators.c socket_err.c md.c \ disassembler.c uvalarm.c $(STRFUNCS) \ replace_program.c master.c function.c \ - debug.c crypt.c add_action.c eval.c fliconv.c console.c applies_table.c + debug.c crypt.c add_action.c eval.c fliconv.c console.c applies_table.c \ + posix_timers.c all: cc.h files main_build main_build2: $(DRIVER_BIN) addr_server portbind @@ -82,7 +83,8 @@ OBJ=grammar.tab.o lex.o main.o rc.o interpret.o simulate.o file.o object.o \ socket_efuns.o socket_ctrl.o qsort.o eoperators.o socket_err.o md.o \ disassembler.o uvalarm.o $(STRFUNCS) \ replace_program.o master.o function.o \ - debug.o crypt.o add_action.o eval.o fliconv.o console.o applies_table.o + debug.o crypt.o add_action.o eval.o fliconv.o console.o applies_table.o \ + posix_timers.o .c.o: $(CC) $(CFLAGS) $(OPTIMIZE) -c $*.c diff --git a/src/add_action.c b/src/add_action.c index 0e463f9ac..34eb64a3a 100644 --- a/src/add_action.c +++ b/src/add_action.c @@ -181,6 +181,8 @@ void setup_new_commands (object_t * dest, object_t * item) continue; if (ob->flags & O_DESTRUCTED) error("An object was destructed at call of " APPLY_INIT "()\n"); + if (dest != ob->super) + error("An object was moved at call of " APPLY_INIT "()\n"); if (ob->flags & O_ENABLE_COMMANDS) { save_command_giver(ob); (void) apply(APPLY_INIT, item, 0, ORIGIN_DRIVER); @@ -396,7 +398,7 @@ static int user_parser (char * buff) && !(command_giver->flags & O_IS_WIZARD) #endif ) - add_moves(&command_object->stats, 1); + add_moves(&s->ob->stats, 1); #endif if (!illegal_sentence_action) illegal_sentence_action = save_illegal_sentence_action; @@ -572,7 +574,7 @@ void remove_sent (object_t * ob, object_t * user) void f_add_action (void) { - long flag; + LPC_INT flag; if (st_num_arg == 3) { flag = (sp--)->u.number; @@ -608,12 +610,12 @@ f_add_action (void) */ void f_command (void) { - long rc = 0; + LPC_INT rc = 0; if (current_object && !(current_object->flags & O_DESTRUCTED)) { char buff[1000]; - int save_eval_cost = get_eval(); + LPC_INT save_eval_cost = get_eval(); if (SVALUE_STRLEN(sp) > sizeof(buff) - 1) error("Too long command.\n"); @@ -627,6 +629,10 @@ void f_command (void) #else rc = 1; #endif + // Make sure we at least return 1 eval cost. + if (rc <= 0) { + rc = 1; + } } free_string_svalue(sp); @@ -738,7 +744,7 @@ void f_query_verb (void) #ifdef F_REMOVE_ACTION void f_remove_action (void) { - long success; + LPC_INT success; success = remove_action((sp - 1)->u.string, sp->u.string); free_string_svalue(sp--); diff --git a/src/addr_server.c b/src/addr_server.c index ba8639c1a..b616e0fec 100644 --- a/src/addr_server.c +++ b/src/addr_server.c @@ -310,7 +310,6 @@ void new_conn_handler() struct sockaddr_in client; #endif socklen_t client_len; - struct hostent *c_hostent; int new_fd; int conn_index; @@ -561,7 +560,7 @@ int name_by_ip (int conn_index, char * buf) return 0; } char tmpbuf[80], tmpp[80]; - if(ret = getnameinfo(res->ai_addr, res->ai_addrlen, tmpbuf, 79, tmpp, 79, NI_NAMEREQD|NI_NUMERICSERV)){ + if((ret = getnameinfo(res->ai_addr, res->ai_addrlen, tmpbuf, 79, tmpp, 79, NI_NAMEREQD|NI_NUMERICSERV))){ sprintf(out_buf, "%s 0\n", &buf[sizeof(int)]); DBG(("%s", out_buf)); OS_socket_write(all_conns[conn_index].fd, out_buf, strlen(out_buf)); diff --git a/src/applies_table.c b/src/applies_table.c deleted file mode 100644 index 492683225..000000000 --- a/src/applies_table.c +++ /dev/null @@ -1,45 +0,0 @@ -/* autogenerated from 'applies' */ - -const char *applies_table[] = { - "author_file", - "compile_object", - "connect", - "crash", - "creator_file", - "domain_file", - "epilog", - "error_handler", - "get_bb_uid", - "get_save_file_name", - "get_root_uid", - "log_error", - "make_path_absolute", - "flag", - "object_name", - "parser_error_message", - "preload", - "privs_file", - "retrieve_ed_setup", - "save_ed_setup", - "slow_shutdown", - "parse_command_users", - "valid_asm", - "valid_bind", - "valid_database", - "valid_hide", - "valid_link", - "parse_command_prepos_list", - "valid_object", - "valid_override", - "parse_command_all_word", - "parse_command_prepos_list", - "valid_read", - "valid_seteuid", - "valid_shadow", - "valid_socket", - "valid_write", - "parse_get_first_inventory", - "parse_get_next_inventory", - "parse_get_environment", - "get_mud_stats", -}; diff --git a/src/arch.h b/src/arch.h index e548a271a..ad4e88c4c 100644 --- a/src/arch.h +++ b/src/arch.h @@ -92,9 +92,11 @@ #define ARCH "A/UX" #endif -#ifdef linux +#if defined(__linux__) # ifdef __mc68000 # define ARCH "Linux/m68k" +# elif defined(__x86_64) +# define ARCH "Linux/x86-64" # else # ifdef __alpha # define ARCH "Linux/alpha" diff --git a/src/array.c b/src/array.c index bb754958f..529291657 100644 --- a/src/array.c +++ b/src/array.c @@ -1250,13 +1250,9 @@ int sort_array_cmp (void *vp1, void *vp2) { if (!d || d->type != T_NUMBER) { return 0; } else { - long n = d->u.number; - //the sort functions all use int, so sometimes the numbers don't fit! - if(n) - if(n>0) - n=1; - else - n=-1; + LPC_INT n = d->u.number; + // sanitize the result. + if(n) { n = n > 0 ? 1 : -1; } return n; } } @@ -1370,28 +1366,28 @@ static void deep_inventory_collect (object_t * ob, array_t * inv, int * i, int m return; } } - if(!fp || fp && fp_result->type==T_NUMBER && fp_result->u.number>0 && !(cur->flags & O_DESTRUCTED)) { + if(!fp || (fp && fp_result->type==T_NUMBER && fp_result->u.number>0 && !(cur->flags & O_DESTRUCTED))) { #ifdef F_SET_HIDE if (cur->flags & O_HIDDEN) { if (valid_hide_flag & 2) { - if(!fp || fp && fp_result->type==T_NUMBER && fp_result->u.number!=3) { + if(!fp || (fp && fp_result->type==T_NUMBER && fp_result->u.number!=3)) { inv->item[*i].type = T_OBJECT; inv->item[*i].u.ob = cur; (*i)++; add_ref(cur, "deep_inventory_collect"); } - if(!fp || fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3)) + if(!fp || (fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3))) deep_inventory_collect(cur, inv, i, max, fp); } } else { #endif - if(!fp || fp && fp_result->type==T_NUMBER && fp_result->u.number!=3) { + if(!fp || (fp && fp_result->type==T_NUMBER && fp_result->u.number!=3)) { inv->item[*i].type = T_OBJECT; inv->item[*i].u.ob = cur; (*i)++; add_ref(cur, "deep_inventory_collect"); } - if(!fp || fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3)) + if(!fp || (fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3))) deep_inventory_collect(cur, inv, i, max, fp); #ifdef F_SET_HIDE } @@ -1439,15 +1435,15 @@ array_t *deep_inventory (object_t * ob, int take_top, funptr_t *fp) return &the_null_array; } } - if(!fp || fp && fp_result->type==T_NUMBER && fp_result->u.number>0 && - !(ob->flags & O_DESTRUCTED)) { - if(!fp || fp && fp_result->type==T_NUMBER && fp_result->u.number!=3) { + if(!fp || (fp && fp_result->type==T_NUMBER && fp_result->u.number>0 && + !(ob->flags & O_DESTRUCTED))) { + if(!fp || (fp && fp_result->type==T_NUMBER && fp_result->u.number!=3)) { dinv->item[0].type = T_OBJECT; dinv->item[0].u.ob = ob; add_ref(ob, "deep_inventory"); i=1; } - if(!fp || fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3)) + if(!fp || (fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3))) deep_inventory_collect(ob, dinv, &i, o, fp); } } @@ -1510,15 +1506,15 @@ array_t *deep_inventory_array (array_t *arr, int take_top, funptr_t *fp) return &the_null_array; } } - if(!fp || fp && fp_result->type==T_NUMBER && fp_result->u.number>0 && - !(arr->item[c].u.ob->flags & O_DESTRUCTED)) { - if(!fp || fp && fp_result->type==T_NUMBER && fp_result->u.number!=3) { + if(!fp || (fp && fp_result->type==T_NUMBER && fp_result->u.number>0 && + !(arr->item[c].u.ob->flags & O_DESTRUCTED))) { + if(!fp || (fp && fp_result->type==T_NUMBER && fp_result->u.number!=3)) { dinv->item[i].type = T_OBJECT; dinv->item[i].u.ob = arr->item[c].u.ob; add_ref(arr->item[c].u.ob, "deep_inventory"); i++; } - if(!fp || fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3)) + if(!fp || (fp && fp_result->type==T_NUMBER && (fp_result->u.number==1 || fp_result->u.number==3))) deep_inventory_collect(arr->item[c].u.ob, dinv, &i, o, fp); } } diff --git a/src/backend.c b/src/backend.c index 1b1842ee4..00cd75501 100644 --- a/src/backend.c +++ b/src/backend.c @@ -331,6 +331,7 @@ static int max_heart_beats = 0; static int heart_beat_index = 0; static int num_hb_objs = 0; static int num_hb_to_do = 0; +int time_for_hb = 0; static int num_hb_calls = 0; /* starts */ static float perc_hb_probes = 100.0; /* decaying avge of how many complete */ @@ -377,8 +378,11 @@ void call_heart_beat() restore_context(&econ); } else { save_command_giver(new_command_giver); + if(ob->interactive) //note, NOT same as new_command_giver + current_interactive = ob; call_direct(ob, ob->prog->heart_beat - 1, ORIGIN_DRIVER, 0); + current_interactive = 0; pop_stack(); /* pop the return value */ restore_command_giver(); } diff --git a/src/backend.h b/src/backend.h index c48d7a55a..de2cb0c34 100644 --- a/src/backend.h +++ b/src/backend.h @@ -15,6 +15,7 @@ extern long current_time; extern object_t *current_heart_beat; extern error_context_t *current_error_context; +extern int time_for_hb; void backend (void); void clear_state (void); diff --git a/src/build.FluffOS b/src/build.FluffOS index 71a0fbecb..6906e21ea 100755 --- a/src/build.FluffOS +++ b/src/build.FluffOS @@ -4,7 +4,7 @@ if test $# -ne 0; then case $1 in develop) echo Preparing to build developmental version of MudOS driver ... - OPTIMIZE="-Wall -Wundef -DPEDANTIC -pedantic -Wmissing-declarations" + OPTIMIZE="-Wall -Wundef -DPEDANTIC -pedantic" DEBUG="-g -DDEBUG -DDEBUG_MACRO" ;; debug) @@ -207,16 +207,20 @@ else if test "${DEBUG-x}" = "x"; then OPTIMIZE=${OPTIMIZE-"-O3"} fi - gcc -m64 comptest.c + $CC -std=c99 -D_GNU_SOURCE comptest.c if test $? -eq 0; then - CC="gcc -m64" + CC="$CC -std=c99 -D_GNU_SOURCE" fi - gcc -flto comptest.c + $CC -m64 comptest.c + if test $? -eq 0; then + CC="$CC -m64" + fi + $CC -flto comptest.c if test $? -eq 0; then CC="$CC -flto" fi - GNUC=1 - CCFLAGS=-D__USE_FIXED_PROTOTYPES__ + GNUC=1 + CCFLAGS="-D__USE_FIXED_PROTOTYPES__" else clcc comptest.c if test $? -eq 0; then @@ -381,12 +385,12 @@ END case $ARCH in AIX) OSFLAGS="$OSFLAGS -D_BSD -D_ALL_SOURCE" - CFLAGS="$CFLAGS -D_BSD -D_ALL_SOURCE" + CFLAGS="$CFLAGS -D_BSD -D_ALL_SOURCE" ;; Solaris) - OSFLAGS="$OSFLAGS -DSunOS_5" - CFLAGS="$CFLAGS -DSunOS_5" - ;; + OSFLAGS="$OSFLAGS -DSunOS_5" + CFLAGS="$CFLAGS -DSunOS_5" + ;; esac #don't use dynamic at the moment # Linux*) diff --git a/src/call_out.c b/src/call_out.c index 7d47b9197..aa0bdc190 100644 --- a/src/call_out.c +++ b/src/call_out.c @@ -20,16 +20,16 @@ #define CHUNK_SIZE 20 typedef struct pending_call_s { - int delta; - union string_or_func function; - object_t *ob; - array_t *vs; - struct pending_call_s *next; + int delta; + union string_or_func function; + object_t *ob; + array_t *vs; + struct pending_call_s *next; #ifdef THIS_PLAYER_IN_CALL_OUT - object_t *command_giver; + object_t *command_giver; #endif #ifdef CALLOUT_HANDLES - int handle; + LPC_INT handle; #endif } pending_call_t; @@ -49,116 +49,116 @@ void remove_all_call_out (object_t *); */ static void free_called_call (pending_call_t * cop) { - cop->next = call_list_free; - if (cop->ob) { - free_string(cop->function.s); - free_object(&cop->ob, "free_call"); - } else { - free_funp(cop->function.f); - } - cop->function.s = 0; + cop->next = call_list_free; + if (cop->ob) { + free_string(cop->function.s); + free_object(&cop->ob, "free_call"); + } else { + free_funp(cop->function.f); + } + cop->function.s = 0; #ifdef THIS_PLAYER_IN_CALL_OUT - if (cop->command_giver){ - free_object(&cop->command_giver, "free_call"); - cop->command_giver = 0; - } + if (cop->command_giver){ + free_object(&cop->command_giver, "free_call"); + cop->command_giver = 0; + } #endif - cop->ob = 0; - call_list_free = cop; + cop->ob = 0; + call_list_free = cop; } INLINE_STATIC void free_call (pending_call_t * cop) { - if (cop->vs) - free_array(cop->vs); - free_called_call(cop); + if (cop->vs) + free_array(cop->vs); + free_called_call(cop); } /* * Setup a new call out. */ #ifdef CALLOUT_HANDLES -int +LPC_INT #else void #endif new_call_out (object_t * ob, svalue_t * fun, int delay, - int num_args, svalue_t * arg) + int num_args, svalue_t * arg) { - pending_call_t *cop, **copp; - int tm; - - if (delay < 0) - delay = 0; - - DBG(("new_call_out: /%s delay %i", ob->obname, delay)); - - if (!call_list_free) { - int i; - - call_list_free = CALLOCATE(CHUNK_SIZE, pending_call_t, - TAG_CALL_OUT, "new_call_out: call_list_free"); - for (i = 0; i < CHUNK_SIZE - 1; i++) - call_list_free[i].next = &call_list_free[i + 1]; - call_list_free[CHUNK_SIZE - 1].next = 0; - num_call += CHUNK_SIZE; - } - cop = call_list_free; - call_list_free = call_list_free->next; - - if (fun->type == T_STRING) { - DBG((" function: %s", fun->u.string)); - cop->function.s = make_shared_string(fun->u.string); - cop->ob = ob; - add_ref(ob, "call_out"); - } else { - DBG((" function: ")); - cop->function.f = fun->u.fp; - fun->u.fp->hdr.ref++; - cop->ob = 0; - } + pending_call_t *cop, **copp; + int tm; + + if (delay < 0) + delay = 0; + + DBG(("new_call_out: /%s delay %i", ob->obname, delay)); + + if (!call_list_free) { + int i; + + call_list_free = CALLOCATE(CHUNK_SIZE, pending_call_t, + TAG_CALL_OUT, "new_call_out: call_list_free"); + for (i = 0; i < CHUNK_SIZE - 1; i++) + call_list_free[i].next = &call_list_free[i + 1]; + call_list_free[CHUNK_SIZE - 1].next = 0; + num_call += CHUNK_SIZE; + } + cop = call_list_free; + call_list_free = call_list_free->next; + + if (fun->type == T_STRING) { + DBG((" function: %s", fun->u.string)); + cop->function.s = make_shared_string(fun->u.string); + cop->ob = ob; + add_ref(ob, "call_out"); + } else { + DBG((" function: ")); + cop->function.f = fun->u.fp; + fun->u.fp->hdr.ref++; + cop->ob = 0; + } #ifdef THIS_PLAYER_IN_CALL_OUT - cop->command_giver = command_giver; /* save current user context */ - if (command_giver) - add_ref(command_giver, "new_call_out"); /* Bump its ref */ + cop->command_giver = command_giver; /* save current user context */ + if (command_giver) + add_ref(command_giver, "new_call_out"); /* Bump its ref */ #endif - if (num_args > 0) { - cop->vs = allocate_empty_array(num_args); - memcpy(cop->vs->item, arg, sizeof(svalue_t) * num_args); - } else - cop->vs = 0; - - /* Find out which slot this one fits in */ - tm = (delay + current_time) & (CALLOUT_CYCLE_SIZE - 1); - /* number of cycles */ - delay = delay / CALLOUT_CYCLE_SIZE; - - DBG(("Current time: %i Executes at: %i Slot: %i Delay: %i", - current_time, current_time + delay, tm, delay)); - - for (copp = &call_list[tm]; *copp; copp = &(*copp)->next) { - if ((*copp)->delta > delay) { - (*copp)->delta -= delay; - cop->delta = delay; - cop->next = *copp; - *copp = cop; + if (num_args > 0) { + cop->vs = allocate_empty_array(num_args); + memcpy(cop->vs->item, arg, sizeof(svalue_t) * num_args); + } else + cop->vs = 0; + + /* Find out which slot this one fits in */ + tm = (delay + current_time) & (CALLOUT_CYCLE_SIZE - 1); + /* number of cycles */ + delay = delay / CALLOUT_CYCLE_SIZE; + + DBG(("Current time: %ld Executes at: %ld Slot: %d Delay: %d", + current_time, current_time + delay, tm, delay)); + + for (copp = &call_list[tm]; *copp; copp = &(*copp)->next) { + if ((*copp)->delta > delay) { + (*copp)->delta -= delay; + cop->delta = delay; + cop->next = *copp; + *copp = cop; #ifdef CALLOUT_HANDLES - tm += CALLOUT_CYCLE_SIZE * ++unique; - cop->handle = tm; - return tm; + tm += CALLOUT_CYCLE_SIZE * ++unique; + cop->handle = tm; + return tm; #else - return; + return; #endif - } - delay -= (*copp)->delta; - } - *copp = cop; - cop->delta = delay; - cop->next = 0; + } + delay -= (*copp)->delta; + } + *copp = cop; + cop->delta = delay; + cop->next = 0; #ifdef CALLOUT_HANDLES - tm += CALLOUT_CYCLE_SIZE * ++unique; - cop->handle = tm; - return tm; + tm += CALLOUT_CYCLE_SIZE * ++unique; + cop->handle = tm; + return tm; #endif } @@ -169,139 +169,148 @@ new_call_out (object_t * ob, svalue_t * fun, int delay, */ void call_out() { - int extra, real_time; - static pending_call_t *cop = 0; - error_context_t econ; - VOLATILE int tm; - - current_interactive = 0; - - /* could be still allocated if an error occured during a call_out */ - if (cop) { - free_called_call(cop); - cop = 0; - } - - real_time = get_current_time(); - DBG(("Calling call_outs: current_time: %i real_time: %i difference: %i", - current_time, real_time, real_time - current_time)); - - /* Slowly advance the clock forward towards real_time, doing call_outs - * as we go. - */ - save_context(&econ); - while (1) { - - tm = current_time & (CALLOUT_CYCLE_SIZE - 1); - DBG((" slot %i", tm)); - while (call_list[tm] && call_list[tm]->delta == 0) { - object_t *ob, *new_command_giver; - - /* - * Move the first call_out out of the chain. - */ - cop = call_list[tm]; - call_list[tm] = call_list[tm]->next; - ob = (cop->ob ? cop->ob : cop->function.f->hdr.owner); + long extra, real_time; + static pending_call_t *cop = 0; + error_context_t econ; + VOLATILE int tm; - DBG((" /%s", (ob ? ob->obname : "(null)"))); + current_interactive = 0; - if (!ob || (ob->flags & O_DESTRUCTED)) { - DBG((" (destructed)")); - free_call(cop); - cop = 0; - } else { - if (SETJMP(econ.context)) { - restore_context(&econ); - if (max_eval_error) { - debug_message("Maximum evaluation cost reached while trying to process call_outs\n"); - pop_context(&econ); - return; - } - } else { - object_t *ob; - - ob = cop->ob; + /* could be still allocated if an error occured during a call_out */ + if (cop) { + free_called_call(cop); + cop = 0; + } + + real_time = get_current_time(); + DBG(("Calling call_outs: current_time: %ld real_time: %ld difference: %d", + current_time, real_time, real_time - current_time)); + + /* Slowly advance the clock forward towards real_time, doing call_outs + * as we go. + */ + save_context(&econ); + while (1) { + + tm = current_time & (CALLOUT_CYCLE_SIZE - 1); + DBG((" slot %i", tm)); + while (call_list[tm] && call_list[tm]->delta == 0) { + object_t *ob, *new_command_giver; + + /* + * Move the first call_out out of the chain. + */ + cop = call_list[tm]; + call_list[tm] = call_list[tm]->next; + ob = (cop->ob ? cop->ob : cop->function.f->hdr.owner); + + DBG((" /%s", (ob ? ob->obname : "(null)"))); + + if (!ob || (ob->flags & O_DESTRUCTED)) { + DBG((" (destructed)")); + free_call(cop); + cop = 0; + } else { + if (SETJMP(econ.context)) { + restore_context(&econ); + if (max_eval_error) { + debug_message("Maximum evaluation cost reached while trying to process call_outs\n"); + pop_context(&econ); + return; + } + } else { + object_t *ob; + + ob = cop->ob; #ifndef NO_SHADOWS - if (ob) - while (ob->shadowing) - ob = ob->shadowing; + if (ob) + while (ob->shadowing) + ob = ob->shadowing; #endif - new_command_giver = 0; + new_command_giver = 0; #ifdef THIS_PLAYER_IN_CALL_OUT - if (cop->command_giver && - !(cop->command_giver->flags & O_DESTRUCTED)) { - new_command_giver = cop->command_giver; - } else if (ob && (ob->flags & O_LISTENER)) { - new_command_giver = ob; - } - if (new_command_giver) - DBG((" command_giver: /%s", new_command_giver->obname)); + if (cop->command_giver && + !(cop->command_giver->flags & O_DESTRUCTED)) { + new_command_giver = cop->command_giver; + } else if (ob && (ob->flags & O_LISTENER)) { + new_command_giver = ob; + } + if (new_command_giver) + DBG((" command_giver: /%s", new_command_giver->obname)); #endif - save_command_giver(new_command_giver); - /* current object no longer set */ - - if (cop->vs) { - array_t *vec = cop->vs; - svalue_t *svp = vec->item + vec->size; - - while (svp-- > vec->item) { - if (svp->type == T_OBJECT && - (svp->u.ob->flags & O_DESTRUCTED)) { - free_object(&svp->u.ob, "call_out"); - *svp = const0u; + save_command_giver(new_command_giver); + /* current object no longer set */ + + if (cop->vs) { + array_t *vec = cop->vs; + svalue_t *svp = vec->item + vec->size; + + while (svp-- > vec->item) { + if (svp->type == T_OBJECT && + (svp->u.ob->flags & O_DESTRUCTED)) { + free_object(&svp->u.ob, "call_out"); + *svp = const0u; + } + } + /* cop->vs is ref one */ + extra = cop->vs->size; + transfer_push_some_svalues(cop->vs->item, extra); + free_empty_array(cop->vs); + } else + extra = 0; + //reset_eval_cost(); + set_eval(max_cost); + + if (cop->ob) { + if (cop->function.s[0] == APPLY___INIT_SPECIAL_CHAR) + error("Illegal function name\n"); + + (void) apply(cop->function.s, cop->ob, extra, + ORIGIN_INTERNAL); + } else { + (void) call_function_pointer(cop->function.f, extra); + } + + restore_command_giver(); + } + free_called_call(cop); + cop = 0; + } } - } - /* cop->vs is ref one */ - extra = cop->vs->size; - transfer_push_some_svalues(cop->vs->item, extra); - free_empty_array(cop->vs); - } else - extra = 0; - //reset_eval_cost(); - set_eval(max_cost); - - if (cop->ob) { - if (cop->function.s[0] == APPLY___INIT_SPECIAL_CHAR) - error("Illegal function name\n"); - - (void) apply(cop->function.s, cop->ob, extra, - ORIGIN_INTERNAL); - } else { - (void) call_function_pointer(cop->function.f, extra); - } - - restore_command_giver(); - } - free_called_call(cop); - cop = 0; + /* Ok, no more scheduled call_outs for current_time */ + if (current_time < real_time) { + /* Time marches onward! */ + if (call_list[tm]) + call_list[tm]->delta--; + current_time++; + DBG((" current_time = %ld", current_time)); +#ifndef POSIX_TIMERS + if(!(current_time%HEARTBEAT_INTERVAL)) + call_heart_beat(); +#endif + } else { + /* We're done! */ + break; + } + } + DBG(("Done.")); + pop_context(&econ); +#ifdef POSIX_TIMERS + if(time_for_hb){ + call_heart_beat(); + time_for_hb--; } - } - /* Ok, no more scheduled call_outs for current_time */ - if (current_time < real_time) { - /* Time marches onward! */ - if (call_list[tm]) - call_list[tm]->delta--; - current_time++; - DBG((" current_time = %i", current_time)); - if(!(current_time%HEARTBEAT_INTERVAL)) - call_heart_beat(); - } else { - /* We're done! */ - break; - } - } - DBG(("Done.")); - pop_context(&econ); +#endif + } static int time_left (int slot, int delay) { - int current_slot = current_time & (CALLOUT_CYCLE_SIZE - 1); - if (slot >= current_slot) { - return (slot - current_slot) + delay * CALLOUT_CYCLE_SIZE; - } else { - return (slot - current_slot) + (delay + 1) * CALLOUT_CYCLE_SIZE; - } + int current_slot = current_time & (CALLOUT_CYCLE_SIZE - 1); + if (slot >= current_slot) { + return (slot - current_slot) + delay * CALLOUT_CYCLE_SIZE; + } else { + return (slot - current_slot) + (delay + 1) * CALLOUT_CYCLE_SIZE; + } } /* @@ -311,142 +320,142 @@ static int time_left (int slot, int delay) { */ int remove_call_out (object_t * ob, const char * fun) { - pending_call_t **copp, *cop; - int delay; - int i; - - if (!ob) return -1; - - DBG(("remove_call_out: /%s \"%s\"", ob->obname, fun)); - - for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { - delay = 0; - for (copp = &call_list[i]; *copp; copp = &(*copp)->next) { - DBG((" Slot: %i\n", i)); - delay += (*copp)->delta; - if ((*copp)->ob == ob && strcmp((*copp)->function.s, fun) == 0) { - cop = *copp; - if (cop->next) - cop->next->delta += cop->delta; - *copp = cop->next; - free_call(cop); - DBG((" found.")); - return time_left(i, delay); + pending_call_t **copp, *cop; + int delay; + int i; + + if (!ob) return -1; + + DBG(("remove_call_out: /%s \"%s\"", ob->obname, fun)); + + for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { + delay = 0; + for (copp = &call_list[i]; *copp; copp = &(*copp)->next) { + DBG((" Slot: %i\n", i)); + delay += (*copp)->delta; + if ((*copp)->ob == ob && strcmp((*copp)->function.s, fun) == 0) { + cop = *copp; + if (cop->next) + cop->next->delta += cop->delta; + *copp = cop->next; + free_call(cop); + DBG((" found.")); + return time_left(i, delay); + } + } } - } - } - DBG((" not found.")); - return -1; + DBG((" not found.")); + return -1; } #ifdef CALLOUT_HANDLES -int remove_call_out_by_handle (int handle) +int remove_call_out_by_handle (LPC_INT handle) { - pending_call_t **copp, *cop; - int delay = 0; - - DBG(("remove_call_out_by_handle: handle: %i slot: %i", - handle, handle & (CALLOUT_CYCLE_SIZE - 1))); - - for (copp = &call_list[handle & (CALLOUT_CYCLE_SIZE - 1)]; *copp; copp = &(*copp)->next) { - delay += (*copp)->delta; - if ((*copp)->handle == handle) { - cop = *copp; - if (cop->next) - cop->next->delta += cop->delta; - *copp = cop->next; - free_call(cop); - return time_left(handle & (CALLOUT_CYCLE_SIZE - 1), delay); - } - } - return -1; + pending_call_t **copp, *cop; + int delay = 0; + + DBG(("remove_call_out_by_handle: handle: %i slot: %i", + handle, handle & (CALLOUT_CYCLE_SIZE - 1))); + + for (copp = &call_list[handle & (CALLOUT_CYCLE_SIZE - 1)]; *copp; copp = &(*copp)->next) { + delay += (*copp)->delta; + if ((*copp)->handle == handle) { + cop = *copp; + if (cop->next) + cop->next->delta += cop->delta; + *copp = cop->next; + free_call(cop); + return time_left(handle & (CALLOUT_CYCLE_SIZE - 1), delay); + } + } + return -1; } -int find_call_out_by_handle (int handle) +int find_call_out_by_handle (LPC_INT handle) { - pending_call_t *cop; - int delay = 0; - - DBG(("find_call_out_by_handle: handle: %i slot: %i", - handle, handle & (CALLOUT_CYCLE_SIZE - 1))); - - for (cop = call_list[handle & (CALLOUT_CYCLE_SIZE - 1)]; cop; cop = cop->next) { - delay += cop->delta; - if (cop->handle == handle) - return time_left(handle & (CALLOUT_CYCLE_SIZE - 1), delay); - } - return -1; + pending_call_t *cop; + int delay = 0; + + DBG(("find_call_out_by_handle: handle: %i slot: %i", + handle, handle & (CALLOUT_CYCLE_SIZE - 1))); + + for (cop = call_list[handle & (CALLOUT_CYCLE_SIZE - 1)]; cop; cop = cop->next) { + delay += cop->delta; + if (cop->handle == handle) + return time_left(handle & (CALLOUT_CYCLE_SIZE - 1), delay); + } + return -1; } #endif int find_call_out (object_t * ob, const char * fun) { - pending_call_t *cop; - int delay; - int i; - - if (!ob) return -1; - - DBG(("find_call_out: /%s \"%s\"", ob->obname, fun)); - - for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { - delay = 0; - DBG((" Slot: %i", i)); - for (cop = call_list[i]; cop; cop = cop->next) { - delay += cop->delta; - if (cop->ob == ob && strcmp(cop->function.s, fun) == 0) - return time_left(i, delay); - } - } - return -1; + pending_call_t *cop; + int delay; + int i; + + if (!ob) return -1; + + DBG(("find_call_out: /%s \"%s\"", ob->obname, fun)); + + for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { + delay = 0; + DBG((" Slot: %i", i)); + for (cop = call_list[i]; cop; cop = cop->next) { + delay += cop->delta; + if (cop->ob == ob && strcmp(cop->function.s, fun) == 0) + return time_left(i, delay); + } + } + return -1; } int print_call_out_usage (outbuffer_t * ob, int verbose) { - int i, j; - pending_call_t *cop; - - for (i = 0, j = 0; j < CALLOUT_CYCLE_SIZE; j++) - for (cop = call_list[j]; cop; cop = cop->next) - i++; - - if (verbose == 1) { - outbuf_add(ob, "Call out information:\n"); - outbuf_add(ob, "---------------------\n"); - outbuf_addv(ob, "Number of allocated call outs: %8d, %8d bytes\n", - num_call, num_call * sizeof(pending_call_t)); - outbuf_addv(ob, "Current length: %d\n", i); - } else { - if (verbose != -1) - outbuf_addv(ob, "call out:\t\t\t%8d %8d (current length %d)\n", num_call, - num_call * sizeof(pending_call_t), i); - } - return num_call * sizeof(pending_call_t); + int i, j; + pending_call_t *cop; + + for (i = 0, j = 0; j < CALLOUT_CYCLE_SIZE; j++) + for (cop = call_list[j]; cop; cop = cop->next) + i++; + + if (verbose == 1) { + outbuf_add(ob, "Call out information:\n"); + outbuf_add(ob, "---------------------\n"); + outbuf_addv(ob, "Number of allocated call outs: %8d, %8d bytes\n", + num_call, num_call * sizeof(pending_call_t)); + outbuf_addv(ob, "Current length: %d\n", i); + } else { + if (verbose != -1) + outbuf_addv(ob, "call out:\t\t\t%8d %8d (current length %d)\n", num_call, + num_call * sizeof(pending_call_t), i); + } + return num_call * sizeof(pending_call_t); } #ifdef DEBUGMALLOC_EXTENSIONS #ifdef DEBUG void mark_call_outs() { - pending_call_t *cop; - int i; - - for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { - for (cop = call_list[i]; cop; cop = cop->next) { - if (cop->vs) - cop->vs->extra_ref++; - if (cop->ob) { - cop->ob->extra_ref++; - EXTRA_REF(BLOCK(cop->function.s))++; - } else { - cop->function.f->hdr.extra_ref++; - } + pending_call_t *cop; + int i; + + for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { + for (cop = call_list[i]; cop; cop = cop->next) { + if (cop->vs) + cop->vs->extra_ref++; + if (cop->ob) { + cop->ob->extra_ref++; + EXTRA_REF(BLOCK(cop->function.s))++; + } else { + cop->function.f->hdr.extra_ref++; + } #ifdef THIS_PLAYER_IN_CALL_OUT - if (cop->command_giver) - cop->command_giver->extra_ref++; + if (cop->command_giver) + cop->command_giver->extra_ref++; #endif - } - } + } + } } #endif #endif @@ -459,111 +468,110 @@ void mark_call_outs() */ array_t *get_all_call_outs() { - int i, j, delay, tm; - pending_call_t *cop; - array_t *v; - - for (i = 0, j = 0; j < CALLOUT_CYCLE_SIZE; j++) - for (cop = call_list[j]; cop; cop = cop->next) { - object_t *ob = (cop->ob ? cop->ob : cop->function.f->hdr.owner); - if (ob && !(ob->flags & O_DESTRUCTED)) - i++; - } - - v = allocate_empty_array(i); - tm = current_time & (CALLOUT_CYCLE_SIZE-1); - - for (i = 0, j = 0; j < CALLOUT_CYCLE_SIZE; j++) { - delay = 0; - for (cop = call_list[j]; cop; cop = cop->next) { - array_t *vv; - object_t *ob; - - delay += cop->delta; - ob = (cop->ob ? cop->ob : cop->function.f->hdr.owner); - if (!ob || (ob->flags & O_DESTRUCTED)) - continue; - vv = allocate_empty_array(3); - if (cop->ob) { - vv->item[0].type = T_OBJECT; - vv->item[0].u.ob = cop->ob; - add_ref(cop->ob, "get_all_call_outs"); - vv->item[1].type = T_STRING; - vv->item[1].subtype = STRING_SHARED; - vv->item[1].u.string = make_shared_string(cop->function.s); - } else { - outbuffer_t tmpbuf; - svalue_t tmpval; - - tmpbuf.real_size = 0; - tmpbuf.buffer = 0; - - tmpval.type = T_FUNCTION; - tmpval.u.fp = cop->function.f; - - svalue_to_string(&tmpval, &tmpbuf, 0, 0, 0); - - vv->item[0].type = T_OBJECT; - vv->item[0].u.ob = cop->function.f->hdr.owner; - add_ref(cop->function.f->hdr.owner, "get_all_call_outs"); - vv->item[1].type = T_STRING; - vv->item[1].subtype = STRING_SHARED; - vv->item[1].u.string = make_shared_string(tmpbuf.buffer); - FREE_MSTR(tmpbuf.buffer); - } - vv->item[2].type = T_NUMBER; - vv->item[2].u.number = time_left(j, delay); - - v->item[i].type = T_ARRAY; - v->item[i++].u.arr = vv; /* Ref count is already 1 */ - } - } - return v; + int i, j, delay; + pending_call_t *cop; + array_t *v; + + for (i = 0, j = 0; j < CALLOUT_CYCLE_SIZE; j++) + for (cop = call_list[j]; cop; cop = cop->next) { + object_t *ob = (cop->ob ? cop->ob : cop->function.f->hdr.owner); + if (ob && !(ob->flags & O_DESTRUCTED)) + i++; + } + + v = allocate_empty_array(i); + + for (i = 0, j = 0; j < CALLOUT_CYCLE_SIZE; j++) { + delay = 0; + for (cop = call_list[j]; cop; cop = cop->next) { + array_t *vv; + object_t *ob; + + delay += cop->delta; + ob = (cop->ob ? cop->ob : cop->function.f->hdr.owner); + if (!ob || (ob->flags & O_DESTRUCTED)) + continue; + vv = allocate_empty_array(3); + if (cop->ob) { + vv->item[0].type = T_OBJECT; + vv->item[0].u.ob = cop->ob; + add_ref(cop->ob, "get_all_call_outs"); + vv->item[1].type = T_STRING; + vv->item[1].subtype = STRING_SHARED; + vv->item[1].u.string = make_shared_string(cop->function.s); + } else { + outbuffer_t tmpbuf; + svalue_t tmpval; + + tmpbuf.real_size = 0; + tmpbuf.buffer = 0; + + tmpval.type = T_FUNCTION; + tmpval.u.fp = cop->function.f; + + svalue_to_string(&tmpval, &tmpbuf, 0, 0, 0); + + vv->item[0].type = T_OBJECT; + vv->item[0].u.ob = cop->function.f->hdr.owner; + add_ref(cop->function.f->hdr.owner, "get_all_call_outs"); + vv->item[1].type = T_STRING; + vv->item[1].subtype = STRING_SHARED; + vv->item[1].u.string = make_shared_string(tmpbuf.buffer); + FREE_MSTR(tmpbuf.buffer); + } + vv->item[2].type = T_NUMBER; + vv->item[2].u.number = time_left(j, delay); + + v->item[i].type = T_ARRAY; + v->item[i++].u.arr = vv; /* Ref count is already 1 */ + } + } + return v; } void remove_all_call_out (object_t * obj) { - pending_call_t **copp, *cop; - int i; - - for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { - copp = &call_list[i]; - while (*copp) { - if ( ((*copp)->ob && - (((*copp)->ob == obj) || ((*copp)->ob->flags & O_DESTRUCTED))) || - (!(*copp)->ob && - ((*copp)->function.f->hdr.owner == obj || - !(*copp)->function.f->hdr.owner || - (*copp)->function.f->hdr.owner->flags & O_DESTRUCTED)) ) - { - cop = *copp; - if (cop->next) - cop->next->delta += cop->delta; - *copp = cop->next; - free_call(cop); - } else - copp = &(*copp)->next; - } - } + pending_call_t **copp, *cop; + int i; + + for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { + copp = &call_list[i]; + while (*copp) { + if ( ((*copp)->ob && + (((*copp)->ob == obj) || ((*copp)->ob->flags & O_DESTRUCTED))) || + (!(*copp)->ob && + ((*copp)->function.f->hdr.owner == obj || + !(*copp)->function.f->hdr.owner || + (*copp)->function.f->hdr.owner->flags & O_DESTRUCTED)) ) + { + cop = *copp; + if (cop->next) + cop->next->delta += cop->delta; + *copp = cop->next; + free_call(cop); + } else + copp = &(*copp)->next; + } + } } void reclaim_call_outs() { - pending_call_t *cop; - int i; + pending_call_t *cop; + int i; - remove_all_call_out(0); /* removes call_outs to destructed objects */ + remove_all_call_out(0); /* removes call_outs to destructed objects */ #ifdef THIS_PLAYER_IN_CALL_OUT - for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { - cop = call_list[i]; - while (cop) { - if (cop->command_giver && (cop->command_giver->flags & O_DESTRUCTED)) { - free_object(&cop->command_giver, "reclaim_call_outs"); - cop->command_giver = 0; - } - cop = cop->next; - } - } + for (i = 0; i < CALLOUT_CYCLE_SIZE; i++) { + cop = call_list[i]; + while (cop) { + if (cop->command_giver && (cop->command_giver->flags & O_DESTRUCTED)) { + free_object(&cop->command_giver, "reclaim_call_outs"); + cop->command_giver = 0; + } + cop = cop->next; + } + } #endif } diff --git a/src/call_out.h b/src/call_out.h index b27030b8e..cc3ec9c6c 100644 --- a/src/call_out.h +++ b/src/call_out.h @@ -9,9 +9,9 @@ void call_out (void); void reclaim_call_outs (void); #ifdef CALLOUT_HANDLES -int find_call_out_by_handle (int); -int remove_call_out_by_handle (int); -int new_call_out (object_t *, svalue_t *, int, int, svalue_t *); +int find_call_out_by_handle (LPC_INT); +int remove_call_out_by_handle (LPC_INT); +LPC_INT new_call_out (object_t *, svalue_t *, int, int, svalue_t *); #else void new_call_out (object_t *, svalue_t *, int, int, svalue_t *); #endif diff --git a/src/comm.c b/src/comm.c index 0880ede53..cd787b811 100644 --- a/src/comm.c +++ b/src/comm.c @@ -80,24 +80,24 @@ static unsigned char telnet_lm_mode[] = { IAC, SB, TELOPT_LINEMODE, LM_MO static unsigned char telnet_char_mode[] = { IAC, DONT, TELOPT_LINEMODE }; static unsigned char slc_default_flags[] = { SLC_NOSUPPORT, SLC_CANTCHANGE, SLC_CANTCHANGE, SLC_CANTCHANGE, SLC_CANTCHANGE, SLC_NOSUPPORT, - SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_CANTCHANGE, SLC_CANTCHANGE, SLC_NOSUPPORT, SLC_NOSUPPORT, - SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT }; + SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_CANTCHANGE, SLC_CANTCHANGE, SLC_NOSUPPORT, SLC_NOSUPPORT, + SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT, SLC_NOSUPPORT }; static unsigned char slc_default_chars[] = { 0x00, BREAK, IP, AO, AYT, 0x00, 0x00, 0x00, - SUSP, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 }; + SUSP, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 }; #ifdef HAVE_ZLIB static unsigned char telnet_compress_send_request_v2[] = { IAC, WILL, - TELOPT_COMPRESS2 }; + TELOPT_COMPRESS2 }; static unsigned char telnet_compress_send_request_v1[] = { IAC, WILL, - TELOPT_COMPRESS }; + TELOPT_COMPRESS }; static unsigned char telnet_compress_v1_response[] = { IAC, SB, - TELOPT_COMPRESS, WILL, - SE }; + TELOPT_COMPRESS, WILL, + SE }; static unsigned char telnet_compress_v2_response[] = { IAC, SB, - TELOPT_COMPRESS2, IAC, - SE }; + TELOPT_COMPRESS2, IAC, + SE }; #endif static unsigned char telnet_do_mxp[] = { IAC, DO, TELOPT_MXP }; @@ -110,15 +110,17 @@ static unsigned char telnet_will_zmp[] = { IAC, WILL, TELOPT_ZMP}; static unsigned char telnet_start_zmp[] = { IAC, SB, TELOPT_ZMP}; static unsigned char telnet_do_newenv[] = { IAC, DO, TELOPT_NEW_ENVIRON }; static unsigned char telnet_send_uservar[] = { IAC, SB, TELOPT_NEW_ENVIRON, NEW_ENV_SEND, IAC, SE }; -static unsigned char telnet_do_gmcp[] = {IAC, DO, TELOPT_GMCP}; +static unsigned char telnet_will_gmcp[] = {IAC, WILL, TELOPT_GMCP}; static unsigned char telnet_start_gmcp[] = {IAC, SB, TELOPT_GMCP}; /* * local function prototypes. */ +#ifndef SIG_IGN #ifdef SIGNAL_FUNC_TAKES_INT static void sigpipe_handler (int); #else -static void sigpipe_handler (void); +static void sigpipe_handler(void); +#endif #endif static void hname_handler (void); @@ -139,7 +141,7 @@ static void new_user_handler (int); static void end_compression (interactive_t *); static void start_compression (interactive_t *); static int send_compressed (interactive_t *ip, unsigned char* data, int length); - +static int flush_compressed_output (interactive_t *ip); #ifdef NO_SNOOP # define handle_snoop(str, len, who) @@ -157,10 +159,10 @@ fd_set readmask, writemask; int num_user; #ifdef F_SET_HIDE int num_hidden_users = 0; /* for the O_HIDDEN flag. This counter must - * be kept up to date at all times! If you - * modify the O_HIDDEN flag in an object, - * make sure that you update this counter if - * the object is interactive. */ + * be kept up to date at all times! If you + * modify the O_HIDDEN flag in an object, + * make sure that you update this counter if + * the object is interactive. */ #endif int add_message_calls = 0; #ifdef F_NETWORK_STATS @@ -191,41 +193,41 @@ static int addr_server_fd = -1; static void set_linemode (interactive_t * ip) { - if (ip->iflags & USING_LINEMODE) { - add_binary_message(ip->ob, telnet_line_mode, sizeof(telnet_line_mode)); - add_binary_message(ip->ob, telnet_lm_mode, sizeof(telnet_lm_mode)); - } else { - add_binary_message(ip->ob, telnet_no_single, sizeof(telnet_no_single)); - } + if (ip->iflags & USING_LINEMODE) { + add_binary_message(ip->ob, telnet_line_mode, sizeof(telnet_line_mode)); + add_binary_message(ip->ob, telnet_lm_mode, sizeof(telnet_lm_mode)); + } else { + add_binary_message(ip->ob, telnet_no_single, sizeof(telnet_no_single)); + } } static void set_charmode (interactive_t * ip) { - if (ip->iflags & USING_LINEMODE) { - add_binary_message(ip->ob, telnet_char_mode, sizeof(telnet_char_mode)); - } else { - add_binary_message(ip->ob, telnet_yes_single, sizeof(telnet_yes_single)); - } + if (ip->iflags & USING_LINEMODE) { + add_binary_message(ip->ob, telnet_char_mode, sizeof(telnet_char_mode)); + } else { + add_binary_message(ip->ob, telnet_yes_single, sizeof(telnet_yes_single)); + } } #ifndef NO_SNOOP static void receive_snoop (const char * buf, int len, object_t * snooper) { - /* command giver no longer set to snooper */ + /* command giver no longer set to snooper */ #ifdef RECEIVE_SNOOP - char *str; + char *str; - str = new_string(len, "receive_snoop"); - memcpy(str, buf, len); - str[len] = 0; - push_malloced_string(str); - apply(APPLY_RECEIVE_SNOOP, snooper, 1, ORIGIN_DRIVER); + str = new_string(len, "receive_snoop"); + memcpy(str, buf, len); + str[len] = 0; + push_malloced_string(str); + apply(APPLY_RECEIVE_SNOOP, snooper, 1, ORIGIN_DRIVER); #else - /* snoop output is now % in all cases */ - add_message(snooper, "%", 1); - add_message(snooper, buf, len); + /* snoop output is now % in all cases */ + add_message(snooper, "%", 1); + add_message(snooper, buf, len); #endif } #endif @@ -238,283 +240,283 @@ void init_user_conn() #ifdef IPV6 struct sockaddr_in6 sin; #else - struct sockaddr_in sin; + struct sockaddr_in sin; #endif - memset(&sin, 0, sizeof(sin)); - socklen_t sin_len; - int optval; - int i; - int have_fd6; - int fd6_which = -1; + memset(&sin, 0, sizeof(sin)); + socklen_t sin_len; + int optval; + int i; + int have_fd6; + int fd6_which = -1; - /* Check for fd #6 open as a valid socket */ - optval = 1; - have_fd6 = (setsockopt(6, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) == 0); + /* Check for fd #6 open as a valid socket */ + optval = 1; + have_fd6 = (setsockopt(6, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)) == 0); - for (i=0; i < 5; i++) { + for (i=0; i < 5; i++) { #ifdef F_NETWORK_STATS - external_port[i].in_packets = 0; - external_port[i].in_volume = 0; - external_port[i].out_packets = 0; - external_port[i].out_volume = 0; + external_port[i].in_packets = 0; + external_port[i].in_volume = 0; + external_port[i].out_packets = 0; + external_port[i].out_volume = 0; #endif - if (!external_port[i].port) { + if (!external_port[i].port) { #if defined(FD6_KIND) && defined(FD6_PORT) - if (!have_fd6) continue; - fd6_which = i; - have_fd6 = 0; - if (FD6_KIND == PORT_UNDEFINED || FD6_PORT < 1) { - debug_message("Socket passed to fd 6 ignored (support is disabled).\n"); - continue; - } - - debug_message("Accepting connections on fd 6 (port %d).\n", FD6_PORT); - external_port[i].kind = FD6_KIND; - external_port[i].port = FD6_PORT; - external_port[i].fd = 6; + if (!have_fd6) continue; + fd6_which = i; + have_fd6 = 0; + if (FD6_KIND == PORT_UNDEFINED || FD6_PORT < 1) { + debug_message("Socket passed to fd 6 ignored (support is disabled).\n"); + continue; + } + + debug_message("Accepting connections on fd 6 (port %d).\n", FD6_PORT); + external_port[i].kind = FD6_KIND; + external_port[i].port = FD6_PORT; + external_port[i].fd = 6; #else - continue; + continue; #endif - } else { - /* - * create socket of proper type. - */ - int sockflags = SOCK_STREAM; + } else { + /* + * create socket of proper type. + */ + int sockflags = SOCK_STREAM; #ifdef IPV6 - if ((external_port[i].fd = socket(PF_INET6, sockflags, 0)) == -1) { + if ((external_port[i].fd = socket(PF_INET6, sockflags, 0)) == -1) { #else - if ((external_port[i].fd = socket(PF_INET, sockflags, 0)) == -1) { -#endif - debug_perror("init_user_conn: socket", 0); - exit(1); - } - - /* - * enable local address reuse. - */ - optval = 1; - if (setsockopt(external_port[i].fd, SOL_SOCKET, SO_REUSEADDR, - (char *) &optval, sizeof(optval)) == -1) { - socket_perror("init_user_conn: setsockopt", 0); - exit(2); - } + if ((external_port[i].fd = socket(PF_INET, sockflags, 0)) == -1) { +#endif + debug_perror("init_user_conn: socket", 0); + exit(1); + } + + /* + * enable local address reuse. + */ + optval = 1; + if (setsockopt(external_port[i].fd, SOL_SOCKET, SO_REUSEADDR, + (char *) &optval, sizeof(optval)) == -1) { + socket_perror("init_user_conn: setsockopt", 0); + exit(2); + } #ifdef FD_CLOEXEC - fcntl(external_port[i].fd, F_SETFD, FD_CLOEXEC); + fcntl(external_port[i].fd, F_SETFD, FD_CLOEXEC); #endif - /* - * fill in socket address information. - */ + /* + * fill in socket address information. + */ #ifdef IPV6 - sin.sin6_family = AF_INET6; - if(MUD_IP[0]) - inet_pton(AF_INET6, MUD_IP, &(sin.sin6_addr)); - else - sin.sin6_addr = in6addr_any; - sin.sin6_port = htons((u_short) external_port[i].port); + sin.sin6_family = AF_INET6; + if(MUD_IP[0]) + inet_pton(AF_INET6, MUD_IP, &(sin.sin6_addr)); + else + sin.sin6_addr = in6addr_any; + sin.sin6_port = htons((u_short) external_port[i].port); #else - sin.sin_family = AF_INET; - if (MUD_IP[0]) - sin.sin_addr.s_addr = inet_addr(MUD_IP); - else - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons((u_short) external_port[i].port); -#endif - - /* - * bind name to socket. - */ - if (bind(external_port[i].fd, (struct sockaddr *) & sin, - sizeof(sin)) == -1) { - socket_perror("init_user_conn: bind", 0); - exit(3); - } - } - /* - * get socket name. - */ - sin_len = sizeof(sin); - if (getsockname(external_port[i].fd, (struct sockaddr *) & sin, - &sin_len) == -1) { - socket_perror("init_user_conn: getsockname", 0); - if (i != fd6_which) { - exit(4); - } - } - /* - * set socket non-blocking, - */ - if (set_socket_nonblocking(external_port[i].fd, 1) == -1) { - socket_perror("init_user_conn: set_socket_nonblocking 1", 0); - if (i != fd6_which) { - exit(8); - } - } - /* - * listen on socket for connections. - */ - if (listen(external_port[i].fd, 128) == -1) { - socket_perror("init_user_conn: listen", 0); - if (i != fd6_which) { - exit(10); - } - } - } - if (have_fd6) { - debug_message("No more ports available; fd #6 ignored.\n"); - } - /* - * register signal handler for SIGPIPE. - */ + sin.sin_family = AF_INET; + if (MUD_IP[0]) + sin.sin_addr.s_addr = inet_addr(MUD_IP); + else + sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = htons((u_short) external_port[i].port); +#endif + + /* + * bind name to socket. + */ + if (bind(external_port[i].fd, (struct sockaddr *) & sin, + sizeof(sin)) == -1) { + socket_perror("init_user_conn: bind", 0); + exit(3); + } + } + /* + * get socket name. + */ + sin_len = sizeof(sin); + if (getsockname(external_port[i].fd, (struct sockaddr *) & sin, + &sin_len) == -1) { + socket_perror("init_user_conn: getsockname", 0); + if (i != fd6_which) { + exit(4); + } + } + /* + * set socket non-blocking, + */ + if (set_socket_nonblocking(external_port[i].fd, 1) == -1) { + socket_perror("init_user_conn: set_socket_nonblocking 1", 0); + if (i != fd6_which) { + exit(8); + } + } + /* + * listen on socket for connections. + */ + if (listen(external_port[i].fd, 128) == -1) { + socket_perror("init_user_conn: listen", 0); + if (i != fd6_which) { + exit(10); + } + } + } + if (have_fd6) { + debug_message("No more ports available; fd #6 ignored.\n"); + } + /* + * register signal handler for SIGPIPE. + */ #if defined(SIGPIPE) && defined(SIGNAL_ERROR) #ifdef SIG_IGN - if (signal(SIGPIPE, SIG_IGN) == SIGNAL_ERROR) { - debug_perror("init_user_conn: signal SIGPIPE",0); - exit(5); - } + if (signal(SIGPIPE, SIG_IGN) == SIGNAL_ERROR) { + debug_perror("init_user_conn: signal SIGPIPE",0); + exit(5); + } #else - if (signal(SIGPIPE, sigpipe_handler) == SIGNAL_ERROR) { - debug_perror("init_user_conn: signal SIGPIPE",0); - exit(5); - } + if (signal(SIGPIPE, sigpipe_handler) == SIGNAL_ERROR) { + debug_perror("init_user_conn: signal SIGPIPE",0); + exit(5); + } #endif #endif } -/* - * Shut down new user accept file descriptor. - */ + /* + * Shut down new user accept file descriptor. + */ void ipc_remove() { - int i; + int i; - for (i = 0; i < 5; i++) { - if (!external_port[i].port) continue; - if (OS_socket_close(external_port[i].fd) == -1) { - socket_perror("ipc_remove: close", 0); - } - } + for (i = 0; i < 5; i++) { + if (!external_port[i].port) continue; + if (OS_socket_close(external_port[i].fd) == -1) { + socket_perror("ipc_remove: close", 0); + } + } - debug_message("closed external ports\n"); + debug_message("closed external ports\n"); } void init_addr_server (char * hostname, int addr_server_port) { #ifdef WIN32 - WORD wVersionRequested = MAKEWORD(1,1); - WSADATA wsaData; - WSAStartup(wVersionRequested, &wsaData); + WORD wVersionRequested = MAKEWORD(1,1); + WSADATA wsaData; + WSAStartup(wVersionRequested, &wsaData); #endif #ifdef IPV6 - struct sockaddr_in6 server; + struct sockaddr_in6 server; #else - struct sockaddr_in server; + struct sockaddr_in server; #endif #ifndef IPV6 - struct hostent *hp; - int addr; + struct hostent *hp; + int addr; #endif - int server_fd; - int optval; + int server_fd; + int optval; - if (addr_server_fd >= 0) - return; + if (addr_server_fd >= 0) + return; - if (!hostname) return; + if (!hostname) return; #ifdef IPV6 - /* - * get network host data for hostname. - */ - struct addrinfo hints, *res; - hints.ai_family = AF_INET6; - hints.ai_socktype = 0; - hints.ai_protocol = 0; + /* + * get network host data for hostname. + */ + struct addrinfo hints, *res; + hints.ai_family = AF_INET6; + hints.ai_socktype = 0; + hints.ai_protocol = 0; #ifndef AI_V4MAPPED - hints.ai_flags = AI_CANONNAME; + hints.ai_flags = AI_CANONNAME; #else - hints.ai_flags = AI_CANONNAME| AI_V4MAPPED; -#endif - - if(getaddrinfo(hostname, "1234", &hints, &res)){ - //failed - socket_perror("init_addr_server: getaddrinfo", 0); - return; - } - - memcpy(&server, res->ai_addr, sizeof(server)); - freeaddrinfo(res); - server.sin6_port = htons((u_short) addr_server_port); - //inet_pton(AF_INET6, hostname, &(server.sin6_addr)); - //memcpy((char *) &server.sin6_addr, (char *) hp->h_addr, hp->h_length); - /* - * create socket of proper type. - */ - server_fd = socket(AF_INET6, SOCK_STREAM, 0); + hints.ai_flags = AI_CANONNAME| AI_V4MAPPED; +#endif + + if(getaddrinfo(hostname, "1234", &hints, &res)){ + //failed + socket_perror("init_addr_server: getaddrinfo", 0); + return; + } + + memcpy(&server, res->ai_addr, sizeof(server)); + freeaddrinfo(res); + server.sin6_port = htons((u_short) addr_server_port); + //inet_pton(AF_INET6, hostname, &(server.sin6_addr)); + //memcpy((char *) &server.sin6_addr, (char *) hp->h_addr, hp->h_length); + /* + * create socket of proper type. + */ + server_fd = socket(AF_INET6, SOCK_STREAM, 0); #else - /* - * get network host data for hostname. - */ - if (hostname[0] >= '0' && hostname[0] <= '9' && - (addr = inet_addr(hostname)) != -1) { - hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); - } else { - hp = gethostbyname(hostname); - } - if (hp == NULL) { - socket_perror("init_addr_server: gethostbyname", 0); - return; - } - - /* - * set up address information for server. - */ - server.sin_family = AF_INET; - server.sin_port = htons((u_short) addr_server_port); - server.sin_addr.s_addr = inet_addr(hostname); - memcpy((char *) &server.sin_addr, (char *) hp->h_addr, hp->h_length); - /* - * create socket of proper type. - */ - server_fd = socket(AF_INET, SOCK_STREAM, 0); -#endif - if (server_fd == INVALID_SOCKET) { /* problem opening socket */ - socket_perror("init_addr_server: socket", 0); - return; - } - /* - * enable local address reuse. - */ - optval = 1; - if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, - sizeof(optval)) == -1) { - socket_perror("init_addr_server: setsockopt", 0); - return; - } - /* - * connect socket to server address. - */ - if (connect(server_fd, (struct sockaddr *) & server, sizeof(server)) == -1) { - if(ADDRFAIL_NOTIFY){ - if (socket_errno == ECONNREFUSED && ADDRFAIL_NOTIFY) - debug_message("Connection to address server (%s %d) refused.\n", - hostname, addr_server_port); - else - socket_perror("init_addr_server: connect", 0); - } - OS_socket_close(server_fd); - return; - } - addr_server_fd = server_fd; - debug_message("Connected to address server on %s port %d\n", hostname, - addr_server_port); - /* - * set socket non-blocking. - */ - if (set_socket_nonblocking(server_fd, 1) == -1) { - socket_perror("init_addr_server: set_socket_nonblocking 1", 0); - return; - } + /* + * get network host data for hostname. + */ + if (hostname[0] >= '0' && hostname[0] <= '9' && + (addr = inet_addr(hostname)) != -1) { + hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET); + } else { + hp = gethostbyname(hostname); + } + if (hp == NULL) { + socket_perror("init_addr_server: gethostbyname", 0); + return; + } + + /* + * set up address information for server. + */ + server.sin_family = AF_INET; + server.sin_port = htons((u_short) addr_server_port); + server.sin_addr.s_addr = inet_addr(hostname); + memcpy((char *) &server.sin_addr, (char *) hp->h_addr, hp->h_length); + /* + * create socket of proper type. + */ + server_fd = socket(AF_INET, SOCK_STREAM, 0); +#endif + if (server_fd == INVALID_SOCKET) { /* problem opening socket */ + socket_perror("init_addr_server: socket", 0); + return; + } + /* + * enable local address reuse. + */ + optval = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optval, + sizeof(optval)) == -1) { + socket_perror("init_addr_server: setsockopt", 0); + return; + } + /* + * connect socket to server address. + */ + if (connect(server_fd, (struct sockaddr *) & server, sizeof(server)) == -1) { + if(ADDRFAIL_NOTIFY){ + if (socket_errno == ECONNREFUSED && ADDRFAIL_NOTIFY) + debug_message("Connection to address server (%s %d) refused.\n", + hostname, addr_server_port); + else + socket_perror("init_addr_server: connect", 0); + } + OS_socket_close(server_fd); + return; + } + addr_server_fd = server_fd; + debug_message("Connected to address server on %s port %d\n", hostname, + addr_server_port); + /* + * set socket non-blocking. + */ + if (set_socket_nonblocking(server_fd, 1) == -1) { + socket_perror("init_addr_server: set_socket_nonblocking 1", 0); + return; + } #ifdef WIN32 - WSACleanup(); + WSACleanup(); #endif } @@ -536,19 +538,19 @@ void init_addr_server (char * hostname, int addr_server_port) #ifdef SHADOW_CATCH_MESSAGE static int shadow_catch_message (object_t * ob, const char * str) { - if (!ob->shadowed) - return 0; - while (ob->shadowed != 0 && ob->shadowed != current_object) - ob = ob->shadowed; - while (ob->shadowing) { - copy_and_push_string(str); - if (apply(APPLY_CATCH_TELL, ob, 1, ORIGIN_DRIVER)) - /* this will work, since we know the */ - /* function is defined */ - return 1; - ob = ob->shadowing; - } - return 0; + if (!ob->shadowed) + return 0; + while (ob->shadowed != 0 && ob->shadowed != current_object) + ob = ob->shadowed; + while (ob->shadowing) { + copy_and_push_string(str); + if (apply(APPLY_CATCH_TELL, ob, 1, ORIGIN_DRIVER)) + /* this will work, since we know the */ + /* function is defined */ + return 1; + ob = ob->shadowing; + } + return 0; } #endif @@ -558,204 +560,204 @@ static int shadow_catch_message (object_t * ob, const char * str) */ void add_message (object_t * who, const char * data, int len) { - interactive_t *ip; - const char *cp; - const char *end; - char *trans; - int translen; - /* - * if who->interactive is not valid, write message on stderr. - * (maybe) - */ - if (!who || (who->flags & O_DESTRUCTED) || !who->interactive || - (who->interactive->iflags & (NET_DEAD | CLOSING))) { + interactive_t *ip; + const char *cp; + const char *end; + char *trans; + int translen; + /* + * if who->interactive is not valid, write message on stderr. + * (maybe) + */ + if (!who || (who->flags & O_DESTRUCTED) || !who->interactive || + (who->interactive->iflags & (NET_DEAD | CLOSING))) { #ifdef NONINTERACTIVE_STDERR_WRITE - putc(']', stderr); - fwrite(data, len, 1, stderr); + putc(']', stderr); + fwrite(data, len, 1, stderr); #endif - return; - } - ip = who->interactive; - trans = translate(ip->trans->outgoing, data, len, &translen); + return; + } + ip = who->interactive; + trans = translate(ip->trans->outgoing, data, len, &translen); #ifdef SHADOW_CATCH_MESSAGE - /* - * shadow handling. - */ - if (shadow_catch_message(who, data)) { + /* + * shadow handling. + */ + if (shadow_catch_message(who, data)) { #ifdef SNOOP_SHADOWED - handle_snoop(data, len, ip); + handle_snoop(data, len, ip); #endif - return; - } + return; + } #endif /* NO_SHADOWS */ - /* - * write message into ip->message_buf. - */ - end = trans + translen; - for (cp = trans; cp < end; cp++) { - if (ip->message_length == MESSAGE_BUF_SIZE) { - if (!flush_message(ip)) { - debug(connections, ("Broken connection during add_message.")); - return; - } - if (ip->message_length == MESSAGE_BUF_SIZE) - break; - } - if ((*cp == '\n' || *cp == -1) + /* + * write message into ip->message_buf. + */ + end = trans + translen; + for (cp = trans; cp < end; cp++) { + if (ip->message_length == MESSAGE_BUF_SIZE) { + if (!flush_message(ip)) { + debug(connections, ("Broken connection during add_message.")); + return; + } + if (ip->message_length == MESSAGE_BUF_SIZE) + break; + } + if ((*cp == '\n' || *cp == -1) #ifndef NO_BUFFER_TYPE - && ip->connection_type != PORT_BINARY -#endif - ) { - if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) { - if (!flush_message(ip)) { - debug(connections, ("Broken connection during add_message.")); - return; - } - if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) - break; - } - ip->message_buf[ip->message_producer] = (*cp == '\n')?'\r':-1; - ip->message_producer = (ip->message_producer + 1) - % MESSAGE_BUF_SIZE; - ip->message_length++; - } - ip->message_buf[ip->message_producer] = *cp; - ip->message_producer = (ip->message_producer + 1) % MESSAGE_BUF_SIZE; - ip->message_length++; - } - - handle_snoop(data, len, ip); + && ip->connection_type != PORT_BINARY +#endif + ) { + if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) { + if (!flush_message(ip)) { + debug(connections, ("Broken connection during add_message.")); + return; + } + if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) + break; + } + ip->message_buf[ip->message_producer] = (*cp == '\n')?'\r':-1; + ip->message_producer = (ip->message_producer + 1) + % MESSAGE_BUF_SIZE; + ip->message_length++; + } + ip->message_buf[ip->message_producer] = *cp; + ip->message_producer = (ip->message_producer + 1) % MESSAGE_BUF_SIZE; + ip->message_length++; + } + + handle_snoop(data, len, ip); #ifdef FLUSH_OUTPUT_IMMEDIATELY - flush_message(ip); + flush_message(ip); #endif - add_message_calls++; + add_message_calls++; } /* add_message() */ /* WARNING: this can only handle results < LARGEST_PRINTABLE_STRING in size */ void add_vmessage (object_t *who, const char *format, ...) { - int len; - interactive_t *ip; - char *cp, new_string_data[LARGEST_PRINTABLE_STRING + 1]; - va_list args; - - V_START(args, format); - V_VAR(object_t *, who, args); - V_VAR(char *, format, args); - /* - * if who->interactive is not valid, write message on stderr. - * (maybe) - */ - if (!who || (who->flags & O_DESTRUCTED) || !who->interactive || - (who->interactive->iflags & (NET_DEAD | CLOSING))) { + int len; + interactive_t *ip; + char *cp, new_string_data[LARGEST_PRINTABLE_STRING + 1]; + va_list args; + + V_START(args, format); + V_VAR(object_t *, who, args); + V_VAR(char *, format, args); + /* + * if who->interactive is not valid, write message on stderr. + * (maybe) + */ + if (!who || (who->flags & O_DESTRUCTED) || !who->interactive || + (who->interactive->iflags & (NET_DEAD | CLOSING))) { #ifdef NONINTERACTIVE_STDERR_WRITE - putc(']', stderr); - vfprintf(stderr, format, args); -#endif - va_end(args); - return; - } - ip = who->interactive; - new_string_data[0] = '\0'; - - vsnprintf(new_string_data, LARGEST_PRINTABLE_STRING, format, args); - va_end(args); - len = strlen(new_string_data); + putc(']', stderr); + vfprintf(stderr, format, args); +#endif + va_end(args); + return; + } + ip = who->interactive; + new_string_data[0] = '\0'; + + vsnprintf(new_string_data, LARGEST_PRINTABLE_STRING, format, args); + va_end(args); + len = strlen(new_string_data); #ifdef SHADOW_CATCH_MESSAGE - /* - * shadow handling. - */ - if (shadow_catch_message(who, new_string_data)) { + /* + * shadow handling. + */ + if (shadow_catch_message(who, new_string_data)) { #ifdef SNOOP_SHADOWED - handle_snoop(new_string_data, len, ip); + handle_snoop(new_string_data, len, ip); #endif - return; - } + return; + } #endif /* NO_SHADOWS */ - /* - * write message into ip->message_buf. - */ - for (cp = new_string_data; *cp != '\0'; cp++) { - if (ip->message_length == MESSAGE_BUF_SIZE) { - if (!flush_message(ip)) { - debug(connections, ("Broken connection during add_message.")); - return; - } - if (ip->message_length == MESSAGE_BUF_SIZE) - break; - } - if (*cp == '\n') { - if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) { - if (!flush_message(ip)) { - debug(connections, ("Broken connection during add_message.\n")); - return; - } - if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) - break; - } - ip->message_buf[ip->message_producer] = '\r'; - ip->message_producer = (ip->message_producer + 1) - % MESSAGE_BUF_SIZE; - ip->message_length++; - } - ip->message_buf[ip->message_producer] = *cp; - ip->message_producer = (ip->message_producer + 1) % MESSAGE_BUF_SIZE; - ip->message_length++; - } - if (ip->message_length != 0) { - if (!flush_message(ip)) { - debug(connections, ("Broken connection during add_message.\n")); - return; - } - } - - handle_snoop(new_string_data, len, ip); + /* + * write message into ip->message_buf. + */ + for (cp = new_string_data; *cp != '\0'; cp++) { + if (ip->message_length == MESSAGE_BUF_SIZE) { + if (!flush_message(ip)) { + debug(connections, ("Broken connection during add_message.")); + return; + } + if (ip->message_length == MESSAGE_BUF_SIZE) + break; + } + if (*cp == '\n') { + if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) { + if (!flush_message(ip)) { + debug(connections, ("Broken connection during add_message.\n")); + return; + } + if (ip->message_length == (MESSAGE_BUF_SIZE - 1)) + break; + } + ip->message_buf[ip->message_producer] = '\r'; + ip->message_producer = (ip->message_producer + 1) + % MESSAGE_BUF_SIZE; + ip->message_length++; + } + ip->message_buf[ip->message_producer] = *cp; + ip->message_producer = (ip->message_producer + 1) % MESSAGE_BUF_SIZE; + ip->message_length++; + } + if (ip->message_length != 0) { + if (!flush_message(ip)) { + debug(connections, ("Broken connection during add_message.\n")); + return; + } + } + + handle_snoop(new_string_data, len, ip); #ifdef FLUSH_OUTPUT_IMMEDIATELY - flush_message(ip); + flush_message(ip); #endif - add_message_calls++; + add_message_calls++; } /* add_message() */ void add_binary_message (object_t * who, const unsigned char * data, int len) { - interactive_t *ip; - const unsigned char *cp, *end; - - /* - * if who->interactive is not valid, bail - */ - if (!who || (who->flags & O_DESTRUCTED) || !who->interactive || - (who->interactive->iflags & (NET_DEAD | CLOSING))) { - return; - } - ip = who->interactive; - - /* - * write message into ip->message_buf. - */ - end = data + len; - for (cp = data; cp < end; cp++) { - if (ip->message_length == MESSAGE_BUF_SIZE) { - if (!flush_message(ip)) { - debug(connections, ("Broken connection during add_message.")); - return; - } - if (ip->message_length == MESSAGE_BUF_SIZE) - break; - } - ip->message_buf[ip->message_producer] = *cp; - ip->message_producer = (ip->message_producer + 1) % MESSAGE_BUF_SIZE; - ip->message_length++; - } - - flush_message(ip); - add_message_calls++; + interactive_t *ip; + const unsigned char *cp, *end; + + /* + * if who->interactive is not valid, bail + */ + if (!who || (who->flags & O_DESTRUCTED) || !who->interactive || + (who->interactive->iflags & (NET_DEAD | CLOSING))) { + return; + } + ip = who->interactive; + + /* + * write message into ip->message_buf. + */ + end = data + len; + for (cp = data; cp < end; cp++) { + if (ip->message_length == MESSAGE_BUF_SIZE) { + if (!flush_message(ip)) { + debug(connections, ("Broken connection during add_message.")); + return; + } + if (ip->message_length == MESSAGE_BUF_SIZE) + break; + } + ip->message_buf[ip->message_producer] = *cp; + ip->message_producer = (ip->message_producer + 1) % MESSAGE_BUF_SIZE; + ip->message_length++; + } + + flush_message(ip); + add_message_calls++; } /* @@ -763,75 +765,98 @@ void add_binary_message (object_t * who, const unsigned char * data, int len) */ int flush_message (interactive_t * ip) { - int length, num_bytes; - - /* - * if ip is not valid, do nothing. - */ - if (!ip || !ip->ob || !IP_VALID(ip, ip->ob) || - (ip->ob->flags & O_DESTRUCTED) || (ip->iflags & (NET_DEAD | CLOSING))){ - //debug(connections, ("flush_message: invalid target!\n")); - return 0; - } - /* - * write ip->message_buf[] to socket. - */ - while (ip->message_length != 0) { - if (ip->message_consumer < ip->message_producer) { - length = ip->message_producer - ip->message_consumer; - } else { - length = MESSAGE_BUF_SIZE - ip->message_consumer; - } -/* Need to use send to get out of band data + int length, num_bytes; + + /* + * if ip is not valid, do nothing. + */ + if (!ip || !ip->ob || !IP_VALID(ip, ip->ob) || + (ip->ob->flags & O_DESTRUCTED) || (ip->iflags & (NET_DEAD | CLOSING))){ + //debug(connections, ("flush_message: invalid target!\n")); + return 0; + } + /* + * write ip->message_buf[] to socket. + */ + while (ip->message_length != 0) { + if (ip->message_consumer < ip->message_producer) { + length = ip->message_producer - ip->message_consumer; + } else { + length = MESSAGE_BUF_SIZE - ip->message_consumer; + } + /* Need to use send to get out of band data num_bytes = write(ip->fd,ip->message_buf + ip->message_consumer,length); - */ + */ #ifdef HAVE_ZLIB - if (ip->compressed_stream) { - num_bytes = send_compressed(ip, (unsigned char *)ip->message_buf + - ip->message_consumer, length); - } else { -#endif - num_bytes = send(ip->fd, ip->message_buf + ip->message_consumer, - length, ip->out_of_band | MSG_NOSIGNAL); + if (ip->compressed_stream) { + num_bytes = send_compressed(ip, (unsigned char *)ip->message_buf + + ip->message_consumer, length); + } else { +#endif + if(ip->connection_type == PORT_WEBSOCKET && (ip->iflags & HANDSHAKE_COMPLETE)){ + ip->out_of_band = 0; + //ok we're in trouble, we have to send the whole thing at once, otherwise we don't know the size! + //try to get away with only sending small chunks + int sendsize = length; + if(length > 125){ + sendsize = 125; + } + unsigned short flags = htons(sendsize | 0x8200); //82 is final packet (of this message) type binary + int sendres = send(ip->fd, &flags, 2, 0); + if(sendres <= 0) + return 1; //wait + if(sendres == 1) { + ip->iflags |= NET_DEAD; + return 0; + } + num_bytes = send(ip->fd, ip->message_buf + ip->message_consumer, sendsize, 0); + if(num_bytes!=sendsize){ + ip->iflags |= NET_DEAD; + return 0; + } + } else { + num_bytes = send(ip->fd, ip->message_buf + ip->message_consumer, + length, ip->out_of_band | MSG_NOSIGNAL); + } #ifdef HAVE_ZLIB - } + } #endif - if (!num_bytes) { - ip->iflags |= NET_DEAD; - return 0; - } - if (num_bytes == -1) { + if (!num_bytes) { + ip->iflags |= NET_DEAD; + return 0; + } + if (num_bytes == -1) { #ifdef EWOULDBLOCK - if (socket_errno == EWOULDBLOCK) { - //debug(connections, ("flush_message: write: Operation would block\n")); - return 1; + if (socket_errno == EWOULDBLOCK) { + //debug(connections, ("flush_message: write: Operation would block\n")); + return 1; #else - if (0) { - ; -#endif - } else if (socket_errno == EINTR) { - //debug(connections, ("flush_message: write: Interrupted system call")); - return 1; - } else { - //socket_perror("flush_message: write", 0); - ip->iflags |= NET_DEAD; - return 0; - } - } - ip->message_consumer = (ip->message_consumer + num_bytes) % - MESSAGE_BUF_SIZE; - ip->message_length -= num_bytes; - ip->out_of_band = 0; - inet_packets++; - inet_volume += num_bytes; + if (0) { + ; +#endif + } else if (socket_errno == EINTR) { + //debug(connections, ("flush_message: write: Interrupted system call")); + return 1; + } else { + //socket_perror("flush_message: write", 0); + ip->iflags |= NET_DEAD; + return 0; + } + } + ip->message_consumer = (ip->message_consumer + num_bytes) % + MESSAGE_BUF_SIZE; + ip->message_length -= num_bytes; + ip->out_of_band = 0; + inet_packets++; + inet_volume += num_bytes; #ifdef F_NETWORK_STATS - inet_out_packets++; - inet_out_volume += num_bytes; - external_port[ip->external_port].out_packets++; - external_port[ip->external_port].out_volume += num_bytes; + inet_out_packets++; + inet_out_volume += num_bytes; + external_port[ip->external_port].out_packets++; + external_port[ip->external_port].out_volume += num_bytes; #endif - } - return 1; + } + return 1; } /* flush_message() */ static int send_mssp_val(mapping_t *map, mapping_node_t *el, void *obp){ @@ -860,527 +885,528 @@ static int send_mssp_val(mapping_t *map, mapping_node_t *el, void *obp){ static void copy_chars (interactive_t * ip, char * from, int num_bytes) { - int i, start, x; - unsigned char dont_response[3] = { IAC, DONT, 0 }; - unsigned char wont_response[3] = { IAC, WONT, 0 }; - - start = ip->text_end; - for (i = 0; i < num_bytes; i++) { - switch (ip->state) { - case TS_DATA: - switch ((unsigned char)from[i]) { - case IAC: - ip->state = TS_IAC; - break; + int i, start, x; + unsigned char dont_response[3] = { IAC, DONT, 0 }; + unsigned char wont_response[3] = { IAC, WONT, 0 }; + + start = ip->text_end; + for (i = 0; i < num_bytes; i++) { + switch (ip->state) { + case TS_DATA: + switch ((unsigned char)from[i]) { + case IAC: + ip->state = TS_IAC; + break; #if defined(NO_ANSI) && defined(STRIP_BEFORE_PROCESS_INPUT) - case 0x1b: - ip->text[ip->text_end++] = ANSI_SUBSTITUTE; - break; -#endif - - case 0x08: - case 0x7f: - if (ip->iflags & SINGLE_CHAR) - ip->text[ip->text_end++] = from[i]; - else { - if (ip->text_end > 0) - ip->text_end--; - } - break; - - default: - ip->text[ip->text_end++] = from[i]; - break; - } - break; - - case TS_IAC: - switch ((unsigned char)from[i]) { - case IAC: - ip->state = TS_DATA; - ip->text[ip->text_end++] = from[i]; - break; - - case WILL: - ip->state = TS_WILL; - break; - - case WONT: - ip->state = TS_WONT; - break; - - case DO: - ip->state = TS_DO; - break; - - case DONT: - ip->state = TS_DONT; - break; - - case SB: - ip->state = TS_SB; - ip->sb_pos = 0; - break; - - case BREAK: - add_binary_message(ip->ob, telnet_break_response, sizeof(telnet_break_response)); - break; - - case IP: /* interrupt process */ - add_binary_message(ip->ob, telnet_ip_response, sizeof(telnet_ip_response)); - break; - - case AYT: /* are you there? you bet */ - add_binary_message(ip->ob, telnet_ayt_response, sizeof(telnet_ayt_response)); - break; - - case AO: /* abort output */ - flush_message(ip); - ip->out_of_band = MSG_OOB; - add_binary_message(ip->ob, telnet_abort_response, sizeof(telnet_abort_response)); - break; - - default: - ip->state = TS_DATA; - break; - } - break; - - case TS_WILL: - ip->iflags |= USING_TELNET; - switch ((unsigned char)from[i]) { - case TELOPT_TTYPE: - add_binary_message(ip->ob, telnet_term_query, sizeof(telnet_term_query)); - break; - - case TELOPT_LINEMODE: - /* Do linemode and set the mode: EDIT + TRAPSIG */ - ip->iflags |= USING_LINEMODE; - set_linemode(ip); - break; - - case TELOPT_ECHO: - case TELOPT_NAWS: - /* do nothing, but don't send a dont response */ - break; - - case TELOPT_MXP : - /* Mxp is enabled, tell the mudlib about it. */ - apply(APPLY_MXP_ENABLE, ip->ob, 0, ORIGIN_DRIVER); - ip->iflags |= USING_MXP; - break; - case TELOPT_GMCP: - apply(APPLY_GMCP_ENABLE, ip->ob, 0, ORIGIN_DRIVER); - ip->iflags |= USING_GMCP; - break; - case TELOPT_NEW_ENVIRON : - add_binary_message(ip->ob, telnet_send_uservar, sizeof(telnet_send_uservar)); - break; - - default: - dont_response[2] = from[i]; - add_binary_message(ip->ob, dont_response, sizeof(dont_response)); - break; - } - ip->state = TS_DATA; - break; - - case TS_WONT: - ip->iflags |= USING_TELNET; - switch ((unsigned char)from[i]) { - case TELOPT_LINEMODE: - /* If we're in single char mode, we just requested for - * linemode to be disabled, so don't remove our flag. - */ - if (!(ip->iflags & SINGLE_CHAR)) - ip->iflags &= ~USING_LINEMODE; - break; - } - ip->state = TS_DATA; - break; - - case TS_DO: - switch ((unsigned char)from[i]) { - case TELOPT_TM: - add_binary_message(ip->ob, telnet_do_tm_response, sizeof(telnet_do_tm_response)); - break; - - case TELOPT_SGA: - if (ip->iflags & USING_LINEMODE) { - ip->iflags |= SUPPRESS_GA; - add_binary_message(ip->ob, telnet_yes_single, sizeof(telnet_yes_single)); - } else { - if (ip->iflags & SINGLE_CHAR) - add_binary_message(ip->ob, telnet_yes_single, sizeof(telnet_yes_single)); - else - add_binary_message(ip->ob, telnet_no_single, sizeof(telnet_no_single)); - } - break; - - case TELOPT_ECHO: - /* do nothing, but don't send a wont response */ - break; - case TELOPT_MSSP: - { - add_binary_message(ip->ob, telnet_start_mssp, sizeof(telnet_start_mssp)); - svalue_t *res = apply_master_ob(APPLY_GET_MUD_STATS, 0); - mapping_t *map; - if(res <= 0 || res->type != T_MAPPING) { - map = allocate_mapping(0); - free_svalue(&apply_ret_value, "telnet neg"); - apply_ret_value.type = T_MAPPING; - apply_ret_value.u.map = map; - } else - map = res->u.map; - //ok, so we have a mapping, first make sure we send the required values - char *tmp = findstring("NAME"); - if(tmp){ - svalue_t *name = find_string_in_mapping(map, tmp); - if(!name || name->type != T_STRING) - tmp = 0; - } - if(!tmp){ - char buf[1024]; - int len = sprintf(buf, (char *)telnet_mssp_value, "NAME", MUD_NAME); - add_binary_message(ip->ob, (unsigned char *)buf, len); - } - tmp = findstring("PLAYERS"); - if(tmp){ - svalue_t *players = find_string_in_mapping(map, tmp); - if(!players || players->type != T_STRING) - tmp = 0; - } - if(!tmp){ - char buf[1024]; - char num[5]; - sprintf(num, "%d", num_user); - int len = sprintf(buf, (char *)telnet_mssp_value, "PLAYERS", num); - add_binary_message(ip->ob, (unsigned char *)buf, len); - } - tmp = findstring("UPTIME"); - if(tmp){ - svalue_t *upt = find_string_in_mapping(map, tmp); - if(!upt || upt->type != T_STRING) - tmp = 0; - } - if(!tmp){ - char buf[1024]; - char num[20]; - - sprintf(num, "%ld", boot_time); - int len = sprintf(buf, (char *)telnet_mssp_value, "UPTIME", num); - add_binary_message(ip->ob, (unsigned char *)buf, len); - } - //now send the rest - mapTraverse(map, send_mssp_val, ip->ob); - add_binary_message(ip->ob, telnet_end_sub, sizeof(telnet_end_sub)); - } -#ifdef HAVE_ZLIB - case TELOPT_COMPRESS : - if(!ip->compressed_stream){ - add_binary_message(ip->ob, telnet_compress_v1_response, - sizeof(telnet_compress_v1_response)); - start_compression(ip); - } - break; - case TELOPT_COMPRESS2 : - if(!ip->compressed_stream){ - add_binary_message(ip->ob, telnet_compress_v2_response, - sizeof(telnet_compress_v2_response)); - start_compression(ip); - } - break; -#endif - case TELOPT_ZMP : - ip->iflags |= USING_ZMP; - break; - default: - wont_response[2] = from[i]; - add_binary_message(ip->ob, wont_response, sizeof(wont_response)); - break; - } - ip->state = TS_DATA; - break; - - case TS_DONT: - switch ((unsigned char)from[i]) { - case TELOPT_SGA: - if (ip->iflags & USING_LINEMODE) { - ip->iflags &= ~SUPPRESS_GA; - add_binary_message(ip->ob, telnet_no_single, sizeof(telnet_no_single)); - } - break; + case 0x1b: + ip->text[ip->text_end++] = ANSI_SUBSTITUTE; + break; +#endif + + case 0x08: + case 0x7f: + if (ip->iflags & SINGLE_CHAR) + ip->text[ip->text_end++] = from[i]; + else { + if (ip->text_end > 0) + ip->text_end--; + } + break; + + default: + ip->text[ip->text_end++] = from[i]; + break; + } + break; + + case TS_IAC: + switch ((unsigned char)from[i]) { + case IAC: + ip->state = TS_DATA; + ip->text[ip->text_end++] = from[i]; + break; + + case WILL: + ip->state = TS_WILL; + break; + + case WONT: + ip->state = TS_WONT; + break; + + case DO: + ip->state = TS_DO; + break; + + case DONT: + ip->state = TS_DONT; + break; + + case SB: + ip->state = TS_SB; + ip->sb_pos = 0; + break; + + case BREAK: + add_binary_message(ip->ob, telnet_break_response, sizeof(telnet_break_response)); + break; + + case IP: /* interrupt process */ + add_binary_message(ip->ob, telnet_ip_response, sizeof(telnet_ip_response)); + break; + + case AYT: /* are you there? you bet */ + add_binary_message(ip->ob, telnet_ayt_response, sizeof(telnet_ayt_response)); + break; + + case AO: /* abort output */ + flush_message(ip); + ip->out_of_band = MSG_OOB; + add_binary_message(ip->ob, telnet_abort_response, sizeof(telnet_abort_response)); + break; + + default: + ip->state = TS_DATA; + break; + } + break; + + case TS_WILL: + ip->iflags |= USING_TELNET; + switch ((unsigned char)from[i]) { + case TELOPT_TTYPE: + add_binary_message(ip->ob, telnet_term_query, sizeof(telnet_term_query)); + break; + + case TELOPT_LINEMODE: + /* Do linemode and set the mode: EDIT + TRAPSIG */ + ip->iflags |= USING_LINEMODE; + set_linemode(ip); + break; + + case TELOPT_ECHO: + case TELOPT_NAWS: + /* do nothing, but don't send a dont response */ + break; + + case TELOPT_MXP : + /* Mxp is enabled, tell the mudlib about it. */ + apply(APPLY_MXP_ENABLE, ip->ob, 0, ORIGIN_DRIVER); + ip->iflags |= USING_MXP; + break; + + case TELOPT_NEW_ENVIRON : + add_binary_message(ip->ob, telnet_send_uservar, sizeof(telnet_send_uservar)); + break; + + default: + dont_response[2] = from[i]; + add_binary_message(ip->ob, dont_response, sizeof(dont_response)); + break; + } + ip->state = TS_DATA; + break; + + case TS_WONT: + ip->iflags |= USING_TELNET; + switch ((unsigned char)from[i]) { + case TELOPT_LINEMODE: + /* If we're in single char mode, we just requested for + * linemode to be disabled, so don't remove our flag. + */ + if (!(ip->iflags & SINGLE_CHAR)) + ip->iflags &= ~USING_LINEMODE; + break; + } + ip->state = TS_DATA; + break; + + case TS_DO: + switch ((unsigned char)from[i]) { + case TELOPT_TM: + add_binary_message(ip->ob, telnet_do_tm_response, sizeof(telnet_do_tm_response)); + break; + + case TELOPT_SGA: + if (ip->iflags & USING_LINEMODE) { + ip->iflags |= SUPPRESS_GA; + add_binary_message(ip->ob, telnet_yes_single, sizeof(telnet_yes_single)); + } else { + if (ip->iflags & SINGLE_CHAR) + add_binary_message(ip->ob, telnet_yes_single, sizeof(telnet_yes_single)); + else + add_binary_message(ip->ob, telnet_no_single, sizeof(telnet_no_single)); + } + break; + case TELOPT_GMCP: + apply(APPLY_GMCP_ENABLE, ip->ob, 0, ORIGIN_DRIVER); + ip->iflags |= USING_GMCP; + break; + case TELOPT_ECHO: + /* do nothing, but don't send a wont response */ + break; + case TELOPT_MSSP: + { + add_binary_message(ip->ob, telnet_start_mssp, sizeof(telnet_start_mssp)); + svalue_t *res = apply_master_ob(APPLY_GET_MUD_STATS, 0); + mapping_t *map; + if(res <= (svalue_t *)0 || res->type != T_MAPPING) { + map = allocate_mapping(0); + free_svalue(&apply_ret_value, "telnet neg"); + apply_ret_value.type = T_MAPPING; + apply_ret_value.u.map = map; + } else + map = res->u.map; + //ok, so we have a mapping, first make sure we send the required values + char *tmp = findstring("NAME"); + if(tmp){ + svalue_t *name = find_string_in_mapping(map, tmp); + if(!name || name->type != T_STRING) + tmp = 0; + } + if(!tmp){ + char buf[1024]; + int len = sprintf(buf, (char *)telnet_mssp_value, "NAME", MUD_NAME); + add_binary_message(ip->ob, (unsigned char *)buf, len); + } + tmp = findstring("PLAYERS"); + if(tmp){ + svalue_t *players = find_string_in_mapping(map, tmp); + if(!players || players->type != T_STRING) + tmp = 0; + } + if(!tmp){ + char buf[1024]; + char num[5]; + sprintf(num, "%d", num_user); + int len = sprintf(buf, (char *)telnet_mssp_value, "PLAYERS", num); + add_binary_message(ip->ob, (unsigned char *)buf, len); + } + tmp = findstring("UPTIME"); + if(tmp){ + svalue_t *upt = find_string_in_mapping(map, tmp); + if(!upt || upt->type != T_STRING) + tmp = 0; + } + if(!tmp){ + char buf[1024]; + char num[20]; + + sprintf(num, "%ld", boot_time); + int len = sprintf(buf, (char *)telnet_mssp_value, "UPTIME", num); + add_binary_message(ip->ob, (unsigned char *)buf, len); + } + //now send the rest + mapTraverse(map, send_mssp_val, ip->ob); + add_binary_message(ip->ob, telnet_end_sub, sizeof(telnet_end_sub)); + } + break; #ifdef HAVE_ZLIB - case TELOPT_COMPRESS2: - // If we are told not to use v2, then try v1. - add_binary_message(ip->ob, telnet_compress_send_request_v1, - sizeof(telnet_compress_send_request_v1)); - break; -#endif - } - ip->state = TS_DATA; - break; - - case TS_SB: - if ((unsigned char)from[i] == IAC) { - ip->state = TS_SB_IAC; - break; - } - if (ip->sb_pos < ip->sb_size - 1) - ip->sb_buf[ip->sb_pos++] = from[i]; - else if(ip->sb_size < MAX_STRING_LENGTH){ - ip->sb_size*=2; - if(ip->sb_size > MAX_STRING_LENGTH) - ip->sb_size = MAX_STRING_LENGTH; - ip->sb_buf = (char *)REALLOC(ip->sb_buf, ip->sb_size); - if (ip->sb_pos < ip->sb_size - 1) - ip->sb_buf[ip->sb_pos++] = from[i]; - } - break; - - case TS_SB_IAC: - switch ((unsigned char)from[i]) { - case IAC: - if (ip->sb_pos < SB_SIZE - 1) { - ip->sb_buf[ip->sb_pos++] = from[i]; - ip->state = TS_SB; - } - break; - - case SE: - ip->state = TS_DATA; - ip->sb_buf[ip->sb_pos] = 0; - switch ((unsigned char)ip->sb_buf[0]) { - - case TELOPT_NEW_ENVIRON : - { - int j, k; - char env_buf[BUF_SIZE]; - j = 0; - k = 1; - while(ip->sb_buf[k] > -1 && k < (ip->sb_pos - 1)){ - k++; - if(!(ip->sb_buf[k])) env_buf[j] = ENV_FILLER; - if(ip->sb_buf[k] == 1) env_buf[j] = 1; - if((ip->sb_buf[k] > 31)){ - env_buf[j] = ip->sb_buf[k]; - } - if(env_buf[j]) j++; - } - env_buf[j] = 0; - copy_and_push_string(env_buf); - apply(APPLY_RECEIVE_ENVIRON, ip->ob, 1, ORIGIN_DRIVER); - break; - - } - case TELOPT_LINEMODE: - switch ((unsigned char)ip->sb_buf[1]) { - case LM_MODE: - /* Don't do anything with an ACK */ - if (!(ip->sb_buf[2] & MODE_ACK)) { - unsigned char sb_ack[] = { IAC, SB, TELOPT_LINEMODE, LM_MODE, MODE_EDIT | MODE_TRAPSIG | MODE_ACK, IAC, SE }; - - /* Accept only EDIT and TRAPSIG && force them too */ - add_binary_message(ip->ob, sb_ack, sizeof(sb_ack)); - } - break; - - case LM_SLC: - { - int slc_length = 4; - unsigned char slc_response[SB_SIZE + 6] = { IAC, SB, TELOPT_LINEMODE, LM_SLC }; - - for (x = 2; x < ip->sb_pos; x += 3) { - /* no response for an ack */ - if (ip->sb_buf[x + 1] & SLC_ACK) - continue; - - /* If we get { 0, SLC_DEFAULT, 0 } or { 0, SLC_VARIABLE, 0 } return a list of values */ - /* If it's SLC_DEFAULT, reset to defaults first */ - if (!ip->sb_buf[x] && !ip->sb_buf[x + 2]) { - if (ip->sb_buf[x + 1] == SLC_DEFAULT || ip->sb_buf[x + 1] == SLC_VARIABLE) { - int n; - - for (n = 0; n < NSLC; n++) { - slc_response[slc_length++] = n + 1; - if (ip->sb_buf[x + 1] == SLC_DEFAULT) { - ip->slc[n][0] = slc_default_flags[n]; - ip->slc[n][1] = slc_default_chars[n]; - slc_response[slc_length++] = SLC_DEFAULT; - } else { - slc_response[slc_length++] = ip->slc[n][0]; - } - slc_response[slc_length++] = ip->slc[n][1]; - } - break; - } - } - - slc_response[slc_length++] = ip->sb_buf[x]--; - - /* If the first octet is out of range, we don't support it */ - /* If the default flag is not supported, we don't support it */ - if (ip->sb_buf[x] >= NSLC || slc_default_flags[ip->sb_buf[x]] == SLC_NOSUPPORT) { - slc_response[slc_length++] = SLC_NOSUPPORT; - slc_response[slc_length++] = ip->sb_buf[x + 2]; - if ((unsigned char)ip->sb_buf[x + 2] == IAC) - slc_response[slc_length++] = IAC; - continue; - } - - switch ((ip->sb_buf[x + 1] & SLC_LEVELBITS)) { - case SLC_NOSUPPORT: - if (slc_default_flags[ip->sb_buf[x]] == SLC_CANTCHANGE) { - slc_response[slc_length++] = SLC_CANTCHANGE; - slc_response[slc_length++] = ip->slc[ip->sb_buf[x]][1]; - break; - } - slc_response[slc_length++] = SLC_ACK | SLC_NOSUPPORT; - slc_response[slc_length++] = ip->sb_buf[x + 2]; - ip->slc[ip->sb_buf[x]][0] = SLC_NOSUPPORT; - ip->slc[ip->sb_buf[x]][1] = 0; - break; - - case SLC_VARIABLE: - if (slc_default_flags[ip->sb_buf[x]] == SLC_CANTCHANGE) { - slc_response[slc_length++] = SLC_CANTCHANGE; - slc_response[slc_length++] = ip->slc[ip->sb_buf[x]][1]; - break; - } - slc_response[slc_length++] = SLC_ACK | SLC_VARIABLE; - slc_response[slc_length++] = ip->sb_buf[x + 2]; - ip->slc[ip->sb_buf[x]][0] = ip->sb_buf[x + 1]; - ip->slc[ip->sb_buf[x]][1] = ip->sb_buf[x + 2]; - break; - - case SLC_CANTCHANGE: - slc_response[slc_length++] = SLC_ACK | SLC_CANTCHANGE; - slc_response[slc_length++] = ip->sb_buf[x + 2]; - ip->slc[ip->sb_buf[x]][0] = ip->sb_buf[x + 1]; - ip->slc[ip->sb_buf[x]][1] = ip->sb_buf[x + 2]; - break; - - case SLC_DEFAULT: - slc_response[slc_length++] = slc_default_flags[ip->sb_buf[x]]; - slc_response[slc_length++] = slc_default_flags[ip->sb_buf[x]]; - ip->slc[ip->sb_buf[x]][0] = slc_default_flags[ip->sb_buf[x]]; - ip->slc[ip->sb_buf[x]][1] = slc_default_chars[ip->sb_buf[x]]; - break; - - default: - slc_response[slc_length++] = SLC_NOSUPPORT; - slc_response[slc_length++] = ip->sb_buf[x + 2]; - if ((unsigned char)slc_response[slc_length - 1] == IAC) - slc_response[slc_length++] = IAC; - break; - } - } - - if (slc_length > 4) { - /* send our response */ - slc_response[slc_length++] = IAC; - slc_response[slc_length++] = SE; - add_binary_message(ip->ob, slc_response, slc_length); - } - } - break; - - case DO: - { - unsigned char sb_wont[] = { IAC, SB, TELOPT_LINEMODE, WONT, 0, IAC, SE }; - - /* send back IAC SB TELOPT_LINEMODE WONT x IAC SE */ - sb_wont[4] = ip->sb_buf[2]; - add_binary_message(ip->ob, sb_wont, sizeof(sb_wont)); - } - break; - - case WILL: - { - unsigned char sb_dont[] = { IAC, SB, TELOPT_LINEMODE, DONT, 0, IAC, SE }; - - /* send back IAC SB TELOPT_LINEMODE DONT x IAC SE */ - sb_dont[4] = ip->sb_buf[2]; - add_binary_message(ip->ob, sb_dont, sizeof(sb_dont)); - } - break; - } - break; - - case TELOPT_NAWS: - if (ip->sb_pos >= 5) { - push_number(((unsigned char)ip->sb_buf[1] << 8) | (unsigned char)ip->sb_buf[2]); - push_number(((unsigned char)ip->sb_buf[3] << 8) | (unsigned char)ip->sb_buf[4]); - apply(APPLY_WINDOW_SIZE, ip->ob, 2, ORIGIN_DRIVER); - } - break; - - case TELOPT_TTYPE: - if (!ip->sb_buf[1]) { - copy_and_push_string(ip->sb_buf + 2); - apply(APPLY_TERMINAL_TYPE, ip->ob, 1, ORIGIN_DRIVER); - } - break; - case TELOPT_ZMP: - { - array_t *arr = allocate_array(max_array_size); - ip->sb_buf = (char *)REALLOC(ip->sb_buf, MAX(ip->sb_pos + 2, SB_SIZE)); - ip->sb_size = MAX(ip->sb_pos + 2, SB_SIZE); - ip->sb_buf[ip->sb_pos] = 0; - copy_and_push_string(ip->sb_buf+1); - int off=0; - int aro = 0; - while(1){ - off += strlen(ip->sb_buf+1+off)+2; - if(off >= ip->sb_pos-1) - break; - arr->item[aro].u.string = string_copy(&ip->sb_buf[off], "ZMP"); - arr->item[aro].type = T_STRING; - arr->item[aro++].subtype = STRING_MALLOC; - } - arr = resize_array(arr, aro); - push_refed_array(arr); - apply(APPLY_ZMP, ip->ob, 2, ORIGIN_DRIVER); - - } + case TELOPT_COMPRESS : + if(!ip->compressed_stream){ + add_binary_message(ip->ob, telnet_compress_v1_response, + sizeof(telnet_compress_v1_response)); + start_compression(ip); + } + break; + case TELOPT_COMPRESS2 : + if(!ip->compressed_stream){ + add_binary_message(ip->ob, telnet_compress_v2_response, + sizeof(telnet_compress_v2_response)); + start_compression(ip); + } + break; +#endif + case TELOPT_ZMP : + ip->iflags |= USING_ZMP; + break; + default: + wont_response[2] = from[i]; + add_binary_message(ip->ob, wont_response, sizeof(wont_response)); + break; + } + ip->state = TS_DATA; break; - case TELOPT_GMCP: - ip->sb_buf[ip->sb_pos] = 0; - copy_and_push_string(&ip->sb_buf[1]); - apply(APPLY_GMCP, ip->ob, 1, ORIGIN_DRIVER); - break; - default: - for (x = 0; x < ip->sb_pos; x++) - ip->sb_buf[x] = (ip->sb_buf[x] ? ip->sb_buf[x] : 'I'); - copy_and_push_string(ip->sb_buf); - apply(APPLY_TELNET_SUBOPTION, ip->ob, 1, ORIGIN_DRIVER); - break; - } - break; - - default: - /* - * Apparently, old versions of MudOS would revert to TS_DATA here. - * Later versions handle the IAC, and then go back to TS_DATA mode. - * I don't think either is proper, but the related RFC documents - * aren't clear on what to do (854, 855). It is my feeling, that - * the safest thing to do here is to ignore the option. - * -- Marius, 6-Jun-2000 - */ - ip->state = TS_SB; - break; - } - break; - } - } - - if (ip->text_end > start) { - /* handle snooping - snooper does not see type-ahead due to + + case TS_DONT: + switch ((unsigned char)from[i]) { + case TELOPT_SGA: + if (ip->iflags & USING_LINEMODE) { + ip->iflags &= ~SUPPRESS_GA; + add_binary_message(ip->ob, telnet_no_single, sizeof(telnet_no_single)); + } + break; +#ifdef HAVE_ZLIB + case TELOPT_COMPRESS2: + // If we are told not to use v2, then try v1. + add_binary_message(ip->ob, telnet_compress_send_request_v1, + sizeof(telnet_compress_send_request_v1)); + break; +#endif + } + ip->state = TS_DATA; + break; + + case TS_SB: + if ((unsigned char)from[i] == IAC) { + ip->state = TS_SB_IAC; + break; + } + if (ip->sb_pos < ip->sb_size - 1) + ip->sb_buf[ip->sb_pos++] = from[i]; + else if(ip->sb_size < MAX_STRING_LENGTH){ + ip->sb_size*=2; + if(ip->sb_size > MAX_STRING_LENGTH) + ip->sb_size = MAX_STRING_LENGTH; + ip->sb_buf = (unsigned char *)REALLOC(ip->sb_buf, ip->sb_size); + if (ip->sb_pos < ip->sb_size - 1) + ip->sb_buf[ip->sb_pos++] = from[i]; + } + break; + + case TS_SB_IAC: + switch ((unsigned char)from[i]) { + case IAC: + if (ip->sb_pos < SB_SIZE - 1) { + ip->sb_buf[ip->sb_pos++] = from[i]; + ip->state = TS_SB; + } + break; + + case SE: + ip->state = TS_DATA; + ip->sb_buf[ip->sb_pos] = 0; + switch ((unsigned char)ip->sb_buf[0]) { + + case TELOPT_NEW_ENVIRON : + { + int j, k; + char env_buf[BUF_SIZE]; + j = 0; + k = 1; + while(ip->sb_buf[k] > -1 && k < (ip->sb_pos - 1)){ + k++; + if(!(ip->sb_buf[k])) env_buf[j] = ENV_FILLER; + if(ip->sb_buf[k] == 1) env_buf[j] = 1; + if((ip->sb_buf[k] > 31)){ + env_buf[j] = ip->sb_buf[k]; + } + if(env_buf[j]) j++; + } + env_buf[j] = 0; + copy_and_push_string(env_buf); + apply(APPLY_RECEIVE_ENVIRON, ip->ob, 1, ORIGIN_DRIVER); + break; + + } + case TELOPT_LINEMODE: + switch ((unsigned char)ip->sb_buf[1]) { + case LM_MODE: + /* Don't do anything with an ACK */ + if (!(ip->sb_buf[2] & MODE_ACK)) { + unsigned char sb_ack[] = { IAC, SB, TELOPT_LINEMODE, LM_MODE, MODE_EDIT | MODE_TRAPSIG | MODE_ACK, IAC, SE }; + + /* Accept only EDIT and TRAPSIG && force them too */ + add_binary_message(ip->ob, sb_ack, sizeof(sb_ack)); + } + break; + + case LM_SLC: + { + int slc_length = 4; + unsigned char slc_response[SB_SIZE + 6] = { IAC, SB, TELOPT_LINEMODE, LM_SLC }; + + for (x = 2; x < ip->sb_pos; x += 3) { + /* no response for an ack */ + if (ip->sb_buf[x + 1] & SLC_ACK) + continue; + + /* If we get { 0, SLC_DEFAULT, 0 } or { 0, SLC_VARIABLE, 0 } return a list of values */ + /* If it's SLC_DEFAULT, reset to defaults first */ + if (!ip->sb_buf[x] && !ip->sb_buf[x + 2]) { + if (ip->sb_buf[x + 1] == SLC_DEFAULT || ip->sb_buf[x + 1] == SLC_VARIABLE) { + int n; + + for (n = 0; n < NSLC; n++) { + slc_response[slc_length++] = n + 1; + if (ip->sb_buf[x + 1] == SLC_DEFAULT) { + ip->slc[n][0] = slc_default_flags[n]; + ip->slc[n][1] = slc_default_chars[n]; + slc_response[slc_length++] = SLC_DEFAULT; + } else { + slc_response[slc_length++] = ip->slc[n][0]; + } + slc_response[slc_length++] = ip->slc[n][1]; + } + break; + } + } + + slc_response[slc_length++] = ip->sb_buf[x]--; + + /* If the first octet is out of range, we don't support it */ + /* If the default flag is not supported, we don't support it */ + if (ip->sb_buf[x] >= NSLC || slc_default_flags[ip->sb_buf[x]] == SLC_NOSUPPORT) { + slc_response[slc_length++] = SLC_NOSUPPORT; + slc_response[slc_length++] = ip->sb_buf[x + 2]; + if ((unsigned char)ip->sb_buf[x + 2] == IAC) + slc_response[slc_length++] = IAC; + continue; + } + + switch ((ip->sb_buf[x + 1] & SLC_LEVELBITS)) { + case SLC_NOSUPPORT: + if (slc_default_flags[ip->sb_buf[x]] == SLC_CANTCHANGE) { + slc_response[slc_length++] = SLC_CANTCHANGE; + slc_response[slc_length++] = ip->slc[ip->sb_buf[x]][1]; + break; + } + slc_response[slc_length++] = SLC_ACK | SLC_NOSUPPORT; + slc_response[slc_length++] = ip->sb_buf[x + 2]; + ip->slc[ip->sb_buf[x]][0] = SLC_NOSUPPORT; + ip->slc[ip->sb_buf[x]][1] = 0; + break; + + case SLC_VARIABLE: + if (slc_default_flags[ip->sb_buf[x]] == SLC_CANTCHANGE) { + slc_response[slc_length++] = SLC_CANTCHANGE; + slc_response[slc_length++] = ip->slc[ip->sb_buf[x]][1]; + break; + } + slc_response[slc_length++] = SLC_ACK | SLC_VARIABLE; + slc_response[slc_length++] = ip->sb_buf[x + 2]; + ip->slc[ip->sb_buf[x]][0] = ip->sb_buf[x + 1]; + ip->slc[ip->sb_buf[x]][1] = ip->sb_buf[x + 2]; + break; + + case SLC_CANTCHANGE: + slc_response[slc_length++] = SLC_ACK | SLC_CANTCHANGE; + slc_response[slc_length++] = ip->sb_buf[x + 2]; + ip->slc[ip->sb_buf[x]][0] = ip->sb_buf[x + 1]; + ip->slc[ip->sb_buf[x]][1] = ip->sb_buf[x + 2]; + break; + + case SLC_DEFAULT: + slc_response[slc_length++] = slc_default_flags[ip->sb_buf[x]]; + slc_response[slc_length++] = slc_default_flags[ip->sb_buf[x]]; + ip->slc[ip->sb_buf[x]][0] = slc_default_flags[ip->sb_buf[x]]; + ip->slc[ip->sb_buf[x]][1] = slc_default_chars[ip->sb_buf[x]]; + break; + + default: + slc_response[slc_length++] = SLC_NOSUPPORT; + slc_response[slc_length++] = ip->sb_buf[x + 2]; + if ((unsigned char)slc_response[slc_length - 1] == IAC) + slc_response[slc_length++] = IAC; + break; + } + } + + if (slc_length > 4) { + /* send our response */ + slc_response[slc_length++] = IAC; + slc_response[slc_length++] = SE; + add_binary_message(ip->ob, slc_response, slc_length); + } + } + break; + + case DO: + { + unsigned char sb_wont[] = { IAC, SB, TELOPT_LINEMODE, WONT, 0, IAC, SE }; + + /* send back IAC SB TELOPT_LINEMODE WONT x IAC SE */ + sb_wont[4] = ip->sb_buf[2]; + add_binary_message(ip->ob, sb_wont, sizeof(sb_wont)); + } + break; + + case WILL: + { + unsigned char sb_dont[] = { IAC, SB, TELOPT_LINEMODE, DONT, 0, IAC, SE }; + + /* send back IAC SB TELOPT_LINEMODE DONT x IAC SE */ + sb_dont[4] = ip->sb_buf[2]; + add_binary_message(ip->ob, sb_dont, sizeof(sb_dont)); + } + break; + } + break; + + case TELOPT_NAWS: + if (ip->sb_pos >= 5) { + push_number(((unsigned char)ip->sb_buf[1] << 8) | (unsigned char)ip->sb_buf[2]); + push_number(((unsigned char)ip->sb_buf[3] << 8) | (unsigned char)ip->sb_buf[4]); + apply(APPLY_WINDOW_SIZE, ip->ob, 2, ORIGIN_DRIVER); + } + break; + + case TELOPT_TTYPE: + if (!ip->sb_buf[1]) { + copy_and_push_string(ip->sb_buf + 2); + apply(APPLY_TERMINAL_TYPE, ip->ob, 1, ORIGIN_DRIVER); + } + break; + case TELOPT_ZMP: + { + array_t *arr = allocate_array(max_array_size); + ip->sb_buf = (unsigned char *)REALLOC(ip->sb_buf, MAX(ip->sb_pos + 2, SB_SIZE)); + ip->sb_size = MAX(ip->sb_pos + 2, SB_SIZE); + ip->sb_buf[ip->sb_pos] = 0; + copy_and_push_string((char *)ip->sb_buf+1); + int off=0; + int aro = 0; + while(1){ + off += strlen((char *)ip->sb_buf+1+off)+2; + if(off >= ip->sb_pos-1) + break; + arr->item[aro].u.string = string_copy((char *)&ip->sb_buf[off], "ZMP"); + arr->item[aro].type = T_STRING; + arr->item[aro++].subtype = STRING_MALLOC; + } + arr = resize_array(arr, aro); + push_refed_array(arr); + apply(APPLY_ZMP, ip->ob, 2, ORIGIN_DRIVER); + + } + break; + case TELOPT_GMCP: + ip->sb_buf[ip->sb_pos] = 0; + copy_and_push_string((char *)&ip->sb_buf[1]); + apply(APPLY_GMCP, ip->ob, 1, ORIGIN_DRIVER); + break; + default: + for (x = 0; x < ip->sb_pos; x++) + ip->sb_buf[x] = (ip->sb_buf[x] ? ip->sb_buf[x] : 'I'); + copy_and_push_string((char *)ip->sb_buf); + apply(APPLY_TELNET_SUBOPTION, ip->ob, 1, ORIGIN_DRIVER); + break; + } + break; + + default: + /* + * Apparently, old versions of MudOS would revert to TS_DATA here. + * Later versions handle the IAC, and then go back to TS_DATA mode. + * I don't think either is proper, but the related RFC documents + * aren't clear on what to do (854, 855). It is my feeling, that + * the safest thing to do here is to ignore the option. + * -- Marius, 6-Jun-2000 + */ + ip->state = TS_SB; + break; + } + break; + } + } + + if (ip->text_end > start) { + /* handle snooping - snooper does not see type-ahead due to telnet being in linemode */ - if (!(ip->iflags & NOECHO)) - handle_snoop(ip->text + start, ip->text_end - start, ip); - } + if (!(ip->iflags & NOECHO)) + handle_snoop(ip->text + start, ip->text_end - start, ip); + } } /* @@ -1389,354 +1415,437 @@ static void copy_chars (interactive_t * ip, char * from, int num_bytes) */ static void get_user_data (interactive_t * ip) { - int num_bytes, text_space; - char buf[MAX_TEXT]; - - /* compute how much data we can read right now */ - switch (ip->connection_type) - { - case PORT_TELNET: - text_space = MAX_TEXT - ip->text_end; - - /* check if we need more space */ - if (text_space < MAX_TEXT / 16) { - if (ip->text_start > 0) { - memmove(ip->text, ip->text + ip->text_start, ip->text_end - ip->text_start); - text_space += ip->text_start; - ip->text_end -= ip->text_start; - ip->text_start = 0; - } - - if (text_space < MAX_TEXT / 16) { - /* the user is sending too much data. flush it */ - ip->iflags |= SKIP_COMMAND; - ip->text_start = ip->text_end = 0; - text_space = MAX_TEXT; - } - } - break; - - case PORT_MUD: - if (ip->text_end < 4) - text_space = 4 - ip->text_end; - else - text_space = *(volatile int *)ip->text - ip->text_end + 4; - break; - - default: - text_space = sizeof(buf); - break; - } - - /* read the data from the socket */ - //debug(connections, ("get_user_data: read on fd %d\n", ip->fd)); - num_bytes = OS_socket_read(ip->fd, buf, text_space); - - if (!num_bytes) { - //if (ip->iflags & CLOSING) - // debug_message("get_user_data: tried to read from closing fd.\n"); - ip->iflags |= NET_DEAD; - remove_interactive(ip->ob, 0); - return; - } - - if (num_bytes == -1) { + int num_bytes, text_space; + char buf[MAX_TEXT]; + int ws_space; + /* compute how much data we can read right now */ + switch (ip->connection_type) + { + case PORT_WEBSOCKET: + ws_space = MAX_TEXT - ip->ws_text_end; + /* check if we need more space */ + if (ws_space < MAX_TEXT / 16) { + if (ip->ws_text_start > 0) { + memmove(ip->ws_text, ip->ws_text + ip->ws_text_start, ip->ws_text_end - ip->ws_text_start); + ws_space += ip->ws_text_start; + ip->ws_text_end -= ip->ws_text_start; + ip->ws_text_start = 0; + } + } + if((ip->iflags & HANDSHAKE_COMPLETE) && (!ip->ws_size) && ws_space > 8) + ws_space = 8; //only read the header or we'll end up queueing several websocket packets with no triggers to read them + if(ip->ws_size && ws_space > ip->ws_size) + ws_space = ip->ws_size; //keep the next packet in the socket + case PORT_TELNET: + text_space = MAX_TEXT - ip->text_end; + + /* check if we need more space */ + if (text_space < MAX_TEXT / 16) { + if (ip->text_start > 0) { + memmove(ip->text, ip->text + ip->text_start, ip->text_end - ip->text_start); + text_space += ip->text_start; + ip->text_end -= ip->text_start; + ip->text_start = 0; + } + } + if(ip->connection_type == PORT_WEBSOCKET){ + text_space = MIN(text_space, ws_space); + } + + break; + + case PORT_MUD: + if (ip->text_end < 4) + text_space = 4 - ip->text_end; + else + text_space = *(volatile int *)ip->text - ip->text_end + 4; + break; + + default: + text_space = sizeof(buf); + break; + } + + /* read the data from the socket */ + //debug(connections, ("get_user_data: read on fd %d\n", ip->fd)); + num_bytes = OS_socket_read(ip->fd, buf, text_space); + + if (!num_bytes) { + //if (ip->iflags & CLOSING) + // debug_message("get_user_data: tried to read from closing fd.\n"); + ip->iflags |= NET_DEAD; + remove_interactive(ip->ob, 0); + return; + } + + if (num_bytes == -1) { #ifdef EWOULDBLOCK - if (socket_errno == EWOULDBLOCK) { - // debug(connections, ("get_user_data: read on fd %d: Operation would block.\n", ip->fd)); - return; - } -#endif - // debug_message("get_user_data: read on fd %d\n", ip->fd); - // socket_perror("get_user_data: read", 0); - ip->iflags |= NET_DEAD; - remove_interactive(ip->ob, 0); - return; - } + if (socket_errno == EWOULDBLOCK) { + // debug(connections, ("get_user_data: read on fd %d: Operation would block.\n", ip->fd)); + return; + } +#endif + // debug_message("get_user_data: read on fd %d\n", ip->fd); + // socket_perror("get_user_data: read", 0); + ip->iflags |= NET_DEAD; + remove_interactive(ip->ob, 0); + return; + } #ifdef F_NETWORK_STATS - inet_in_packets++; - inet_in_volume += num_bytes; - external_port[ip->external_port].in_packets++; - external_port[ip->external_port].in_volume += num_bytes; -#endif - - /* process the data that we've just read */ - switch (ip->connection_type) - { - case PORT_TELNET: - copy_chars(ip, buf, num_bytes); - if (cmd_in_buf(ip)) - ip->iflags |= CMD_IN_BUF; - break; - - case PORT_MUD: - memcpy(ip->text + ip->text_end, buf, num_bytes); - ip->text_end += num_bytes; - - if (num_bytes == text_space) { - if (ip->text_end == 4) { - *(volatile int *)ip->text = ntohl(*(int *)ip->text); - if (*(volatile int *)ip->text > MAX_TEXT - 5) - remove_interactive(ip->ob, 0); - } else { - svalue_t value; - - ip->text[ip->text_end] = 0; - if (restore_svalue(ip->text + 4, &value) == 0) { - STACK_INC; - *sp = value; - } else { - push_undefined(); - } - ip->text_end = 0; - apply(APPLY_PROCESS_INPUT, ip->ob, 1, ORIGIN_DRIVER); - } - } - break; - - case PORT_ASCII: - { - char *nl, *p; - - memcpy(ip->text + ip->text_end, buf, num_bytes); - ip->text_end += num_bytes; - - p = ip->text + ip->text_start; - while ((nl = ( char *)memchr(p, '\n', ip->text_end - ip->text_start))) { - ip->text_start = (nl + 1) - ip->text; - - *nl = 0; - if (*(nl - 1) == '\r') - *--nl = 0; - - if (!(ip->ob->flags & O_DESTRUCTED)) { - char *str; - - str = new_string(nl - p, "PORT_ASCII"); - memcpy(str, p, nl - p + 1); - push_malloced_string(str); - apply(APPLY_PROCESS_INPUT, ip->ob, 1, ORIGIN_DRIVER); - } - - if (ip->text_start == ip->text_end) { - ip->text_start = ip->text_end = 0; - break; - } - - p = nl + 1; - } - } - break; + inet_in_packets++; + inet_in_volume += num_bytes; + external_port[ip->external_port].in_packets++; + external_port[ip->external_port].in_volume += num_bytes; +#endif + + /* process the data that we've just read */ + + switch (ip->connection_type) + { + case PORT_WEBSOCKET: + if(ip->iflags & HANDSHAKE_COMPLETE){ + memcpy(ip->ws_text + ip->ws_text_end, buf, num_bytes); + ip->ws_text_end += num_bytes; + if(!ip->ws_size){ + unsigned char *data = (unsigned char *)&ip->ws_text[ip->ws_text_start]; + if(ip->ws_text_end- ip->ws_text_start < 8) + break; + unsigned char msize = data[1]; + int size = msize & 0x7f; + ip->ws_text_start+=2; + if(size == 126){ + size = (data[2] << 8)|data[3]; + ip->ws_text_start+=2; + } + else if(size == 127){ //insane real size + ip->iflags |= NET_DEAD; + remove_interactive(ip->ob, 0); + return; + } + ip->ws_size = size; + if(msize & 0x80){ + memcpy(&ip->ws_mask, &ip->ws_text[ip->ws_text_start], 4); + ip->ws_text_start += 4; + } else ip->ws_mask = 0; + ip->ws_maskoffs = 0; + } + int i; + if(ip->ws_size){ + int *wdata = (int *)&ip->ws_text[ip->ws_text_start]; + int *dest = (int *)&buf[0]; + if(ip->ws_maskoffs){ + int newmask; + for(i=0; i<4;i++) + ((char *)&newmask)[i] = ((char *)&ip->ws_mask)[(i+ip->ws_maskoffs)%4]; + ip->ws_mask = newmask; + ip->ws_maskoffs = 0; + } + i=0; + while(ip->ws_size > 3 && ip->ws_text_end-ip->ws_text_start > 3){ + dest[i] = wdata[i]^ip->ws_mask; + i++; + ip->ws_text_start+=4; + ip->ws_size-=4; + } + num_bytes = i*4; + int left = ip->ws_size; + if(left > ip->ws_text_end-ip->ws_text_start) + left = ip->ws_text_end-ip->ws_text_start; + if(left){ + ip->ws_maskoffs = left; + dest[i] = wdata[i]^ip->ws_mask; + num_bytes += left; + ip->ws_text_start+= left; + ip->ws_size -= left; + } + } +// for(i=0;iws_size = 0; + ip->ws_text_end = 0; + str[num_bytes] = 0; + push_malloced_string(str); + if(current_interactive){ + printf("eek! someone already here\n"); + exit(1); + } + object_t *ob = ip->ob; + set_command_giver(ob); + current_interactive = ob; + apply(APPLY_PROCESS_INPUT, ob, 1, ORIGIN_DRIVER); + set_command_giver(0); + current_interactive = 0; + + break; //they're not allowed to send the other stuff until we replied, so all data should be handshake stuff + } + case PORT_TELNET: + copy_chars(ip, buf, num_bytes); + if (cmd_in_buf(ip)) + ip->iflags |= CMD_IN_BUF; + break; + + case PORT_MUD: + memcpy(ip->text + ip->text_end, buf, num_bytes); + ip->text_end += num_bytes; + + if (num_bytes == text_space) { + if (ip->text_end == 4) { + *(volatile int *)ip->text = ntohl(*(int *)ip->text); + if (*(volatile int *)ip->text > MAX_TEXT - 5) + remove_interactive(ip->ob, 0); + } else { + svalue_t value; + + ip->text[ip->text_end] = 0; + if (restore_svalue(ip->text + 4, &value) == 0) { + STACK_INC; + *sp = value; + } else { + push_undefined(); + } + ip->text_end = 0; + apply(APPLY_PROCESS_INPUT, ip->ob, 1, ORIGIN_DRIVER); + } + } + break; + + case PORT_ASCII: + { + char *nl, *p; + + memcpy(ip->text + ip->text_end, buf, num_bytes); + ip->text_end += num_bytes; + + p = ip->text + ip->text_start; + while ((nl = ( char *)memchr(p, '\n', ip->text_end - ip->text_start))) { + ip->text_start = (nl + 1) - ip->text; + + *nl = 0; + if (*(nl - 1) == '\r') + *--nl = 0; + + if (!(ip->ob->flags & O_DESTRUCTED)) { + char *str; + + str = new_string(nl - p, "PORT_ASCII"); + memcpy(str, p, nl - p + 1); + push_malloced_string(str); + apply(APPLY_PROCESS_INPUT, ip->ob, 1, ORIGIN_DRIVER); + } + + if (ip->text_start == ip->text_end) { + ip->text_start = ip->text_end = 0; + break; + } + + p = nl + 1; + } + } + break; #ifndef NO_BUFFER_TYPE - case PORT_BINARY: - { - buffer_t *buffer; + case PORT_BINARY: + { + buffer_t *buffer; - buffer = allocate_buffer(num_bytes); - memcpy(buffer->item, buf, num_bytes); + buffer = allocate_buffer(num_bytes); + memcpy(buffer->item, buf, num_bytes); - push_refed_buffer(buffer); - apply(APPLY_PROCESS_INPUT, ip->ob, 1, ORIGIN_DRIVER); - } - break; + push_refed_buffer(buffer); + apply(APPLY_PROCESS_INPUT, ip->ob, 1, ORIGIN_DRIVER); + } + break; #endif - } + } } static int clean_buf (interactive_t * ip) { - /* skip null input */ - while (ip->text_start < ip->text_end && !*(ip->text + ip->text_start)) - ip->text_start++; + /* skip null input */ + while (ip->text_start < ip->text_end && !*(ip->text + ip->text_start)) + ip->text_start++; - /* if we've advanced beyond the end of the buffer, reset it */ - if (ip->text_start >= ip->text_end) { - ip->text_start = ip->text_end = 0; - } + /* if we've advanced beyond the end of the buffer, reset it */ + if (ip->text_start >= ip->text_end) { + ip->text_start = ip->text_end = 0; + } - /* if we're skipping the current command, check to see if it has been + /* if we're skipping the current command, check to see if it has been completed yet. if it has, flush it and clear the skip bit */ - if (ip->iflags & SKIP_COMMAND) { - char *p; - - for (p = ip->text + ip->text_start; p < ip->text + ip->text_end; p++) { - if (*p == '\r' || *p == '\n') { - ip->text_start += p - (ip->text + ip->text_start) + 1; - ip->iflags &= ~SKIP_COMMAND; - return clean_buf(ip); - } - } - } - - return (ip->text_end > ip->text_start); + if (ip->iflags & SKIP_COMMAND) { + char *p; + + for (p = ip->text + ip->text_start; p < ip->text + ip->text_end; p++) { + if (*p == '\r' || *p == '\n') { + ip->text_start += p - (ip->text + ip->text_start) + 1; + ip->iflags &= ~SKIP_COMMAND; + return clean_buf(ip); + } + } + } + + return (ip->text_end > ip->text_start); } static int cmd_in_buf (interactive_t * ip) { - char *p; + char *p; - /* do standard input buffer cleanup */ - if (!clean_buf(ip)) - return 0; + /* do standard input buffer cleanup */ + if (!clean_buf(ip)) + return 0; - /* if we're in single character mode, we've got input */ - if (ip->iflags & SINGLE_CHAR) - return 1; + /* if we're in single character mode, we've got input */ + if (ip->iflags & SINGLE_CHAR) + return 1; - /* search for a newline. if found, we have a command */ - for (p = ip->text + ip->text_start; p < ip->text + ip->text_end; p++) { - if (*p == '\r' || *p == '\n') - return 1; - } + /* search for a newline. if found, we have a command */ + for (p = ip->text + ip->text_start; p < ip->text + ip->text_end; p++) { + if (*p == '\r' || *p == '\n') + return 1; + } - /* duh, no command */ - return 0; + /* duh, no command */ + return 0; } static char *first_cmd_in_buf (interactive_t * ip) { - char *p; + char *p; #ifdef GET_CHAR_IS_BUFFERED - static char tmp[2]; + static char tmp[2]; #endif - /* do standard input buffer cleanup */ - if (!clean_buf(ip)) - return 0; + /* do standard input buffer cleanup */ + if (!clean_buf(ip)) + return 0; - p = ip->text + ip->text_start; + p = ip->text + ip->text_start; - /* if we're in single character mode, we've got input */ - if (ip->iflags & SINGLE_CHAR) { - if (*p == 8 || *p == 127) - *p = 0; + /* if we're in single character mode, we've got input */ + if (ip->iflags & SINGLE_CHAR) { + if (*p == 8 || *p == 127) + *p = 0; #ifndef GET_CHAR_IS_BUFFERED - ip->text_start++; - if (!clean_buf(ip)) - ip->iflags &= ~CMD_IN_BUF; - return p; + ip->text_start++; + if (!clean_buf(ip)) + ip->iflags &= ~CMD_IN_BUF; + return p; #else - tmp[0] = *p; - ip->text[ip->text_start++] = 0; - if (!clean_buf(ip)) - ip->iflags &= ~CMD_IN_BUF; - return tmp; -#endif - } - - /* search for the newline */ - while (ip->text[ip->text_start] != '\n' && ip->text[ip->text_start] != '\r') - ip->text_start++; - - /* check for "\r\n" or "\n\r" */ - if (ip->text_start + 1 < ip->text_end && - ((ip->text[ip->text_start] == '\r' && ip->text[ip->text_start + 1] == '\n') || - (ip->text[ip->text_start] == '\n' && ip->text[ip->text_start + 1] == '\r'))) { - ip->text[ip->text_start++] = 0; - } - - ip->text[ip->text_start++] = 0; - if (!cmd_in_buf(ip)) - ip->iflags &= ~CMD_IN_BUF; - - return p; + tmp[0] = *p; + ip->text[ip->text_start++] = 0; + if (!clean_buf(ip)) + ip->iflags &= ~CMD_IN_BUF; + return tmp; +#endif + } + + /* search for the newline */ + while (ip->text[ip->text_start] != '\n' && ip->text[ip->text_start] != '\r') + ip->text_start++; + + /* check for "\r\n" or "\n\r" */ + if (ip->text_start + 1 < ip->text_end && + ((ip->text[ip->text_start] == '\r' && ip->text[ip->text_start + 1] == '\n') || + (ip->text[ip->text_start] == '\n' && ip->text[ip->text_start + 1] == '\r'))) { + ip->text[ip->text_start++] = 0; + } + + ip->text[ip->text_start++] = 0; + if (!cmd_in_buf(ip)) + ip->iflags &= ~CMD_IN_BUF; + + return p; } /* * SIGPIPE handler -- does very little for now. */ #ifndef SIG_IGN #ifdef SIGNAL_FUNC_TAKES_INT -void sigpipe_handler (int sig) +static void sigpipe_handler (int sig) #else -void sigpipe_handler() +static void sigpipe_handler(void) #endif { - debug(connections, ("SIGPIPE received.")); - //don't comment the next line out, i'm pretty sure we'd crash on the next SIGPIPE, they're not worth it - signal(SIGPIPE, sigpipe_handler); + debug(connections, ("SIGPIPE received.")); + //don't comment the next line out, i'm pretty sure we'd crash on the next SIGPIPE, they're not worth it + signal(SIGPIPE, sigpipe_handler); } /* sigpipe_handler() */ #endif -/* - * SIGALRM handler. - */ -#ifdef SIGNAL_FUNC_TAKES_INT -void sigalrm_handler (int sig) -#else -void sigalrm_handler() -#endif -{ - outoftime = 1; -} /* sigalrm_handler() */ int max_fd; INLINE void make_selectmasks() { - int i; - max_fd = addr_server_fd; - /* - * generate readmask and writemask for select() call. - */ - FD_ZERO(&readmask); - FD_ZERO(&writemask); + int i; + max_fd = addr_server_fd; + /* + * generate readmask and writemask for select() call. + */ + FD_ZERO(&readmask); + FD_ZERO(&writemask); #ifdef HAS_CONSOLE - /* set up a console */ - if(has_console > 0) - FD_SET(STDIN_FILENO, &readmask); -#endif - /* - * set new user accept fd in readmask. - */ - for (i = 0; i < 5; i++) { - if (!external_port[i].port) continue; - FD_SET(external_port[i].fd, &readmask); - if(external_port[i].fd > max_fd) - max_fd = external_port[i].fd; - } - /* - * set user fds in readmask. - */ - for (i = 0; i < max_users; i++) { - if (!all_users[i] || (all_users[i]->iflags & (CLOSING | CMD_IN_BUF))) - continue; - /* - * if this user needs more input to make a complete command, set his - * fd so we can get it. - */ - FD_SET(all_users[i]->fd, &readmask); - if(all_users[i]->fd > max_fd) - max_fd = all_users[i]->fd; - if (all_users[i]->message_length != 0) - FD_SET(all_users[i]->fd, &writemask); - } - /* - * if addr_server_fd is set, set its fd in readmask. - */ - if (addr_server_fd >= 0) { - FD_SET(addr_server_fd, &readmask); - - } + /* set up a console */ + if(has_console > 0) + FD_SET(STDIN_FILENO, &readmask); +#endif + /* + * set new user accept fd in readmask. + */ + for (i = 0; i < 5; i++) { + if (!external_port[i].port) continue; + FD_SET(external_port[i].fd, &readmask); + if(external_port[i].fd > max_fd) + max_fd = external_port[i].fd; + } + /* + * set user fds in readmask. + */ + for (i = 0; i < max_users; i++) { + if (!all_users[i] || (all_users[i]->iflags & (CLOSING | CMD_IN_BUF))) + continue; + /* + * if this user needs more input to make a complete command, set his + * fd so we can get it. + */ + FD_SET(all_users[i]->fd, &readmask); + if(all_users[i]->fd > max_fd) + max_fd = all_users[i]->fd; + if (all_users[i]->message_length != 0) + FD_SET(all_users[i]->fd, &writemask); + } + /* + * if addr_server_fd is set, set its fd in readmask. + */ + if (addr_server_fd >= 0) { + FD_SET(addr_server_fd, &readmask); + + } #if defined(PACKAGE_SOCKETS) || defined(PACKAGE_EXTERNAL) - /* - * set fd's for efun sockets. - */ - for (i = 0; i < max_lpc_socks; i++) { - if (lpc_socks[i].state != STATE_CLOSED) { - if (lpc_socks[i].state != STATE_FLUSHING && - (lpc_socks[i].flags & S_WACCEPT) == 0){ - FD_SET(lpc_socks[i].fd, &readmask); - if(lpc_socks[i].fd > max_fd) - max_fd = lpc_socks[i].fd; - } - if (lpc_socks[i].flags & S_BLOCKED){ - FD_SET(lpc_socks[i].fd, &writemask); - if(lpc_socks[i].fd > max_fd) - max_fd = lpc_socks[i].fd; - } - } - } + /* + * set fd's for efun sockets. + */ + for (i = 0; i < max_lpc_socks; i++) { + if (lpc_socks[i].state != STATE_CLOSED) { + if (lpc_socks[i].state != STATE_FLUSHING && + (lpc_socks[i].flags & S_WACCEPT) == 0){ + FD_SET(lpc_socks[i].fd, &readmask); + if(lpc_socks[i].fd > max_fd) + max_fd = lpc_socks[i].fd; + } + if (lpc_socks[i].flags & S_BLOCKED){ + FD_SET(lpc_socks[i].fd, &writemask); + if(lpc_socks[i].fd > max_fd) + max_fd = lpc_socks[i].fd; + } + } + } #endif } /* make_selectmasks() */ @@ -1745,82 +1854,82 @@ INLINE void make_selectmasks() */ INLINE void process_io() { - int i; - - /* - * check for new user connection. - */ - for (i = 0; i < 5; i++) { - if (!external_port[i].port) continue; - if (FD_ISSET(external_port[i].fd, &readmask)) { - debug(connections, ("process_io: NEW_USER\n")); - new_user_handler(i); - } - } - /* - * check for data pending on user connections. - */ - for (i = 0; i < max_users; i++) { - if (!all_users[i] || (all_users[i]->iflags & (CLOSING | CMD_IN_BUF))) - continue; - if (all_users[i]->iflags & NET_DEAD) { - remove_interactive(all_users[i]->ob, 0); - continue; - } - if (FD_ISSET(all_users[i]->fd, &readmask)) { - debug(connections, ("process_io: USER %d\n", i)); - get_user_data(all_users[i]); - if (!all_users[i]) - continue; - } - if (FD_ISSET(all_users[i]->fd, &writemask)) - flush_message(all_users[i]); - } + int i; + + /* + * check for new user connection. + */ + for (i = 0; i < 5; i++) { + if (!external_port[i].port) continue; + if (FD_ISSET(external_port[i].fd, &readmask)) { + debug(connections, ("process_io: NEW_USER\n")); + new_user_handler(i); + } + } + /* + * check for data pending on user connections. + */ + for (i = 0; i < max_users; i++) { + if (!all_users[i] || (all_users[i]->iflags & (CLOSING | CMD_IN_BUF))) + continue; + if (all_users[i]->iflags & NET_DEAD) { + remove_interactive(all_users[i]->ob, 0); + continue; + } + if (FD_ISSET(all_users[i]->fd, &readmask)) { + debug(connections, ("process_io: USER %d\n", i)); + get_user_data(all_users[i]); + if (!all_users[i]) + continue; + } + if (FD_ISSET(all_users[i]->fd, &writemask)) + flush_message(all_users[i]); + } #if defined(PACKAGE_SOCKETS) || defined(PACKAGE_EXTERNAL) - /* - * check for data pending on efun socket connections. - */ - for (i = 0; i < max_lpc_socks; i++) { - if (lpc_socks[i].state != STATE_CLOSED) - if (FD_ISSET(lpc_socks[i].fd, &readmask)) - socket_read_select_handler(i); - if (lpc_socks[i].state != STATE_CLOSED) - if (FD_ISSET(lpc_socks[i].fd, &writemask)) - socket_write_select_handler(i); - } -#endif - /* - * check for data pending from address server. - */ - if (addr_server_fd >= 0) { - if (FD_ISSET(addr_server_fd, &readmask)) { - debug(connections, ("process_io: IP_DAEMON\n")); - hname_handler(); - } - } + /* + * check for data pending on efun socket connections. + */ + for (i = 0; i < max_lpc_socks; i++) { + if (lpc_socks[i].state != STATE_CLOSED) + if (FD_ISSET(lpc_socks[i].fd, &readmask)) + socket_read_select_handler(i); + if (lpc_socks[i].state != STATE_CLOSED) + if (FD_ISSET(lpc_socks[i].fd, &writemask)) + socket_write_select_handler(i); + } +#endif +/* + * check for data pending from address server. + */ + if (addr_server_fd >= 0) { + if (FD_ISSET(addr_server_fd, &readmask)) { + debug(connections, ("process_io: IP_DAEMON\n")); + hname_handler(); + } + } #ifdef HAS_CONSOLE - /* Process console input */ - /* Note: need the has_console on the next line because linux (at least) + /* Process console input */ + /* Note: need the has_console on the next line because linux (at least) recycles fds, even STDIN_FILENO - */ - if((has_console > 0) && FD_ISSET(STDIN_FILENO, &readmask)) { - char s[1024]; - int sz; - - if((sz = read(STDIN_FILENO, s, 1023)) > 0) { - s[sz-1] = '\0'; - console_command(s); - } - else if(sz == 0) { - printf("Console exiting. The MUD remains.\n"); - has_console = 0; - } - else { - printf("Console read error: %d %d. Closing console.\n", sz, errno); - has_console = 0; - restore_sigttin(); - } - } + */ + if((has_console > 0) && FD_ISSET(STDIN_FILENO, &readmask)) { + char s[1024]; + int sz; + + if((sz = read(STDIN_FILENO, s, 1023)) > 0) { + s[sz-1] = '\0'; + console_command(s); + } + else if(sz == 0) { + printf("Console exiting. The MUD remains.\n"); + has_console = 0; + } + else { + printf("Console read error: %d %d. Closing console.\n", sz, errno); + has_console = 0; + restore_sigttin(); + } + } #endif } @@ -1833,756 +1942,760 @@ INLINE void process_io() */ static void new_user_handler (int which) { - int new_socket_fd; + int new_socket_fd; #ifdef IPV6 - struct sockaddr_in6 addr; + struct sockaddr_in6 addr; #else - struct sockaddr_in addr; -#endif - socklen_t length; - int i, x; - object_t *master, *ob; - svalue_t *ret; - - length = sizeof(addr); - debug(connections, ("new_user_handler: accept on fd %d\n", external_port[which].fd)); - new_socket_fd = accept(external_port[which].fd, - (struct sockaddr *) & addr, &length); - if (new_socket_fd < 0) { + struct sockaddr_in addr; +#endif + socklen_t length; + int i, x; + object_t *master, *ob; + svalue_t *ret; + + length = sizeof(addr); + debug(connections, ("new_user_handler: accept on fd %d\n", external_port[which].fd)); + new_socket_fd = accept(external_port[which].fd, + (struct sockaddr *) & addr, &length); + if (new_socket_fd < 0) { #ifdef EWOULDBLOCK - if (socket_errno == EWOULDBLOCK) { - debug(connections, ("new_user_handler: accept: Operation would block\n")); - } else { + if (socket_errno == EWOULDBLOCK) { + debug(connections, ("new_user_handler: accept: Operation would block\n")); + } else { #else - if (1) { -#endif - socket_perror("new_user_handler: accept", 0); - } - return; - } - - /* - * according to Amylaar, 'accepted' sockets in Linux 0.99p6 don't - * properly inherit the nonblocking property from the listening socket. - * Marius, 19-Jun-2000: this happens on other platforms as well, so just - * do it for everyone - */ - if (set_socket_nonblocking(new_socket_fd, 1) == -1) { - socket_perror("new_user_handler: set_socket_nonblocking 1", 0); - OS_socket_close(new_socket_fd); - return; - } + if (1) { +#endif + socket_perror("new_user_handler: accept", 0); + } + return; + } + + /* + * according to Amylaar, 'accepted' sockets in Linux 0.99p6 don't + * properly inherit the nonblocking property from the listening socket. + * Marius, 19-Jun-2000: this happens on other platforms as well, so just + * do it for everyone + */ + if (set_socket_nonblocking(new_socket_fd, 1) == -1) { + socket_perror("new_user_handler: set_socket_nonblocking 1", 0); + OS_socket_close(new_socket_fd); + return; + } #if defined(SO_NOSIGPIPE) - i = 1; - - if (setsockopt(new_socket_fd, 1, SO_NOSIGPIPE, &i, sizeof(i)) == -1) - { - socket_perror("new_user_handler: setsockopt SO_NOSIGPIPE", 0); - /* it's ok if this fails */ - } -#endif - /* find the first available slot */ - for (i = 0; i < max_users; i++) - if (!all_users[i]) break; - - if (i == max_users) { - if (all_users) { - all_users = RESIZE(all_users, max_users + 10, interactive_t *, - TAG_USERS, "new_user_handler"); - } else { - all_users = CALLOCATE(10, interactive_t *, - TAG_USERS, "new_user_handler"); - } - while (max_users < i + 10) - all_users[max_users++] = 0; - } - - set_command_giver(master_ob); - master_ob->interactive = - (interactive_t *) - DXALLOC(sizeof(interactive_t), TAG_INTERACTIVE, - "new_user_handler"); + i = 1; + + if (setsockopt(new_socket_fd, 1, SO_NOSIGPIPE, &i, sizeof(i)) == -1) + { + socket_perror("new_user_handler: setsockopt SO_NOSIGPIPE", 0); + /* it's ok if this fails */ + } +#endif + /* find the first available slot */ + for (i = 0; i < max_users; i++) + if (!all_users[i]) break; + + if (i == max_users) { + if (all_users) { + all_users = RESIZE(all_users, max_users + 10, interactive_t *, + TAG_USERS, "new_user_handler"); + } else { + all_users = CALLOCATE(10, interactive_t *, + TAG_USERS, "new_user_handler"); + } + while (max_users < i + 10) + all_users[max_users++] = 0; + } + + set_command_giver(master_ob); + master_ob->interactive = + (interactive_t *) + DXALLOC(sizeof(interactive_t), TAG_INTERACTIVE, + "new_user_handler"); #ifndef NO_ADD_ACTION - master_ob->interactive->default_err_message.s = 0; -#endif - master_ob->interactive->connection_type = external_port[which].kind; - master_ob->interactive->sb_buf = (char *)MALLOC(SB_SIZE); - master_ob->interactive->sb_size = SB_SIZE; - master_ob->flags |= O_ONCE_INTERACTIVE; - /* - * initialize new user interactive data structure. - */ - master_ob->interactive->ob = master_ob; + master_ob->interactive->default_err_message.s = 0; +#endif + master_ob->interactive->connection_type = external_port[which].kind; + master_ob->interactive->sb_buf = (unsigned char *)DMALLOC(SB_SIZE, + TAG_PERMANENT, "new_user_handler"); + master_ob->interactive->sb_size = SB_SIZE; + master_ob->flags |= O_ONCE_INTERACTIVE; + /* + * initialize new user interactive data structure. + */ + master_ob->interactive->ob = master_ob; #if defined(F_INPUT_TO) || defined(F_GET_CHAR) - master_ob->interactive->input_to = 0; + master_ob->interactive->input_to = 0; #endif - master_ob->interactive->iflags = 0; - master_ob->interactive->text[0] = '\0'; - master_ob->interactive->text_end = 0; - master_ob->interactive->text_start = 0; + master_ob->interactive->iflags = 0; + master_ob->interactive->text[0] = '\0'; + master_ob->interactive->text_end = 0; + master_ob->interactive->text_start = 0; #if defined(F_INPUT_TO) || defined(F_GET_CHAR) - master_ob->interactive->carryover = NULL; - master_ob->interactive->num_carry = 0; + master_ob->interactive->carryover = NULL; + master_ob->interactive->num_carry = 0; #endif #ifndef NO_SNOOP - master_ob->interactive->snooped_by = 0; + master_ob->interactive->snooped_by = 0; #endif - master_ob->interactive->last_time = current_time; + master_ob->interactive->last_time = current_time; #ifdef TRACE - master_ob->interactive->trace_level = 0; - master_ob->interactive->trace_prefix = 0; + master_ob->interactive->trace_level = 0; + master_ob->interactive->trace_prefix = 0; #endif #ifdef OLD_ED - master_ob->interactive->ed_buffer = 0; + master_ob->interactive->ed_buffer = 0; #endif #ifdef HAVE_ZLIB - master_ob->interactive->compressed_stream = NULL; + master_ob->interactive->compressed_stream = NULL; #endif - master_ob->interactive->message_producer = 0; - master_ob->interactive->message_consumer = 0; - master_ob->interactive->message_length = 0; - master_ob->interactive->state = TS_DATA; - master_ob->interactive->out_of_band = 0; + master_ob->interactive->message_producer = 0; + master_ob->interactive->message_consumer = 0; + master_ob->interactive->message_length = 0; + master_ob->interactive->state = TS_DATA; + master_ob->interactive->out_of_band = 0; + master_ob->interactive->ws_text_start = 0; + master_ob->interactive->ws_text_end = 0; + master_ob->interactive->ws_size = 0; #ifdef USE_ICONV - master_ob->interactive->trans = get_translator("UTF-8"); + master_ob->interactive->trans = get_translator("UTF-8"); #else - master_ob->interactive->trans = (struct translation *) master_ob; - //never actually used, but avoids multiple ifdefs later on! -#endif - for (x = 0; x < NSLC; x++) { - master_ob->interactive->slc[x][0] = slc_default_flags[x]; - master_ob->interactive->slc[x][1] = slc_default_chars[x]; - } - all_users[i] = master_ob->interactive; - all_users[i]->fd = new_socket_fd; + master_ob->interactive->trans = (struct translation *) master_ob; + //never actually used, but avoids multiple ifdefs later on! +#endif + for (x = 0; x < NSLC; x++) { + master_ob->interactive->slc[x][0] = slc_default_flags[x]; + master_ob->interactive->slc[x][1] = slc_default_chars[x]; + } + all_users[i] = master_ob->interactive; + all_users[i]->fd = new_socket_fd; #ifdef F_QUERY_IP_PORT - all_users[i]->local_port = external_port[which].port; + all_users[i]->local_port = external_port[which].port; #endif #ifdef F_NETWORK_STATS - all_users[i]->external_port = which; + all_users[i]->external_port = which; #endif - set_prompt("> "); + set_prompt("> "); - memcpy((char *) &all_users[i]->addr, (char *) &addr, length); + memcpy((char *) &all_users[i]->addr, (char *) &addr, length); #ifdef IPV6 - char tmp[INET6_ADDRSTRLEN]; - debug(connections, ("New connection from %s.\n", inet_ntop(AF_INET6, &addr.sin6_addr, &tmp, INET6_ADDRSTRLEN))); + char tmp[INET6_ADDRSTRLEN]; + debug(connections, ("New connection from %s.\n", inet_ntop(AF_INET6, &addr.sin6_addr, &tmp, INET6_ADDRSTRLEN))); #else - debug(connections, ("New connection from %s.\n", inet_ntoa(addr.sin_addr))); -#endif - num_user++; - /* - * The user object has one extra reference. It is asserted that the - * master_ob is loaded. Save a pointer to the master ob incase it - * changes during APPLY_CONNECT. We want to free the reference on - * the right copy of the object. - */ - master = master_ob; - add_ref(master_ob, "new_user"); - push_number(external_port[which].port); - ret = apply_master_ob(APPLY_CONNECT, 1); - /* master_ob->interactive can be zero if the master object self + debug(connections, ("New connection from %s.\n", inet_ntoa(addr.sin_addr))); +#endif + num_user++; + /* + * The user object has one extra reference. It is asserted that the + * master_ob is loaded. Save a pointer to the master ob incase it + * changes during APPLY_CONNECT. We want to free the reference on + * the right copy of the object. + */ + master = master_ob; + add_ref(master_ob, "new_user"); + push_number(external_port[which].port); + ret = apply_master_ob(APPLY_CONNECT, 1); + /* master_ob->interactive can be zero if the master object self destructed in the above (don't ask) */ - set_command_giver(0); - if (ret == 0 || ret == (svalue_t *)-1 || ret->type != T_OBJECT - || !master_ob->interactive) { - if (master_ob->interactive) - remove_interactive(master_ob, 0); - else - free_object(&master, "new_user"); + set_command_giver(0); + if (ret == 0 || ret == (svalue_t *)-1 || ret->type != T_OBJECT + || !master_ob->interactive) { + if (master_ob->interactive) + remove_interactive(master_ob, 0); + else + free_object(&master, "new_user"); #ifdef IPV6 - debug_message("Connection from %s aborted.\n", inet_ntop(AF_INET6, &addr.sin6_addr, tmp, INET6_ADDRSTRLEN)); + debug_message("Connection from %s aborted.\n", inet_ntop(AF_INET6, &addr.sin6_addr, tmp, INET6_ADDRSTRLEN)); #else - debug_message("Connection from %s aborted.\n", inet_ntoa(addr.sin_addr)); -#endif - return; - } - /* - * There was an object returned from connect(). Use this as the user - * object. - */ - ob = ret->u.ob; + debug_message("Connection from %s aborted.\n", inet_ntoa(addr.sin_addr)); +#endif + return; + } + /* + * There was an object returned from connect(). Use this as the user + * object. + */ + ob = ret->u.ob; #ifdef F_SET_HIDE - if (ob->flags & O_HIDDEN) - num_hidden_users++; -#endif - ob->interactive = master_ob->interactive; - ob->interactive->ob = ob; - ob->flags |= O_ONCE_INTERACTIVE; - /* - * assume the existance of write_prompt and process_input in user.c - * until proven wrong (after trying to call them). - */ - ob->interactive->iflags |= (HAS_WRITE_PROMPT | HAS_PROCESS_INPUT); - - free_object(&master, "new_user"); - - master_ob->flags &= ~O_ONCE_INTERACTIVE; - master_ob->interactive = 0; - add_ref(ob, "new_user"); - set_command_giver(ob); - if (addr_server_fd >= 0) { - query_addr_name(ob); - } - - if (external_port[which].kind == PORT_TELNET) { - /* Ask permission to ask them for their terminal type */ - add_binary_message(ob, telnet_do_ttype, sizeof(telnet_do_ttype)); - /* Ask them for their window size */ - add_binary_message(ob, telnet_do_naws, sizeof(telnet_do_naws)); + if (ob->flags & O_HIDDEN) + num_hidden_users++; +#endif + ob->interactive = master_ob->interactive; + ob->interactive->ob = ob; + ob->flags |= O_ONCE_INTERACTIVE; + /* + * assume the existance of write_prompt and process_input in user.c + * until proven wrong (after trying to call them). + */ + ob->interactive->iflags |= (HAS_WRITE_PROMPT | HAS_PROCESS_INPUT); + + free_object(&master, "new_user"); + + master_ob->flags &= ~O_ONCE_INTERACTIVE; + master_ob->interactive = 0; + add_ref(ob, "new_user"); + set_command_giver(ob); + if (addr_server_fd >= 0) { + query_addr_name(ob); + } + + if (external_port[which].kind == PORT_TELNET) { + /* Ask permission to ask them for their terminal type */ + add_binary_message(ob, telnet_do_ttype, sizeof(telnet_do_ttype)); + /* Ask them for their window size */ + add_binary_message(ob, telnet_do_naws, sizeof(telnet_do_naws)); #ifdef HAVE_ZLIB - add_binary_message(ob, telnet_compress_send_request_v2, - sizeof(telnet_compress_send_request_v2)); -#endif - // Ask them if they support mxp. - add_binary_message(ob, telnet_do_mxp, sizeof(telnet_do_mxp)); - // And mssp - add_binary_message(ob, telnet_will_mssp, sizeof(telnet_will_mssp)); - // May as well ask for zmp while we're there! - add_binary_message(ob, telnet_will_zmp, sizeof(telnet_will_zmp)); - // Also newenv - add_binary_message(ob, telnet_do_newenv, sizeof(telnet_do_newenv)); - // gmcp *yawn* - add_binary_message(ob, telnet_do_gmcp, sizeof(telnet_do_gmcp)); - } - - logon(ob); - debug(connections, ("new_user_handler: end\n")); - set_command_giver(0); + add_binary_message(ob, telnet_compress_send_request_v2, + sizeof(telnet_compress_send_request_v2)); +#endif + // Ask them if they support mxp. + add_binary_message(ob, telnet_do_mxp, sizeof(telnet_do_mxp)); + // And mssp + add_binary_message(ob, telnet_will_mssp, sizeof(telnet_will_mssp)); + // May as well ask for zmp while we're there! + add_binary_message(ob, telnet_will_zmp, sizeof(telnet_will_zmp)); + // Also newenv + add_binary_message(ob, telnet_do_newenv, sizeof(telnet_do_newenv)); + // gmcp *yawn* + add_binary_message(ob, telnet_will_gmcp, sizeof(telnet_will_gmcp)); + } + + logon(ob); + debug(connections, ("new_user_handler: end\n")); + set_command_giver(0); } /* new_user_handler() */ -/* - * Return the first command of the next user in sequence that has a complete - * command in their buffer. A command is defined to be a single character - * when SINGLE_CHAR is set, or a newline terminated string otherwise. - */ + /* + * Return the first command of the next user in sequence that has a complete + * command in their buffer. A command is defined to be a single character + * when SINGLE_CHAR is set, or a newline terminated string otherwise. + */ static char *get_user_command() { - static int NextCmdGiver = 0; - - int i; - interactive_t *ip; - char *user_command = 0; - - /* find and return a user command */ - for (i = 0; i < max_users; i++) { - ip = all_users[NextCmdGiver++]; - NextCmdGiver %= max_users; - - if (!ip || !ip->ob || ip->ob->flags & O_DESTRUCTED) - continue; - - /* if we've got text to send, try to flush it, could lose the link here */ - if (ip->message_length) { - object_t *ob = ip->ob; - flush_message(ip); - if (!IP_VALID(ip, ob) || (ip->iflags & NET_DEAD)) - continue; - } - - /* if there's a command in the buffer, pull it out! */ - if (ip->iflags & CMD_IN_BUF) { - NextCmdGiver++; - NextCmdGiver %= max_users; - user_command = first_cmd_in_buf(ip); - break; - } - } - - /* no command found - return 0 */ - if (!user_command) - return 0; - - /* got a command - return it and set command_giver */ - debug(connections, ("get_user_command: user_command = (%s)\n", user_command)); - save_command_giver(ip->ob); + static int NextCmdGiver = 0; + + int i; + interactive_t *ip; + char *user_command = 0; + + /* find and return a user command */ + for (i = 0; i < max_users; i++) { + ip = all_users[NextCmdGiver++]; + NextCmdGiver %= max_users; + + if (!ip || !ip->ob || ip->ob->flags & O_DESTRUCTED) + continue; + + /* if we've got text to send, try to flush it, could lose the link here */ + if (ip->message_length) { + object_t *ob = ip->ob; + flush_message(ip); + if (!IP_VALID(ip, ob) || (ip->iflags & NET_DEAD)) + continue; + } + + /* if there's a command in the buffer, pull it out! */ + if (ip->iflags & CMD_IN_BUF) { + user_command = first_cmd_in_buf(ip); + break; + } + } + + /* no command found - return 0 */ + if (!user_command) + return 0; + + /* got a command - return it and set command_giver */ + debug(connections, ("get_user_command: user_command = (%s)\n", user_command)); + save_command_giver(ip->ob); #ifndef GET_CHAR_IS_BUFFERED - if (ip->iflags & NOECHO) { + if (ip->iflags & NOECHO) { #else - if ((ip->iflags & NOECHO) && !(ip->iflags & SINGLE_CHAR)) { + if ((ip->iflags & NOECHO) && !(ip->iflags & SINGLE_CHAR)) { #endif - /* must not enable echo before the user input is received */ - add_binary_message(command_giver, telnet_no_echo, sizeof(telnet_no_echo)); - ip->iflags &= ~NOECHO; - } + /* must not enable echo before the user input is received */ + add_binary_message(command_giver, telnet_no_echo, sizeof(telnet_no_echo)); + ip->iflags &= ~NOECHO; + } - ip->last_time = current_time; - return user_command; -} /* get_user_command() */ + ip->last_time = current_time; + return user_command; + } /* get_user_command() */ -static int escape_command (interactive_t * ip, char * user_command) -{ - if (user_command[0] != '!') - return 0; + static int escape_command (interactive_t * ip, char * user_command) + { + if (user_command[0] != '!') + return 0; #ifdef OLD_ED - if (ip->ed_buffer) - return 1; + if (ip->ed_buffer) + return 1; #endif #if defined(F_INPUT_TO) || defined(F_GET_CHAR) - if (ip->input_to && ( !(ip->iflags & NOESC) && !(ip->iflags & I_SINGLE_CHAR) ) ) - return 1; + if (ip->input_to && ( !(ip->iflags & NOESC) && !(ip->iflags & I_SINGLE_CHAR) ) ) + return 1; #endif - return 0; -} + return 0; + } -static void process_input (interactive_t * ip, char * user_command) -{ - svalue_t *ret; - - if (!(ip->iflags & HAS_PROCESS_INPUT)) { - parse_command(user_command, command_giver); - return; - } - - /* - * send a copy of user input back to user object to provide - * support for things like command history and mud shell - * programming languages. - */ - copy_and_push_string(user_command); - ret = apply(APPLY_PROCESS_INPUT, command_giver, 1, ORIGIN_DRIVER); - if (!IP_VALID(ip, command_giver)) - return; - if (!ret) { - ip->iflags &= ~HAS_PROCESS_INPUT; - parse_command(user_command, command_giver); - return; - } + static void process_input (interactive_t * ip, char * user_command) + { + svalue_t *ret; -#ifndef NO_ADD_ACTION - if (ret->type == T_STRING) { - static char buf[MAX_TEXT]; + if (!(ip->iflags & HAS_PROCESS_INPUT)) { + parse_command(user_command, command_giver); + return; + } - strncpy(buf, ret->u.string, MAX_TEXT - 1); - parse_command(buf, command_giver); - } else { - if (ret->type != T_NUMBER || !ret->u.number) - parse_command(user_command, command_giver); - } + /* + * send a copy of user input back to user object to provide + * support for things like command history and mud shell + * programming languages. + */ + copy_and_push_string(user_command); + ret = apply(APPLY_PROCESS_INPUT, command_giver, 1, ORIGIN_DRIVER); + if (!IP_VALID(ip, command_giver)) + return; + if (!ret) { + ip->iflags &= ~HAS_PROCESS_INPUT; + parse_command(user_command, command_giver); + return; + } + +#ifndef NO_ADD_ACTION + if (ret->type == T_STRING) { + static char buf[MAX_TEXT]; + + strncpy(buf, ret->u.string, MAX_TEXT - 1); + parse_command(buf, command_giver); + } else { + if (ret->type != T_NUMBER || !ret->u.number) + parse_command(user_command, command_giver); + } #endif -} + } -/* - * This is the user command handler. This function is called when - * a user command needs to be processed. - * This function calls get_user_command() to get a user command. - * One user command is processed per execution of this function. - */ -int process_user_command() -{ - char *user_command; - interactive_t *ip=NULL;//for if(ip) below - - /* - * WARNING: get_user_command() sets command_giver via - * save_command_giver(), but only when the return is non-zero! - */ - if (!(user_command = get_user_command())) - return 0; - - if(command_giver) ip = command_giver->interactive; - current_interactive = command_giver; /* this is yuck phooey, sigh */ - if(ip) clear_notify(ip->ob); - update_load_av(); - debug(connections, ("process_user_command: command_giver = /%s\n", command_giver->obname)); - - if(!ip) - goto exit; - - user_command = translate_easy(ip->trans->incoming, user_command); - - if(ip->iflags & USING_MXP && user_command[0] == ' ' && user_command[1] == '[' && user_command[3] == 'z' ){ - svalue_t *ret; - copy_and_push_string(user_command); - - ret=apply(APPLY_MXP_TAG, ip->ob, 1, ORIGIN_DRIVER); - if(ret && ret->type==T_NUMBER && ret->u.number){ - goto exit; - } - } - - if (escape_command(ip, user_command)) { - if (ip->iflags & SINGLE_CHAR) { - /* only 1 char ... switch to line buffer mode */ - ip->iflags |= WAS_SINGLE_CHAR; - ip->iflags &= ~SINGLE_CHAR; + /* + * This is the user command handler. This function is called when + * a user command needs to be processed. + * This function calls get_user_command() to get a user command. + * One user command is processed per execution of this function. + */ + int process_user_command() + { + char *user_command; + interactive_t *ip=NULL;//for if(ip) below + + /* + * WARNING: get_user_command() sets command_giver via + * save_command_giver(), but only when the return is non-zero! + */ + if (!(user_command = get_user_command())) + return 0; + + if(command_giver) ip = command_giver->interactive; + current_interactive = command_giver; /* this is yuck phooey, sigh */ + if(ip) clear_notify(ip->ob); + update_load_av(); + debug(connections, ("process_user_command: command_giver = /%s\n", command_giver->obname)); + + if(!ip) + goto exit; + + user_command = translate_easy(ip->trans->incoming, user_command); + + if(ip->iflags & USING_MXP && user_command[0] == ' ' && user_command[1] == '[' && user_command[3] == 'z' ){ + svalue_t *ret; + copy_and_push_string(user_command); + + ret=apply(APPLY_MXP_TAG, ip->ob, 1, ORIGIN_DRIVER); + if(ret && ret->type==T_NUMBER && ret->u.number){ + goto exit; + } + } + + if (escape_command(ip, user_command)) { + if (ip->iflags & SINGLE_CHAR) { + /* only 1 char ... switch to line buffer mode */ + ip->iflags |= WAS_SINGLE_CHAR; + ip->iflags &= ~SINGLE_CHAR; #ifdef GET_CHAR_IS_BUFFERED - ip->text_start = ip->text_end = *ip->text = 0; -#endif - set_linemode(ip); - } else { - if (ip->iflags & WAS_SINGLE_CHAR) { - /* we now have a string ... switch back to char mode */ - ip->iflags &= ~WAS_SINGLE_CHAR; - ip->iflags |= SINGLE_CHAR; - set_charmode(ip); - if (!IP_VALID(ip, command_giver)) { - goto exit; - } - } - - process_input(ip, user_command + 1); - } - - goto exit; - } + ip->text_start = ip->text_end = *ip->text = 0; +#endif + set_linemode(ip); + } else { + if (ip->iflags & WAS_SINGLE_CHAR) { + /* we now have a string ... switch back to char mode */ + ip->iflags &= ~WAS_SINGLE_CHAR; + ip->iflags |= SINGLE_CHAR; + set_charmode(ip); + if (!IP_VALID(ip, command_giver)) { + goto exit; + } + } + + process_input(ip, user_command + 1); + } + + goto exit; + } #ifdef OLD_ED - if (ip->ed_buffer) { - ed_cmd(user_command); - goto exit; - } + if (ip->ed_buffer) { + ed_cmd(user_command); + goto exit; + } #endif #if defined(F_INPUT_TO) || defined(F_GET_CHAR) - if (call_function_interactive(ip, user_command)) { - goto exit; - } + if (call_function_interactive(ip, user_command)) { + goto exit; + } #endif - process_input(ip, user_command); + process_input(ip, user_command); -exit: - /* - * Print a prompt if user is still here. - */ - if (IP_VALID(ip, command_giver)) - print_prompt(ip); + exit: + /* + * Print a prompt if user is still here. + */ + if (IP_VALID(ip, command_giver)) + print_prompt(ip); - current_interactive = 0; - restore_command_giver(); - return 1; -} + current_interactive = 0; + restore_command_giver(); + return 1; + } #define HNAME_BUF_SIZE 200 -/* - * This is the hname input data handler. This function is called by the - * master handler when data is pending on the hname socket (addr_server_fd). - */ - -static void hname_handler() -{ - static char hname_buf[HNAME_BUF_SIZE]; - static int hname_buf_pos; - int num_bytes; - - num_bytes = HNAME_BUF_SIZE - hname_buf_pos - 1; /* room for nul */ - num_bytes = OS_socket_read(addr_server_fd, hname_buf + hname_buf_pos, num_bytes); - if (num_bytes <= 0) { - if (num_bytes == -1) { + /* + * This is the hname input data handler. This function is called by the + * master handler when data is pending on the hname socket (addr_server_fd). + */ + + static void hname_handler() + { + static char hname_buf[HNAME_BUF_SIZE]; + static int hname_buf_pos; + int num_bytes; + + num_bytes = HNAME_BUF_SIZE - hname_buf_pos - 1; /* room for nul */ + num_bytes = OS_socket_read(addr_server_fd, hname_buf + hname_buf_pos, num_bytes); + if (num_bytes <= 0) { + if (num_bytes == -1) { #ifdef EWOULDBLOCK - if (socket_errno == EWOULDBLOCK) { - debug(connections, ("hname_handler: read on fd %d: Operation would block.\n", - addr_server_fd)); - return; - } -#endif - debug_message("hname_handler: read on fd %d\n", addr_server_fd); - socket_perror("hname_handler: read", 0); - } else { - debug_message("hname_handler: closing address server connection.\n"); - } - OS_socket_close(addr_server_fd); - addr_server_fd = -1; - return; - } - - hname_buf_pos += num_bytes; - hname_buf[hname_buf_pos] = 0; - debug(connections, ("hname_handler: address server replies: %s", hname_buf)); - - while (hname_buf_pos) { - char *nl, *pp; - - /* if there's no newline, there's more data to come */ - if (!(nl = strchr(hname_buf, '\n'))) - break; - *nl++ = 0; - - if ((pp = strchr(hname_buf, ' ')) != 0) { - *pp++ = 0; - got_addr_number(pp, hname_buf); - - if (isdigit(hname_buf[0]) || hname_buf[0] == ':') { + if (socket_errno == EWOULDBLOCK) { + debug(connections, ("hname_handler: read on fd %d: Operation would block.\n", + addr_server_fd)); + return; + } +#endif + debug_message("hname_handler: read on fd %d\n", addr_server_fd); + socket_perror("hname_handler: read", 0); + } else { + debug_message("hname_handler: closing address server connection.\n"); + } + OS_socket_close(addr_server_fd); + addr_server_fd = -1; + return; + } -#ifdef IPV6 - struct in6_addr addr; - int ret; - if(1 ==(ret = inet_pton(AF_INET6, hname_buf, &addr))) { - if (strcmp(pp, "0") != 0) - add_ip_entry(addr, pp); - } -#else - unsigned long laddr; + hname_buf_pos += num_bytes; + hname_buf[hname_buf_pos] = 0; + debug(connections, ("hname_handler: address server replies: %s", hname_buf)); - if ((laddr = inet_addr(hname_buf)) != INADDR_NONE) { - if (strcmp(pp, "0") != 0) - add_ip_entry(laddr, pp); - } -#endif - } - } + while (hname_buf_pos) { + char *nl, *pp; - hname_buf_pos -= (nl - hname_buf); - if (hname_buf_pos) - memmove(hname_buf, nl, hname_buf_pos + 1); /* be sure to get the nul */ - } -} + /* if there's no newline, there's more data to come */ + if (!(nl = strchr(hname_buf, '\n'))) + break; + *nl++ = 0; -/* - * Remove an interactive user immediately. - */ -void remove_interactive (object_t * ob, int dested) -{ - int idx; - /* don't have to worry about this dangling, since this is the routine - * that causes this to dangle elsewhere, and we are protected from - * getting called recursively by CLOSING. safe_apply() should be - * used here, since once we start this process we can't back out, - * so jumping out with an error would be bad. - */ - interactive_t *ip = ob->interactive; + if ((pp = strchr(hname_buf, ' ')) != 0) { + *pp++ = 0; + got_addr_number(pp, hname_buf); + + if (isdigit(hname_buf[0]) || hname_buf[0] == ':') { - if (!ip) return; +#ifdef IPV6 + struct in6_addr addr; + int ret; + if(1 ==(ret = inet_pton(AF_INET6, hname_buf, &addr))) { + if (strcmp(pp, "0") != 0) + add_ip_entry(addr, pp); + } +#else + unsigned long laddr; - if (ip->iflags & CLOSING) { - if (!dested) - debug_message("Double call to remove_interactive()\n"); - return; - } + if ((laddr = inet_addr(hname_buf)) != INADDR_NONE) { + if (strcmp(pp, "0") != 0) + add_ip_entry(laddr, pp); + } +#endif + } + } - debug(connections, ("Closing connection from %s.\n", - inet_ntoa(ip->addr.sin_addr))); + hname_buf_pos -= (nl - hname_buf); + if (hname_buf_pos) + memmove(hname_buf, nl, hname_buf_pos + 1); /* be sure to get the nul */ + } + } - flush_message(ip); - ip->iflags |= CLOSING; + /* + * Remove an interactive user immediately. + */ + void remove_interactive (object_t * ob, int dested) + { + int idx; + /* don't have to worry about this dangling, since this is the routine + * that causes this to dangle elsewhere, and we are protected from + * getting called recursively by CLOSING. safe_apply() should be + * used here, since once we start this process we can't back out, + * so jumping out with an error would be bad. + */ + interactive_t *ip = ob->interactive; + + if (!ip) return; + + if (ip->iflags & CLOSING) { + if (!dested) + debug_message("Double call to remove_interactive()\n"); + return; + } +#ifdef IPV6 + char tmp[INET6_ADDRSTRLEN]; + debug(connections, ("Closing connection from %s.\n", inet_ntop(AF_INET6, &ip->addr.sin6_addr, &tmp, INET6_ADDRSTRLEN))); +#else + debug(connections, ("Closing connection from %s.\n", inet_ntoa(ip->addr.sin_addr))); +#endif + flush_message(ip); + ip->iflags |= CLOSING; #ifdef OLD_ED - if (ip->ed_buffer) { - save_ed_buffer(ob); - } + if (ip->ed_buffer) { + save_ed_buffer(ob); + } #else - if (ob->flags & O_IN_EDIT) { - object_save_ed_buffer(ob); - ob->flags &= ~O_IN_EDIT; - } + if (ob->flags & O_IN_EDIT) { + object_save_ed_buffer(ob); + ob->flags &= ~O_IN_EDIT; + } #endif - if (!dested) { - /* - * auto-notification of net death - */ - save_command_giver(ob); - safe_apply(APPLY_NET_DEAD, ob, 0, ORIGIN_DRIVER); - restore_command_giver(); - } + if (!dested) { + /* + * auto-notification of net death + */ + save_command_giver(ob); + safe_apply(APPLY_NET_DEAD, ob, 0, ORIGIN_DRIVER); + restore_command_giver(); + } #ifndef NO_SNOOP - if (ip->snooped_by) { - ip->snooped_by->flags &= ~O_SNOOP; - ip->snooped_by = 0; - } + if (ip->snooped_by) { + ip->snooped_by->flags &= ~O_SNOOP; + ip->snooped_by = 0; + } #endif #ifdef HAVE_ZLIB - if (ip->compressed_stream) { - end_compression(ip); - } + if (ip->compressed_stream) { + end_compression(ip); + } #endif - debug(connections, ("remove_interactive: closing fd %d\n", ip->fd)); - if (OS_socket_close(ip->fd) == -1) { - socket_perror("remove_interactive: close", 0); - } + debug(connections, ("remove_interactive: closing fd %d\n", ip->fd)); + if (OS_socket_close(ip->fd) == -1) { + socket_perror("remove_interactive: close", 0); + } #ifdef F_SET_HIDE - if (ob->flags & O_HIDDEN) - num_hidden_users--; + if (ob->flags & O_HIDDEN) + num_hidden_users--; #endif - num_user--; - clear_notify(ip->ob); + num_user--; + clear_notify(ip->ob); #if defined(F_INPUT_TO) || defined(F_GET_CHAR) - if (ip->input_to) { - free_object(&ip->input_to->ob, "remove_interactive"); - free_sentence(ip->input_to); - if (ip->num_carry > 0) - free_some_svalues(ip->carryover, ip->num_carry); - ip->carryover = NULL; - ip->num_carry = 0; - ip->input_to = 0; - } -#endif - for (idx = 0; idx < max_users; idx++) - if (all_users[idx] == ip) break; - DEBUG_CHECK(idx == max_users, "remove_interactive: could not find and remove user!\n"); - FREE(ip->sb_buf); - FREE(ip); - ob->interactive = 0; - all_users[idx] = 0; - free_object(&ob, "remove_interactive"); - return; -} /* remove_interactive() */ + if (ip->input_to) { + free_object(&ip->input_to->ob, "remove_interactive"); + free_sentence(ip->input_to); + if (ip->num_carry > 0) + free_some_svalues(ip->carryover, ip->num_carry); + ip->carryover = NULL; + ip->num_carry = 0; + ip->input_to = 0; + } +#endif + for (idx = 0; idx < max_users; idx++) + if (all_users[idx] == ip) break; + DEBUG_CHECK(idx == max_users, "remove_interactive: could not find and remove user!\n"); + FREE(ip->sb_buf); + FREE(ip); + ob->interactive = 0; + all_users[idx] = 0; + free_object(&ob, "remove_interactive"); + return; + } /* remove_interactive() */ #if defined(F_INPUT_TO) || defined(F_GET_CHAR) -static int call_function_interactive (interactive_t * i, char * str) -{ - object_t *ob; - funptr_t *funp; - char *function; - svalue_t *args; - sentence_t *sent; - int num_arg; + static int call_function_interactive (interactive_t * i, char * str) + { + object_t *ob; + funptr_t *funp; + char *function; + svalue_t *args; + sentence_t *sent; + int num_arg; #ifdef GET_CHAR_IS_BUFFERED - int was_single = 0; - int was_noecho = 0; -#endif - - i->iflags &= ~NOESC; - if (!(sent = i->input_to)) - return (0); - - /* - * Special feature: input_to() has been called to setup a call to a - * function. - */ - if (sent->ob->flags & O_DESTRUCTED) { - /* Sorry, the object has selfdestructed ! */ - free_object(&sent->ob, "call_function_interactive"); - free_sentence(sent); - i->input_to = 0; - if (i->num_carry) - free_some_svalues(i->carryover, i->num_carry); - i->carryover = NULL; - i->num_carry = 0; - i->input_to = 0; - if (i->iflags & SINGLE_CHAR) { - /* - * clear single character mode - */ - i->iflags &= ~SINGLE_CHAR; + int was_single = 0; + int was_noecho = 0; +#endif + + i->iflags &= ~NOESC; + if (!(sent = i->input_to)) + return (0); + + /* + * Special feature: input_to() has been called to setup a call to a + * function. + */ + if (sent->ob->flags & O_DESTRUCTED) { + /* Sorry, the object has selfdestructed ! */ + free_object(&sent->ob, "call_function_interactive"); + free_sentence(sent); + i->input_to = 0; + if (i->num_carry) + free_some_svalues(i->carryover, i->num_carry); + i->carryover = NULL; + i->num_carry = 0; + i->input_to = 0; + if (i->iflags & SINGLE_CHAR) { + /* + * clear single character mode + */ + i->iflags &= ~SINGLE_CHAR; #ifndef GET_CHAR_IS_BUFFERED - set_linemode(i); + set_linemode(i); #else - was_single = 1; - if (i->iflags & NOECHO) { - was_noecho = 1; - i->iflags &= ~NOECHO; - } -#endif - } - - return (0); - } - /* - * We must all references to input_to fields before the call to apply(), - * because someone might want to set up a new input_to(). - */ - - /* we put the function on the stack in case of an error */ - STACK_INC; - if (sent->flags & V_FUNCTION) { - function = 0; - sp->type = T_FUNCTION; - sp->u.fp = funp = sent->function.f; - funp->hdr.ref++; - } else { - sp->type = T_STRING; - sp->subtype = STRING_SHARED; - sp->u.string = function = sent->function.s; - ref_string(function); - } - ob = sent->ob; - - free_object(&sent->ob, "call_function_interactive"); - free_sentence(sent); - - /* - * If we have args, we have to copy them, so the svalues on the - * interactive struct can be FREEd - */ - num_arg = i->num_carry; - if (num_arg) { - args = i->carryover; - i->num_carry = 0; - i->carryover = NULL; - } else - args = NULL; - - i->input_to = 0; - if (i->iflags & SINGLE_CHAR) { - /* - * clear single character mode - */ - i->iflags &= ~SINGLE_CHAR; + was_single = 1; + if (i->iflags & NOECHO) { + was_noecho = 1; + i->iflags &= ~NOECHO; + } +#endif + } + + return (0); + } + /* + * We must all references to input_to fields before the call to apply(), + * because someone might want to set up a new input_to(). + */ + + /* we put the function on the stack in case of an error */ + STACK_INC; + if (sent->flags & V_FUNCTION) { + function = 0; + sp->type = T_FUNCTION; + sp->u.fp = funp = sent->function.f; + funp->hdr.ref++; + } else { + sp->type = T_STRING; + sp->subtype = STRING_SHARED; + sp->u.string = function = sent->function.s; + ref_string(function); + } + ob = sent->ob; + + free_object(&sent->ob, "call_function_interactive"); + free_sentence(sent); + + /* + * If we have args, we have to copy them, so the svalues on the + * interactive struct can be FREEd + */ + num_arg = i->num_carry; + if (num_arg) { + args = i->carryover; + i->num_carry = 0; + i->carryover = NULL; + } else + args = NULL; + + i->input_to = 0; + if (i->iflags & SINGLE_CHAR) { + /* + * clear single character mode + */ + i->iflags &= ~SINGLE_CHAR; #ifndef GET_CHAR_IS_BUFFERED - set_linemode(i); + set_linemode(i); #else - was_single = 1; - if (i->iflags & NOECHO) { - was_noecho = 1; - i->iflags &= ~NOECHO; - } -#endif - } - - copy_and_push_string(str); - /* - * If we have args, we have to push them onto the stack in the order they - * were in when we got them. They will be popped off by the called - * function. - */ - if (args) { - transfer_push_some_svalues(args, num_arg); - FREE(args); - } - /* current_object no longer set */ - if (function) { - if (function[0] == APPLY___INIT_SPECIAL_CHAR) - error("Illegal function name.\n"); - (void) apply(function, ob, num_arg + 1, ORIGIN_INTERNAL); - } else - call_function_pointer(funp, num_arg + 1); - - pop_stack(); /* remove `function' from stack */ + was_single = 1; + if (i->iflags & NOECHO) { + was_noecho = 1; + i->iflags &= ~NOECHO; + } +#endif + } + + copy_and_push_string(str); + /* + * If we have args, we have to push them onto the stack in the order they + * were in when we got them. They will be popped off by the called + * function. + */ + if (args) { + transfer_push_some_svalues(args, num_arg); + FREE(args); + } + /* current_object no longer set */ + if (function) { + if (function[0] == APPLY___INIT_SPECIAL_CHAR) + error("Illegal function name.\n"); + (void) apply(function, ob, num_arg + 1, ORIGIN_INTERNAL); + } else + call_function_pointer(funp, num_arg + 1); + + pop_stack(); /* remove `function' from stack */ #ifdef GET_CHAR_IS_BUFFERED - if (IP_VALID(i, ob)) { - if (was_single && !(i->iflags & SINGLE_CHAR)) { - i->text_start = i->text_end = 0; - i->text[0] = '\0'; - i->iflags &= ~CMD_IN_BUF; - set_linemode(i); - } - if (was_noecho && !(i->iflags & NOECHO)) - add_binary_message(i->ob, telnet_no_echo, sizeof(telnet_no_echo)); - } -#endif - - return (1); -} /* call_function_interactive() */ - -int set_call (object_t * ob, sentence_t * sent, int flags) -{ - if (ob == 0 || sent == 0) - return (0); - if (ob->interactive == 0 || ob->interactive->input_to) - return (0); - ob->interactive->input_to = sent; - ob->interactive->iflags |= (flags & (I_NOECHO | I_NOESC | I_SINGLE_CHAR)); - if (flags & I_NOECHO) - add_binary_message(ob, telnet_yes_echo, sizeof(telnet_yes_echo)); - if (flags & I_SINGLE_CHAR) - set_charmode(ob->interactive); - return (1); -} /* set_call() */ + if (IP_VALID(i, ob)) { + if (was_single && !(i->iflags & SINGLE_CHAR)) { + i->text_start = i->text_end = 0; + i->text[0] = '\0'; + i->iflags &= ~CMD_IN_BUF; + set_linemode(i); + } + if (was_noecho && !(i->iflags & NOECHO)) + add_binary_message(i->ob, telnet_no_echo, sizeof(telnet_no_echo)); + } +#endif + + return (1); + } /* call_function_interactive() */ + + int set_call (object_t * ob, sentence_t * sent, int flags) + { + if (ob == 0 || sent == 0) + return (0); + if (ob->interactive == 0 || ob->interactive->input_to) + return (0); + ob->interactive->input_to = sent; + ob->interactive->iflags |= (flags & (I_NOECHO | I_NOESC | I_SINGLE_CHAR)); + if (flags & I_NOECHO) + add_binary_message(ob, telnet_yes_echo, sizeof(telnet_yes_echo)); + if (flags & I_SINGLE_CHAR) + set_charmode(ob->interactive); + return (1); + } /* set_call() */ #endif void set_prompt (const char * str) { - if (command_giver && command_giver->interactive) { - command_giver->interactive->prompt = str; - } + if (command_giver && command_giver->interactive) { + command_giver->interactive->prompt = str; + } } /* set_prompt() */ /* @@ -2590,35 +2703,35 @@ void set_prompt (const char * str) */ static void print_prompt (interactive_t* ip) { - object_t *ob = ip->ob; + object_t *ob = ip->ob; #if defined(F_INPUT_TO) || defined(F_GET_CHAR) - if (ip->input_to == 0) { + if (ip->input_to == 0) { #endif - /* give user object a chance to write its own prompt */ - if (!(ip->iflags & HAS_WRITE_PROMPT)) - tell_object(ip->ob, ip->prompt, strlen(ip->prompt)); + /* give user object a chance to write its own prompt */ + if (!(ip->iflags & HAS_WRITE_PROMPT)) + tell_object(ip->ob, ip->prompt, strlen(ip->prompt)); #ifdef OLD_ED - else if (ip->ed_buffer) - tell_object(ip->ob, ip->prompt, strlen(ip->prompt)); -#endif - else if (!apply(APPLY_WRITE_PROMPT, ip->ob, 0, ORIGIN_DRIVER)) { - if (!IP_VALID(ip, ob)) return; - ip->iflags &= ~HAS_WRITE_PROMPT; - tell_object(ip->ob, ip->prompt, strlen(ip->prompt)); - } + else if (ip->ed_buffer) + tell_object(ip->ob, ip->prompt, strlen(ip->prompt)); +#endif + else if (!apply(APPLY_WRITE_PROMPT, ip->ob, 0, ORIGIN_DRIVER)) { + if (!IP_VALID(ip, ob)) return; + ip->iflags &= ~HAS_WRITE_PROMPT; + tell_object(ip->ob, ip->prompt, strlen(ip->prompt)); + } #if defined(F_INPUT_TO) || defined(F_GET_CHAR) - } -#endif - if (!IP_VALID(ip, ob)) return; - /* - * Put the IAC GA thing in here... Moved from before writing the prompt; - * vt src says it's a terminator. Should it be inside the no-input_to - * case? We'll see, I guess. - */ - if ((ip->iflags & USING_TELNET) && !(ip->iflags & SUPPRESS_GA)) - add_binary_message(command_giver, telnet_ga, sizeof(telnet_ga)); - if (!IP_VALID(ip, ob)) return; + } +#endif + if (!IP_VALID(ip, ob)) return; + /* + * Put the IAC GA thing in here... Moved from before writing the prompt; + * vt src says it's a terminator. Should it be inside the no-input_to + * case? We'll see, I guess. + */ + if ((ip->iflags & USING_TELNET) && !(ip->iflags & SUPPRESS_GA)) + add_binary_message(command_giver, telnet_ga, sizeof(telnet_ga)); + if (!IP_VALID(ip, ob)) return; } /* print_prompt() */ /* @@ -2635,102 +2748,102 @@ static void print_prompt (interactive_t* ip) #ifndef NO_SNOOP int new_set_snoop (object_t * by, object_t * victim) { - interactive_t *ip; - object_t *tmp; - - if (by->flags & O_DESTRUCTED) - return 0; - if (victim && (victim->flags & O_DESTRUCTED)) - return 0; - - if (victim) { - if (!victim->interactive) - error("Second argument of snoop() is not interactive!\n"); - ip = victim->interactive; - } else { - /* - * Stop snoop. - */ - if (by->flags & O_SNOOP) { - int i; - - for (i = 0; i < max_users; i++) { - if (all_users[i] && all_users[i]->snooped_by == by) - all_users[i]->snooped_by = 0; - } - by->flags &= ~O_SNOOP; - } - return 1; - } - - /* - * Protect against snooping loops. - */ - tmp = by; - while (tmp) { - if (tmp == victim) - return 0; - - /* the person snooping us, if any */ - tmp = (tmp->interactive ? tmp->interactive->snooped_by : 0); - } - - /* - * Terminate previous snoop, if any. - */ - if (by->flags & O_SNOOP) { - int i; - - for (i = 0; i < max_users; i++) { - if (all_users[i] && all_users[i]->snooped_by == by) - all_users[i]->snooped_by = 0; - } - } - if (ip->snooped_by) - ip->snooped_by->flags &= ~O_SNOOP; - by->flags |= O_SNOOP; - ip->snooped_by = by; - - return 1; + interactive_t *ip; + object_t *tmp; + + if (by->flags & O_DESTRUCTED) + return 0; + if (victim && (victim->flags & O_DESTRUCTED)) + return 0; + + if (victim) { + if (!victim->interactive) + error("Second argument of snoop() is not interactive!\n"); + ip = victim->interactive; + } else { + /* + * Stop snoop. + */ + if (by->flags & O_SNOOP) { + int i; + + for (i = 0; i < max_users; i++) { + if (all_users[i] && all_users[i]->snooped_by == by) + all_users[i]->snooped_by = 0; + } + by->flags &= ~O_SNOOP; + } + return 1; + } + + /* + * Protect against snooping loops. + */ + tmp = by; + while (tmp) { + if (tmp == victim) + return 0; + + /* the person snooping us, if any */ + tmp = (tmp->interactive ? tmp->interactive->snooped_by : 0); + } + + /* + * Terminate previous snoop, if any. + */ + if (by->flags & O_SNOOP) { + int i; + + for (i = 0; i < max_users; i++) { + if (all_users[i] && all_users[i]->snooped_by == by) + all_users[i]->snooped_by = 0; + } + } + if (ip->snooped_by) + ip->snooped_by->flags &= ~O_SNOOP; + by->flags |= O_SNOOP; + ip->snooped_by = by; + + return 1; } /* set_new_snoop() */ #endif static void query_addr_name (object_t * ob) { - static char buf[100]; - static char *dbuf = &buf[sizeof(int) + sizeof(int) + sizeof(int)]; - int msglen; - int msgtype; - - sprintf(dbuf, "%s", query_ip_number(ob)); - msglen = sizeof(int) + strlen(dbuf) +1; - - msgtype = DATALEN; - memcpy(buf, (char *) &msgtype, sizeof(msgtype)); - memcpy(&buf[sizeof(int)], (char *) &msglen, sizeof(msglen)); - - msgtype = NAMEBYIP; - memcpy(&buf[sizeof(int) + sizeof(int)], (char *) &msgtype, sizeof(msgtype)); - debug(connections, ("query_addr_name: sent address server %s\n", dbuf)); - - if (OS_socket_write(addr_server_fd, buf, msglen + sizeof(int) + sizeof(int)) == -1) { - switch (socket_errno) { - case EBADF: - debug_message("Address server has closed connection.\n"); - addr_server_fd = -1; - break; - default: - socket_perror("query_addr_name: write", 0); - break; - } - } + static char buf[100]; + static char *dbuf = &buf[sizeof(int) + sizeof(int) + sizeof(int)]; + int msglen; + int msgtype; + + sprintf(dbuf, "%s", query_ip_number(ob)); + msglen = sizeof(int) + strlen(dbuf) +1; + + msgtype = DATALEN; + memcpy(buf, (char *) &msgtype, sizeof(msgtype)); + memcpy(&buf[sizeof(int)], (char *) &msglen, sizeof(msglen)); + + msgtype = NAMEBYIP; + memcpy(&buf[sizeof(int) + sizeof(int)], (char *) &msgtype, sizeof(msgtype)); + debug(connections, ("query_addr_name: sent address server %s\n", dbuf)); + + if (OS_socket_write(addr_server_fd, buf, msglen + sizeof(int) + sizeof(int)) == -1) { + switch (socket_errno) { + case EBADF: + debug_message("Address server has closed connection.\n"); + addr_server_fd = -1; + break; + default: + socket_perror("query_addr_name: write", 0); + break; + } + } } /* query_addr_name() */ #define IPSIZE 200 typedef struct { - char *name; - svalue_t call_back; - object_t *ob_to_call; + char *name; + svalue_t call_back; + object_t *ob_to_call; } ipnumberentry_t; static ipnumberentry_t ipnumbertable[IPSIZE]; @@ -2740,134 +2853,134 @@ static ipnumberentry_t ipnumbertable[IPSIZE]; */ int query_addr_number (const char * name, svalue_t * call_back) { - static char buf[100]; - static char *dbuf = &buf[sizeof(int) + sizeof(int) + sizeof(int)]; - int msglen; - int msgtype; - int i; - - if ((addr_server_fd < 0) || (strlen(name) >= - 100 - (sizeof(msgtype) + sizeof(msglen) + sizeof(int)))) { - share_and_push_string(name); - push_undefined(); - if (call_back->type == T_STRING) - apply(call_back->u.string, current_object, 2, ORIGIN_INTERNAL); - else - call_function_pointer(call_back->u.fp, 2); - return 0; - } - strcpy(dbuf, name); - msglen = sizeof(int) + strlen(name) +1; - - msgtype = DATALEN; - memcpy(buf, (char *) &msgtype, sizeof(msgtype)); - memcpy(&buf[sizeof(int)], (char *) &msglen, sizeof(msglen)); - - msgtype = NAMEBYIP; - for (i = 0; i < strlen(name); i++){ - if (isalpha(name[i])) { - msgtype = IPBYNAME; - break; - } - } - - memcpy(&buf[sizeof(int) + sizeof(int)], (char *) &msgtype, sizeof(msgtype)); - - debug(connections, ("query_addr_number: sent address server %s\n", dbuf)); - - if (addr_server_fd && OS_socket_write(addr_server_fd, buf, msglen + sizeof(int) + sizeof(int)) == -1) { - switch (socket_errno) { - case EBADF: - debug_message("Address server has closed connection.\n"); - addr_server_fd = -1; - break; - default: - socket_perror("query_addr_name: write", 0); - break; - } - share_and_push_string(name); - push_undefined(); - if (call_back->type == T_STRING) - apply(call_back->u.string, current_object, 2, ORIGIN_INTERNAL); - else - call_function_pointer(call_back->u.fp, 2); - return 0; - } else { - int i; - -/* We put ourselves into the pending name lookup entry table */ -/* Find the first free entry */ - for (i = 0; i < IPSIZE && ipnumbertable[i].name; i++) - ; - if (i == IPSIZE) { -/* We need to error... */ - share_and_push_string(name); - push_undefined(); - if (call_back->type == T_STRING) - apply(call_back->u.string, current_object, 2, ORIGIN_INTERNAL); - else - call_function_pointer(call_back->u.fp, 2); - return 0; - } -/* Create our entry... */ - ipnumbertable[i].name = make_shared_string(name); - assign_svalue_no_free(&ipnumbertable[i].call_back, call_back); - ipnumbertable[i].ob_to_call = current_object; - add_ref(current_object, "query_addr_number: "); - return i + 1; - } + static char buf[100]; + static char *dbuf = &buf[sizeof(int) + sizeof(int) + sizeof(int)]; + int msglen; + int msgtype; + int i; + + if ((addr_server_fd < 0) || (strlen(name) >= + 100 - (sizeof(msgtype) + sizeof(msglen) + sizeof(int)))) { + share_and_push_string(name); + push_undefined(); + if (call_back->type == T_STRING) + apply(call_back->u.string, current_object, 2, ORIGIN_INTERNAL); + else + call_function_pointer(call_back->u.fp, 2); + return 0; + } + strcpy(dbuf, name); + msglen = sizeof(int) + strlen(name) +1; + + msgtype = DATALEN; + memcpy(buf, (char *) &msgtype, sizeof(msgtype)); + memcpy(&buf[sizeof(int)], (char *) &msglen, sizeof(msglen)); + + msgtype = NAMEBYIP; + for (i = 0; i < strlen(name); i++){ + if (isalpha(name[i])) { + msgtype = IPBYNAME; + break; + } + } + + memcpy(&buf[sizeof(int) + sizeof(int)], (char *) &msgtype, sizeof(msgtype)); + + debug(connections, ("query_addr_number: sent address server %s\n", dbuf)); + + if (addr_server_fd && OS_socket_write(addr_server_fd, buf, msglen + sizeof(int) + sizeof(int)) == -1) { + switch (socket_errno) { + case EBADF: + debug_message("Address server has closed connection.\n"); + addr_server_fd = -1; + break; + default: + socket_perror("query_addr_name: write", 0); + break; + } + share_and_push_string(name); + push_undefined(); + if (call_back->type == T_STRING) + apply(call_back->u.string, current_object, 2, ORIGIN_INTERNAL); + else + call_function_pointer(call_back->u.fp, 2); + return 0; + } else { + int i; + + /* We put ourselves into the pending name lookup entry table */ + /* Find the first free entry */ + for (i = 0; i < IPSIZE && ipnumbertable[i].name; i++) + ; + if (i == IPSIZE) { + /* We need to error... */ + share_and_push_string(name); + push_undefined(); + if (call_back->type == T_STRING) + apply(call_back->u.string, current_object, 2, ORIGIN_INTERNAL); + else + call_function_pointer(call_back->u.fp, 2); + return 0; + } + /* Create our entry... */ + ipnumbertable[i].name = make_shared_string(name); + assign_svalue_no_free(&ipnumbertable[i].call_back, call_back); + ipnumbertable[i].ob_to_call = current_object; + add_ref(current_object, "query_addr_number: "); + return i + 1; + } } /* query_addr_number() */ static void got_addr_number (char * number, char * name) { - int i; - char *theName, *theNumber; - - /* First remove all the dested ones... */ - for (i = 0; i < IPSIZE; i++) - if (ipnumbertable[i].name - && ipnumbertable[i].ob_to_call->flags & O_DESTRUCTED) { - free_svalue(&ipnumbertable[i].call_back, "got_addr_number"); - free_string(ipnumbertable[i].name); - free_object(&ipnumbertable[i].ob_to_call, "got_addr_number: "); - ipnumbertable[i].name = NULL; - } - for (i = 0; i < IPSIZE; i++) { - if (ipnumbertable[i].name && strcmp(name, ipnumbertable[i].name)== 0) { - /* Found one, do the call back... */ - theName = ipnumbertable[i].name; - theNumber = number; - - if (uisdigit(theName[0])) { - char *tmp; - - tmp = theName; - theName = theNumber; - theNumber = tmp; - } - if (strcmp(theName, "0")) { - share_and_push_string(theName); - } else { - push_undefined(); - } - if (strcmp(theNumber, "0")) { - share_and_push_string(theNumber); - } else { - push_undefined(); - } - push_number(i + 1); - if (ipnumbertable[i].call_back.type == T_STRING) - safe_apply(ipnumbertable[i].call_back.u.string, - ipnumbertable[i].ob_to_call, - 3, ORIGIN_INTERNAL); - else - safe_call_function_pointer(ipnumbertable[i].call_back.u.fp, 3); - free_svalue(&ipnumbertable[i].call_back, "got_addr_number"); - free_string(ipnumbertable[i].name); - free_object(&ipnumbertable[i].ob_to_call, "got_addr_number: "); - ipnumbertable[i].name = NULL; - } - } + int i; + char *theName, *theNumber; + + /* First remove all the dested ones... */ + for (i = 0; i < IPSIZE; i++) + if (ipnumbertable[i].name + && ipnumbertable[i].ob_to_call->flags & O_DESTRUCTED) { + free_svalue(&ipnumbertable[i].call_back, "got_addr_number"); + free_string(ipnumbertable[i].name); + free_object(&ipnumbertable[i].ob_to_call, "got_addr_number: "); + ipnumbertable[i].name = NULL; + } + for (i = 0; i < IPSIZE; i++) { + if (ipnumbertable[i].name && strcmp(name, ipnumbertable[i].name)== 0) { + /* Found one, do the call back... */ + theName = ipnumbertable[i].name; + theNumber = number; + + if (uisdigit(theName[0])) { + char *tmp; + + tmp = theName; + theName = theNumber; + theNumber = tmp; + } + if (strcmp(theName, "0")) { + share_and_push_string(theName); + } else { + push_undefined(); + } + if (strcmp(theNumber, "0")) { + share_and_push_string(theNumber); + } else { + push_undefined(); + } + push_number(i + 1); + if (ipnumbertable[i].call_back.type == T_STRING) + safe_apply(ipnumbertable[i].call_back.u.string, + ipnumbertable[i].ob_to_call, + 3, ORIGIN_INTERNAL); + else + safe_call_function_pointer(ipnumbertable[i].call_back.u.fp, 3); + free_svalue(&ipnumbertable[i].call_back, "got_addr_number"); + free_string(ipnumbertable[i].name); + free_object(&ipnumbertable[i].ob_to_call, "got_addr_number: "); + ipnumbertable[i].name = NULL; + } + } } /* got_addr_number() */ #undef IPSIZE @@ -2876,9 +2989,9 @@ typedef struct { #ifdef IPV6 struct in6_addr addr; #else - long addr; + long addr; #endif - char *name; + char *name; } ipentry_t; static ipentry_t iptable[IPSIZE]; @@ -2886,11 +2999,11 @@ static int ipcur; #ifdef DEBUGMALLOC_EXTENSIONS void mark_iptable() { - int i; + int i; - for (i=0; i < IPSIZE; i++) - if (iptable[i].name) - EXTRA_REF(BLOCK(iptable[i].name))++; + for (i=0; i < IPSIZE; i++) + if (iptable[i].name) + EXTRA_REF(BLOCK(iptable[i].name))++; } #endif @@ -2900,28 +3013,28 @@ char ipv6addr[INET6_ADDRSTRLEN]; char *query_ip_name (object_t * ob) { - int i; + int i; - if (ob == 0) - ob = command_giver; - if (!ob || ob->interactive == 0) - return NULL; + if (ob == 0) + ob = command_giver; + if (!ob || ob->interactive == 0) + return NULL; #ifdef IPV6 - for (i = 0; i < IPSIZE; i++) { - if (!memcmp(&iptable[i].addr, &ob->interactive->addr.sin6_addr, sizeof(ob->interactive->addr.sin6_addr)) && - iptable[i].name) - return (iptable[i].name); - } - - inet_ntop(AF_INET6, &ob->interactive->addr.sin6_addr, ipv6addr, INET6_ADDRSTRLEN); - return ipv6addr; + for (i = 0; i < IPSIZE; i++) { + if (!memcmp(&iptable[i].addr, &ob->interactive->addr.sin6_addr, sizeof(ob->interactive->addr.sin6_addr)) && + iptable[i].name) + return (iptable[i].name); + } + + inet_ntop(AF_INET6, &ob->interactive->addr.sin6_addr, ipv6addr, INET6_ADDRSTRLEN); + return ipv6addr; #else - for (i = 0; i < IPSIZE; i++) { - if (iptable[i].addr == ob->interactive->addr.sin_addr.s_addr && - iptable[i].name) - return (iptable[i].name); - } - return (inet_ntoa(ob->interactive->addr.sin_addr)); + for (i = 0; i < IPSIZE; i++) { + if (iptable[i].addr == ob->interactive->addr.sin_addr.s_addr && + iptable[i].name) + return (iptable[i].name); + } + return (inet_ntoa(ob->interactive->addr.sin_addr)); #endif } @@ -2931,30 +3044,30 @@ static void add_ip_entry (struct in6_addr addr, char * name) static void add_ip_entry (long addr, char * name) #endif { - int i; - - for (i = 0; i < IPSIZE; i++) { - if (!memcmp(&iptable[i].addr, &addr, sizeof(addr))) - return; - } - iptable[ipcur].addr = addr; - if (iptable[ipcur].name) - free_string(iptable[ipcur].name); - iptable[ipcur].name = make_shared_string(name); - ipcur = (ipcur + 1) % IPSIZE; + int i; + + for (i = 0; i < IPSIZE; i++) { + if (!memcmp(&iptable[i].addr, &addr, sizeof(addr))) + return; + } + iptable[ipcur].addr = addr; + if (iptable[ipcur].name) + free_string(iptable[ipcur].name); + iptable[ipcur].name = make_shared_string(name); + ipcur = (ipcur + 1) % IPSIZE; } const char *query_ip_number (object_t * ob) { - if (ob == 0) - ob = command_giver; - if (!ob || ob->interactive == 0) - return 0; + if (ob == 0) + ob = command_giver; + if (!ob || ob->interactive == 0) + return 0; #ifdef IPV6 - inet_ntop(AF_INET6, &ob->interactive->addr.sin6_addr, ipv6addr, INET6_ADDRSTRLEN); - return &ipv6addr[0]; + inet_ntop(AF_INET6, &ob->interactive->addr.sin6_addr, ipv6addr, INET6_ADDRSTRLEN); + return &ipv6addr[0]; #else - return (inet_ntoa(ob->interactive->addr.sin_addr)); + return (inet_ntoa(ob->interactive->addr.sin_addr)); #endif } @@ -2965,333 +3078,333 @@ const char *query_ip_number (object_t * ob) */ char *inet_ntoa (struct in_addr ad) { - u_long s_ad; - int a, b, c, d; - static char addr[20]; /* 16 + 1 should be enough */ - - s_ad = ad.s_addr; - d = s_ad % 256; - s_ad /= 256; - c = s_ad % 256; - s_ad /= 256; - b = s_ad % 256; - a = s_ad / 256; - sprintf(addr, "%d.%d.%d.%d", a, b, c, d); - return (addr); + u_long s_ad; + int a, b, c, d; + static char addr[20]; /* 16 + 1 should be enough */ + + s_ad = ad.s_addr; + d = s_ad % 256; + s_ad /= 256; + c = s_ad % 256; + s_ad /= 256; + b = s_ad % 256; + a = s_ad / 256; + sprintf(addr, "%d.%d.%d.%d", a, b, c, d); + return (addr); } #endif /* INET_NTOA_OK */ char *query_host_name() { - static char name[400]; + static char name[400]; - gethostname(name, sizeof(name)); - name[sizeof(name) - 1] = '\0'; /* Just to make sure */ - return (name); + gethostname(name, sizeof(name)); + name[sizeof(name) - 1] = '\0'; /* Just to make sure */ + return (name); } /* query_host_name() */ #ifndef NO_SNOOP object_t *query_snoop (object_t * ob) { - if (!ob->interactive) - return 0; - return ob->interactive->snooped_by; + if (!ob->interactive) + return 0; + return ob->interactive->snooped_by; } /* query_snoop() */ object_t *query_snooping (object_t * ob) { - int i; - - if (!(ob->flags & O_SNOOP)) return 0; - for (i = 0; i < max_users; i++) { - if (all_users[i] && all_users[i]->snooped_by == ob) - return all_users[i]->ob; - } - fatal("couldn't find snoop target.\n"); - return 0; + int i; + + if (!(ob->flags & O_SNOOP)) return 0; + for (i = 0; i < max_users; i++) { + if (all_users[i] && all_users[i]->snooped_by == ob) + return all_users[i]->ob; + } + fatal("couldn't find snoop target.\n"); + return 0; } /* query_snooping() */ #endif int query_idle (object_t * ob) { - if (!ob->interactive) - error("query_idle() of non-interactive object.\n"); - return (current_time - ob->interactive->last_time); + if (!ob->interactive) + error("query_idle() of non-interactive object.\n"); + return (current_time - ob->interactive->last_time); } /* query_idle() */ #ifdef F_EXEC int replace_interactive (object_t * ob, object_t * obfrom) { - if (ob->interactive) { - error("Bad argument 1 to exec()\n"); - } - if (!obfrom->interactive) { - error("Bad argument 2 to exec()\n"); - } + if (ob->interactive) { + error("Bad argument 1 to exec()\n"); + } + if (!obfrom->interactive) { + error("Bad argument 2 to exec()\n"); + } #ifdef F_SET_HIDE - if ((ob->flags & O_HIDDEN) != (obfrom->flags & O_HIDDEN)) { - if (ob->flags & O_HIDDEN) { - num_hidden_users++; - } else { - num_hidden_users--; - } - } -#endif - ob->interactive = obfrom->interactive; - /* - * assume the existance of write_prompt and process_input in user.c until - * proven wrong (after trying to call them). - */ - ob->interactive->iflags |= (HAS_WRITE_PROMPT | HAS_PROCESS_INPUT); - obfrom->interactive = 0; - ob->interactive->ob = ob; - ob->flags |= O_ONCE_INTERACTIVE; - obfrom->flags &= ~O_ONCE_INTERACTIVE; - add_ref(ob, "exec"); - if (obfrom == command_giver) { - set_command_giver(ob); - } - - free_object(&obfrom, "exec"); - return (1); + if ((ob->flags & O_HIDDEN) != (obfrom->flags & O_HIDDEN)) { + if (ob->flags & O_HIDDEN) { + num_hidden_users++; + } else { + num_hidden_users--; + } + } +#endif +ob->interactive = obfrom->interactive; +/* + * assume the existance of write_prompt and process_input in user.c until + * proven wrong (after trying to call them). + */ +ob->interactive->iflags |= (HAS_WRITE_PROMPT | HAS_PROCESS_INPUT); +obfrom->interactive = 0; +ob->interactive->ob = ob; +ob->flags |= O_ONCE_INTERACTIVE; +obfrom->flags &= ~O_ONCE_INTERACTIVE; +add_ref(ob, "exec"); +if (obfrom == command_giver) { + set_command_giver(ob); +} + +free_object(&obfrom, "exec"); +return (1); } /* replace_interactive() */ #endif void outbuf_zero (outbuffer_t * outbuf) { - outbuf->real_size = 0; - outbuf->buffer = 0; + outbuf->real_size = 0; + outbuf->buffer = 0; } int outbuf_extend (outbuffer_t * outbuf, int l) { - int limit; - - DEBUG_CHECK(l < 0, "Negative length passed to outbuf_extend.\n"); - - l = (l > MAX_STRING_LENGTH ? MAX_STRING_LENGTH : l); - - if (outbuf->buffer) { - limit = MSTR_SIZE(outbuf->buffer); - if (outbuf->real_size + l > limit) { - if (outbuf->real_size == MAX_STRING_LENGTH) return 0; /* TRUNCATED */ - - /* assume it's going to grow some more */ - limit = (outbuf->real_size + l) * 2; - if (limit > MAX_STRING_LENGTH) { - limit = MAX_STRING_LENGTH; - outbuf->buffer = extend_string(outbuf->buffer, limit); - return limit - outbuf->real_size; - } - outbuf->buffer = extend_string(outbuf->buffer, limit); - } - } else { - outbuf->buffer = new_string(l, "outbuf_extend"); - outbuf->real_size = 0; - } - return l; + int limit; + + DEBUG_CHECK(l < 0, "Negative length passed to outbuf_extend.\n"); + + l = (l > MAX_STRING_LENGTH ? MAX_STRING_LENGTH : l); + + if (outbuf->buffer) { + limit = MSTR_SIZE(outbuf->buffer); + if (outbuf->real_size + l > limit) { + if (outbuf->real_size == MAX_STRING_LENGTH) return 0; /* TRUNCATED */ + + /* assume it's going to grow some more */ + limit = (outbuf->real_size + l) * 2; + if (limit > MAX_STRING_LENGTH) { + limit = MAX_STRING_LENGTH; + outbuf->buffer = extend_string(outbuf->buffer, limit); + return limit - outbuf->real_size; + } + outbuf->buffer = extend_string(outbuf->buffer, limit); + } + } else { + outbuf->buffer = new_string(l, "outbuf_extend"); + outbuf->real_size = 0; + } + return l; } void outbuf_add (outbuffer_t * outbuf, const char * str) { - int l, limit; - - if (!outbuf) return; - l = strlen(str); - if ((limit = outbuf_extend(outbuf, l)) > 0) { - strncpy(outbuf->buffer + outbuf->real_size, str, limit); - outbuf->real_size += (l > limit ? limit : l); - *(outbuf->buffer + outbuf->real_size) = 0; - } + int l, limit; + + if (!outbuf) return; + l = strlen(str); + if ((limit = outbuf_extend(outbuf, l)) > 0) { + strncpy(outbuf->buffer + outbuf->real_size, str, limit); + outbuf->real_size += (l > limit ? limit : l); + *(outbuf->buffer + outbuf->real_size) = 0; + } } void outbuf_addchar (outbuffer_t * outbuf, char c) { - if(outbuf && (outbuf_extend(outbuf, 1) > 0)) { - *(outbuf->buffer + outbuf->real_size++) = c; - *(outbuf->buffer + outbuf->real_size) = 0; - } + if(outbuf && (outbuf_extend(outbuf, 1) > 0)) { + *(outbuf->buffer + outbuf->real_size++) = c; + *(outbuf->buffer + outbuf->real_size) = 0; + } } void outbuf_addv (outbuffer_t *outbuf, const char *format, ...) { - char buf[LARGEST_PRINTABLE_STRING + 1]; - va_list args; + char buf[LARGEST_PRINTABLE_STRING + 1]; + va_list args; - V_START(args, format); - V_VAR(outbuffer_t *, outbuf, args); - V_VAR(char *, format, args); + V_START(args, format); + V_VAR(outbuffer_t *, outbuf, args); + V_VAR(char *, format, args); - vsnprintf(buf, LARGEST_PRINTABLE_STRING, format, args); - va_end(args); + vsnprintf(buf, LARGEST_PRINTABLE_STRING, format, args); + va_end(args); - if (!outbuf) return; + if (!outbuf) return; - outbuf_add(outbuf, buf); + outbuf_add(outbuf, buf); } void outbuf_fix (outbuffer_t * outbuf) { - if (outbuf && outbuf->buffer) - outbuf->buffer = extend_string(outbuf->buffer, outbuf->real_size); + if (outbuf && outbuf->buffer) + outbuf->buffer = extend_string(outbuf->buffer, outbuf->real_size); } void outbuf_push (outbuffer_t * outbuf) { - STACK_INC; - sp->type = T_STRING; - if (outbuf && outbuf->buffer) { - outbuf->buffer = extend_string(outbuf->buffer, outbuf->real_size); - - sp->subtype = STRING_MALLOC; - sp->u.string = outbuf->buffer; - } else { - sp->subtype = STRING_CONSTANT; - sp->u.string = ""; - } + STACK_INC; + sp->type = T_STRING; + if (outbuf && outbuf->buffer) { + outbuf->buffer = extend_string(outbuf->buffer, outbuf->real_size); + + sp->subtype = STRING_MALLOC; + sp->u.string = outbuf->buffer; + } else { + sp->subtype = STRING_CONSTANT; + sp->u.string = ""; + } } #ifdef HAVE_ZLIB void* zlib_alloc(void* opaque, unsigned int items, unsigned int size) { - return CALLOC(items, size); + return CALLOC(items, size); } void zlib_free(void* opaque, void* address) { - FREE(address); + FREE(address); } static void end_compression (interactive_t *ip) { - unsigned char dummy[1]; - - if (!ip->compressed_stream) { - return ; - } + unsigned char dummy[1]; - ip->compressed_stream->avail_in = 0; - ip->compressed_stream->next_in = dummy; + if (!ip->compressed_stream) { + return ; + } - if (deflate(ip->compressed_stream, Z_FINISH) != Z_STREAM_END) { - } + ip->compressed_stream->avail_in = 0; + ip->compressed_stream->next_in = dummy; - deflateEnd(ip->compressed_stream); - FREE(ip->compressed_stream); - ip->compressed_stream = NULL; + if (deflate(ip->compressed_stream, Z_FINISH) != Z_STREAM_END) { + } + flush_compressed_output(ip); + deflateEnd(ip->compressed_stream); + FREE(ip->compressed_stream); + ip->compressed_stream = NULL; } static void start_compression (interactive_t *ip) { - z_stream* zcompress; - - if (ip->compressed_stream) { - return ; - } - zcompress = (z_stream *) DXALLOC(sizeof(z_stream), TAG_INTERACTIVE, - "start_compression"); - zcompress->next_in = NULL; - zcompress->avail_in = 0; - zcompress->next_out = ip->compress_buf; - zcompress->avail_out = COMPRESS_BUF_SIZE; - zcompress->zalloc = zlib_alloc; - zcompress->zfree = zlib_free; - zcompress->opaque = NULL; - - if (deflateInit(zcompress, 9) != Z_OK) { - FREE(zcompress); - fprintf(stderr, "Compression failed.\n"); - return ; - } - - // Ok, compressing. - ip->compressed_stream = zcompress; + z_stream* zcompress; + + if (ip->compressed_stream) { + return ; + } + zcompress = (z_stream *) DXALLOC(sizeof(z_stream), TAG_INTERACTIVE, + "start_compression"); + zcompress->next_in = NULL; + zcompress->avail_in = 0; + zcompress->next_out = ip->compress_buf; + zcompress->avail_out = COMPRESS_BUF_SIZE; + zcompress->zalloc = zlib_alloc; + zcompress->zfree = zlib_free; + zcompress->opaque = NULL; + + if (deflateInit(zcompress, 9) != Z_OK) { + FREE(zcompress); + fprintf(stderr, "Compression failed.\n"); + return ; + } + + // Ok, compressing. + ip->compressed_stream = zcompress; } static int flush_compressed_output (interactive_t *ip) { - int iStart, nBlock, nWrite, len; - z_stream* zcompress; - int ret = 1; - - if (!ip->compressed_stream) { - return ret; - } - - zcompress = ip->compressed_stream; - - /* Try to write out some data.. */ - len = zcompress->next_out - ip->compress_buf; - if (len > 0) { - /* we have some data to write */ - - nWrite = 0; - for (iStart = 0; iStart < len; iStart += nWrite) - { - if (len - iStart < 4096) { - nBlock =len - iStart; - } else { - nBlock = 4096; - } - nWrite = send(ip->fd, &ip->compress_buf[iStart], nBlock, - ip->out_of_band); - if (nWrite < 0) { - fprintf(stderr, "Error sending compressed data (%d)\n", - errno); - - if (errno == EAGAIN + int iStart, nBlock, nWrite, len; + z_stream* zcompress; + int ret = 1; + + if (!ip->compressed_stream) { + return ret; + } + + zcompress = ip->compressed_stream; + + /* Try to write out some data.. */ + len = zcompress->next_out - ip->compress_buf; + if (len > 0) { + /* we have some data to write */ + + nWrite = 0; + for (iStart = 0; iStart < len; iStart += nWrite) + { + if (len - iStart < 4096) { + nBlock =len - iStart; + } else { + nBlock = 4096; + } + nWrite = send(ip->fd, &ip->compress_buf[iStart], nBlock, + ip->out_of_band); + if (nWrite < 0) { + fprintf(stderr, "Error sending compressed data (%d)\n", + errno); + + if (errno == EAGAIN #ifndef WIN32 - || errno == ENOSR + || errno == ENOSR #endif - ) { - ret = 2; - break; - } + ) { + ret = 2; + break; + } - return FALSE; /* write error */ - } + return FALSE; /* write error */ + } - if (nWrite <= 0) { - break; - } - } + if (nWrite <= 0) { + break; + } + } - if (iStart) { - /* We wrote "iStart" bytes */ - if (iStart < len) { - memmove(ip->compress_buf, ip->compress_buf+iStart, len - - iStart); + if (iStart) { + /* We wrote "iStart" bytes */ + if (iStart < len) { + memmove(ip->compress_buf, ip->compress_buf+iStart, len - + iStart); - } + } - zcompress->next_out = ip->compress_buf + len - iStart; - } - } + zcompress->next_out = ip->compress_buf + len - iStart; + } + } - return ret; + return ret; } static int send_compressed (interactive_t *ip, unsigned char* data, int length) { - z_stream* zcompress; - int wr = 1; - int first = 1; - - zcompress = ip->compressed_stream; - zcompress->next_in = data; - zcompress->avail_in = length; - while (zcompress->avail_in && (wr == 1 || first)) { - if(wr == 2) - first = 0; - zcompress->avail_out = COMPRESS_BUF_SIZE - (zcompress->next_out - - ip->compress_buf); - - if (zcompress->avail_out) { - deflate(zcompress, Z_SYNC_FLUSH); - } - - if(!( wr = flush_compressed_output(ip))) - return 0; - } - return length; + z_stream* zcompress; + int wr = 1; + int first = 1; + + zcompress = ip->compressed_stream; + zcompress->next_in = data; + zcompress->avail_in = length; + while (zcompress->avail_in && (wr == 1 || first)) { + if(wr == 2) + first = 0; + zcompress->avail_out = COMPRESS_BUF_SIZE - (zcompress->next_out - + ip->compress_buf); + + if (zcompress->avail_out) { + deflate(zcompress, Z_SYNC_FLUSH); + } + + if(!( wr = flush_compressed_output(ip))) + return 0; + } + return length; } #endif #ifdef F_ACT_MXP void f_act_mxp(){ - add_binary_message(current_object, telnet_will_mxp, sizeof(telnet_will_mxp)); + add_binary_message(current_object, telnet_will_mxp, sizeof(telnet_will_mxp)); } #endif @@ -3318,30 +3431,60 @@ void f_send_gmcp(){ add_binary_message(current_object, telnet_start_gmcp, sizeof(telnet_start_gmcp)); add_binary_message(current_object, (const unsigned char *)(sp->u.string), strlen(sp->u.string)); add_binary_message(current_object, telnet_end_sub, sizeof(telnet_end_sub)); + + pop_stack(); } #endif #ifdef F_REQUEST_TERM_TYPE void f_request_term_type(){ - add_binary_message(command_giver, telnet_term_query, sizeof(telnet_term_query)); + add_binary_message(command_giver, telnet_term_query, sizeof(telnet_term_query)); } #endif #ifdef F_START_REQUEST_TERM_TYPE void f_start_request_term_type(){ - add_binary_message(command_giver, telnet_do_ttype, sizeof(telnet_do_ttype)); + add_binary_message(command_giver, telnet_do_ttype, sizeof(telnet_do_ttype)); } #endif #ifdef F_REQUEST_TERM_SIZE void f_request_term_size(){ - if((st_num_arg == 1) && (sp->u.number == 0)) - add_binary_message(command_giver, telnet_dont_naws, - sizeof(telnet_dont_naws)); - else - add_binary_message(command_giver, telnet_do_naws, sizeof(telnet_do_naws)); - - if(st_num_arg == 1) - sp--; + if((st_num_arg == 1) && (sp->u.number == 0)) + add_binary_message(command_giver, telnet_dont_naws, + sizeof(telnet_dont_naws)); + else + add_binary_message(command_giver, telnet_do_naws, sizeof(telnet_do_naws)); + + if(st_num_arg == 1) + sp--; +} +#endif + +#ifdef F_WEBSOCKET_HANDSHAKE_DONE +void f_websocket_handshake_done(){ + if(!current_interactive) + return; + + flush_message(current_interactive->interactive); + current_interactive->interactive->iflags |= HANDSHAKE_COMPLETE; + object_t * ob = current_interactive;//command_giver; + /* Ask permission to ask them for their terminal type */ + add_binary_message(ob, telnet_do_ttype, sizeof(telnet_do_ttype)); + /* Ask them for their window size */ + add_binary_message(ob, telnet_do_naws, sizeof(telnet_do_naws)); + + // Ask them if they support mxp. + add_binary_message(ob, telnet_do_mxp, sizeof(telnet_do_mxp)); + // And mssp + add_binary_message(ob, telnet_will_mssp, sizeof(telnet_will_mssp)); + // May as well ask for zmp while we're there! + + add_binary_message(ob, telnet_will_zmp, sizeof(telnet_will_zmp)); + // Also newenv + add_binary_message(ob, telnet_do_newenv, sizeof(telnet_do_newenv)); + // gmcp *yawn* + add_binary_message(ob, telnet_will_gmcp, sizeof(telnet_will_gmcp)); + } #endif diff --git a/src/comm.h b/src/comm.h index ba54a32e0..19d5abc69 100644 --- a/src/comm.h +++ b/src/comm.h @@ -67,6 +67,7 @@ enum msgtypes { #define USING_MXP 0x4000 /* we've negotiated mxp */ #define USING_ZMP 0x8000 /* we've negotiated zmp */ #define USING_GMCP 0x10000 /* we've negotiated gmcp */ +#define HANDSHAKE_COMPLETE 0x20000 /* websocket connected */ typedef struct interactive_s { object_t *ob; /* points to the associated object */ @@ -116,15 +117,21 @@ typedef struct interactive_s { int message_producer; /* message buffer producer index */ int message_consumer; /* message buffer consumer index */ int message_length; /* message buffer length */ - char message_buf[MESSAGE_BUF_SIZE]; /* message buffer */ + unsigned char message_buf[MESSAGE_BUF_SIZE]; /* message buffer */ int iflags; /* interactive flags */ char out_of_band; /* Send a telnet sync operation */ int state; /* Current telnet state. Bingly wop */ int sb_pos; /* Telnet suboption negotiation stuff */ struct translation *trans; - char *sb_buf; + unsigned char *sb_buf; int sb_size; char slc[NSLC][2]; + char ws_text[MAX_TEXT]; /* input buffer for interactive object */ + int ws_text_end; /* first free char in buffer */ + int ws_text_start; /* where we are up to in user command buffer */ + int ws_size; + int ws_mask; + char ws_maskoffs; } interactive_t; /* @@ -191,11 +198,7 @@ void CDECL add_vmessage (object_t *, const char *, ...); void add_message (object_t *, const char *, int); void add_binary_message (object_t *, const unsigned char *, int); -#ifdef SIGNAL_FUNC_TAKES_INT -void sigalrm_handler (int); -#else -void sigalrm_handler (void); -#endif + void update_ref_counts_for_users (void); INLINE void make_selectmasks (void); void init_user_conn (void); diff --git a/src/compiler.c b/src/compiler.c index 1d626bd58..8d659c88b 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -2450,7 +2450,7 @@ static program_t *epilog (void) { #ifdef DEBUG if (p - (char *)prog != size) { fprintf(stderr, "Program size miscalculated for /%s.\n", prog->filename); - fprintf(stderr, "is: %i, expected: %i\n", p-(char *)prog, size); + fprintf(stderr, "is: %ld, expected: %d\n", p-(char *)prog, size); } #endif @@ -2630,7 +2630,7 @@ static int string_case_compare(void *c1, void *c2) { void prepare_cases (parse_node_t * pn, int start) { parse_node_t **ce_start, **ce_end, **ce; - long end, last_key, this_key; + LPC_INT end, last_key, this_key; int direct = 1; ce_start = (parse_node_t **)&mem_block[A_CASES].block[start]; diff --git a/src/debug.c b/src/debug.c index 26b3357d3..d7ee97243 100644 --- a/src/debug.c +++ b/src/debug.c @@ -41,7 +41,7 @@ mapping_t *debug_levels() { return ret; } -void debug_level_set (char * level) { +void debug_level_set (const char * level) { int i; for (i = 0; i < NELEM(levels); i++) { @@ -52,7 +52,7 @@ void debug_level_set (char * level) { } } -void debug_level_clear (char * level) { +void debug_level_clear (const char * level) { int i; for (i = 0; i < NELEM(levels); i++) { diff --git a/src/debug.h b/src/debug.h index d46e6a23f..359c4d6d3 100644 --- a/src/debug.h +++ b/src/debug.h @@ -20,8 +20,8 @@ extern int debug_level; void handle_debug_level (char *); -void debug_level_set (char *); -void debug_level_clear (char *); +void debug_level_set (const char *); +void debug_level_clear (const char *); #ifdef DEBUG_MACRO #define debug(x,y) if (debug_level & DBG_##x) { printf("%s: ", #x); printf y; putchar('\n'); fflush(stdout); } diff --git a/src/disassembler.c b/src/disassembler.c index beeb3a800..667430073 100644 --- a/src/disassembler.c +++ b/src/disassembler.c @@ -28,18 +28,29 @@ f_dump_prog (void) int narg = st_num_arg; if (st_num_arg == 2) { + if ((sp-1)->type != T_OBJECT) + bad_argument(sp-1, T_OBJECT, 1, F_DUMP_PROG); + ob = sp[-1].u.ob; d = sp->u.number; where = 0; } else if (st_num_arg == 3) { + if ((sp-2)->type != T_OBJECT) + bad_argument(sp-2, T_OBJECT, 1, F_DUMP_PROG); + ob = sp[-2].u.ob; d = sp[-1].u.number; where = (sp->type == T_STRING) ? sp->u.string : 0; } else { + if (sp->type != T_OBJECT) + bad_argument(sp, T_OBJECT, 1, F_DUMP_PROG); + ob = sp->u.ob; d = 0; where = 0; } + + if (!(prog = ob->prog)) { error("No program for object.\n"); } else { @@ -228,7 +239,7 @@ disassemble (FILE * f, char * code, int start, int end, program_t * prog) { extern int num_simul_efun; - long i, j, instr, iarg, is_efun, ri; + long i, j, instr, iarg, ri; unsigned short sarg; unsigned short offset; char *pc, buff[2048]; @@ -274,8 +285,6 @@ disassemble (FILE * f, char * code, int start, int end, program_t * prog) fprintf(f, "%04x: ", (unsigned) (pc - code)); - is_efun = (instr = EXTRACT_UCHAR(pc)) >= BASE; - pc++; buff[0] = 0; sarg = 0; @@ -524,7 +533,7 @@ disassemble (FILE * f, char * code, int start, int end, program_t * prog) case FP_ANONYMOUS: case FP_ANONYMOUS | FP_NOT_BINDABLE: COPY_SHORT(&sarg, &pc[2]); - sprintf(buff, "\nCode:", + sprintf(buff, "\nCode:", pc[0], pc[1], (pc + 3 + sarg - code)); pc += 4; break; @@ -532,23 +541,21 @@ disassemble (FILE * f, char * code, int start, int end, program_t * prog) break; case F_NUMBER: + { + LPC_INT iarg_tmp; - COPY_INT(&iarg, pc); - sprintf(buff, "%ld", iarg); -#if SIZEOF_LONG == 4 - pc += 4; -#else - pc += 8; -#endif + COPY_INT(&iarg_tmp, pc); + sprintf(buff, "%ld", iarg_tmp); + pc += sizeof(LPC_INT); break; - + } case F_REAL: { - double farg; + LPC_FLOAT farg; COPY_FLOAT(&farg, pc); sprintf(buff, "%f", farg); - pc += 4; + pc += sizeof(LPC_FLOAT); break; } @@ -613,9 +620,9 @@ disassemble (FILE * f, char * code, int start, int end, program_t * prog) COPY_SHORT(&sarg, pc + SIZEOF_PTR); if (ttype == 1 || !parg) { if (sarg == 1) - fprintf(f, "\t%-4ld\t\n", (long)parg); + fprintf(f, "\t%-4ld\t\n", (LPC_INT)parg); else - fprintf(f, "\t%-4ld\t%04x\n", (long)parg, addr+sarg); + fprintf(f, "\t%-4ld\t%04x\n", (LPC_INT)parg, addr+sarg); } else { fprintf(f, "\t\"%s\"\t%04x\n", disassem_string(parg), addr+sarg); diff --git a/src/ed.c b/src/ed.c index 6f2801054..d37b2913f 100644 --- a/src/ed.c +++ b/src/ed.c @@ -2541,9 +2541,7 @@ static void print_help (int arg) char *pos = edout; char *outstr; int n; - svalue_t *ret; struct strlst *curp; - int i; switch (arg) { case 'I': diff --git a/src/edit_source.c b/src/edit_source.c index 7f0eb6169..5a85c7117 100644 --- a/src/edit_source.c +++ b/src/edit_source.c @@ -6,6 +6,7 @@ #define NO_OPCODES #include "std.h" #include "lex.h" +#include "lpc.h" #include "preprocess.h" #include "make_func.h" #include "cc.h" @@ -682,7 +683,7 @@ static void preprocess() { register char *yyp, *yyp2; int c; - int cond; + long cond; while (buffered ? (yyp = yyp2 = outp) : fgets(yyp = yyp2 = defbuf + (DEFMAX >> 1), MAXLINE-1, yyin)) { if (!buffered) current_line++; @@ -906,6 +907,15 @@ void make_efun_tables() "/*\n\tThis file is automatically generated by make_func.\n"); fprintf(files[i], "\tdo not make any manual changes to this file.\n*/\n\n"); + + if (outfiles[i][strlen(outfiles[i])-1] == 'h') { + char buf[100]; + int size = strlen(outfiles[i]) - 2; + strncpy(buf, outfiles[i], size); + buf[size+1] = '\0'; + fprintf(files[i], + "#ifndef __AUTOGEN_%s_H\n#define __AUTOGEN_%s_H\n\n", buf, buf); + } } fprintf(files[0],"\n#include \"efun_protos.h\"\n\n"); @@ -970,8 +980,12 @@ void make_efun_tables() } fprintf(files[4],"};\n"); - for (i=0; i < NUM_FILES; i++) + for (i=0; i < NUM_FILES; i++) { + if (outfiles[i][strlen(outfiles[i])-1] == 'h') { + fprintf(files[i], "#endif\n"); + } fclose(files[i]); + } } static void handle_local_defines(int check) { @@ -1187,6 +1201,8 @@ static void handle_malloc() { the_malloc = "64bitmalloc.c"; if(lookup_define("MALLOC32")) the_malloc = "32bitmalloc.c"; + if(lookup_define("GCMALLOC")) + the_malloc = "gcmalloc.c"; if (lookup_define("GNUMALLOC")) the_malloc = "gnumalloc.c"; @@ -1431,6 +1447,7 @@ static void handle_configure() { check_include("INCL_DOS_H", "dos.h"); check_include("INCL_USCLKC_H", "usclkc.h"); check_include("INCL_LIMITS_H", "limits.h"); + check_include("INCL_FLOAT_H", "float.h"); check_include("INCL_LOCALE_H", "locale.h"); if (!check_prog(0, 0, "int x = USHRT_MAX;", 0)) { if (!check_prog(0, 0, "int x = MAXSHORT;", 0)) @@ -1566,11 +1583,13 @@ static void handle_configure() { find_memmove(); #endif - fprintf(yyout, "#define SIZEOF_INT %i\n", sizeof(int)); - fprintf(yyout, "#define SIZEOF_PTR %i\n", sizeof(char *)); - fprintf(yyout, "#define SIZEOF_SHORT %i\n", sizeof(short)); - fprintf(yyout, "#define SIZEOF_FLOAT %i\n", sizeof(double)); - fprintf(yyout, "#define SIZEOF_LONG %i\n", sizeof(long)); + fprintf(yyout, "#define SIZEOF_INT %lu\n", sizeof(int)); + fprintf(yyout, "#define SIZEOF_PTR %lu\n", sizeof(char *)); + fprintf(yyout, "#define SIZEOF_SHORT %lu\n", sizeof(short)); + fprintf(yyout, "#define SIZEOF_FLOAT %lu\n", sizeof(double)); + fprintf(yyout, "#define SIZEOF_LONG %lu\n", sizeof(long)); + fprintf(yyout, "#define SIZEOF_LPC_INT %lu\n", sizeof(LPC_INT)); + fprintf(yyout, "#define SIZEOF_LPC_FLOAT %lu\n", sizeof(LPC_FLOAT)); if (sizeof(unsigned long) == 4) fprintf(yyout, "#define UINT32 unsigned long\n"); @@ -1652,9 +1671,8 @@ static void handle_configure() { check_library("-lseq"); check_library("-lm"); - if (lookup_define("CYGWIN")) - check_library("-liconv"); - + if (lookup_define("GCMALLOC")) + check_library("-lgc"); if (lookup_define("MINGW")){ check_library("-lwsock32"); @@ -1670,6 +1688,10 @@ static void handle_configure() { check_library("-lssl"); if (lookup_define("PACKAGE_PCRE")) check_library("-lpcre"); + if (lookup_define("PACKAGE_CRYPTO")) + check_library("-lcrypto"); + if (lookup_define("POSIX_TIMERS")) + check_library("-lrt"); fprintf(stderr, "Checking for flaky Linux systems ...\n"); check_linux_libc(); diff --git a/src/efuns_main.c b/src/efuns_main.c index 3d081fafc..1d3be6a39 100644 --- a/src/efuns_main.c +++ b/src/efuns_main.c @@ -163,16 +163,16 @@ static void print_cache_stats (outbuffer_t * ob) outbuf_add(ob, "Function cache information\n"); outbuf_add(ob, "-------------------------------\n"); outbuf_addv(ob, "%% cache hits: %10.2f\n", - 100 * ((double) apply_low_cache_hits / apply_low_call_others)); + 100 * ((LPC_FLOAT) apply_low_cache_hits / apply_low_call_others)); outbuf_addv(ob, "call_others: %10lu\n", apply_low_call_others); outbuf_addv(ob, "cache hits: %10lu\n", apply_low_cache_hits); outbuf_addv(ob, "cache size: %10lu\n", APPLY_CACHE_SIZE); outbuf_addv(ob, "slots used: %10lu\n", apply_low_slots_used); outbuf_addv(ob, "%% slots used: %10.2f\n", - 100 * ((double) apply_low_slots_used / APPLY_CACHE_SIZE)); + 100 * ((LPC_FLOAT) apply_low_slots_used / APPLY_CACHE_SIZE)); outbuf_addv(ob, "collisions: %10lu\n", apply_low_collisions); outbuf_addv(ob, "%% collisions: %10.2f\n", - 100 * ((double) apply_low_collisions / apply_low_call_others)); + 100 * ((LPC_FLOAT) apply_low_collisions / apply_low_call_others)); } void f_cache_stats (void) @@ -260,7 +260,7 @@ f_call_out (void) svalue_t *arg = sp - st_num_arg + 1; int num = st_num_arg - 2; #ifdef CALLOUT_HANDLES - int ret; + LPC_INT ret; if (!(current_object->flags & O_DESTRUCTED)) { ret = new_call_out(current_object, arg, arg[1].u.number, num, arg + 2); @@ -322,8 +322,8 @@ f_call_stack (void) int i, n = csp - &control_stack[0] + 1; array_t *ret; - if (sp->u.number < 0 || sp->u.number > 3) - error("First argument of call_stack() must be 0, 1, 2, or 3.\n"); + if (sp->u.number < 0 || sp->u.number > 4) + error("First argument of call_stack() must be 0, 1, 2, 3, or 4.\n"); ret = allocate_empty_array(n); @@ -376,7 +376,25 @@ f_call_stack (void) ret->item[i].u.string = origin_name((csp-i+1)->caller_type); } break; + case 4: + for (i = 0; i < n; i++) { + ret->item[i].type = T_STRING; + if (1 ||((csp - i)->framekind & FRAME_MASK) == FRAME_FUNCTION || ((csp - i)->framekind & FRAME_MASK) == FRAME_FUNP) { + const program_t *prog = (i ? (csp-i+1)->prog : current_prog); + int index = (csp-i)->fr.table_index; + char *progc = (i ? (csp-i+1)->pc:pc); + function_t *cfp = &prog->function_table[index]; + ret->item[i].type = T_STRING; + ret->item[i].subtype = STRING_MALLOC; + ret->item[i].u.string = string_copy(get_line_number(progc, prog), "call_stack"); + } else { + ret->item[i].subtype = STRING_CONSTANT; + ret->item[i].u.string = (((csp - i)->framekind & FRAME_MASK) == FRAME_CATCH) ? "CATCH" : ""; + } + } + break; } + put_array(ret); } #endif @@ -570,6 +588,7 @@ f_set_debug_level (void) void f_clear_debug_level (void) { debug_level_clear(sp->u.string); + pop_stack(); } void @@ -648,10 +667,15 @@ f_ed (void) ed_start(0, 0, 0, 0, 0, 0); } else if (st_num_arg == 1) { /* ed(fname) */ + if (!(sp->type == T_STRING)) + bad_argument(sp, T_STRING, 1, F_ED); ed_start(sp->u.string, 0, 0, 0, 0, 0); pop_stack(); } else if (st_num_arg == 2) { /* ed(fname,exitfn) / ed(fname, scroll_lines) */ + if (!((sp - 1)->type == T_STRING)) + bad_argument(sp - 1, T_STRING, 1, F_ED); + if(sp->type == T_STRING) ed_start((sp - 1)->u.string, 0, sp->u.string, 0, current_object, 0); else if(sp->type == T_NUMBER) @@ -662,6 +686,11 @@ f_ed (void) } else if (st_num_arg == 3) { /* ed(fname,exitfn,restricted) / ed(fname,writefn,exitfn) / ed(fname,exitfn,scroll_lines) */ + if (!((sp - 1)->type == T_STRING)) + bad_argument(sp - 1, T_STRING, 2, F_ED); + if (!((sp - 2)->type == T_STRING)) + bad_argument(sp - 2, T_STRING, 1, F_ED); + if (sp->type == T_NUMBER) { if(sp->u.number == 1) ed_start((sp - 2)->u.string, 0, (sp - 1)->u.string, sp->u.number, @@ -679,10 +708,15 @@ f_ed (void) } else if (st_num_arg == 4) { /* ed(fname,writefn,exitfn,restricted) / ed(fname,writefn,exitfn,scroll_lines) */ - if (!((sp - 1)->type == T_STRING)) - bad_argument(sp - 1, T_STRING, 3, F_ED); if (!(sp->type == T_NUMBER)) bad_argument(sp, T_NUMBER, 4, F_ED); + if (!((sp - 1)->type == T_STRING)) + bad_argument(sp - 1, T_STRING, 3, F_ED); + if (!((sp - 2)->type == T_STRING)) + bad_argument(sp - 2, T_STRING, 2, F_ED); + if (!((sp - 3)->type == T_STRING)) + bad_argument(sp - 3, T_STRING, 1, F_ED); + if(sp->u.number == 1) ed_start((sp - 3)->u.string, (sp - 2)->u.string, (sp - 1)->u.string, sp->u.number, current_object, 0); @@ -698,6 +732,10 @@ f_ed (void) bad_argument(sp-1, T_NUMBER, 4, F_ED); if(!((sp-2)->type == T_STRING)) bad_argument(sp-2, T_STRING, 3, F_ED); + if(!((sp-3)->type == T_STRING)) + bad_argument(sp-3, T_STRING, 2, F_ED); + if(!((sp-4)->type == T_STRING)) + bad_argument(sp-4, T_STRING, 1, F_ED); ed_start((sp - 4)->u.string, (sp - 3)->u.string, (sp - 2)->u.string, (sp - 1)->u.number, current_object, sp->u.number); @@ -796,7 +834,7 @@ f_error (void) int l = SVALUE_STRLEN(sp); char err_buf[2048]; - if (sp->u.string[l - 1] == '\n') + if (l && sp->u.string[l - 1] == '\n') l--; if (l > 2045) l = 2045; @@ -891,7 +929,7 @@ f_file_name (void) void f_file_size (void) { - long i = file_size(sp->u.string); + LPC_INT i = file_size(sp->u.string); free_string_svalue(sp); put_number(i); } @@ -1171,7 +1209,7 @@ inherits (program_t * prog, program_t * thep) return 1; if (!strcmp(pg->filename, thep->filename)) return 2; - if (l=inherits(pg, thep)) + if ((l=inherits(pg, thep))) return l; } return 0; @@ -2758,9 +2796,10 @@ void f_save_object (void) { int flag; - if (st_num_arg == 2 ) { flag = (sp--)->u.number; + if(sp->type != T_STRING) + error("first argument must be a string for save_object with 2 args"); } else { flag = 0; } @@ -3075,8 +3114,7 @@ f_sizeof (void) i = 0; free_svalue(sp, "f_sizeof"); } - sp->type = T_NUMBER; - sp->u.number = i; + put_number(i); } #endif @@ -3454,6 +3492,8 @@ f_this_player (void) } #endif +int playerchanged; + #ifdef F_SET_THIS_PLAYER void f_set_this_player (void) @@ -3463,6 +3503,7 @@ f_set_this_player (void) else set_command_giver(sp->u.ob); pop_stack(); + playerchanged = 1; } #endif @@ -3488,12 +3529,12 @@ f_time (void) void f__to_float (void) { - double temp = 0; + LPC_FLOAT temp = 0; switch(sp->type) { case T_NUMBER: sp->type = T_REAL; - sp->u.real = (double) sp->u.number; + sp->u.real = (LPC_FLOAT) sp->u.number; break; case T_STRING: sscanf(sp->u.string, "%lf", &temp); @@ -3511,11 +3552,11 @@ f__to_int (void) switch(sp->type) { case T_REAL: sp->type = T_NUMBER; - sp->u.number = (long) sp->u.real; + sp->u.number = (LPC_INT) sp->u.real; break; case T_STRING: { - long temp; + LPC_INT temp; char *p; temp = strtol(sp->u.string, &p, 10); @@ -3793,7 +3834,7 @@ void f_reclaim_objects (void) void f_memory_info (void) { - long mem; + LPC_INT mem; object_t *ob; if (st_num_arg == 0) { @@ -3948,7 +3989,7 @@ f_next_inventory (void) #ifdef F_DEFER void f_defer(){ - struct defer_list *newlist = MALLOC(sizeof(struct defer_list)); + struct defer_list *newlist = (struct defer_list *)MALLOC(sizeof(struct defer_list)); newlist->next = csp->defers; newlist->func = *sp--; if(command_giver){ diff --git a/src/efuns_port.c b/src/efuns_port.c index 85125c043..50307a2f1 100644 --- a/src/efuns_port.c +++ b/src/efuns_port.c @@ -99,72 +99,76 @@ f_localtime (void) lt = sp->u.number; tm = localtime(<); - vec = allocate_empty_array(11); - vec->item[LT_SEC].type = T_NUMBER; - vec->item[LT_SEC].u.number = tm->tm_sec; - vec->item[LT_MIN].type = T_NUMBER; - vec->item[LT_MIN].u.number = tm->tm_min; - vec->item[LT_HOUR].type = T_NUMBER; - vec->item[LT_HOUR].u.number = tm->tm_hour; - vec->item[LT_MDAY].type = T_NUMBER; - vec->item[LT_MDAY].u.number = tm->tm_mday; - vec->item[LT_MON].type = T_NUMBER; - vec->item[LT_MON].u.number = tm->tm_mon; - vec->item[LT_YEAR].type = T_NUMBER; - vec->item[LT_YEAR].u.number = tm->tm_year + 1900; - vec->item[LT_WDAY].type = T_NUMBER; - vec->item[LT_WDAY].u.number = tm->tm_wday; - vec->item[LT_YDAY].type = T_NUMBER; - vec->item[LT_YDAY].u.number = tm->tm_yday; - vec->item[LT_GMTOFF].type = T_NUMBER; - vec->item[LT_ZONE].type = T_STRING; - vec->item[LT_ZONE].subtype = STRING_MALLOC; - vec->item[LT_ISDST].type = T_NUMBER; + + if (tm) { + vec->item[LT_SEC].type = T_NUMBER; + vec->item[LT_SEC].u.number = tm->tm_sec; + vec->item[LT_MIN].type = T_NUMBER; + vec->item[LT_MIN].u.number = tm->tm_min; + vec->item[LT_HOUR].type = T_NUMBER; + vec->item[LT_HOUR].u.number = tm->tm_hour; + vec->item[LT_MDAY].type = T_NUMBER; + vec->item[LT_MDAY].u.number = tm->tm_mday; + vec->item[LT_MON].type = T_NUMBER; + vec->item[LT_MON].u.number = tm->tm_mon; + vec->item[LT_YEAR].type = T_NUMBER; + vec->item[LT_YEAR].u.number = tm->tm_year + 1900; + vec->item[LT_WDAY].type = T_NUMBER; + vec->item[LT_WDAY].u.number = tm->tm_wday; + vec->item[LT_YDAY].type = T_NUMBER; + vec->item[LT_YDAY].u.number = tm->tm_yday; + vec->item[LT_GMTOFF].type = T_NUMBER; + vec->item[LT_ZONE].type = T_STRING; + vec->item[LT_ZONE].subtype = STRING_MALLOC; + vec->item[LT_ISDST].type = T_NUMBER; #if defined(BSD42) || defined(apollo) || defined(_AUX_SOURCE) \ - || defined(OLD_ULTRIX) - /* 4.2 BSD doesn't seem to provide any way to get these last three values */ - vec->item[LT_GMTOFF].u.number = 0; - vec->item[LT_ZONE].type = T_NUMBER; - vec->item[LT_ZONE].u.number = 0; - vec->item[LT_ISDST].u.number = -1; + || defined(OLD_ULTRIX) + /* 4.2 BSD doesn't seem to provide any way to get these last three values */ + vec->item[LT_GMTOFF].u.number = 0; + vec->item[LT_ZONE].type = T_NUMBER; + vec->item[LT_ZONE].u.number = 0; + vec->item[LT_ISDST].u.number = -1; #else /* BSD42 */ - vec->item[LT_ISDST].u.number = tm->tm_isdst; + vec->item[LT_ISDST].u.number = tm->tm_isdst; #if defined(sequent) - vec->item[LT_GMTOFF].u.number = 0; - gettimeofday(NULL, &tz); - vec->item[LT_GMTOFF].u.number = tz.tz_minuteswest; - vec->item[LT_ZONE].u.string = + vec->item[LT_GMTOFF].u.number = 0; + gettimeofday(NULL, &tz); + vec->item[LT_GMTOFF].u.number = tz.tz_minuteswest; + vec->item[LT_ZONE].u.string = string_copy(timezone(tz.tz_minuteswest, tm->tm_isdst), "f_localtime"); #else /* sequent */ #if (defined(hpux) || defined(_SEQUENT_) || defined(_AIX) || defined(SunOS_5) \ - || defined(SVR4) || defined(sgi) || defined(linux) || defined(cray) \ - || defined(__CYGWIN__)\ + || defined(SVR4) || defined(sgi) || defined(__linux__) || defined(cray) \ + || defined(__CYGWIN__)\ ) - if (!tm->tm_isdst) { + if (!tm->tm_isdst) { vec->item[LT_GMTOFF].u.number = timezone; vec->item[LT_ZONE].u.string = string_copy(tzname[0], "f_localtime"); - } else { -#if (defined(_AIX) || defined(hpux) || defined(linux) || defined(cray) \ - || defined(__CYGWIN__)\ - ) + } else { +#if (defined(_AIX) || defined(hpux) || defined(__linux__) || defined(cray) \ + || defined(__CYGWIN__)\ + ) vec->item[LT_GMTOFF].u.number = timezone; #else vec->item[LT_GMTOFF].u.number = altzone; #endif vec->item[LT_ZONE].u.string = string_copy(tzname[1], "f_localtime"); - } + } #else #ifndef WIN32 - vec->item[LT_GMTOFF].u.number = tm->tm_gmtoff; - vec->item[LT_ZONE].u.string = string_copy(tm->tm_zone, "f_localtime"); + vec->item[LT_GMTOFF].u.number = tm->tm_gmtoff; + vec->item[LT_ZONE].u.string = string_copy(tm->tm_zone, "f_localtime"); #else +#if defined(WIN32) || defined(__CYGWIN__) vec->item[LT_GMTOFF].u.number = _timezone; vec->item[LT_ZONE].u.string = string_copy(_tzname[_daylight?1:0],"f_localtime"); #endif #endif +#endif #endif /* sequent */ #endif /* BSD42 */ + } put_array(vec); } #endif diff --git a/src/eval.c b/src/eval.c index bd527bd6a..76c2bab31 100644 --- a/src/eval.c +++ b/src/eval.c @@ -4,37 +4,47 @@ #include "uvalarm.h" #include #include "backend.h" +#include "posix_timers.h" int outoftime = 0; struct timeval tv; int lasttime; +LPC_INT max_cost; void set_eval(int etime){ #ifndef WIN32 - long diff; - gettimeofday(&tv, NULL); - if((diff = tv.tv_sec-current_time) > 1){ - diff *= 1000000; - if(diff > max_cost*100){ - //put some hard limit to eval times - outoftime = 1; - return; - } - } - signal(SIGVTALRM, sigalrm_handler); - uvalarm(etime, 0); + long diff; + gettimeofday(&tv, NULL); + if((diff = tv.tv_sec-current_time) > 1){ + diff *= 1000000; + if(diff > max_cost*100L){ + //put some hard limit to eval times + debug(d_flag, ("difft:%ld, max_cost:%d", diff, max_cost)); + outoftime = 1; + return; + } + } +#ifdef POSIX_TIMERS + posix_eval_timer_set(etime); +#else + signal(SIGVTALRM, sigalrm_handler); + uvalarm(etime, 0); #endif - outoftime = 0; - +#endif + outoftime = 0; } -int get_eval(){ +LPC_INT get_eval(){ #ifndef WIN32 - struct timeval now; - gettimeofday(&now, NULL); - return max_cost - (1000000*(now.tv_sec - tv.tv_sec))-(now.tv_usec - tv.tv_usec); +#ifdef POSIX_TIMERS + return posix_eval_timer_get(); +#else + struct timeval now; + gettimeofday(&now, NULL); + return max_cost - (1000000*(now.tv_sec - tv.tv_sec))-(now.tv_usec - tv.tv_usec); +#endif #else - return 100; + return 100; #endif } diff --git a/src/eval.h b/src/eval.h index 795adf900..e4813a585 100644 --- a/src/eval.h +++ b/src/eval.h @@ -1,6 +1,7 @@ #ifndef FLUFF_EVAL_H #define FLUFF_EVAL_H extern int outoftime; -void set_eval(int time); -int get_eval(); +extern LPC_INT max_cost; +void set_eval(LPC_INT time); +LPC_INT get_eval(); #endif diff --git a/src/file.c b/src/file.c index 8ac0bf242..a035f4223 100644 --- a/src/file.c +++ b/src/file.c @@ -484,7 +484,7 @@ char *read_file(const char * file, int start, int len) { p = str; while (start > 1) { /* skip newlines */ - p2 = (char *)memchr(p, '\n', 2*READ_FILE_MAX_SIZE+str-p); + p2 = (char *)memchr(p, '\n', chunk+str-p); if (p2) { p = p2 + 1; start--; diff --git a/src/file_incl.h b/src/file_incl.h index 207962af6..5bb20f319 100644 --- a/src/file_incl.h +++ b/src/file_incl.h @@ -8,7 +8,7 @@ # include #endif -#ifndef linux +#ifndef __linux__ #ifdef INCL_SYS_DIRENT_H # include #endif diff --git a/src/fliconv.c b/src/fliconv.c index 77c686416..e16545dc6 100644 --- a/src/fliconv.c +++ b/src/fliconv.c @@ -23,10 +23,12 @@ struct translation *get_translator(const char *encoding){ struct translation *ret = find_translator(encoding); if(ret) return ret; - ret = (struct translation *)MALLOC(sizeof(struct translation)); - char *name = (char *)MALLOC(strlen(encoding)+18+1); + ret = (struct translation *)DMALLOC(sizeof(struct translation), + TAG_PERMANENT, "get_translator"); + char *name = (char *)DMALLOC(strlen(encoding)+18+1, + TAG_PERMANENT, "get_translator"); strcpy(name, encoding); -#ifdef linux +#ifdef __linux__ strcat(name, "//TRANSLIT//IGNORE"); #endif ret->name = name; @@ -60,7 +62,7 @@ char *translate(iconv_t tr, const char *mes, int inlen, int *outlen){ char *tmp2; if(!res){ - res = (char *)MALLOC(1); + res = (char *)DMALLOC(1, TAG_PERMANENT, "translate"); reslen = 1; } @@ -84,7 +86,7 @@ char *translate(iconv_t tr, const char *mes, int inlen, int *outlen){ len = strlen(mes)+1; FREE(res); reslen *= 2; - res = (char *)MALLOC(reslen); + res = (char *)DMALLOC(reslen, TAG_PERMANENT, "translate"); tmp2 = res; len2 = reslen; continue; @@ -182,7 +184,7 @@ void f_arr_to_str(){ newt = get_translator("UTF-32"); } int len = sp->u.arr->size; - int *in = (int *)MALLOC(sizeof(int)*(len+1)); + int *in = (int *)DMALLOC(sizeof(int)*(len+1), TAG_TEMPORARY, "f_arr_to_str"); char *trans; in[len] = 0; while(len--) diff --git a/src/func_spec.c b/src/func_spec.c index d401b8518..7d95826ac 100644 --- a/src/func_spec.c +++ b/src/func_spec.c @@ -404,6 +404,7 @@ void message(mixed, mixed, string | string * | object | object *, string arr_to_str(int *); #endif void act_mxp(); + void websocket_handshake_done(); void request_term_type(); void start_request_term_type(); void request_term_size(void | int); diff --git a/src/function.c b/src/function.c index 4fecc1bd6..13afe6dbb 100644 --- a/src/function.c +++ b/src/function.c @@ -222,7 +222,6 @@ call_function_pointer (funptr_t * funp, int num_arg) { static func_t *oefun_table = efun_table - BASE; array_t *v; - int extfr = 1; if (!funp->hdr.owner || (funp->hdr.owner->flags & O_DESTRUCTED)) error("Owner (/%s) of function pointer is destructed.\n", diff --git a/src/malloc.c b/src/gcmalloc.c similarity index 63% rename from src/malloc.c rename to src/gcmalloc.c index 0e37aef26..15f584223 100644 --- a/src/malloc.c +++ b/src/gcmalloc.c @@ -1,13 +1,11 @@ #define IN_MALLOC_WRAPPER -#define NO_OPCODES -#include "std.h" -#include "lpc_incl.h" -#include "simulate.h" -#include "comm.h" +#include +void malloc_init() { + GC_INIT(); +} #ifdef DO_MSTATS void show_mstats (outbuffer_t * ob, char * s) { outbuf_add(ob, "No malloc statistics available with SYSMALLOC\n"); } #endif - diff --git a/src/generate.c b/src/generate.c index 137a39edd..3fe2147d5 100644 --- a/src/generate.c +++ b/src/generate.c @@ -251,11 +251,11 @@ static void lpc_tree (parse_node_t * dest, int num) { } } -static void lpc_tree_number (parse_node_t * dest, int num) { +static void lpc_tree_number (parse_node_t * dest, LPC_INT num) { CREATE_NUMBER(dest->v.expr, num); } -static void lpc_tree_real (parse_node_t * dest, double real) { +static void lpc_tree_real (parse_node_t * dest, LPC_FLOAT real) { CREATE_REAL(dest->v.expr, real); } @@ -605,13 +605,13 @@ dump_tree (parse_node_t * expr) { case NODE_UNARY_OP_1: printf("(%s ", instrs[expr->v.number].name); dump_tree(expr->r.expr); - printf(" %i)", expr->l.number); + printf(" %ld)", expr->l.number); break; case NODE_OPCODE_1: - printf("(%s %i)", instrs[expr->v.number].name, expr->l.number); + printf("(%s %ld)", instrs[expr->v.number].name, expr->l.number); break; case NODE_OPCODE_2: - printf("(%s %i %i)", instrs[expr->v.number].name, expr->l.number, expr->r.number); + printf("(%s %ld %ld)", instrs[expr->v.number].name, expr->l.number, expr->r.number); break; case NODE_RETURN: if (expr->r.expr) { @@ -623,13 +623,13 @@ dump_tree (parse_node_t * expr) { } break; case NODE_STRING: - printf("(string %i)", expr->v.number); + printf("(string %ld)", expr->v.number); break; case NODE_REAL: printf("(real %f)", expr->v.real); break; case NODE_NUMBER: - printf("(number %i)", expr->v.number); + printf("(number %ld)", expr->v.number); break; case NODE_LAND_LOR: if (expr->v.number == F_LAND) @@ -647,19 +647,19 @@ dump_tree (parse_node_t * expr) { printf(")"); break; case NODE_CALL_2: - printf("(%s %i %i %i ", instrs[expr->v.number].name, expr->l.number >> 16, + printf("(%s %ld %ld %i ", instrs[expr->v.number].name, expr->l.number >> 16, expr->l.number & 0xffff, (expr->r.expr ? expr->r.expr->kind : 0)); dump_expr_list(expr->r.expr); printf(")"); break; case NODE_CALL_1: - printf("(%s %i %i ", instrs[expr->v.number].name, expr->l.number, + printf("(%s %ld %i ", instrs[expr->v.number].name, expr->l.number, (expr->r.expr ? expr->r.expr->kind : 0)); dump_expr_list(expr->r.expr); printf(")"); break; case NODE_CALL: - printf("(%s %i ", instrs[expr->v.number].name, expr->l.number); + printf("(%s %ld ", instrs[expr->v.number].name, expr->l.number); dump_expr_list(expr->r.expr); printf(")"); break; @@ -680,10 +680,10 @@ dump_tree (parse_node_t * expr) { } break; case NODE_PARAMETER: - printf("(parameter %i)", expr->v.number); + printf("(parameter %ld)", expr->v.number); break; case NODE_PARAMETER_LVALUE: - printf("(parameter_lvalue %i)", expr->v.number); + printf("(parameter_lvalue %ld)", expr->v.number); break; case NODE_IF: printf("(if "); @@ -740,7 +740,7 @@ dump_tree (parse_node_t * expr) { printf(")"); break; case NODE_FUNCTION_CONSTRUCTOR: - printf("(function %i ", expr->v.number & 0xff); + printf("(function %ld ", expr->v.number & 0xff); if (expr->r.expr) { printf("(array "); dump_expr_list(expr->r.expr); @@ -750,25 +750,25 @@ dump_tree (parse_node_t * expr) { } switch (expr->v.number & 0xff) { case FP_SIMUL: - printf("(fp-simul %i)", expr->v.number >> 8); + printf("(fp-simul %ld)", expr->v.number >> 8); break; case FP_LOCAL: - printf("(fp-local %i)", expr->v.number >> 8); + printf("(fp-local %ld)", expr->v.number >> 8); break; case FP_EFUN: printf("(fp-efun %s)", instrs[expr->v.number >> 8].name); break; case FP_FUNCTIONAL: case FP_FUNCTIONAL | FP_NOT_BINDABLE: - printf("(fp-functional %i ", expr->v.number >> 8); + printf("(fp-functional %ld ", expr->v.number >> 8); dump_tree(expr->l.expr); printf(")"); break; } - printf(" %i)", expr->v.number >> 8); + printf(" %ld)", expr->v.number >> 8); break; case NODE_ANON_FUNC: - printf("(anon-func %i %i ", expr->v.number, expr->l.number); + printf("(anon-func %ld %ld ", expr->v.number, expr->l.number); dump_tree(expr->r.expr); printf(")"); break; diff --git a/src/grammar.y.pre b/src/grammar.y.pre index eb37a05a1..5988e764b 100644 --- a/src/grammar.y.pre +++ b/src/grammar.y.pre @@ -130,8 +130,8 @@ int yyparse (void); %union { POINTER_INT pointer_int; - long number; - float real; + LPC_INT number; /* 4 or 8 */ + LPC_FLOAT real; /* 8 */ char *string; struct { short num_arg; char flags; } argument; ident_hash_elem_t *ihe; @@ -1193,7 +1193,7 @@ for: $7 = pop_value($7); if ($7 && IS_NODE($7, NODE_UNARY_OP, F_INC) && IS_NODE($7->r.expr, NODE_OPCODE_1, F_LOCAL_LVALUE)) { - long lvar = $7->r.expr->l.number; + LPC_INT lvar = $7->r.expr->l.number; CREATE_OPCODE_1($7, F_LOOP_INCR, 0, lvar); } @@ -1397,7 +1397,7 @@ first_for_expr: $$ = $2; $$->v.expr = new_node(); $$->v.expr->kind = NODE_CASE_NUMBER; - $$->v.expr->r.number = ((unsigned long)-1)/2; //maxint + $$->v.expr->r.number = LPC_INT_MAX; //maxint add_to_mem_block(A_CASES, (char *)&($2), sizeof($2)); } @@ -1409,7 +1409,7 @@ first_for_expr: context |= SWITCH_RANGES; $$ = new_node(); $$->kind = NODE_CASE_NUMBER; - $$->r.number = (long) 1+ ((unsigned long)-1)/2; //maxint +1 wraps to min_int, on all computers i know, just not in the C standard iirc + $$->r.number = LPC_INT_MIN; //maxint +1 wraps to min_int, on all computers i know, just not in the C standard iirc $$->v.expr = $3; add_to_mem_block(A_CASES, (char *)&($$), sizeof($$)); @@ -1602,10 +1602,10 @@ expr0: side of the tree node. */ CREATE_BINARY_OP($$, $2, r->type, r, l); + /* allow TYPE_STRING += TYPE_NUMBER | TYPE_OBJECT */ if (exact_types && !compatible_types(r->type, l->type) && - !($2 == F_ADD_EQ - && l->type == TYPE_STRING && - (COMP_TYPE(r->type, TYPE_NUMBER))||r->type == TYPE_OBJECT)) { + !($2 == F_ADD_EQ && l->type == TYPE_STRING && + ((COMP_TYPE(r->type, TYPE_NUMBER)) || r->type == TYPE_OBJECT))) { char buf[256]; char *end = EndOf(buf); char *p; @@ -1966,7 +1966,7 @@ expr0: case NODE_STRING: if ($3->kind == NODE_STRING) { /* Combine strings */ - long n1, n2; + LPC_INT n1, n2; const char *s1, *s2; char *news; int l; diff --git a/src/icode.c b/src/icode.c index f15b7c6d7..ed51ce8e4 100644 --- a/src/icode.c +++ b/src/icode.c @@ -19,16 +19,13 @@ #error CFG_MAX_GLOBAL_VARIABLES must not be greater than 65536 #endif -static void ins_real (double); +static void ins_real (LPC_FLOAT); static void ins_short (short); static void upd_short (int, int, const char *); static void ins_byte (unsigned char); static void upd_byte (int, unsigned char); -static void write_number (long); -static void ins_int (long); -#if SIZEOF_PTR == 8 -static void ins_long (long); -#endif +static void write_number (LPC_INT); +static void ins_int (LPC_INT); void i_generate_node (parse_node_t *); static void i_generate_if_branch (parse_node_t *, int); static void i_generate_loop (int, parse_node_t *, parse_node_t *, @@ -50,11 +47,11 @@ static parse_node_t *branch_list[3]; static int nforward_branches, nforward_branches_max; static int *forward_branches = 0; -static void ins_real (double l) -{ - double f = (double)l; +static void ins_real (LPC_FLOAT l) + { + LPC_FLOAT f = l; - if (prog_code + 4 > prog_code_max) { + if (prog_code + sizeof(double) > prog_code_max) { mem_block_t *mbp = &mem_block[A_PROGRAM]; UPDATE_PROGRAM_SIZE; @@ -85,13 +82,14 @@ static void ins_short (short l) } /* - * Store a 4 byte number. It is stored in such a way as to be sure + * Store a 8 byte number. It is stored in such a way as to be sure * that correct byte order is used, regardless of machine architecture. */ -static void ins_int (long l) +// FIXME: needs ins_int32 & ins_int64 to support 32bit compile. +static void ins_int (LPC_INT l) { - if (prog_code + SIZEOF_LONG > prog_code_max) { + if (prog_code + sizeof(LPC_INT) > prog_code_max) { mem_block_t *mbp = &mem_block[A_PROGRAM]; UPDATE_PROGRAM_SIZE; realloc_mem_block(mbp); @@ -102,25 +100,6 @@ static void ins_int (long l) STORE_INT(prog_code, l); } -/* - * Store a 8 byte number. It is stored in such a way as to be sure - * that correct byte order is used, regardless of machine architecture. - */ -#if SIZEOF_PTR == 8 -static void ins_long (long l) -{ - if (prog_code + 8 > prog_code_max) { - mem_block_t *mbp = &mem_block[A_PROGRAM]; - UPDATE_PROGRAM_SIZE; - realloc_mem_block(mbp); - - prog_code = mbp->block + mbp->current_size; - prog_code_max = mbp->block + mbp->max_size; - } - STORE_PTR(prog_code, l); -} -#endif - static void upd_short (int offset, int l, const char * where) { unsigned short s; @@ -236,7 +215,7 @@ static void write_small_number (int val) { ins_byte(val); } -static void write_number (long val) +static void write_number (LPC_INT val) { if ((val & ~0xff) == 0) write_small_number(val); @@ -250,11 +229,7 @@ static void write_number (long val) ins_short(val); } else { ins_byte(F_NUMBER); -#if SIZEOF_LONG == 4 ins_int(val); -#else - ins_long(val); -#endif } } } @@ -433,11 +408,7 @@ i_generate_node (parse_node_t * expr) { ins_byte(expr->v.number); ins_byte(expr->l.number); if (expr->v.number == F_LOOP_COND_NUMBER) -#if SIZEOF_LONG == 8 - ins_long(expr->r.number); -#else - ins_int(expr->r.number); -#endif + ins_int(expr->r.number); else ins_byte(expr->r.number); break; @@ -1235,7 +1206,7 @@ optimize_icode (char * start, char * pc, char * end) { LOAD_SHORT(etable, pc); pc += 2; /* def */ //break; //doesn't seem to work! - printf("stable: %x pc %x swstart %x etable %x\n", stable, pc, swstart, etable); + printf("stable: %x pc %p swstart %p etable %x\n", stable, (void *)pc, (void *)swstart, etable); DEBUG_CHECK(stable < pc - swstart || etable < pc - swstart || etable < stable, "Error in switch table found while optimizing\n"); diff --git a/src/include/runtime_config.h b/src/include/runtime_config.h index 4ba52b0d4..a16278766 100644 --- a/src/include/runtime_config.h +++ b/src/include/runtime_config.h @@ -32,6 +32,8 @@ #define __LOG_DIR__ CFG_STR(4) #define __INCLUDE_DIRS__ CFG_STR(5) +#define __PLACEHOLDER1__ CFG_STR(6) + #define __MASTER_FILE__ CFG_STR(7) #define __SIMUL_EFUN_FILE__ CFG_STR(8) #define __SWAP_FILE__ CFG_STR(9) diff --git a/src/interpret.c b/src/interpret.c index 4db7c37d9..13a388a46 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -54,7 +54,6 @@ static const char *type_names[] = { #ifdef PACKAGE_UIDS extern userid_t *backbone_uid; #endif -extern int max_cost; extern int call_origin; static int find_line (char *, const program_t *, const char **, int *); INLINE void push_indexed_lvalue (int); @@ -66,7 +65,7 @@ INLINE_STATIC void do_loop_cond_number (void); INLINE_STATIC void do_loop_cond_local (void); static void do_catch (char *, unsigned short); int last_instructions (void); -static double _strtof (char *, char **); +static LPC_FLOAT _strtof (char *, char **); #ifdef TRACE_CODE static char *get_arg (int, int); #endif @@ -316,7 +315,7 @@ int validate_shadowing (object_t * ob) * Push a number on the value stack. */ INLINE void -push_number (long n) +push_number (LPC_INT n) { STACK_INC; sp->type = T_NUMBER; @@ -325,7 +324,7 @@ push_number (long n) } INLINE void -push_real (double n) +push_real (LPC_FLOAT n) { STACK_INC; sp->type = T_REAL; @@ -1235,6 +1234,9 @@ push_control_stack (int frkind) * Pop the control stack one element, and restore registers. * extern_call must not be modified here, as it is used imediately after pop. */ + +extern int playerchanged; + void pop_control_stack() { DEBUG_CHECK(csp == (control_stack - 1), @@ -1276,12 +1278,11 @@ void pop_control_stack() if(outoftime) set_eval(max_cost); save_command_giver(stuff->tp.u.ob); - object_t *cgo = command_giver; + playerchanged = 0; safe_call_efun_callback(&ftc, 0); - int changed = (cgo != command_giver); - cgo = command_giver; + object_t *cgo = command_giver; restore_command_giver(); - if(changed) + if(playerchanged) set_command_giver(cgo); outoftime = s; free_svalue(&(stuff->func), "pop_stack"); @@ -1754,7 +1755,7 @@ INLINE_STATIC void do_loop_cond_local() INLINE_STATIC void do_loop_cond_number() { svalue_t *s1; - long i; + LPC_INT i; s1 = fp + EXTRACT_UCHAR(pc++); /* a from (a < b) */ LOAD_INT(i, pc); @@ -1890,8 +1891,8 @@ eval_instruction (char * p) #ifdef DEBUG int num_arg; #endif - long i, n; - double real; + LPC_INT i, n; + LPC_FLOAT real; svalue_t *lval; int instruction; #if defined(TRACE_CODE) || defined(TRACE) || defined(OPCPROF) || defined(OPCPROF_2D) @@ -1915,7 +1916,7 @@ eval_instruction (char * p) char *f; int l; /* this could be much more efficient ... */ - get_line_number_info(&f, &l); + get_line_number_info((const char**)&f, &l); show_lpc_line(f, l); } # endif @@ -4036,15 +4037,16 @@ void mark_apply_low_cache() { } #endif -void check_co_args2 (unsigned short *types, int num_arg, const char *name, const char *ob_name){ - int argc = num_arg; +void check_co_args2 (unsigned short *types, int num_arg, const char *name, const char *ob_name, int sparg){ + int argc = sparg; int exptype, i = 0; do{ argc--; if((types[i] & DECL_MODS) == LOCAL_MOD_REF) exptype = T_REF; else - exptype = convert_type(types[i++]); + exptype = convert_type(types[i]); + i++; if(exptype == T_ANY) continue; @@ -4053,13 +4055,13 @@ void check_co_args2 (unsigned short *types, int num_arg, const char *name, const if((sp-argc)->type == T_NUMBER && !(sp-argc)->u.number) continue; sprintf(buf, "Bad argument %d in call to %s() in %s\nExpected: %s Got %s.\n", - num_arg - argc, name, ob_name, + i, name, ob_name, type_name(exptype), type_name((sp-argc)->type)); #ifdef CALL_OTHER_WARN if(current_prog){ const char *file; int line; - find_line(pc, current_prog, &file, &line); + get_line_number_info(&file, &line); int prsave = pragmas; pragmas &= ~PRAGMA_ERROR_CONTEXT; smart_log(file, line, buf, 1); @@ -4070,7 +4072,7 @@ void check_co_args2 (unsigned short *types, int num_arg, const char *name, const error(buf); #endif } - } while (argc); + } while (itype_start && + int num_arg_check = MIN(num_arg, fun->num_arg); + if(num_arg_check && prog->type_start && prog->type_start[findex] != INDEX_START_NONE) check_co_args2(&prog->argument_types[prog->type_start[findex]], num_arg, - fun->funcname, prog->filename); + fun->funcname, prog->filename, num_arg); #endif } @@ -4221,6 +4224,9 @@ int apply_low (const char * fun, object_t * ob, int num_arg) DEBUG_CHECK(save_csp - 1 != csp, "Bad csp after execution in apply_low.\n"); return 1; + } else { + pop_n_elems(num_arg); + return 0; } } /* when we come here, the cache has told us * that the function isn't defined in the @@ -4239,10 +4245,9 @@ int apply_low (const char * fun, object_t * ob, int num_arg) } else { if (entry->funp){ free_string((char *)entry->funp); - entry->funp = 0; + entry->funp = 0; } } - #ifdef CACHE_STATS if (!entry->funp) { apply_low_slots_used++; @@ -4250,6 +4255,7 @@ int apply_low (const char * fun, object_t * ob, int num_arg) apply_low_collisions++; } #endif + entry->funp = 0; sfun = fun; prog = find_function_by_name2(ob, &sfun, &findex, &runtime_index, &fio, &vio); @@ -4321,6 +4327,9 @@ int apply_low (const char * fun, object_t * ob, int num_arg) * resulting value is always returned on the stack. */ return 1; + } else { + pop_n_elems(num_arg); + return 0; } } @@ -4675,6 +4684,10 @@ static int find_line (char * p, const program_t * progp, while (offset > *lns) { offset -= *lns; lns += (sizeof(ADDRESS_TYPE) + 1); + if(offset > progp->program_size || offset < 0) { + debug_message("Something is wrong when looking for line number, bail out."); + return 0; + } } #if !defined(USE_32BIT_ADDRESSES) @@ -4690,48 +4703,43 @@ static int find_line (char * p, const program_t * progp, return 0; } -static void get_explicit_line_number_info (char * p, const program_t * prog, +static void get_explicit_line_number_info (char * p, const program_t * progp, const char ** ret_file, int * ret_line) { - find_line(p, prog, ret_file, ret_line); + int i = find_line(p, progp, ret_file, ret_line); + + switch (i) { + case 1: + *ret_file = "(no program)"; + break; + case 2: + *ret_file = "(fake)"; + break; + case 3: + *ret_file = "(compiled program)"; + break; + case 4: + *ret_file = "(no line numbers)"; + break; + case 5: + *ret_file = "(includes too deep)"; + } if (!(*ret_file)) - *ret_file = prog->filename; + *ret_file = progp->filename; } void get_line_number_info (const char ** ret_file, int * ret_line) { - find_line(pc, current_prog, ret_file, ret_line); - if (!(*ret_file)) - *ret_file = current_prog->filename; + get_explicit_line_number_info(pc, current_prog, ret_file, ret_line); } char* get_line_number (char * p, const program_t * progp) { static char buf[256]; - int i; const char *file; int line; - i = find_line(p, progp, &file, &line); + get_explicit_line_number_info(p, progp, &file, &line); - switch (i) { - case 1: - strcpy(buf, "(no program)"); - return buf; - case 2: - *buf = 0; - return buf; - case 3: - strcpy(buf, "(compiled program)"); - return buf; - case 4: - strcpy(buf, "(no line numbers)"); - return buf; - case 5: - strcpy(buf, "(includes too deep)"); - return buf; - } - if (!file) - file = progp->filename; sprintf(buf, "/%s:%d", file, line); return buf; } @@ -5180,7 +5188,7 @@ int inter_sscanf (svalue_t * arg, svalue_t * s0, svalue_t * s1, int num_arg) int number_of_matches; int skipme; /* Encountered a '*' ? */ int base = 10; - long num; + LPC_INT num; const char *match; char old_char; const char *tmp; @@ -5244,18 +5252,20 @@ int inter_sscanf (svalue_t * arg, svalue_t * s0, svalue_t * s1, int num_arg) /* fallthrough */ case 'd': { + LPC_INT tmp_num; + tmp = in_string; - num = strtol((char *)in_string, (char **)&in_string, base); + tmp_num = strtol((char *)in_string, (char **)&in_string, base); if (tmp == in_string) return number_of_matches; if (!skipme) { - SSCANF_ASSIGN_SVALUE_NUMBER(num); + SSCANF_ASSIGN_SVALUE_NUMBER(tmp_num); } base = 10; continue; } case 'f': { - double tmp_num; + LPC_FLOAT tmp_num; tmp = in_string; tmp_num = _strtof((char *)in_string, (char **)&in_string); @@ -5476,7 +5486,7 @@ int inter_sscanf (svalue_t * arg, svalue_t * s0, svalue_t * s1, int num_arg) } case 'f': { - double tmp_num = _strtof((char *)in_string, (char **)&in_string); + LPC_FLOAT tmp_num = _strtof((char *)in_string, (char **)&in_string); if (!skipme2) { SSCANF_ASSIGN_SVALUE(T_REAL, u.real, tmp_num); } @@ -5741,10 +5751,10 @@ int strpref (const char * p, const char * s) return 1; } -static double _strtof (char * nptr, char ** endptr) +static LPC_FLOAT _strtof (char * nptr, char ** endptr) { register char *s = nptr; - register double acc; + register LPC_FLOAT acc; register int neg, c, any, divv; divv = 1; @@ -5770,10 +5780,10 @@ static double _strtof (char * nptr, char ** endptr) } else break; if (divv == 1) { - acc *= (double) 10; - acc += (double) c; + acc *= (LPC_FLOAT) 10; + acc += (LPC_FLOAT) c; } else { - acc += (double) c / (double) divv; + acc += (LPC_FLOAT) c / (LPC_FLOAT) divv; divv *= 10; } any = 1; diff --git a/src/lex.c b/src/lex.c index 6e75e0c1c..b7cf16d51 100644 --- a/src/lex.c +++ b/src/lex.c @@ -230,7 +230,7 @@ static void add_define (const char *, int, const char *); static void add_predefine (const char *, int, const char *); static int expand_define (void); static void add_input (const char *); -static int cond_get_exp (int); +static long cond_get_exp (int); static void merge (char *name, char *dest); static void add_quoted_predefine (const char *, const char *); static void lexerror (const char *); @@ -259,7 +259,7 @@ static void yyerrorp (const char *); int lookup_predef(const char * name) { - int x; + unsigned int x; for(x = 0; x < (sizeof(predefs) / sizeof(keyword_t)); x++) { @@ -445,7 +445,7 @@ include_error (const char * msg, int global) static void handle_include (char * name, int global) { - char *p, *nameptr; + char *p; static char buf[MAXLINE]; incstate_t *is; int delim, f; @@ -553,7 +553,7 @@ get_terminator (char * terminator) static int get_array_block (char * term) { - int termlen; /* length of terminator */ + unsigned int termlen; /* length of terminator */ char *array_line[NUMCHUNKS];/* allocate memory in chunks */ int header, len; /* header length; position in chunk */ int startpos, startchunk; /* start of line */ @@ -694,7 +694,7 @@ get_array_block (char * term) static int get_text_block (char * term) { - int termlen; /* length of terminator */ + unsigned int termlen; /* length of terminator */ char *text_line[NUMCHUNKS]; /* allocate memory in chunks */ int len; /* position in chunk */ int startpos, startchunk; /* start of line */ @@ -1194,7 +1194,7 @@ int yylex() static char partial[MAXLINE + 5]; /* extra 5 for safety buffer */ static char terminator[MAXLINE + 5]; int is_float; - double myreal; + LPC_FLOAT myreal; char *partp; register char *yyp; @@ -2139,7 +2139,7 @@ static void add_quoted_predefine (const char * def, const char * val) void add_predefines() { - char save_buf[80]; + char save_buf[1024]; int i; lpc_predef_t *tmpf; @@ -2198,6 +2198,9 @@ void add_predefines() #endif #ifdef DEBUG_MACRO add_predefine("HAS_DEBUG_LEVEL", -1, ""); +#endif +#ifdef DEBUG + add_predefine("__DEBUG__", -1, ""); #endif for (tmpf = lpc_predefs; tmpf; tmpf = tmpf->next) { char namebuf[NSIZE]; @@ -2211,10 +2214,16 @@ void add_predefines() fatal("MLEN exceeded"); add_predefine(namebuf, -1, mtext); } - sprintf(save_buf, "%ld", sizeof(long)); + sprintf(save_buf, "%ld", sizeof(LPC_INT)); add_predefine("SIZEOFINT", -1, save_buf); - sprintf(save_buf, "%ld", LONG_MAX); + sprintf(save_buf, "%ld", LPC_INT_MAX); add_predefine("MAX_INT", -1, save_buf); + sprintf(save_buf, "%ld", LPC_INT_MIN); + add_predefine("MIN_INT", -1, save_buf); + sprintf(save_buf, "%lf", LPC_FLOAT_MAX); + add_predefine("MAX_FLOAT", -1, save_buf); + sprintf(save_buf, "%lf", LPC_FLOAT_MIN); + add_predefine("MIN_FLOAT", -1, save_buf); } void start_new_file (int f) @@ -2292,7 +2301,7 @@ static void int_add_instr_name (const char * name, int n, short t) static void init_instrs() { - int i, n; + unsigned int i, n; for (i = 0; i < BASE; i++) { instrs[i].ret_type = -1; @@ -3456,7 +3465,7 @@ static void add_keyword_t (const char * name, keyword_t * entry) { } void init_identifiers() { - int i; + unsigned int i; ident_hash_elem_t *ihe; init_instrs(); diff --git a/src/lex.h b/src/lex.h index 94b2eb626..1e556d36a 100644 --- a/src/lex.h +++ b/src/lex.h @@ -81,7 +81,7 @@ typedef struct { /* the fields above must correspond to struct ident_hash_elem */ short min_args; /* Minimum number of arguments. */ short max_args; /* Maximum number of arguments. */ - short ret_type; /* The return type used by the compiler. */ + unsigned short ret_type; /* The return type used by the compiler. */ unsigned short arg_type1; /* Type of argument 1 */ unsigned short arg_type2; /* Type of argument 2 */ unsigned short arg_type3; /* Type of argument 1 */ @@ -115,7 +115,7 @@ typedef struct { short max_arg, min_arg; /* Can't use char to represent -1 */ short type[4]; /* need a short to hold the biggest type flag */ short Default; - short ret_type; + unsigned short ret_type; const char *name; int arg_index; } instr_t; diff --git a/src/local_options.test b/src/local_options.test new file mode 100644 index 000000000..2bdf59b29 --- /dev/null +++ b/src/local_options.test @@ -0,0 +1,917 @@ +/* + * options.h: defines for the compile-time configuration of the MudOS driver + */ + +#ifndef _OPTIONS_H_ +#define _OPTIONS_H_ + +/* + * YOU PROBABLY DO NOT WANT TO MODIFY THIS FILE. + * + * Do 'cp options.h local_options' and edit that instead. local_options, + * if it exists, overrides this file. + * + * The advantage is that when you upgrade to a newer MudOS driver, you can + * simply copy your local_options file into the src directory. The build + * process will warn you if new options have been added that you should + * choose settings for. + */ + +/**************************************************************************** + * EVERY time you change ANYTHING in this file, RECOMPILE from scratch. * + * (type "make clean" then "make" on a UNIX system) Failure to do so may * + * cause the driver to behave oddly. * + ****************************************************************************/ + +/* NOTES: + * Many of the configurable options are now set via the configuration file + * that is specified as the first argument to the driver. + * See port.h for those #defines related to portability (compatibility) if + * you have problems compiling on your system. + * Removing an efun from func_spec.c usually removes most, if not all, + * of the code associated with it. + * Note that anything defined in this file is also visible to LPC files + * surrounded by __. So #define FOO in this file defines __FOO__ for + * all LPC files. This allows code like: + * + * #ifdef __SENSIBLE_MODIFIERS__ + * ... + */ + +/**************************************************************************** + * MALLOC * + * -------- * + * For performance reasons, LP drivers have a variety of memory allocation * + * packages. If you don't care, use the default one on your system: * + * #define SYSMALLOC, #undef the others. * + ****************************************************************************/ + +/* You must choose exactly one of these malloc packages: + * ~~~~ + * SYSMALLOC: + * * Built-in system malloc. + * * No statistics. + * * SYSMALLOC incurs no additional CPU or memory overhead. + * + * MALLOC64 + * * Wodan's malloc, uses system malloc for small allocations and spreads + * * large allocations through the 64 bit memory space + * * won't work on 32 bit systems. + * MALLOC32 + * * fixes realloc by always doing a malloc/memcpy/free instead, try this + * * if you use more memory than expected (or MALLOC64 on a 64bit system). + */ +#define SYSMALLOC +#undef MMALLOC +#undef MALLOC64 +#undef MALLOC32 +#undef GCMALLOC /* needs -lgc in system_libs */ +/* You may optionally choose one (or none) of these malloc wrappers. These + * can be used in conjunction with any of the above malloc packages. + * + * WRAPPEDMALLOC: + * * Limited statistics. + * * Limited additional cpu overhead and no additional memory overhead. + * + * DEBUGMALLOC: + * * Statistics on precisely how much memory has been malloc'd (as well + * as the stats provided by WRAPPEDMALLOC). + * * Incurs a fair amount of overhead (both memory and CPU) + */ +#undef WRAPPEDMALLOC +#define DEBUGMALLOC + +/* The following add certain bells and whistles to malloc: */ + +/* + * SBRK_OK: do not define this unless SMALLOC is chosen above. + * Defining this causes smalloc to use the low level memory allocation + * routines, and to act as a malloc replacement. Conversely, undef'ing + * SBRK_OK causes smalloc to act as a wrapper for the system malloc + * routines. + * + * Note: + * NeXTStep 3.x users should always #undef SBRK_OK. + */ +#undef SBRK_OK + +/* DO_MSTATS: do not define this unless BSDMALLOC or SMALLOC is chosen above. + * Defining this causes those replacement mallocs to keep statistics that + * the malloc_status() efun will print out (including total memory + * allocated/used). + */ +#undef DO_MSTATS + +/* DEBUGMALLOC_EXTENSIONS: defining this (in addition to DEBUGMALLOC) enables + * the set_malloc_mask(int) and debugmalloc(string,int) efuns. These two + * efuns basically allow you to cause certain malloc's and free's (with tags + * selected by a specified mask) to print debug information (addr, tag, + * description, size) to stdio (in the shell that invoked the driver) or to a + * file. Not defining this does reduce the overhead of DEBUGMALLOC from 16 + * bytes per malloc down to 8. This macro has no effect if DEBUGMALLOC isn't + * defined. + */ +#define DEBUGMALLOC_EXTENSIONS + +/* CHECK_MEMORY: defining this (in addition to DEBUGMALLOC and + * DEBUGMALLOC_EXTENSIONS) causes the driver to check for memory + * corruption due to writing before the start or end of a block. This + * also adds the check_memory() efun. Takes a considerable ammount + * more memory. Mainly for debugging. + */ +#define CHECK_MEMORY + +/**************************************************************************** + * COMPATIBILITY * + * --------------- * + * The MudOS driver has evolved quite a bit over the years. These defines * + * are mainly to preserve old behavior in case people didn't want to * + * rewrite the relevant portions of their code. * + * * + * In most cases, code which needs these defines should be rewritten when * + * possible. The 'Compat status' field is designed to give an idea how * + * likely it is that support for that option will be removed in the near * + * future. Certain options are fairly easy to work around, and double * + * the size of the associated code, as well as the maintenance workload, * + * and can make the code significantly more complex or harder to read, so * + * supporting them indefinitely is impractical. * + * * + * WARNING: If you are using software designed to run with the MudOS driver * + * it may assume certain settings of these options. Check the * + * instructions for details. * + ****************************************************************************/ + +/* HAS_STATUS_TYPE: old MudOS drivers had a 'status' type which was + * identical to the 'int' type. Define this to bring it back. + * + * Compat status: very archaic, but easy to support. + */ +#undef HAS_STATUS_TYPE + +/* explode(): + * + * The old behavior (#undef both of the below) strips any number of + * delimiters at the start of the string, and one at the end. So + * explode("..x.y..z..", ".") gives ({ "x", "y", "", "z", "" }) + * + * SANE_EXPLODE_STRING strips off at most one leading delimiter, and + * still strips off one at the end, so the example above gives + * ({ "", "x", "y", "", "z", "" }). + * + * REVERSIBLE_EXPLODE_STRING overrides SANE_EXPLODE_STRING, and makes + * it so that implode(explode(x, y), y) is always x; i.e. no delimiters + * are ever stripped. So the example above gives + * ({ "", "", "x", "y", "", "z", "", "" }). + */ +#define SANE_EXPLODE_STRING +#undef REVERSIBLE_EXPLODE_STRING + +/* CAST_CALL_OTHERS: define this if you want to require casting of call_other's; + * this was the default behavior of the driver prior to this addition. + * + * Compat status: code that requires it doesn't break, and it promotes + * sloppy coding with no benefits. + */ +#undef CAST_CALL_OTHERS + +/* NONINTERACTIVE_STDERR_WRITE: if defined, all writes/tells/etc to + * noninteractive objects will be written to stderr prefixed with a ']' + * (old behavior). + * + * Compat status: Easy to support, and also on the "It's a bug! No, it's + * a feature!" religious war list. + */ +#define NONINTERACTIVE_STDERR_WRITE + +/* NO_LIGHT: define this to disable the set_light() and driver maintenance + * of light levels in objects. You can simulate it via LPC if you want... + * + * Compat status: Very dated, easy to simulate, and gross. + */ +#define NO_LIGHT + +/* NO_ADD_ACTION: define this to remove add_action, commands, livings, etc. + * process_input() then becomes the only way to deal with player input. + * + * Compat status: next to impossible to simulate, hard to replace, and + * very, very widely used. + */ +#undef NO_ADD_ACTION + +/* NO_SNOOP: disables the snoop() efun and all related functionality. + */ +#undef NO_SNOOP + +/* NO_ADD_ACTION: define this to remove add_action, commands, livings, etc. + process_input() then becomes the only way to deal with player input. */ + +/* NO_ENVIRONMENT: define this to remove the handling of object containment + * relationships by the driver + * + * Compat status: hard to simulate efficiently, and very widely used. + */ +#undef NO_ENVIRONMENT + +/* NO_WIZARDS: for historical reasons, MudOS used to keep track of who + * is and isn't a wizard. Defining this removes that completely. + * If this is defined, the wizardp() and related efuns don't exist. + * + * Also note that if it is not defined, then non-wizards are always put + * in restricted mode when ed() is used, regardless of the setting of + * the restrict parameter. + * + * Compat status: easy to simulate and dated. + */ +#define NO_WIZARDS + +/* OLD_TYPE_BEHAVIOR: reintroduces a bug in type-checking that effectively + * renders compile time type checking useless. For backwards compatibility. + * + * Compat status: dealing with all the resulting compile errors can be + * a huge pain even if they are correct, and the impact on the code is + * small. + */ +#undef OLD_TYPE_BEHAVIOR + +/* OLD_RANGE_BEHAVIOR: define this if you want negative indexes in string + * or buffer range values (not lvalue, i.e. x[-2..-1]; for e.g. not + * x[-2..-1] = foo, the latter is always illegal) to mean counting from the + * end + * + * Compat status: Not horribly difficult to replace reliance on this, but not + * trivial, and cannot be simulated. + */ +#undef OLD_RANGE_BEHAVIOR + +/* define to get a warning for code that might use the old range behavior + * when you're not actually using the old range behavior*/ +#undef WARN_OLD_RANGE_BEHAVIOR + + +/* OLD_ED: ed() efun backwards compatible with the old version. The new + * version requires/allows a mudlib front end. + * + * Compat status: Easily simulated. + */ +#define OLD_ED + +/* In ed auto-indent, + * 1) does the case line get indented after the switch() ? + * 2) How far do we indent? (this can also be set in the mudlib) + */ +#undef ED_INDENT_CASE +#define ED_INDENT_SPACES 4 + +/* SENSIBLE_MODIFIERS: + * Turning this on changes a few things, which may break old code: + * + * (1) 'static' is not recognized; either 'nosave' or 'protected' must + * be used instead. + * (2) The old meaning of 'public' is no longer allowed. Explicit + * functions must be defined at each level to allow access to + * privately inherited functions. + * (3) 'public' now means the default visibility. Previously there was + * no keyword that meant this (before you ask, 'public' meant something + * else, and if you don't know that, you probably don't have any reason + * to care about the old meaning). + */ +#define SENSIBLE_MODIFIERS + +/**************************************************************************** + * MISCELLANEOUS * + * --------------- * + * Various options that affect the way the driver behaves. * + * * + * WARNING: If you are using software designed to run with the MudOS driver * + * it may assume certain settings of these options. Check the * + * instructions for details. * + ****************************************************************************/ + +/* + * Define this in order to use Fermat@Equilibria's MD5 based crypt() instead + * of the operating system's. It has the advantage of giving the same value + * on all architectures, and being stronger than the standard UNIX crypt(). + */ +#define CUSTOM_CRYPT + +/* + * Some minor tweaks that make it a bit easier to run code designed to run + * on LPmud 3.2/3.2.1. Currently has the following effects: + * + * . m_indices() and m_values() are synonyms for keys() and values(), + * respectively + * . map_delete() returns it's first argument + * . inherit_list() means deep_inherit_list(), not shallow_inherit_list() + * . heart_beat_info() is a synonym for heart_beats() + */ +#undef COMPAT_32 + +/* + * Keep statistics about allocated strings, etc. Which can be viewed with + * the mud_status() efun. If this is off, mud_status() and memory_info() + * ignore allocated strings, but string operations run faster. + */ +#define STRING_STATS + +/* + * Similarly for arrays ... + */ +#define ARRAY_STATS +#define CLASS_STATS +/* LOG_CATCHES: define this to cause errors that are catch()'d to be + * sent to the debug log anyway. + * + * On by default, because newer libs use catch() a lot, and it's confusing + * if the errors don't show up in the logs. + */ +#define LOG_CATCHES + +/* ARGUMENTS_IN_TRACEBACK: prints out function call arguments in error + * tracebacks, to aid in debugging. Note: it prints the values of + * the arguments at the time of the error, not when the function + * was called. It looks like this: + * + * Failed to load file: read_buffer + * program: command/update.c, object: command/update line 15 + * ' commandHook' in ' clone/user.c' (' clone/user#1')line 72 + * arguments were ("/read_buffer.c") + * ' main' in ' command/update.c' (' command/update')line 15 + * arguments were ("/read_buffer.c") + * + * The only down side is some people like their logs shorter + */ +#define ARGUMENTS_IN_TRACEBACK + +/* LOCALS_IN_TRACEBACK: similar to ARGUMENTS_IN_TRACEBACK, but for local + * variables. The output looks more or less like: + * + * locals: 1, "local_value" + * + * Same as above. Tends to produce even longer logs, but very useful for + * tracking errors. + */ +#define LOCALS_IN_TRACEBACK + +/* MUDLIB_ERROR_HANDLER: If you define this, the driver doesn't do any + * handling of runtime errors, other than to turn the heartbeats of + * objects off. Information about the error is passed in a mapping + * to the error_handler() function in the master object. Whatever is + * returned is put in the debug.log. + * + * A good mudlib error handler is one of the best tools for tracking down + * errors. Unfortunately, you need to have one. Check the testsuite or + * other libs for an example. + */ +#define MUDLIB_ERROR_HANDLER + +/* CONFIG_FILE_DIR specifies a directory in which the driver will search for + * config files by default. If you don't wish to use this define, you may + * always specify a full path to the config file when starting the driver. + */ +#define CONFIG_FILE_DIR "/home/atuin/bin" + +/* DEFAULT_PRAGMAS: This should be a sum of pragmas you want to always + * be on, i.e. + * + * #define DEFAULT_PRAGMAS PRAGMA_STRICT_TYPES + PRAGMA_SAVE_TYPES + * + * will make every LPC file behave as if it had the lines: + * #pragma strict_types + * #pragma save_types + * + * for no default pragmas: + * #define DEFAULT_PRAGMAS 0 + * + * If you don't know what these are, 0 is a good choice. + * + * Supported pragmas: + * PRAGMA_STRICT_TYPES: enforces strict type checking + * PRAGMA_WARNINGS: issues warnings about various dangerous things in + * your code + * PRAGMA_SAVE_TYPES: save the types of function arguments for checking + * calls to functions in this object by objects that + * inherit it. + * PRAGMA_OPTIMIZE: make a second pass over the generated code to + * optimize it further. Currently maybe broken. + * PRAGMA_ERROR_CONTEXT:include some text telling where on the line a + * compilation error occured. + */ +#define DEFAULT_PRAGMAS PRAGMA_WARNINGS + PRAGMA_SAVE_TYPES + PRAGMA_ERROR_CONTEXT + +/* supress warnings about unused arguments; only warn about unused local + * variables. Makes older code (where argument names were required) compile + * more quietly. + */ +#define SUPPRESS_ARGUMENT_WARNINGS + +/* NO_RESETS: completely disable the periodic calling of reset() */ +#undef NO_RESETS + +/* LAZY_RESETS: if this is defined, an object will only have reset() + * called in it when it is touched via call_other() or move_object() + * (assuming enough time has passed since the last reset). If LAZY_RESETS + * is #undef'd, then reset() will be called as always (which guaranteed that + * reset would always be called at least once). The advantage of lazy + * resets is that reset doesn't get called in an object that is touched + * once and never again (which can save memory since some objects won't get + * reloaded that otherwise would). + */ +#undef LAZY_RESETS + +/* SAVE_EXTENSION: defines the file extension used by save_object(). + * and restore_object(). Some sysadmins run scripts that periodically + * scan for and remove files ending in .o (but many mudlibs are already + * set up to use .o thus we leave .o as the default). + */ +#define SAVE_EXTENSION ".o" + +/* NO_ANSI: define if you wish to disallow users from typing in commands that + * contain ANSI escape sequences. Defining NO_ANSI causes all escapes + * (ASCII 27) to be replaced with a space ' ' before the string is passed + * to the action routines added with add_action. + * + * STRIP_BEFORE_PROCESS_INPUT allows the location where the stripping is + * done to be controlled. If it is defined, then process_input() doesn't + * see ANSI characters either; if it is undefined ESC chars can be processed + * by process_input(), but are stripped before add_actions are called. + * Note that if NO_ADD_ACTION is defined, then #define NO_ANSI without + * #define STRIP_BEFORE_PROCESS_INPUT is the same as #undef NO_ANSI. + * + * If you anticipate problems with users intentionally typing in ANSI codes + * to make your terminal flash, etc define this. + */ +#define NO_ANSI +#define STRIP_BEFORE_PROCESS_INPUT + +/* OPCPROF: define this if you wish to enable OPC profiling. Allows a dump + * of the # of times each efun is invoked (via the opcprof() efun). + */ +#define OPCPROF + +/* OPCPROF_2D: define this if you wish to enable 2-D OPC profiling. Allows a + * dump of the # of times each *pair* of eoperators is invoked. + * + * You can't use this and OPCPROF at the same time. + */ +#undef OPCPROF_2D + +/* TRAP_CRASHES: define this if you want MudOS to call crash() in master.c + * and then shutdown when signals are received that would normally crash the + * driver. + */ +#define TRAP_CRASHES + +/* THIS_PLAYER_IN_CALL_OUT: define this if you wish this_player() to be + * usable from within call_out() callbacks. + */ +#define THIS_PLAYER_IN_CALL_OUT + +/* CALLOUT_HANDLES: If this is defined, call_out() returns an integer, which + * can be passed to remove_call_out() or find_call_out(). Removing call_outs + * by name is still allowed, but is significantly less efficient, and also + * doesn't work for function pointers. This option adds 4 bytes overhead + * per callout to keep track of the handle. + */ +#define CALLOUT_HANDLES + +/* FLUSH_OUTPUT_IMMEDIATELY: Causes output to be written to sockets + * immediately after being generated. Useful for debugging. + */ +#undef FLUSH_OUTPUT_IMMEDIATELY + +/* PRIVS: define this if you want object privileges. Your mudlib must + * explicitly make use of this functionality to be useful. Defining this + * this will increase the size of the object structure by 4 bytes (8 bytes + * on the DEC Alpha) and will add a new master apply during object creation + * to "privs_file". In general, privileges can be used to increase the + * granularity of security beyond the current root uid mechanism. + * + * [NOTE: for those who'd rather do such things at the mudlib level, look at + * the inherits() efun and the 'valid_object' apply to master.] + */ +#undef PRIVS + +/* INTERACTIVE_CATCH_TELL: define this if you want catch_tell called on + * interactives as well as NPCs. If this is defined, user.c will need a + * catch_tell(msg) method that calls receive(msg); +*/ +#undef INTERACTIVE_CATCH_TELL + +/* RECEIVE_ED: define this if you want normal ed output to go to a + receive_ed() apply in the player ob. Some errors still go directly + to output. Useful for post-processing (perhaps colorizing?) ed + output. Prototype: mixed receive_ed(string txt, string fname); + If fname, return a string that ed will output, 0 to let ed handle + the output in the default way, or 1 to handle the output yourself. + If fname == 0, output is help text and you may return any of the above + or an array of strings that will be more'ed. +*/ +#undef RECEIVE_ED + +/* RESTRICTED_ED: define this if you want restricted ed mode enabled. + */ +#define RESTRICTED_ED + +/* NO_SHADOWS: define this if you want to disable shadows in your driver. + */ +#undef NO_SHADOWS + +/* SNOOP_SHADOWED: define this if you want snoop to report what is + * sent to the player even in the event that the player's catch_tell() is + * shadowed and the player may not be seeing what is being sent. Messages + * of this sort will be prefixed with $$. + */ +#undef SNOOP_SHADOWED + +/* RECEIVE_SNOOP: define this if you want snoop text to be sent to + * the receive_snoop() function in the snooper object (instead of being + * sent directly via add_message()). This is useful if you want to + * build a smart client that does something different with snoop messages. + */ +#define RECEIVE_SNOOP + +/* PROFILE_FUNCTIONS: define this to be able to measure the CPU time used by + * all of the user-defined functions in each LPC object. Note: defining + * this adds three long ints (12 bytes on 32-bit machines) to the function + * header structs. Also note that the resolution of the getrusage() timer + * may not be high enough on some machines to give non-zero execution + * times to very small (fast) functions. In particular if the clock + * resolution is 1/60 of a second, then any time less than approxmately 15k + * microseconds will resolve to zero (0). + */ +#define PROFILE_FUNCTIONS + +/* NO_BUFFER_TYPE: if this is #define'd then LPC code using the 'buffer' + * type won't be allowed to compile (since the 'buffer' type won't be + * recognized by the lexer). + */ +#undef NO_BUFFER_TYPE + +/* ARRAY_RESERVED_WORD: If this is defined then the word 'array' can + * be used to define arrays, as in: + * + * int array x = ({ .... }); + * + * A side effect is that 'array' cannot be a variable or function name. + */ +#undef ARRAY_RESERVED_WORD + +/* REF_RESERVED_WORD: If this is defined then the word 'ref' can be + * used to pass arguments to functions by value. Example: + * + * void inc(int ref x) { + * x++; + * } + * + * ... y = 1; inc(ref y); ... + * + * A side effect is that 'ref' cannot be a variable or function name. + * + * Note: ref must be used in *both* places; this is intentional. It protects + * against passing references to routines which don't intend to return values + * through their arguments, and against forgetting to pass a reference + * to a function which wants one (or accidentally having a variable modified!) + */ +#define REF_RESERVED_WORD + +/**************************************************************************** + * PACKAGES * + * -------- * + * Defining some/all of the following add certain efuns, and sometimes * + * add/remove code from the driver. * + * * + * if PACKAGE_XYZZY is defined here, then the code in packages/xyzzy.c * + * and the efuns in packages/xyzzy_spec.c will be added to the driver. * + ****************************************************************************/ + +/* various miscellaneous efuns */ +#define PACKAGE_CONTRIB + +/* efuns that are only of use to those that know something about driver + internals */ +#define PACKAGE_DEVELOP + +/* PACKAGE_MATH: determines whether or not the math efuns (for floats) are + included. + */ +#define PACKAGE_MATH + +/* PACKAGE_MATRIX: determines whether or not the 3d graphics efuns (for floats) + * are included - see packages/matrix.spec for a list. + */ +#undef PACKAGE_MATRIX + +/* PACKAGE_MUDLIB_STATS: define this to enable domain and author stats + * maintenance by the driver. These mudlib stats are more domain + * based than user based, and replaces the traditional wiz_list stats. + */ +#define PACKAGE_MUDLIB_STATS + +/* PACKAGE_SOCKETS: define this to enable the socket efunctions. This + * causes HAS_SOCKETS to be defined for all LPC objects. + */ +#define PACKAGE_SOCKETS + +/* PACKAGE_PARSER: Natural language parsing efuns for interactive fiction + * type applications + */ +#undef PACKAGE_PARSER + +/* PACKAGE_EXTERNAL: Allows the driver to exec() commands specified in the + * config file. + */ +#define PACKAGE_EXTERNAL + +/* NUM_EXTERNAL_CMDS: the number of external commands supported */ +#ifdef PACKAGE_EXTERNAL +#define NUM_EXTERNAL_CMDS 100 +#endif + +/* PACKAGE_DB: efuns for external database access using msql */ +#undef PACKAGE_DB + +/* If PACKAGE_DB is defined above, you must pick ONE of the following supported + * databases + */ +#ifdef PACKAGE_DB +#undef USE_MSQL +#define USE_MYSQL 2 +#undef USE_POSTGRES +#endif + +/**************************************************************************** + * UID PACKAGE * + * ----------- * + * UIDS are the basis for some mudlib security systems. Basically, they're * + * preserved for backwards compatibility, as several ways of breaking * + * almost any system which relies on them are known. (No, it's not a flaw * + * of uids; only that b/c of the ease with which LPC objects can call * + * each other, it's far too easy to leave holes) * + * * + * If you don't care about security, the first option is probably what you * + * want. * + ****************************************************************************/ + +/* + * PACKAGE_UIDS: define this if you want a driver that does use uids. + * + */ +#define PACKAGE_UIDS + +/*PACKAGE DWLIB: some discworld mudlib simuls coded in C (well just one right + now) */ + +#undef PACKAGE_DWLIB + +/* AUTO_SETEUID: when an object is created it's euid is automatically set to + * the equivalent of seteuid(getuid(this_object())). undef AUTO_SETEUID + * if you would rather have the euid of the created object be set to 0. + */ +#define AUTO_SETEUID + +/* AUTO_TRUST_BACKBONE: define this if you want objects with the backbone + * uid to automatically be trusted and to have their euid set to the uid of + * the object that forced the object's creation. + */ +#undef AUTO_TRUST_BACKBONE + +/************************************************************************* + * FOR EXPERIENCED USERS * + * ----------------------- * + * Most of these options will probably be of no interest to many users. * + *************************************************************************/ + +/* USE_32BIT_ADDRESSES: Use 32 bits for addresses of function, instead of + * the usual 16 bits. This increases the maximum program size from 64k + * of LPC bytecode (NOT source) to 4 GB. Branches are still 16 bits, + * imposing a 64k limit on catch(), if(), switch(), loops, and most other + * control structures. It would take an extremely large function to hit + * those limits, though. + * + * Overhead: 2 bytes/function with LPC->C off. Having LPC->C on forces + * this option, since it needs 4 bytes to store the function pointers + * anyway, and this setting is ignored. + */ +#undef USE_32BIT_ADDRESSES + +/* HEARTBEAT_INTERVAL: define heartbeat interval in seconds. + */ +#define HEARTBEAT_INTERVAL 1 + +/* + * CALLOUT_CYCLE_SIZE: This is the number of slots in the call_out list. + * It should be approximately the average number of active call_outs, or + * a few times smaller. It should also be a power of 2, and also be relatively + * prime to any common call_out lengths. If all this is too confusing, 32 + * isn't a bad number :-) + */ +#define CALLOUT_CYCLE_SIZE 512 + +/* LARGEST_PRINTABLE_STRING: defines the size of the vsprintf() buffer in + * comm.c's add_message(). Instead of blindly making this value larger, + * your mudlib should be coded to not send huge strings to users. + */ +#define LARGEST_PRINTABLE_STRING 8192 + +/* MESSAGE_BUFFER_SIZE: determines the size of the buffer for output that + * is sent to users. + */ +#define MESSAGE_BUFFER_SIZE 4096 + +/* APPLY_CACHE_BITS: defines the number of bits to use in the call_other cache + * (in interpret.c). + * + * Memory overhead is (1 << APPLY_CACHE_BITS)*16. + * [assuming 32 bit pointers and 16 bit shorts] + * + * ACB: entries: overhead: + * 6 64 1k + * 8 256 4k + * 10 1024 16k + * 12 4096 64k + * 14 16384 256k + * 16 65536 1M + */ +#define APPLY_CACHE_BITS 20 + +/* CACHE_STATS: define this if you want call_other (apply_low) cache + * statistics. Causes HAS_CACHE_STATS to be defined in all LPC objects. + */ +#define CACHE_STATS + +/* TRACE: define this to enable the trace() and traceprefix() efuns. + * (keeping this undefined will cause the driver to run faster). + */ +#define TRACE + +/* RUNTIME_LOADING: On systems which support it, it allows LPC->C compilation + * 'on the fly' without having to recompile the driver. + * + * Note: This currently only works on machines that have the dlopen() system + * call. SunOS and IRIX do, as do a number of others. AIX and Ultrix don't. + * Linux does if you are using ELF. + */ +#undef RUNTIME_LOADING + +/* TRACE_CODE: define this to enable code tracing (the driver will print + * out the previous lines of code to an error) eval_instruction() runs about + * twice as fast when this is not defined (for the most common eoperators). + */ +#define TRACE_CODE + +/* HEART_BEAT_CHUNK: The number of heart_beat chunks allocated at a time. + * A large number wastes memory as some will be sitting around unused, while + * a small one wastes more CPU reallocating when it needs to grow. Default + * to a medium value. + */ +#define HEART_BEAT_CHUNK 32 + +/* SERVER_IP: For machines with multiple IP addresses, this specifies which + * one to use. This is useful for IP accounting and is necessary to be + * able to do ident lookups on such machines. + * + * example: #define SERVER_IP "194.229.18.27" + */ +#undef SERVER_IP + +/* Some maximum string sizes + */ +#define SMALL_STRING_SIZE 100 +#define LARGE_STRING_SIZE 1000 +#define COMMAND_BUF_SIZE 2000 + +/* Number of levels of nested datastructures allowed -- this limit prevents + * crashes from occuring when saving objects containing variables containing + * recursive datastructures (with circular references). + */ +#define MAX_SAVE_SVALUE_DEPTH 100 + +/* Miscellaneous config options that should probably be in the runtime + * config file. + */ +/* MAX_LOCAL: maximum number of local variables allowed per LPC function */ +#define CFG_MAX_LOCAL_VARIABLES 50 + +/* CFG_MAX_GLOBAL_VARIABLES: This value determines the maximum number of + * global variables per object. The maximum value is 65536. There is + * a marginal memory increase for a value over 256. + */ +#define CFG_MAX_GLOBAL_VARIABLES 65536 + +#define CFG_EVALUATOR_STACK_SIZE 3000 +#define CFG_COMPILER_STACK_SIZE 600 +#define CFG_MAX_CALL_DEPTH 150 +/* This must be one of 4, 16, 64, 256, 1024, 4096 */ +#define CFG_LIVING_HASH_SIZE 256 + +/* NEXT_MALLOC_DEBUG: define this if using a NeXT and you want to enable + * the malloc_check() and/or malloc_debug() efuns. Run the 'man malloc_debug' + * command on the NeXT to find out what the arguments to malloc_debug(int) + * mean. The malloc_check() efun calls the NeXT NXMallocCheck() system + * call which does a consistency check on malloc's data structures (this + * consistency check is done at each malloc() and free() for certain + * malloc_debug() levels). A non-zero return value indicates there was + * a consistency problem. For those NeXT users wanting a bit more + * performance out of malloc, try defining NEXT_MALLOC_DEBUG and calling the + * malloc_debug(-1) efun (with an arg of -1). This will turn all + * malloc debugging off and call malloc_singlethreaded() which the NeXT + * malloc man page claims can make NeXT system malloc 10% to 15% faster. + * + * [NOTE: This #define has no affect on the driver if not using the + * NeXTSTEP OS.] + * + * Warning: if you use a NeXT and define NEXT_MALLOC_DEBUG, be sure to + * protect the use of the malloc_check() and malloc_debug() efuns + * since setting certain debug levels can cause malloc() and free() + * to become _very_ slow (protect efuns by using simul_efuns and + * valid_override). + * + * [NOTE: malloc_debug(6) is a good compromise between efficiency and + * completeness of malloc debugging (malloc/free will be about half as fast).] + */ +#define NEXT_MALLOC_DEBUG + + +/* GET_CHAR_IS_BUFFERED: Normally get_char() is unbuffered. That is, once + * a character is received for get_char(), anything else is in the input + * stream is immediately thrown away. This can be very undesirable, especially + * if you're calling get_char() again from the handler from the previous call. + * Define this if you want get_char() to be buffered. In this case, the buffer + * will only get flushed if get_char() is not called from the first get_char()'s + * LPC callback handler. + */ +#undef GET_CHAR_IS_BUFFERED + +/* PACKAGE_COMPRESS: Enable MCCP support and compressed save files + SAVE_GZ_EXTENSION: save extension for compressed files + */ +#define HAVE_ZLIB +#define PACKAGE_COMPRESS +#define SAVE_GZ_EXTENSION ".o.gz" + +/* CALL_OTHER_TYPE_CHECK: enable type checking for call_other() + * (-> operator on objects) + */ +#undef CALL_OTHER_TYPE_CHECK + +/* CALL_OTHER_WARN, make it warning instead of errors */ +#undef CALL_OTHER_WARN + +/* WARN_TAB: Some versions of the editor built in indent function use + * tabs for indenting. This options turns on a warning message for + * files indented with tabs instead of spaces. + */ +#undef WARN_TAB + +/* USE_ICONV: Use iconv to translate input and output from/to the users char + * encoding + */ +#define USE_ICONV + +/* WOMBLES: don't allow spaces between start/end of array/mapping/functional token chars so ({1,2,3}) still works, but ( { 1 , 2 , 3 } ) doesn't and ({ 1 , 2 , 3 }) does.*/ +#define WOMBLES + +/* ALLOW_INHERIT_AFTER_FUNCTION: allow inheriting after functions have been defined (this includes prototypes). This caused crashes in v22.2a but it may have been fixed since */ +#undef ALLOW_INHERIT_AFTER_FUNCTION + +/*PACKAGE_ASYNC: adds some efuns for asyncronous IO */ +#define PACKAGE_ASYNC + +/*PACKAGE_SHA1: adds a function to calculate the sha1 hash of a string sha1(string)*/ +#define PACKAGE_SHA1 + +/*PACKAGE_CRYPTO: adds a function that does multiple hash types hash(hash, string), needs openssl lib and includes and -lssl in system_libs*/ +#undef PACKAGE_CRYPTO + +/* PROG_REF_TYPE size of program ref counter: + * char for 8 bit, short for 16, int for 32, + * long long for 64 (completely useless on 32 bit machines though!) */ +#define PROG_REF_TYPE short + +/* HAS_CONSOLE: If defined, the driver can take the argument -C + * which will give the driver an interactive console (you can type + * commands at the terminal.) Backgrounding the driver will turn off + * the console, but sending signal SIGTTIN (kill -21) to the driver can + * turn it back on. Typing 'help' will display commands available. + * The intent is to allow the inspection of things that are difficult + * to inspect from inside the mud. + */ +#define HAS_CONSOLE + +/* IPV6: Use IP version 6 instead of 4, for most people the only difference + * will be that numerical IP addresses get ::ffff: added in front.*/ +#undef IPV6 + +/* static user space dtrace probes, try them if you have dtrace! */ +#undef DTRACE + +/* use class keyword for lpc structs */ +#define STRUCT_CLASS + +/* use struct keyword for lpc structs */ +#define STRUCT_STRUCT + +/* use POSIX timers for eval_cost */ +#define POSIX_TIMERS + +#endif diff --git a/src/lpc.h b/src/lpc.h index f9e49c7d2..6b88ede02 100644 --- a/src/lpc.h +++ b/src/lpc.h @@ -4,14 +4,23 @@ /* It is usually better to include "lpc_incl.h" instead of including this directly */ +/* type definiation for LPC types. */ +typedef int64_t LPC_INT; +#define LPC_INT_MAX INT64_MAX +#define LPC_INT_MIN INT64_MIN + +typedef double LPC_FLOAT; +#define LPC_FLOAT_MAX DBL_MAX +#define LPC_FLOAT_MIN DBL_MIN + typedef struct { unsigned short ref; } refed_t; union u { const char *string; - long number; - double real; + LPC_INT number; + LPC_FLOAT real; refed_t *refed; /* any of the block below */ diff --git a/src/macros.h b/src/macros.h index 5077ed114..b471ba01e 100644 --- a/src/macros.h +++ b/src/macros.h @@ -51,7 +51,7 @@ Please refer to options.h for selecting malloc package and wrapper. */ -#if (defined(SYSMALLOC) + defined(SMALLOC) + defined(BSDMALLOC) + defined(MMALLOC)) > 1 +#if (defined(SYSMALLOC) + defined(SMALLOC) + defined(BSDMALLOC) + defined(MMALLOC) + defined(GCMALLOC)) > 1 !Only one malloc package should be defined #endif @@ -63,6 +63,10 @@ !'DO_MSTATS' not available with 'SYSMALLOC' #endif +#if defined(DO_MSTATS) && defined(GCMALLOC) +!'DO_MSTATS' not available with 'GCMALLOC' +#endif + #if defined (WRAPPEDMALLOC) && !defined(IN_MALLOC_WRAPPER) # define MALLOC(x) wrappedmalloc(x) @@ -168,16 +172,12 @@ !shorts of size other than 2 not implemented #endif -#if SIZEOF_INT == 4 -#define INT_32 int -#endif - -#if SIZEOF_LONG == 4 +#if SIZEOF_LPC_INT == 4 #define COPY_INT(x, y) COPY4(x,y) #define LOAD_INT(x, y) LOAD4(x,y) #define STORE_INT(x, y) STORE4(x,y) #else -#if SIZEOF_LONG == 8 +#if SIZEOF_LPC_INT == 8 #define COPY_INT(x, y) COPY8(x,y) #define LOAD_INT(x, y) LOAD8(x,y) #define STORE_INT(x, y) STORE8(x,y) @@ -186,7 +186,7 @@ #endif #endif -#if SIZEOF_FLOAT == 8 +#if SIZEOF_LPC_FLOAT == 8 #define COPY_FLOAT(x, y) COPY8(x,y) #define LOAD_FLOAT(x, y) LOAD8(x,y) #define STORE_FLOAT(x, y) STORE8(x,y) @@ -194,12 +194,16 @@ !floats of size other than 8 not implemented #endif +#if SIZEOF_PTR != SIZEOF_LPC_INT +!different size of LPC_INT and pointer is not supported. +#endif + #if SIZEOF_PTR == 4 # define COPY_PTR(x, y) COPY4(x,y) # define LOAD_PTR(x, y) LOAD4(x,y) # define STORE_PTR(x, y) STORE4(x,y) -# define POINTER_INT int +# define POINTER_INT intptr_t # define INS_POINTER ins_int #else # if SIZEOF_PTR == 8 @@ -207,8 +211,8 @@ # define LOAD_PTR(x, y) LOAD8(x,y) # define STORE_PTR(x, y) STORE8(x,y) -# define POINTER_INT long -# define INS_POINTER ins_long +# define POINTER_INT intptr_t +# define INS_POINTER ins_int # else !pointers of size other than 4 or 8 not implemented # endif diff --git a/src/main.c b/src/main.c index 09357eb7f..2d4cda4d9 100644 --- a/src/main.c +++ b/src/main.c @@ -14,13 +14,13 @@ #include "socket_efuns.h" #include "master.h" #include "eval.h" +#include "posix_timers.h" port_def_t external_port[5]; static int e_flag = 0; /* Load empty, without preloads. */ int t_flag = 0; /* Disable heart beat and reset */ int comp_flag = 0; /* Trace compilations */ -int max_cost; int time_to_clean_up; const char *default_fail_message; time_t boot_time; @@ -61,384 +61,391 @@ static void CDECL sig_int SIGPROT; #ifndef DEBUG static void CDECL sig_hup SIGPROT, - CDECL sig_abrt SIGPROT, - CDECL sig_segv SIGPROT, - CDECL sig_ill SIGPROT, - CDECL sig_bus SIGPROT, - CDECL sig_iot SIGPROT; +CDECL sig_abrt SIGPROT, +CDECL sig_segv SIGPROT, +CDECL sig_ill SIGPROT, +CDECL sig_bus SIGPROT, +CDECL sig_iot SIGPROT; #endif #endif #ifdef DEBUG_MACRO /* used by debug.h: please leave this in here -- Tru (you can change its value if you like). -*/ + */ int debug_level = 0; #endif int main (int argc, char ** argv) { - time_t tm; - int i, new_mudlib = 0, got_defaults = 0; - char *p; - char version_buf[80]; + time_t tm; + int i, new_mudlib = 0, got_defaults = 0; + char *p; + char version_buf[80]; #if 0 - int dtablesize; + int dtablesize; #endif - error_context_t econ; + error_context_t econ; #ifdef PROTO_TZSET - void tzset(); + void tzset(); #endif #ifdef INCL_LOCALE_H - setlocale(LC_ALL, "C"); + setlocale(LC_ALL, "C"); #endif - -#if !defined(__SASC) && (defined(AMITCP) || defined(AS225)) - amiga_sockinit(); - atexit(amiga_sockexit); +#ifdef MALLOC_NEED_INIT + malloc_init(); #endif + #ifdef WRAPPEDMALLOC - wrappedmalloc_init(); + wrappedmalloc_init(); #endif /* WRAPPEDMALLOC */ #ifdef DEBUGMALLOC - MDinit(); + MDinit(); #endif #if (defined(PROFILING) && !defined(PROFILE_ON) && defined(HAS_MONCONTROL)) - moncontrol(0); + 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); - } + 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()); + srand(get_current_time()); #else # ifdef DRAND48 - srand48(get_current_time()); + srand48(get_current_time()); # else # ifdef RANDOM - srandom(get_current_time()); + srandom(get_current_time()); # else - fprintf(stderr, "Warning: no random number generator specified!\n"); + 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. - */ + current_time = get_current_time(); + /* + * Initialize the microsecond clock. + */ + init_usec_clock(); + +#ifdef POSIX_TIMERS + /* + * Initialize the POSIX timers. + */ + init_posix_timers(); +#endif + + /* 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); - } + 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 > 2147483647){ - fprintf(stderr, "Maximum array size can not exceed 65535"); - max_array_size = 2147483647; - } - 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; + /* + * 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 > INT_MAX){ + fprintf(stderr, "Maximum array size can not exceed %i", INT_MAX); + max_array_size = INT_MAX; + } + 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; + case 'C': + has_console = 1; + continue; #endif #ifdef YYDEBUG - case 'y': - yydebug = 1; - continue; + 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(); + 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(); + _tzset(); #endif #ifndef NO_IP_DEMON - if (!no_ip_demon && ADDR_SERVER_IP) - init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT); + if (!no_ip_demon && ADDR_SERVER_IP) + init_addr_server(ADDR_SERVER_IP, ADDR_SERVER_PORT); #endif /* NO_IP_DEMON */ - 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(); - } - set_eval(max_cost); - 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': + 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(); + } + set_eval(max_cost); + 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; + if (argv[i][2]) + debug_level_set(&argv[i][2]); + else + debug_level |= DBG_d_flag; + debug_message("Debug Level: %d\n", debug_level); #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"; + 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(); + restore_stat_files(); #endif - preload_objects(e_flag); + preload_objects(e_flag); #ifdef SIGFPE - signal(SIGFPE, sig_fpe); + signal(SIGFPE, sig_fpe); #endif #ifdef TRAP_CRASHES #ifdef SIGUSR1 - signal(SIGUSR1, sig_usr1); + signal(SIGUSR1, sig_usr1); #endif #ifdef SIGUSR2 - signal(SIGUSR2, sig_usr2); + signal(SIGUSR2, sig_usr2); #endif - signal(SIGTERM, sig_term); - signal(SIGINT, sig_int); + signal(SIGTERM, sig_term); + signal(SIGINT, sig_int); #ifndef DEBUG #if defined(SIGABRT) - signal(SIGABRT, sig_abrt); + signal(SIGABRT, sig_abrt); #endif #ifdef SIGIOT - signal(SIGIOT, sig_iot); + signal(SIGIOT, sig_iot); #endif #ifdef SIGHUP - signal(SIGHUP, sig_hup); + signal(SIGHUP, sig_hup); #endif #ifdef SIGBUS - signal(SIGBUS, sig_bus); + signal(SIGBUS, sig_bus); #endif - signal(SIGSEGV, sig_segv); - signal(SIGILL, sig_ill); + signal(SIGSEGV, sig_segv); + signal(SIGILL, sig_ill); #endif /* DEBUG */ #endif #ifndef WIN32 #ifdef USE_BSD_SIGNALS - signal(SIGCHLD, sig_cld); + signal(SIGCHLD, sig_cld); #else - signal(SIGCLD, sig_cld); + signal(SIGCLD, sig_cld); #endif #endif #ifdef HAS_CONSOLE - if(has_console >= 0) - signal(SIGTTIN, sig_ttin); - signal(SIGTTOU, SIG_IGN); + if(has_console >= 0) + signal(SIGTTIN, sig_ttin); + signal(SIGTTOU, SIG_IGN); #endif -backend(); - return 0; + backend(); + return 0; } #ifdef DEBUGMALLOC @@ -447,21 +454,21 @@ char *int_string_copy (const char * const str, char * desc) char *int_string_copy (const char * const str) #endif { - char *p; - int len; - - DEBUG_CHECK(!str, "Null string passed to string_copy.\n"); - len = strlen(str); - if (len > max_string_length) { - len = max_string_length; - p = new_string(len, desc); - (void) strncpy(p, str, len); - p[len] = '\0'; - } else { - p = new_string(len, desc); - (void) strncpy(p, str, len + 1); - } - return p; + char *p; + int len; + + DEBUG_CHECK(!str, "Null string passed to string_copy.\n"); + len = strlen(str); + if (len > max_string_length) { + len = max_string_length; + p = new_string(len, desc); + (void) strncpy(p, str, len); + p[len] = '\0'; + } else { + p = new_string(len, desc); + (void) strncpy(p, str, len + 1); + } + return p; } #ifdef DEBUGMALLOC @@ -470,67 +477,67 @@ char *int_string_unlink (const char * str, char * desc) char *int_string_unlink (const char * str) #endif { - malloc_block_t *mbt, *newmbt; - - mbt = ((malloc_block_t *)str) - 1; - mbt->ref--; - - if (mbt->size == USHRT_MAX) { - int l = strlen(str + USHRT_MAX) + USHRT_MAX; /* ouch */ - - newmbt = (malloc_block_t *)DXALLOC(l + sizeof(malloc_block_t) + 1, TAG_MALLOC_STRING, desc); - memcpy((char *)(newmbt + 1), (char *)(mbt + 1), l+1); - newmbt->size = USHRT_MAX; - ADD_NEW_STRING(USHRT_MAX, sizeof(malloc_block_t)); - } else { - newmbt = (malloc_block_t *)DXALLOC(mbt->size + sizeof(malloc_block_t) + 1, TAG_MALLOC_STRING, desc); - memcpy((char *)(newmbt + 1), (char *)(mbt + 1), mbt->size+1); - newmbt->size = mbt->size; - ADD_NEW_STRING(mbt->size, sizeof(malloc_block_t)); - } - newmbt->ref = 1; - CHECK_STRING_STATS; - - return (char *)(newmbt + 1); + malloc_block_t *mbt, *newmbt; + + mbt = ((malloc_block_t *)str) - 1; + mbt->ref--; + + if (mbt->size == USHRT_MAX) { + int l = strlen(str + USHRT_MAX) + USHRT_MAX; /* ouch */ + + newmbt = (malloc_block_t *)DXALLOC(l + sizeof(malloc_block_t) + 1, TAG_MALLOC_STRING, desc); + memcpy((char *)(newmbt + 1), (char *)(mbt + 1), l+1); + newmbt->size = USHRT_MAX; + ADD_NEW_STRING(USHRT_MAX, sizeof(malloc_block_t)); + } else { + newmbt = (malloc_block_t *)DXALLOC(mbt->size + sizeof(malloc_block_t) + 1, TAG_MALLOC_STRING, desc); + memcpy((char *)(newmbt + 1), (char *)(mbt + 1), mbt->size+1); + newmbt->size = mbt->size; + ADD_NEW_STRING(mbt->size, sizeof(malloc_block_t)); + } + newmbt->ref = 1; + CHECK_STRING_STATS; + + return (char *)(newmbt + 1); } static FILE *debug_message_fp = 0; void debug_message (const char *fmt, ...) { - static char deb_buf[1024]; - static char *deb = deb_buf; - va_list args; - - if (!debug_message_fp) { - /* - * check whether config file specified this option - */ - if (strlen(DEBUG_LOG_FILE)) - snprintf(deb, 1023, "%s/%s", LOG_DIR, DEBUG_LOG_FILE); - else - snprintf(deb, 1023, "%s/debug.log", LOG_DIR); - deb[1023] = 0; - while (*deb == '/') - deb++; - debug_message_fp = fopen(deb, "w"); - if (!debug_message_fp) { - /* darn. We're in trouble */ - perror(deb); - abort(); - } - } - - V_START(args, fmt); - V_VAR(char *, fmt, args); - vfprintf(debug_message_fp, fmt, args); - fflush(debug_message_fp); - va_end(args); - V_START(args, fmt); - V_VAR(char *, fmt, args); - vfprintf(stderr, fmt, args); - fflush(stderr); - va_end(args); + static char deb_buf[1024]; + static char *deb = deb_buf; + va_list args; + + if (!debug_message_fp) { + /* + * check whether config file specified this option + */ + if (strlen(DEBUG_LOG_FILE)) + snprintf(deb, 1023, "%s/%s", LOG_DIR, DEBUG_LOG_FILE); + else + snprintf(deb, 1023, "%s/debug.log", LOG_DIR); + deb[1023] = 0; + while (*deb == '/') + deb++; + debug_message_fp = fopen(deb, "w"); + if (!debug_message_fp) { + /* darn. We're in trouble */ + perror(deb); + abort(); + } + } + + V_START(args, fmt); + V_VAR(char *, fmt, args); + vfprintf(debug_message_fp, fmt, args); + fflush(debug_message_fp); + va_end(args); + V_START(args, fmt); + V_VAR(char *, fmt, args); + vfprintf(stderr, fmt, args); + fflush(stderr); + va_end(args); } int slow_shut_down_to_do = 0; @@ -566,26 +573,26 @@ char *xalloc (int size) static void CDECL PSIG(sig_cld) { #ifndef WIN32 - int status; + int status; #ifdef USE_BSD_SIGNALS - while (wait3(&status, WNOHANG, NULL) > 0) - ; + while (wait3(&status, WNOHANG, NULL) > 0) + ; #else - wait(&status); - signal(SIGCLD, sig_cld); + wait(&status); + signal(SIGCLD, sig_cld); #endif #endif } static void CDECL PSIG(sig_fpe) { - signal(SIGFPE, sig_fpe); + signal(SIGFPE, sig_fpe); } #ifdef HAS_CONSOLE void restore_sigttin(void) { - if(has_console >= 0) - signal(SIGTTIN, sig_ttin); + if(has_console >= 0) + signal(SIGTTIN, sig_ttin); } /* The console goes to sleep when backgrounded and can @@ -593,24 +600,24 @@ void restore_sigttin(void) { */ static void CDECL PSIG(sig_ttin) { char junk[1024]; - int fl; +int fl; - has_console = !has_console; +has_console = !has_console; - signal(SIGTTIN, SIG_IGN); +signal(SIGTTIN, SIG_IGN); - if(has_console) { - /* now eat all the gibberish they typed in the console when it was dead */ - fl = fcntl(STDIN_FILENO, F_GETFL); - fcntl(STDIN_FILENO, F_SETFL, fl | O_NONBLOCK); +if(has_console) { + /* now eat all the gibberish they typed in the console when it was dead */ + fl = fcntl(STDIN_FILENO, F_GETFL); + fcntl(STDIN_FILENO, F_SETFL, fl | O_NONBLOCK); - while(read(STDIN_FILENO, junk, 1023) > 0); /* ; */ + while(read(STDIN_FILENO, junk, 1023) > 0); /* ; */ - /* leaving the output nonblocking is a bad idea. large outputs tend + /* leaving the output nonblocking is a bad idea. large outputs tend to get truncated. - */ - fcntl(STDIN_FILENO, F_SETFL, fl); - } + */ + fcntl(STDIN_FILENO, F_SETFL, fl); +} } #endif @@ -624,18 +631,18 @@ static void CDECL PSIG(sig_ttin) static void CDECL PSIG(sig_usr1) { - push_constant_string("Host machine shutting down"); - push_undefined(); - push_undefined(); - apply_master_ob(APPLY_CRASH, 3); - debug_message("Received SIGUSR1, calling exit(-1)\n"); - exit(-1); + push_constant_string("Host machine shutting down"); + push_undefined(); + push_undefined(); + apply_master_ob(APPLY_CRASH, 3); + debug_message("Received SIGUSR1, calling exit(-1)\n"); + exit(-1); } /* Abort evaluation */ static void CDECL PSIG(sig_usr2) { - outoftime = 1; + outoftime = 1; } /* @@ -644,43 +651,43 @@ static void CDECL PSIG(sig_usr2) */ static void CDECL PSIG(sig_term) { - fatal("Process terminated"); + fatal("Process terminated"); } static void CDECL PSIG(sig_int) { - fatal("Process interrupted"); + fatal("Process interrupted"); } #ifndef DEBUG static void CDECL PSIG(sig_segv) { - fatal("Segmentation fault"); + fatal("Segmentation fault"); } static void CDECL PSIG(sig_bus) { - fatal("Bus error"); + fatal("Bus error"); } static void CDECL PSIG(sig_ill) { - fatal("Illegal instruction"); + fatal("Illegal instruction"); } static void CDECL PSIG(sig_hup) { - fatal("Hangup!"); + fatal("Hangup!"); } static void CDECL PSIG(sig_abrt) { - fatal("Aborted"); + fatal("Aborted"); } static void CDECL PSIG(sig_iot) { - fatal("Aborted(IOT)"); + fatal("Aborted(IOT)"); } #endif /* !DEBUG */ diff --git a/src/main.h b/src/main.h index 0e71b7839..69ceef65a 100644 --- a/src/main.h +++ b/src/main.h @@ -12,6 +12,7 @@ #define PORT_BINARY 2 #define PORT_ASCII 3 #define PORT_MUD 4 +#define PORT_WEBSOCKET 5 typedef struct { int kind; @@ -35,7 +36,7 @@ extern int comp_flag; extern int time_to_clean_up; extern const char *default_fail_message; extern time_t boot_time; -extern int max_cost; +extern LPC_INT max_cost; extern int max_array_size; extern int max_buffer_size; extern int max_string_length; diff --git a/src/mallocwrapper.c b/src/mallocwrapper.c deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/mapping.c b/src/mapping.c index d15262b76..4d23d08f6 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -60,7 +60,7 @@ INLINE int growMap (mapping_t * m) } /* hash table doubles in size -- keep track of the memory used */ total_mapping_size += sizeof(mapping_node_t *) * oldsize; - debug(mapping,("mapping.c: growMap ptr = %p, size = %d\n", m, newsize)); + debug(mapping,("mapping.c: growMap ptr = %p, size = %d\n", (void *)m, newsize)); m->unfilled = oldsize * (unsigned)FILL_PERCENT / (unsigned)100; m->table_size = newsize - 1; /* zero out the new storage area (2nd half of table) */ @@ -96,7 +96,7 @@ INLINE mapping_t *mapTraverse (mapping_t *m, int (*func) (mapping_t *, mapping_n mapping_node_t *elt, *nelt; int j = m->table_size; - debug(mapping,("mapTraverse %p\n", m)); + debug(mapping,("mapTraverse %p\n", (void *)m)); do { for (elt = m->table[j]; elt; elt = nelt) { nelt = elt->next; @@ -111,7 +111,7 @@ INLINE mapping_t *mapTraverse (mapping_t *m, int (*func) (mapping_t *, mapping_n INLINE void dealloc_mapping (mapping_t * m) { - debug(mapping,("mapping.c: actual free of %p\n", m)); + debug(mapping,("mapping.c: actual free of %p\n", (void *)m)); num_mappings--; { int j = m->table_size, c = MAP_COUNT(m); @@ -147,7 +147,7 @@ dealloc_mapping (mapping_t * m) INLINE void free_mapping (mapping_t * m) { - debug(mapping,("mapping.c: free_mapping begin, ptr = %p\n", m)); + debug(mapping,("mapping.c: free_mapping begin, ptr = %p\n", (void *)m)); /* some other object is still referencing this mapping */ if (--m->ref > 0) return; @@ -234,7 +234,7 @@ allocate_mapping (int n) if (n > MAX_MAPPING_SIZE) n = MAX_MAPPING_SIZE; newmap = ALLOCATE(mapping_t, TAG_MAPPING, "allocate_mapping: 1"); - debug(mapping,("mapping.c: allocate_mapping begin, newmap = %p\n", newmap)); + debug(mapping,("mapping.c: allocate_mapping begin, newmap = %p\n", (void *)newmap)); if (newmap == NULL) error("Allocate_mapping - out of memory.\n"); @@ -437,15 +437,17 @@ int svalue_to_int (svalue_t *v) } int msameval (svalue_t * arg1, svalue_t * arg2) { - return (arg1->u.number == arg2->u.number); - /* it's a union so those all do the same anyway! switch (arg1->type | arg2->type) { - case T_NUMBER: - return arg1->u.number == arg2->u.number; - case T_REAL: - return arg1->u.real == arg2->u.real; - default: - return arg1->u.arr == arg2->u.arr; - }*/ + if (sizeof(long) == 8) + return (arg1->u.number == arg2->u.number); + else + switch (arg1->type | arg2->type) { + case T_NUMBER: + return arg1->u.number == arg2->u.number; + case T_REAL: + return arg1->u.real == arg2->u.real; + default: + return arg1->u.arr == arg2->u.arr; + } } /* @@ -499,12 +501,12 @@ find_for_insert (mapping_t * m, svalue_t * lv, int doTheFree) do { if (msameval(lv, n->values)) { /* normally, the f_assign would free the old value */ - debug(mapping,("mapping.c: found %p\n", n->values)); + debug(mapping,("mapping.c: found %p\n", (void *) (n->values))); if (doTheFree) free_svalue(n->values + 1, "find_for_insert"); return n->values + 1; } } while ((n = n->next)); - debug(mapping,("mapping.c: didn't find %p\n", lv)); + debug(mapping,("mapping.c: didn't find %p\n", (void *)lv)); n = *a; } else if (!(--m->unfilled)) { @@ -633,8 +635,10 @@ void f_unique_mapping (void) sv = call_efun_callback(&ftc, 1); if(sv) i = (oi = svalue_to_int(sv)) & mask; - else + else { i = oi = 0; + sv = &const0; + } if ((uptr = table[i])) { do { if (msameval(&uptr->key, sv)) { @@ -1010,7 +1014,7 @@ add_mapping (mapping_t *m1, mapping_t *m2) { mapping_t *newmap; - debug(mapping,("mapping.c: add_mapping begin: %p, %p", m1, m2)); + debug(mapping,("mapping.c: add_mapping begin: %p, %p", (void *)m1, (void *)m2)); if (MAP_COUNT(m1) >= MAP_COUNT(m2)) { if (MAP_COUNT(m2)) { add_to_mapping(newmap = copyMapping(m1), m2, 1); diff --git a/src/master.c b/src/master.c index 9441879d6..3255f845b 100644 --- a/src/master.c +++ b/src/master.c @@ -73,7 +73,7 @@ static void get_master_applies (object_t * ob) { TAG_SIMULS, "get_master_applies"); for (i = 0; i < NUM_MASTER_APPLIES; i++) { - char *name = applies_table[i]; + const char *name = applies_table[i]; int ind, ri; if (find_function_by_name(ob, name, &ind, &ri)) { diff --git a/src/md.c b/src/md.c index c31453de9..b2c67c2ee 100644 --- a/src/md.c +++ b/src/md.c @@ -126,6 +126,9 @@ MDmalloc (md_node_t * node, int size, int tag, char * desc) node->tag = tag; node->id = count++; node->desc = desc ? desc : "default"; + if(!desc) { + fatal("Trying to alloc memory without accounting info."); + } if (malloc_mask == node->tag) { debug_message("MDmalloc: %5d, [%-25s], %8lx:(%d)\n", node->tag, node->desc, PTR(node), node->size); @@ -505,6 +508,21 @@ void compute_string_totals (int * asp, int * abp, int * bp) { } } +INLINE_STATIC void dump_stralloc() { + md_node_t *entry; + fprintf(stderr, "===STRALLOC DUMP: allocd_strings: %i \n", allocd_strings); + + for (int hsh = 0; hsh < MD_TABLE_SIZE; hsh++) { + for (entry = table[hsh]; entry; entry = entry->next) { + if(entry->tag == TAG_MALLOC_STRING || entry->tag == TAG_SHARED_STRING) { + fprintf(stderr, "%-30s: sz %7d: id %6d: tag %08x, a %8lx\n", + entry->desc, entry->size, entry->id, entry->tag, + (unsigned long) PTR(entry)); + } + } + } +} + /* * Verify string statistics. out can be zero, in which case any errors * are printed to stdout and abort() is called. Otherwise the error messages @@ -515,6 +533,7 @@ void check_string_stats (outbuffer_t * out) { + blocks[TAG_MALLOC_STRING & 0xff] * sizeof(malloc_block_t); int num = blocks[TAG_SHARED_STRING & 0xff] + blocks[TAG_MALLOC_STRING & 0xff]; int bytes, as, ab; + int need_dump = 0; compute_string_totals(&as, &ab, &bytes); @@ -523,6 +542,7 @@ void check_string_stats (outbuffer_t * out) { overhead += base_overhead; if (num != num_distinct_strings) { + need_dump = 1; if (out) { outbuf_addv(out, "WARNING: num_distinct_strings is: %i should be: %i\n", num_distinct_strings, num); @@ -533,6 +553,7 @@ void check_string_stats (outbuffer_t * out) { } } if (overhead != overhead_bytes) { + need_dump = 1; if (out) { outbuf_addv(out, "WARNING: overhead_bytes is: %i should be: %i\n", overhead_bytes, overhead); @@ -543,6 +564,7 @@ void check_string_stats (outbuffer_t * out) { } } if (bytes != bytes_distinct_strings) { + need_dump = 1; if (out) { outbuf_addv(out, "WARNING: bytes_distinct_strings is: %i should be: %i\n", bytes_distinct_strings, bytes - (overhead - base_overhead)); @@ -553,6 +575,7 @@ void check_string_stats (outbuffer_t * out) { } } if (allocd_strings != as) { + need_dump = 1; if (out) { outbuf_addv(out, "WARNING: allocd_strings is: %i should be: %i\n", allocd_strings, as); @@ -563,6 +586,7 @@ void check_string_stats (outbuffer_t * out) { } } if (allocd_bytes != ab) { + need_dump = 1; if (out) { outbuf_addv(out, "WARNING: allocd_bytes is: %i should be: %i\n", allocd_bytes, ab); @@ -572,6 +596,10 @@ void check_string_stats (outbuffer_t * out) { abort(); } } + + if (need_dump) { + dump_stralloc(); + } } #endif @@ -695,8 +723,8 @@ void check_all_blocks (int flag) { outbuf_add(&out, "WARNING: more than one identifier hash table allocated.\n"); if (blocks[TAG_RESERVED & 0xff] > 1) outbuf_add(&out, "WARNING: more than one reserved block allocated.\n"); - if (blocks[TAG_OBJ_TBL & 0xff] > 1) - outbuf_add(&out, "WARNING: more than object table allocated.\n"); + if (blocks[TAG_OBJ_TBL & 0xff] > 2) + outbuf_add(&out, "WARNING: more than two object table allocated.\n"); if (blocks[TAG_CONFIG & 0xff] > 1) outbuf_add(&out, "WARNING: more than config file table allocated.\n"); if (blocks[TAG_STR_TBL & 0xff] > 1) @@ -758,6 +786,10 @@ void check_all_blocks (int flag) { if (all_users[i]) { DO_MARK(all_users[i], TAG_INTERACTIVE); all_users[i]->ob->extra_ref++; + // FIXME(sunyc): I can't explain this, appearently somewhere + // is giving interactive object an addtional ref. + all_users[i]->ob->extra_ref++; + if (all_users[i]->input_to) { all_users[i]->input_to->ob->extra_ref++; DO_MARK(all_users[i]->input_to, TAG_SENTENCE); @@ -768,8 +800,9 @@ void check_all_blocks (int flag) { } } #ifdef PACKAGE_COMPRESS - if(all_users[i]->compressed_stream) + if(all_users[i]->compressed_stream) { DO_MARK(all_users[i]->compressed_stream, TAG_INTERACTIVE); + } #endif #ifndef NO_ADD_ACTION @@ -785,7 +818,8 @@ void check_all_blocks (int flag) { strcpy(buf, DEFAULT_FAIL_MESSAGE); strcat(buf, "\n"); - EXTRA_REF(BLOCK(findstring(buf)))++; + char *target = findstring(buf); + if (target) EXTRA_REF(BLOCK(target))++; } #ifdef PACKAGE_UIDS @@ -1035,6 +1069,24 @@ void check_all_blocks (int flag) { case TAG_MAP_NODE_BLOCK: outbuf_addv(&out, "WARNING: Found orphan mapping node block: %s %04x\n", entry->desc, entry->tag); break; + /* FIXME: need to account these. */ + case TAG_PERMANENT: /* only save_object|resotre_object uses this */ + case TAG_INC_LIST: + case TAG_IDENT_TABLE: + case TAG_OBJ_TBL: + case TAG_SIMULS: + case TAG_STR_TBL: + case TAG_LOCALS: + case TAG_CALL_OUT: + case TAG_USERS: + case TAG_HEART_BEAT: + case TAG_INPUT_TO: + break; + default: + if (entry->tag < TAG_MARKED) { + printf("WARNING: unaccounted node block: %s %d\n", entry->desc, entry->tag); + } + break; } entry->tag &= ~TAG_MARKED; } diff --git a/src/my_malloc.h b/src/my_malloc.h index 17ac5bc84..908fee23f 100644 --- a/src/my_malloc.h +++ b/src/my_malloc.h @@ -60,6 +60,18 @@ void *malloc32(int size); #endif #endif +#ifdef GCMALLOC +#define MALLOC_NEED_INIT 1 +#define MALLOC(x) GC_MALLOC((x)) +#define FREE(x) +#define REALLOC(x,y) GC_REALLOC((x),(y)) +#define CALLOC(x,y) GC_MALLOC(((x)*(y))) +#ifndef _FUNC_SPEC_ +#include +void malloc_init(); +#endif +#endif + #define DXALLOC(x,tag,desc) xalloc(x) #define DMALLOC(x,tag,desc) MALLOC(x) #define DREALLOC(x,y,tag,desc) REALLOC(x,y) diff --git a/src/object.c b/src/object.c index fceae32fc..ee51aaed7 100644 --- a/src/object.c +++ b/src/object.c @@ -512,7 +512,7 @@ restore_interior_string (char ** val, svalue_t * sv) static int parse_numeric (char ** cpp, unsigned char c, svalue_t * dest) { char *cp = *cpp; - long res, neg; + LPC_INT res, neg; if (c == '-') { neg = 1; @@ -529,7 +529,7 @@ static int parse_numeric (char ** cpp, unsigned char c, svalue_t * dest) res += c - '0'; } if (c == '.') { - double f1 = 0.0, f2 = 10.0; + LPC_FLOAT f1 = 0.0, f2 = 10.0; c = *cp++; if (!c) { @@ -569,7 +569,7 @@ static int parse_numeric (char ** cpp, unsigned char c, svalue_t * dest) return 1; } else if (c == 'e') { int expo = 0; - double f1; + LPC_FLOAT f1; if ((c = *cp++) == '+') { while ((c = *cp++) && isdigit(c)) { @@ -1253,7 +1253,6 @@ restore_object_from_gzip (object_t * ob, static char *buff = NULL; static long buffsize = 0; const char* tmp = ""; - int idx; int t; t = 65536 << *count; //should be big enough most of the time @@ -1263,14 +1262,13 @@ restore_object_from_gzip (object_t * ob, } if(!buff){ - buff = (char *)DXALLOC(t, TAG_TEMPORARY, "restore_object: 6"); + buff = (char *)DXALLOC(t, TAG_PERMANENT, "restore_object: 6"); buffsize = t; } t = buffsize; while (!gzeof(gzf) && tmp != Z_NULL) { - idx = 0; buff[t - 2] = 0; // gzgets appaears to pay attension to zero termination even on short // strings @@ -1374,7 +1372,7 @@ static int save_object_recurse (program_t * prog, svalue_t ** if (new_str) { FREE(new_str); } - new_str = (char *)DXALLOC(theSize, TAG_TEMPORARY, "save_object: 2"); + new_str = (char *)DXALLOC(theSize, TAG_PERMANENT, "save_object: 2"); oldSize = theSize; } @@ -1453,7 +1451,7 @@ static int save_object_recurse_str (program_t * prog, svalue_t **svp, int type, if (new_str) { FREE(new_str); } - new_str = (char *)DXALLOC(theSize, TAG_TEMPORARY, "save_object: 2"); + new_str = (char *)DXALLOC(theSize, TAG_PERMANENT, "save_object: 2"); oldSize = theSize; } @@ -1814,7 +1812,7 @@ int restore_object (object_t * ob, const char * file, int noclear) if (theBuff) { FREE(theBuff); } - theBuff = DXALLOC(tmp_len + 1, TAG_TEMPORARY, "restore_object: 4"); + theBuff = DXALLOC(tmp_len + 1, TAG_PERMANENT, "restore_object: 4"); buff_len = tmp_len; } #ifdef WIN32 @@ -1896,7 +1894,7 @@ void tell_object (object_t * ob, const char * str, int len) void dealloc_object (object_t * ob, const char * from) { #ifdef DEBUG - object_t *tmp, *prev_all = 0; + object_t *prev_all = 0; #endif debug(d_flag, ("free_object: /%s.\n", ob->obname)); diff --git a/src/options.h b/src/options.h index faeafc4ad..45489c42d 100644 --- a/src/options.h +++ b/src/options.h @@ -65,6 +65,7 @@ #undef MMALLOC #undef MALLOC64 #undef MALLOC32 +#undef GCMALLOC /* needs -lgc in system_libs */ /* You may optionally choose one (or none) of these malloc wrappers. These * can be used in conjunction with any of the above malloc packages. * @@ -316,7 +317,7 @@ * Similarly for arrays ... */ #define ARRAY_STATS - +#define CLASS_STATS /* LOG_CATCHES: define this to cause errors that are catch()'d to be * sent to the debug log anyway. * @@ -391,7 +392,7 @@ * calls to functions in this object by objects that * inherit it. * PRAGMA_OPTIMIZE: make a second pass over the generated code to - * optimize it further. Currently does jump threading. + * optimize it further. Currently maybe broken. * PRAGMA_ERROR_CONTEXT:include some text telling where on the line a * compilation error occured. */ @@ -693,17 +694,9 @@ */ #undef USE_32BIT_ADDRESSES -/* HEARTBEAT_INTERVAL: define heartbeat interval in microseconds (us). - * 1,000,000 us = 1 second. The value of this macro specifies - * the frequency with which the heart_beat method will be called in - * those LPC objects which have called set_heart_beat(1). - * - * [NOTE: if ualarm() isn't available, alarm() is used instead. Since - * alarm() requires its argument in units of a second, we map 1 - 1,000,000 us - * to an actual interval of one (1) second and 1,000,001 - 2,000,000 maps to - * an actual interval of two (2) seconds, etc.] +/* HEARTBEAT_INTERVAL: define heartbeat interval in seconds. */ -#define HEARTBEAT_INTERVAL 2000000 +#define HEARTBEAT_INTERVAL 1 /* * CALLOUT_CYCLE_SIZE: This is the number of slots in the call_out list. @@ -884,7 +877,7 @@ /*PACKAGE_ASYNC: adds some efuns for asyncronous IO */ #define PACKAGE_ASYNC -/*PACKAGE_SHA1: adds a function to calculate the sha1 hash of a string sha1(string)*/ +/*PACKAGE_SHA1: adds a function to calculate the sha1 hash of a string sha1(string). Use PACKAGE_CRYPTO instead if possible. */ #undef PACKAGE_SHA1 /*PACKAGE_CRYPTO: adds a function that does multiple hash types hash(hash, string), needs openssl lib and includes and -lssl in system_libs*/ @@ -917,5 +910,8 @@ /* use struct keyword for lpc structs */ #define STRUCT_STRUCT + +/* use POSIX timers for eval_cost */ +#define POSIX_TIMERS #endif diff --git a/src/otable.c b/src/otable.c index efdd4a032..292b4a6e3 100644 --- a/src/otable.c +++ b/src/otable.c @@ -33,7 +33,7 @@ static object_t *find_obj_n(const char *); static object_t **obj_table = 0; static object_t **ch_table = 0; -static char *basename(const char *full, int *size) { +static char *_basename(const char *full, int *size) { char *tmp; char *name= new_string(*size = strlen(full), "base_name: name"); while (*full == '/') { @@ -113,7 +113,7 @@ array_t *children(const char * s) { int size; int count = 0; - s = basename(s, &size); + s = _basename(s, &size); ch = ObjHash(s); curr = ch_table[ch]; @@ -164,7 +164,7 @@ void enter_object_hash(object_t * ob) { objs_in_table++; //for children() - base = basename(ob->obname, &dummy); + base = _basename(ob->obname, &dummy); ch = ObjHash(base); ob->next_ch_hash = ch_table[ch]; @@ -195,7 +195,7 @@ void remove_object_hash(object_t * ob) { ob->next_hash = 0; objs_in_table--; - base = basename(ob->obname, &dummy); + base = _basename(ob->obname, &dummy); ch = ObjHash(base); FREE_MSTR(base); s = ch_table[ch]; diff --git a/src/packages/GNUmakefile b/src/packages/GNUmakefile deleted file mode 100644 index a244e1254..000000000 --- a/src/packages/GNUmakefile +++ /dev/null @@ -1,19 +0,0 @@ - -SRC=uids.c db.c compress.c math.c develop.c external.c contrib.c sockets.c async.c dwlib.c -OBJ=uids.$(O) db.$(O) compress.$(O) math.$(O) develop.$(O) external.$(O) contrib.$(O) sockets.$(O) async.$(O) dwlib.$(O) - -OBJ=$(addprefix $(OBJDIR)/,$(subst .c,.o,$(SRC))) - -$(OBJDIR)/%.o: %.c - $(CC) -I$(OBJDIR) -I.. $(CFLAGS) -o $@ -c $< - -all: $(OBJ) - ar rcu packages.$(A) $(OBJ) - $(RANLIB) packages.$(A) - -$(OBJDIR)/db.o: db.c - $(CC) -I$(OBJDIR) -I.. -I/usr/include/mysql $(CFLAGS) -o $@ -c $< - -clean: - rm -f *.$(O) - rm -f packages.$(A) diff --git a/src/packages/Makefile b/src/packages/Makefile deleted file mode 100644 index eadc5ac17..000000000 --- a/src/packages/Makefile +++ /dev/null @@ -1,17 +0,0 @@ - -SRC=uids.c db.c compress.c math.c develop.c external.c contrib.c sockets.c async.c dwlib.c -OBJ=uids.$(O) db.$(O) compress.$(O) math.$(O) develop.$(O) external.$(O) contrib.$(O) sockets.$(O) async.$(O) dwlib.$(O) - -.c.$(O): - $(CC) $(CFLAGS) -I.. -c $*.c - -all: $(OBJ) - ar rcu packages.$(A) $(OBJ) - $(RANLIB) packages.$(A) - -db.$(O): db.c - $(CC) $(CFLAGS) -I.. -I/usr/include/mysql -c $*.c - -clean: - rm -f *.$(O) - rm -f packages.$(A) diff --git a/src/packages/async.c b/src/packages/async.c index fb2844178..87ad6a376 100644 --- a/src/packages/async.c +++ b/src/packages/async.c @@ -266,7 +266,7 @@ pthread_mutex_t *db_mut = NULL; void *dbexecthread(struct request *req){ pthread_mutex_lock(db_mut); - db_t *db = find_db_conn((int)req->buf); + db_t *db = find_db_conn((long)req->buf); int ret = -1; if (db->type->execute) { if (db->type->cleanup) { @@ -391,7 +391,7 @@ int add_write(const char *fname, const char *buf, int size, char flags, function } #ifdef F_ASYNC_DB_EXEC -int add_db_exec(int handle, function_to_call_t *fun) { +int add_db_exec(long handle, function_to_call_t *fun) { struct request *req = get_req(); req->fun = fun; req->type = adbexec; diff --git a/src/packages/async_spec.c b/src/packages/async_spec.c index ab6c1da77..9caf36ad3 100644 --- a/src/packages/async_spec.c +++ b/src/packages/async_spec.c @@ -2,7 +2,7 @@ void async_read(string, function); void async_write(string, string, int, function); -#ifdef linux +#ifdef __linux__ void async_getdir(string, function); #endif #ifdef PACKAGE_DB diff --git a/src/packages/compress.c b/src/packages/compress.c index e23020b44..a4251171b 100644 --- a/src/packages/compress.c +++ b/src/packages/compress.c @@ -186,7 +186,6 @@ void f_uncompress_file (void) in_file = gzopen(real_input_file, "rb"); if (!in_file) { - gzclose(in_file); pop_n_elems(num_arg); push_number(0); return ; @@ -194,7 +193,7 @@ void f_uncompress_file (void) out_file = fopen(output_file, "wb"); if (!out_file) { - fclose(out_file); + gzclose(in_file); pop_n_elems(num_arg); push_number(0); return ; diff --git a/src/packages/contrib.c b/src/packages/contrib.c index d4e0e9a5b..d4b642bf5 100644 --- a/src/packages/contrib.c +++ b/src/packages/contrib.c @@ -12,6 +12,7 @@ #include "../add_action.h" #include "../port.h" #include "../applies.h" +#include "../object.h" #define MAX_COLOUR_STRING 200 /* should be done in configure */ @@ -75,9 +76,9 @@ void f_named_livings() { continue; } #endif -if (nob == max_array_size) - break; -obtab[nob++] = ob; + if (nob == max_array_size) + break; + obtab[nob++] = ob; } } @@ -641,10 +642,11 @@ f_terminal_colour (void) resetstrname = findstring("RESET"); k = sp->u.map->table_size; if (resetstrname) { - int tmp; static svalue_t str = {T_STRING, STRING_SHARED}; + int tmp; str.u.string = resetstrname; tmp = MAP_SVAL_HASH(str); + for (elt = mtab[tmp & k]; elt; elt = elt->next) { if ( elt->values->type == T_STRING && (elt->values + 1)->type == T_STRING && @@ -673,16 +675,16 @@ f_terminal_colour (void) // Look it up in the mapping. repused = 0; copy_and_push_string(parts[i]); - svalue_t *tmp = apply(APPLY_TERMINAL_COLOUR_REPLACE, current_object, 1, ORIGIN_EFUN); - if(tmp && tmp->type == T_STRING){ - rep = alloca(SVALUE_STRLEN(tmp)+1); - strcpy(rep, tmp->u.string); + svalue_t *reptmp = apply(APPLY_TERMINAL_COLOUR_REPLACE, current_object, 1, ORIGIN_EFUN); + if(reptmp && reptmp->type == T_STRING){ + rep = (char *)alloca(SVALUE_STRLEN(reptmp)+1); + strcpy(rep, reptmp->u.string); repused = 1; } if((repused && (cp = findstring(rep))) || (!repused && (cp = findstring(parts[i])))) { - int tmp; static svalue_t str = {T_STRING, STRING_SHARED}; + int tmp; str.u.string = cp; tmp = MAP_SVAL_HASH(str); for (elt = mtab[tmp & k]; elt; elt = elt->next) { @@ -706,13 +708,25 @@ f_terminal_colour (void) break; } } - if (!elt) { - lens[i] = SHARED_STRLEN(cp); + if (!elt) { //end of for loop, so not found! + if(repused){ + parts[i] = rep; + lens[i] = wrap?-SVALUE_STRLEN(reptmp):SVALUE_STRLEN(reptmp); + if (curcolourlen + SVALUE_STRLEN(reptmp) < MAX_COLOUR_STRING - 1) { + strcat(curcolour, rep); + curcolourlen += SVALUE_STRLEN(reptmp); + } + } else + lens[i] = SHARED_STRLEN(cp); } } else { if(repused){ parts[i] = rep; - lens[i] = wrap?-SVALUE_STRLEN(tmp):SVALUE_STRLEN(tmp); + lens[i] = wrap?-SVALUE_STRLEN(reptmp):SVALUE_STRLEN(reptmp); + if (curcolourlen + SVALUE_STRLEN(reptmp) < MAX_COLOUR_STRING - 1) { + strcat(curcolour, rep); + curcolourlen += SVALUE_STRLEN(reptmp); + } } else lens[i] = strlen(parts[i]); @@ -1198,8 +1212,8 @@ static char *pluralize (const char * str) { break; } if (!strcasecmp(rel + 1, "ech")) { - found = PLURAL_SUFFIX; - suffix = "s"; + found = PLURAL_SUFFIX; + suffix = "s"; } break; case 'O': @@ -1779,7 +1793,7 @@ void f_zonetime (void) { const char *timezone, *old_tz; char *retv; - long time_val; + LPC_INT time_val; int len; time_val = sp->u.number; @@ -1789,6 +1803,11 @@ void f_zonetime (void) old_tz = set_timezone(timezone); retv = ctime((time_t *)&time_val); + if(!retv) { + reset_timezone(old_tz); + error("bad argument to zonetime."); + return ; + } len = strlen(retv); retv[len-1] = '\0'; reset_timezone(old_tz); @@ -1801,7 +1820,7 @@ void f_zonetime (void) void f_is_daylight_savings_time (void) { struct tm *t; - long time_to_check; + LPC_INT time_to_check; const char *timezone; char *old_tz; @@ -1813,9 +1832,9 @@ void f_is_daylight_savings_time (void) old_tz = set_timezone(timezone); t = localtime((time_t *)&time_to_check); - - push_number((t->tm_isdst) > 0); - + if (t) { + push_number((t->tm_isdst) > 0); + } else push_number(-1); reset_timezone(old_tz); } #endif @@ -1895,12 +1914,12 @@ static int memory_share (svalue_t * sv) { switch (sv->subtype) { case STRING_MALLOC: return total + - (1 + COUNTED_STRLEN(sv->u.string) + sizeof(malloc_block_t))/ - (COUNTED_REF(sv->u.string)); + (1 + COUNTED_STRLEN(sv->u.string) + sizeof(malloc_block_t))/ + (COUNTED_REF(sv->u.string)); case STRING_SHARED: return total + - (1 + COUNTED_STRLEN(sv->u.string) + sizeof(block_t))/ - (COUNTED_REF(sv->u.string)); + (1 + COUNTED_STRLEN(sv->u.string) + sizeof(block_t))/ + (COUNTED_REF(sv->u.string)); } break; case T_ARRAY: @@ -1911,11 +1930,11 @@ static int memory_share (svalue_t * sv) { /* first svalue is stored inside the array struct, so sizeof(array_t) * includes one svalue. */ - subtotal = sizeof(array_t) - sizeof(svalue_t); - for (i = 0; i < sv->u.arr->size; i++) - subtotal += memory_share(&sv->u.arr->item[i]); - calldepth--; - return total + subtotal/sv->u.arr->ref; + subtotal = sizeof(array_t) - sizeof(svalue_t); + for (i = 0; i < sv->u.arr->size; i++) + subtotal += memory_share(&sv->u.arr->item[i]); + calldepth--; + return total + subtotal/sv->u.arr->ref; case T_MAPPING: if (1+calldepth > 100) return 0; @@ -2197,7 +2216,7 @@ void f_event (void){ #ifdef F_QUERY_NUM -void number_as_string (char * buf, long n){ +void number_as_string (char * buf, LPC_INT n){ const char *low[] = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" }; @@ -2227,7 +2246,7 @@ void number_as_string (char * buf, long n){ void f_query_num (void){ char ret[100]; int i; - long n, limit; + LPC_INT n, limit; int changed = 0; char *res; @@ -2654,7 +2673,7 @@ f_abs() { void f_roll_MdN() { - long roll = 0; + LPC_INT roll = 0; if ( (sp - 1)->u.number > 0 && sp->u.number > 0 ) { while( (sp - 1)->u.number-- ) @@ -2807,25 +2826,20 @@ void f_remove_charmode (void){ #endif #ifdef F_REMOVE_GET_CHAR static int remove_get_char (object_t * ob){ - int ret; if (!ob || ob->interactive == 0){ - ret = -2; + return -2; } - else ret = 0; if (ob->interactive->input_to) { - ret = 1; free_sentence(ob->interactive->input_to); if (ob->interactive->num_carry > 0) free_some_svalues(ob->interactive->carryover, ob->interactive->num_carry); ob->interactive->carryover = NULL; ob->interactive->num_carry = 0; ob->interactive->input_to = 0; + return 1; } - else { - ret = -1; - } - return ret; + return -1; } void f_remove_get_char (void){ @@ -2868,7 +2882,7 @@ void f_send_nullbyte (void){ #ifdef F_RESTORE_FROM_STRING void f_restore_from_string(){ const char *buf; - long noclear; + LPC_INT noclear; buf = (sp-1)->u.string; noclear = sp->u.number; @@ -2883,66 +2897,106 @@ void f_restore_from_string(){ #ifdef F_CLASSES void f_classes() { - int i, j, num, size, offset, flag; - array_t *vec, *subvec, *subsubvec; - unsigned short *types; - char buf[256]; - char *end; - program_t *prog; - - flag = (sp--)->u.number; - end = EndOf( buf ); - - prog = sp->u.ob->prog; - num = prog->num_classes; - vec = allocate_empty_array( num ); - - // Pull out data for each class. - for( i = 0; i < num; i++ ) { - // Do we want additional info on each class? - if( flag ) { - size = prog->classes[i].size; - - vec->item[i].type = T_ARRAY; - subvec = vec->item[i].u.arr = allocate_empty_array( 1 + size ); - - // First item of return array: the class's name. - subvec->item[0].type = T_STRING; - subvec->item[0].subtype = STRING_SHARED; - subvec->item[0].u.string = make_shared_string( - prog->strings[prog->classes[i].classname] ); - - offset = prog->classes[i].index; - - // Find the name and type of each class member. - for( j = 0; j < size; j++, offset++ ) { - subvec->item[j + 1].type = T_ARRAY; - subsubvec = subvec->item[j + 1].u.arr = allocate_empty_array( 2 ); - - // Each subarray contains the member's name... - subsubvec->item[0].type = T_STRING; - subsubvec->item[0].subtype = STRING_SHARED; - subsubvec->item[0].u.string = make_shared_string( - prog->strings[prog->class_members[offset].membername] ); - - // ...and type. - get_type_name( buf, end, prog->class_members[offset].type ); - subsubvec->item[1].type = T_STRING; - subsubvec->item[1].subtype = STRING_SHARED; - subsubvec->item[1].u.string = make_shared_string( buf ); - } - } - else { - // No additional info. Just pull out the class name. - vec->item[i].type = T_STRING; - vec->item[i].subtype = STRING_SHARED; - vec->item[i].u.string = make_shared_string( - prog->strings[prog->classes[i].classname] ); - } - } - - pop_stack(); - push_refed_array( vec ); + int i, j, num, size, offset, flag; + array_t *vec, *subvec, *subsubvec; + char buf[256]; + char *end; + program_t *prog; + + flag = (sp--)->u.number; + end = EndOf( buf ); + + prog = sp->u.ob->prog; + num = prog->num_classes; + vec = allocate_empty_array( num ); + + // Pull out data for each class. + for( i = 0; i < num; i++ ) { + // Do we want additional info on each class? + if( flag ) { + size = prog->classes[i].size; + + vec->item[i].type = T_ARRAY; + subvec = vec->item[i].u.arr = allocate_empty_array( 1 + size ); + + // First item of return array: the class's name. + subvec->item[0].type = T_STRING; + subvec->item[0].subtype = STRING_SHARED; + subvec->item[0].u.string = make_shared_string( + prog->strings[prog->classes[i].classname] ); + + offset = prog->classes[i].index; + + // Find the name and type of each class member. + for( j = 0; j < size; j++, offset++ ) { + subvec->item[j + 1].type = T_ARRAY; + subsubvec = subvec->item[j + 1].u.arr = allocate_empty_array( 2 ); + + // Each subarray contains the member's name... + subsubvec->item[0].type = T_STRING; + subsubvec->item[0].subtype = STRING_SHARED; + subsubvec->item[0].u.string = make_shared_string( + prog->strings[prog->class_members[offset].membername] ); + + // ...and type. + get_type_name( buf, end, prog->class_members[offset].type ); + subsubvec->item[1].type = T_STRING; + subsubvec->item[1].subtype = STRING_SHARED; + subsubvec->item[1].u.string = make_shared_string( buf ); + } + } + else { + // No additional info. Just pull out the class name. + vec->item[i].type = T_STRING; + vec->item[i].subtype = STRING_SHARED; + vec->item[i].u.string = make_shared_string( + prog->strings[prog->classes[i].classname] ); + } + } + + pop_stack(); + push_refed_array( vec ); +} + +#endif + +#ifdef F_TEST_LOAD +const char *saved_extra_name; +object_t *testloadob; +static void fix_object_names() { + if(testloadob) + SETOBNAME(testloadob, saved_extra_name); +} + +void f_test_load(){ + const char *tmp = sp->u.string; + object_t *new_ob, *tmp_ob; + if(testloadob = find_object2(sp->u.string)){ + tmp = testloadob->obname; + SETOBNAME(testloadob, ""); + + } + saved_extra_name = tmp; + STACK_INC; + sp->type = T_ERROR_HANDLER; + sp->u.error_handler = fix_object_names; + + + new_ob = int_load_object(tmp, 0); + if (!new_ob) { + if(testloadob) + SETOBNAME(testloadob, tmp); + sp--; + pop_stack(); + push_number(0); + return; + } + destruct_object(new_ob); + sp--; + pop_stack(); + push_number(1); + if(testloadob) + SETOBNAME(testloadob, saved_extra_name); } #endif diff --git a/src/packages/contrib_spec.c b/src/packages/contrib_spec.c index d1748b3c4..13a7dbb40 100644 --- a/src/packages/contrib_spec.c +++ b/src/packages/contrib_spec.c @@ -60,3 +60,4 @@ int remove_get_char(object); int send_nullbyte(object); void restore_from_string(string, int default:0); mixed *classes( object, int default : 0 ); +int test_load(string); diff --git a/src/packages/crypto.c b/src/packages/crypto.c index 55f96fef2..95e3397a6 100755 --- a/src/packages/crypto.c +++ b/src/packages/crypto.c @@ -9,12 +9,26 @@ * -- coded by Ajandurah@Demonslair (Mark Lyndoe) 10/03/09 */ +#include + +#ifndef OPENSSL_NO_SHA +#include +#endif +#ifndef OPENSSL_NO_MD5 +#include +#endif +#ifndef OPENSSL_NO_MD2 #include +#endif +#ifndef OPENSSL_NO_MD4 #include -#include -#include +#endif +#ifndef OPENSSL_NO_MDC2 #include +#endif +#ifndef OPENSSL_NO_RIPEMD160 #include +#endif #ifdef LATTICE #include "/lpc_incl.h" @@ -24,92 +38,81 @@ #endif #ifdef F_HASH -char *hexdump(unsigned char *data, size_t len) +INLINE_STATIC char *hexdump(const unsigned char *data, int len) { - char *buf; - int i; + const char hexchars[] = "0123456789abcdef"; + char *result, *p; - buf = malloc((len*2)+1); - memset(buf, '\0', (len*2)); + p = result = new_string(len * 2 + 1, "f_hash"); - for (i=0; i> 4]; + *p++ = hexchars[(*data++) & 0xf]; } + + *p = 0; - return buf; + return result; } void f_hash(void) { - const char *algo; - const char *data; - char *res; + const char *algo, *data; + char *result = NULL; + int data_len; algo = (sp - 1)->u.string; data = sp->u.string; + data_len = SVALUE_STRLEN(sp); - /* MD2 Digest */ - if (strcasecmp(algo, (const char *)"md2") == 0) - { - unsigned char md[MD2_DIGEST_LENGTH]; - MD2((unsigned char *)data, strlen(data), md); - res = hexdump(md, MD2_DIGEST_LENGTH); - } - - /* MD4 Digest */ - else if (strcasecmp(algo, (const char *)"md4") == 0) - { - unsigned char md[MD4_DIGEST_LENGTH]; - MD4((unsigned char *)data, strlen(data), md); - res = hexdump(md, MD4_DIGEST_LENGTH); - } +#define DO_HASH_IF(id, func, hash_size) SAFE( \ + if (strcasecmp(algo, id) == 0) { \ + unsigned char md[hash_size]; \ + func((unsigned char *) data, data_len, md); \ + result = hexdump(md, hash_size); \ + } \ +) - /* MD5 Digest */ - else if (strcasecmp(algo, (const char *)"md5") == 0) - { - unsigned char md[MD5_DIGEST_LENGTH]; - MD5((unsigned char *)data, strlen(data), md); - res = hexdump(md, MD5_DIGEST_LENGTH); - } +#ifndef OPENSSL_NO_SHA1 + DO_HASH_IF("sha1", SHA1, SHA_DIGEST_LENGTH); +#endif + +#ifndef OPENSSL_NO_MD5 + DO_HASH_IF("md5", MD5, MD5_DIGEST_LENGTH); +#endif - /* MDC2 Digest */ - else if (strcasecmp(algo, (const char *)"mdc2") == 0) - { - unsigned char md[MDC2_DIGEST_LENGTH]; - MDC2((unsigned char *)data, strlen(data), md); - res = hexdump(md, MDC2_DIGEST_LENGTH); - } +#ifndef OPENSSL_NO_SHA256 + DO_HASH_IF("sha256", SHA256, SHA256_DIGEST_LENGTH); + DO_HASH_IF("sha224", SHA224, SHA224_DIGEST_LENGTH); +#endif - /* RIPEMD160 Digest */ - else if (strcasecmp(algo, (const char *)"ripemd160") == 0) - { - unsigned char md[RIPEMD160_DIGEST_LENGTH]; - RIPEMD160((unsigned char *)data, strlen(data), md); - res = hexdump(md, RIPEMD160_DIGEST_LENGTH); - } +#ifndef OPENSSL_NO_SHA512 + DO_HASH_IF("sha512", SHA512, SHA512_DIGEST_LENGTH); + DO_HASH_IF("sha384", SHA384, SHA384_DIGEST_LENGTH); +#endif - /* SHA1 Digest */ - else if (strcasecmp(algo, (const char *)"sha1") == 0) - { - unsigned char md[SHA_DIGEST_LENGTH]; - SHA1((unsigned char *)data, strlen(data), md); - res = hexdump(md, SHA_DIGEST_LENGTH); - } +#ifndef OPENSSL_NO_MD2 + DO_HASH_IF("md2", MD2, MD2_DIGEST_LENGTH); +#endif + +#ifndef OPENSSL_NO_MD4 + DO_HASH_IF("md4", MD4, MD4_DIGEST_LENGTH); +#endif + +#ifndef OPENSSL_NO_MDC2 + DO_HASH_IF("mdc2", MDC2, MDC2_DIGEST_LENGTH); +#endif - else - { - pop_stack(); - res = malloc(29 + strlen(algo)); - sprintf(res, "hash() unknown hash type: %s.\n", algo); - error(res); +#ifndef OPENSSL_NO_RIPEMD160 + DO_HASH_IF("ripemd160", RIPEMD160, RIPEMD160_DIGEST_LENGTH); +#endif + + if (!result) { + error("hash() unknown hash type: %s", algo); } /* Pop the arguments off the stack and push the result */ - free_string_svalue(sp--); - free_string_svalue(sp); - - sp->subtype = STRING_MALLOC; - sp->u.string = res; + pop_n_elems(st_num_arg); + push_malloced_string(result); } #endif diff --git a/src/packages/db.c b/src/packages/db.c index e8bdea316..0dad8e208 100644 --- a/src/packages/db.c +++ b/src/packages/db.c @@ -579,14 +579,18 @@ int create_db_conn (void) if (!dbConnList) { dbConnList = CALLOCATE(dbConnAlloc, db_t, TAG_DB, "create_db_conn"); } else { +#ifdef PACKAGE_ASYNC pthread_mutex_lock(db_mut); +#endif dbConnList = RESIZE(dbConnList, dbConnAlloc, db_t, TAG_DB, "create_db_conn"); +#ifdef PACKAGE_ASYNC pthread_mutex_unlock(db_mut); +#endif } - while (i < dbConnAlloc) { - dbConnList[i++].flags = DB_FLAG_EMPTY; - } - } + while (i < dbConnAlloc) { + dbConnList[i++].flags = DB_FLAG_EMPTY; + } + } for (i = 0; i < dbConnAlloc; i++) { if (dbConnList[i].flags & DB_FLAG_EMPTY) { diff --git a/src/packages/debug.c b/src/packages/debug.c index c63d3d46d..7c39eb982 100644 --- a/src/packages/debug.c +++ b/src/packages/debug.c @@ -59,7 +59,7 @@ void f_thread() { DMALLOC(len + 5, TAG_TEMPORARY, "socket_write: default"); if (buf == NULL) break; - *(INT_32 *) buf = htonl((long) len); + *(uint32_t *) buf = htonl((uint32_t) len); len += 4; buf[4] = '\0'; p = buf + 4; diff --git a/src/packages/external.c b/src/packages/external.c index d7817e2b9..f6d820e11 100644 --- a/src/packages/external.c +++ b/src/packages/external.c @@ -77,7 +77,7 @@ int external_start (int which, svalue_t * args, } } - argv = CALLOCATE(n, char *, TAG_TEMPORARY, "external args"); + argv = CALLOCATE(n+1, char *, TAG_TEMPORARY, "external args"); argv[0] = cmd; diff --git a/src/packages/math.c b/src/packages/math.c index d36b8c31a..7d00d3ad0 100644 --- a/src/packages/math.c +++ b/src/packages/math.c @@ -88,10 +88,11 @@ f_atan (void) #ifdef F_SQRT void f_sqrt (void) -{ double val; +{ + LPC_FLOAT val; if(sp->type == T_NUMBER) - val = (double) sp->u.number; + val = (LPC_FLOAT) sp->u.number; else val = sp->u.real; @@ -99,7 +100,7 @@ f_sqrt (void) error("math: sqrt(x) with (x < 0.0)\n"); return; } - sp->u.real = (double) sqrt(val); + sp->u.real = (LPC_FLOAT) sqrt(val); sp->type = T_REAL; } #endif @@ -120,10 +121,10 @@ f_log (void) void f_log10 (void) { - double val; + LPC_FLOAT val; if(sp->type == T_NUMBER) - val = (double) sp->u.number; + val = (LPC_FLOAT) sp->u.number; else val = sp->u.real; @@ -140,10 +141,10 @@ f_log10 (void) void f_log2 (void) { - double val; + LPC_FLOAT val; if(sp->type == T_NUMBER) - val = (double) sp->u.number; + val = (LPC_FLOAT) sp->u.number; else val = sp->u.real; @@ -151,7 +152,7 @@ f_log2 (void) error("math: log2(x) with (x <= 0.0)\n"); return; } - sp->u.real = (double) log2((double)val); + sp->u.real = (LPC_FLOAT) log2((LPC_FLOAT)val); sp->type = T_REAL; } #endif @@ -160,15 +161,15 @@ f_log2 (void) void f_pow (void) { - double val, val2; + LPC_FLOAT val, val2; if((sp-1)->type == T_NUMBER) - val = (double) (sp-1)->u.number; + val = (LPC_FLOAT) (sp-1)->u.number; else val = (sp-1)->u.real; if(sp->type == T_NUMBER) - val2 = (double) sp->u.number; + val2 = (LPC_FLOAT) sp->u.number; else val2 = sp->u.real; @@ -206,7 +207,7 @@ f_ceil (void) #ifdef F_ROUND void f_round (void) { - sp->u.real = (double) round(sp->u.real); + sp->u.real = (LPC_FLOAT) round(sp->u.real); } #endif @@ -215,24 +216,24 @@ void f_round (void) Yes, you could use dotprod() below to implement norm(), but in the interest of speed, norm() has less cases. */ -static double norm(array_t *a) { - int len = sp->u.arr->size; - double total = 0.0; +static LPC_FLOAT norm(array_t *a) { + LPC_INT len = sp->u.arr->size; + LPC_FLOAT total = 0.0; while(len-- > 0) if(a->item[len].type == T_NUMBER) - total += SQUARE((double) a->item[len].u.number); + total += SQUARE((LPC_FLOAT) a->item[len].u.number); else if(a->item[len].type == T_REAL) total += SQUARE(a->item[len].u.real); else { return -INT_MAX + 1; } - return (double) sqrt(total); + return (LPC_FLOAT) sqrt(total); } void f_norm(void) { - double val = norm(sp->u.arr); + LPC_FLOAT val = norm(sp->u.arr); if(val == (-INT_MAX + 1)) { pop_stack(); @@ -246,10 +247,10 @@ void f_norm(void) { #endif #if defined(F_DOTPROD) | defined(F_DISTANCE) | defined(F_ANGLE) -static double vector_op(array_t *a, array_t *b, - double (*func)(const double, const double)) { - int len = a->size; - double total = 0.0; +static LPC_FLOAT vector_op(array_t *a, array_t *b, + LPC_FLOAT (*func)(const LPC_FLOAT, const LPC_FLOAT)) { + LPC_INT len = a->size; + LPC_FLOAT total = 0.0; if(b->size != len) { return -INT_MAX; @@ -258,18 +259,18 @@ static double vector_op(array_t *a, array_t *b, while(len-- > 0) { if(b->item[len].type == T_NUMBER) { if(a->item[len].type == T_NUMBER) - total += func((double) a->item[len].u.number, - (double) b->item[len].u.number); + total += func((LPC_FLOAT) a->item[len].u.number, + (LPC_FLOAT) b->item[len].u.number); else if(a->item[len].type == T_REAL) total += func(a->item[len].u.real, - (double) b->item[len].u.number); + (LPC_FLOAT) b->item[len].u.number); else { return -INT_MAX + 1; } } else if(b->item[len].type == T_REAL) { if(a->item[len].type == T_NUMBER) - total += func((double) a->item[len].u.number, + total += func((LPC_FLOAT) a->item[len].u.number, b->item[len].u.real); else if(a->item[len].type == T_REAL) @@ -288,17 +289,17 @@ static double vector_op(array_t *a, array_t *b, #endif #ifdef F_DOTPROD -static double dotprod_mult(const double a, const double b) { +static LPC_FLOAT dotprod_mult(const LPC_FLOAT a, const LPC_FLOAT b) { return a * b; } /* dot product of two vectors */ -static double dotprod(array_t *a, array_t *b) { +static LPC_FLOAT dotprod(array_t *a, array_t *b) { return vector_op(a, b, dotprod_mult); } void f_dotprod(void) { - double total = vector_op((sp-1)->u.arr, sp->u.arr, dotprod_mult); + LPC_FLOAT total = vector_op((sp-1)->u.arr, sp->u.arr, dotprod_mult); if(total == -INT_MAX) { pop_2_elems(); @@ -318,13 +319,13 @@ void f_dotprod(void) { #endif #ifdef F_DISTANCE -static double distance_mult(const double a, const double b) { +static LPC_FLOAT distance_mult(const LPC_FLOAT a, const LPC_FLOAT b) { return SQUARE(b - a); } /* The (Euclidian) distance between two points */ void f_distance(void) { - double total = vector_op((sp-1)->u.arr, sp->u.arr, distance_mult); + LPC_FLOAT total = vector_op((sp-1)->u.arr, sp->u.arr, distance_mult); if(total == -INT_MAX) { pop_2_elems(); @@ -339,13 +340,13 @@ void f_distance(void) { } pop_2_elems(); - push_real((double)sqrt(total)); + push_real((LPC_FLOAT)sqrt(total)); } #endif #ifdef F_ANGLE void f_angle(void) { - double dot, norma, normb; + LPC_FLOAT dot, norma, normb; dot = dotprod((sp-1)->u.arr, sp->u.arr); @@ -375,6 +376,6 @@ void f_angle(void) { } pop_2_elems(); - push_real((double)acos( dot / (norma * normb) )); + push_real((LPC_FLOAT)acos( dot / (norma * normb) )); } #endif diff --git a/src/packages/matrix.c b/src/packages/matrix.c index c1120476f..99504d873 100644 --- a/src/packages/matrix.c +++ b/src/packages/matrix.c @@ -42,7 +42,7 @@ void f_id_matrix (void) void f_translate (void) { array_t *matrix; - double x, y, z; + LPC_FLOAT x, y, z; Matrix current_matrix; Matrix trans_matrix; Matrix final_matrix; @@ -88,7 +88,7 @@ void f_translate (void) void f_scale (void) { array_t *matrix; - double x, y, z; + LPC_FLOAT x, y, z; Matrix current_matrix; Matrix scaling_matrix; Matrix final_matrix; @@ -133,7 +133,7 @@ void f_scale (void) void f_rotate_x (void) { array_t *matrix; - double angle; + LPC_FLOAT angle; Matrix current_matrix; Matrix rot_matrix; Matrix final_matrix; @@ -169,7 +169,7 @@ void f_rotate_x (void) void f_rotate_y (void) { array_t *matrix; - double angle; + LPC_FLOAT angle; Matrix current_matrix; Matrix rot_matrix; Matrix final_matrix; @@ -205,7 +205,7 @@ void f_rotate_y (void) void f_rotate_z (void) { array_t *matrix; - double angle; + LPC_FLOAT angle; Matrix current_matrix; Matrix rot_matrix; Matrix final_matrix; @@ -241,7 +241,7 @@ void f_rotate_z (void) void f_lookat_rotate (void) { array_t *matrix; - double x, y, z; + LPC_FLOAT x, y, z; Matrix current_matrix; Matrix lookat_matrix; int i; @@ -282,7 +282,7 @@ void f_lookat_rotate (void) void f_lookat_rotate2 (void) { array_t *matrix; - double ex, ey, ez, lx, ly, lz; + LPC_FLOAT ex, ey, ez, lx, ly, lz; Matrix current_matrix; Matrix lookat_matrix; int i, j; @@ -347,7 +347,7 @@ static void print_array (Vector * v, char * label) static Vector *normalize_array (Vector * v) { - double xx, yy, zz, mm, m; + LPC_FLOAT xx, yy, zz, mm, m; xx = v->x * v->x; yy = v->y * v->y; @@ -378,7 +378,7 @@ static Vector *points_to_array (Vector * v, Vector * pa, Vector * pb) return (v); } -void lookat_rotate (Matrix T, double x, double y, double z, Matrix M) +void lookat_rotate (Matrix T, LPC_FLOAT x, LPC_FLOAT y, LPC_FLOAT z, Matrix M) { static Vector N, V, U; static Vector ep, lp; @@ -439,7 +439,7 @@ void lookat_rotate (Matrix T, double x, double y, double z, Matrix M) #endif /* DEBUG */ } -void lookat_rotate2 (double ex, double ey, double ez, double lx, double ly, double lz, Matrix M) +void lookat_rotate2 (LPC_FLOAT ex, LPC_FLOAT ey, LPC_FLOAT ez, LPC_FLOAT lx, LPC_FLOAT ly, LPC_FLOAT lz, Matrix M) { static Vector N, V, U; static Vector ep, lp; @@ -500,7 +500,7 @@ void lookat_rotate2 (double ex, double ey, double ez, double lx, double ly, doub #endif /* DEBUG */ } -void translate_matrix (double x, double y, double z, Matrix m) +void translate_matrix (LPC_FLOAT x, LPC_FLOAT y, LPC_FLOAT z, Matrix m) { m[0] = 1.; m[1] = 0.; @@ -520,7 +520,7 @@ void translate_matrix (double x, double y, double z, Matrix m) m[15] = 1.; } -void scale_matrix (double x, double y, double z, Matrix m) +void scale_matrix (LPC_FLOAT x, LPC_FLOAT y, LPC_FLOAT z, Matrix m) { m[0] = x; m[1] = 0.; @@ -540,12 +540,12 @@ void scale_matrix (double x, double y, double z, Matrix m) m[15] = 1.; } -void rotate_x_matrix (double a, Matrix m) +void rotate_x_matrix (LPC_FLOAT a, Matrix m) { - double a_rad; - double c, s; + LPC_FLOAT a_rad; + LPC_FLOAT c, s; - a_rad = (double) (a * RADIANS_PER_DEGREE); + a_rad = (LPC_FLOAT) (a * RADIANS_PER_DEGREE); c = cos(a_rad); s = sin(a_rad); m[0] = 1.; @@ -566,12 +566,12 @@ void rotate_x_matrix (double a, Matrix m) m[15] = 1.; } -void rotate_y_matrix (double a, Matrix m) +void rotate_y_matrix (LPC_FLOAT a, Matrix m) { - double a_rad; - double c, s; + LPC_FLOAT a_rad; + LPC_FLOAT c, s; - a_rad = (double) (a * RADIANS_PER_DEGREE); + a_rad = (LPC_FLOAT) (a * RADIANS_PER_DEGREE); c = cos(a_rad); s = sin(a_rad); m[0] = c; @@ -592,12 +592,12 @@ void rotate_y_matrix (double a, Matrix m) m[15] = 1.; } -void rotate_z_matrix (double a, Matrix m) +void rotate_z_matrix (LPC_FLOAT a, Matrix m) { - double a_rad; - double c, s; + LPC_FLOAT a_rad; + LPC_FLOAT c, s; - a_rad = (double) (a * RADIANS_PER_DEGREE); + a_rad = (LPC_FLOAT) (a * RADIANS_PER_DEGREE); c = cos(a_rad); s = sin(a_rad); m[0] = c; diff --git a/src/packages/packages b/src/packages/packages deleted file mode 100644 index 1bddaf958..000000000 --- a/src/packages/packages +++ /dev/null @@ -1,2 +0,0 @@ -SRC=uids.c db.c compress.c math.c develop.c external.c contrib.c sockets.c async.c dwlib.c -OBJ=uids.$(O) db.$(O) compress.$(O) math.$(O) develop.$(O) external.$(O) contrib.$(O) sockets.$(O) async.$(O) dwlib.$(O) diff --git a/src/packages/sha1.c b/src/packages/sha1.c index 0c4381b87..a4f48269f 100755 --- a/src/packages/sha1.c +++ b/src/packages/sha1.c @@ -1,134 +1,131 @@ -/** - * sha1.c: this file provides the sha1 hashing algorithm - * based in part on code in the public domain by Niyaz PK. - * -- coded by Ajandurah@Demonslair 21/02/08 - */ - -#include - -#ifdef LATTICE -#include "/lpc_incl.h" -#else -#include "../lpc_incl.h" -#include "../efun_protos.h" -#endif - -#define rotateleft(x,n) ((x<>(32-n))) -#define rotateright(x,n) ((x>>n) | (x<<(32-n))) - -#ifdef F_SHA1 -void f_sha1(void) -{ - unsigned long int h0,h1,h2,h3,h4,a,b,c,d,e,f,k,temp; - int i, j, m; - - h0 = 0x67452301; - h1 = 0xEFCDAB89; - h2 = 0x98BADCFE; - h3 = 0x10325476; - h4 = 0xC3D2E1F0; - - unsigned char *str; - str = (unsigned char *)malloc(SVALUE_STRLEN(sp)+100); - - strcpy((char *)str, (const char *)sp->u.string); - - int current_length = strlen((const char *)str); - int original_length = current_length; - str[current_length] = 0x80; - str[current_length + 1] = '\0'; - - char ic = str[current_length]; - current_length++; - - int ib = current_length % 64; - if (ib < 56) - ib = 56 - ib; - else - ib = 120 - ib; - - for (i=0; i>(32-(n)))) + +#ifdef F_SHA1 +static inline void sha1_hash_block( + const unsigned char *block, + uint32_t *h0, + uint32_t *h1, + uint32_t *h2, + uint32_t *h3, + uint32_t *h4) +{ + uint32_t a = *h0, b = *h1, c = *h2, d = *h3, e = *h4, tmp; + uint32_t word[80]; + int i, f, k; + + for (i = 0; i < 16; i++) { + word[i] = + block[i * 4 + 0] << 24 | + block[i * 4 + 1] << 16 | + block[i * 4 + 2] << 8 | + block[i * 4 + 3] << 0; + } + + for (i = 16; i < 80; i++) { + word[i] = rotateleft((word[i - 3] ^ word[i - 8] ^ word[i - 14] ^ word[i - 16]), 1); + } + + for (i = 0; i < 80; i++) { + if (i < 20) { + f = (b & c) | ((~b) & d); + k = 0x5A827999; + } else if (i < 40) { + f = b ^ c ^ d; + k = 0x6ED9EBA1; + } else if (i < 60) { + f = (b & c) | (b & d) | (c & d); + k = 0x8F1BBCDC; + } else { + f = b ^ c ^ d; + k = 0xCA62C1D6; + } + + tmp = (rotateleft(a, 5) + f + e + k + word[i]) & 0xFFFFFFFF; + e = d; + d = c; + c = rotateleft(b, 30); + b = a; + a = tmp; + } + + *h0 += a; + *h1 += b; + *h2 += c; + *h3 += d; + *h4 += e; +} + +void f_sha1(void) +{ + uint32_t h0, h1, h2, h3, h4; + const unsigned char *str; + unsigned char final[128] = { 0 }; + int input_length, final_length, i; + +#ifndef NO_BUFFER_TYPE + if (sp->type == T_BUFFER) { + str = (const unsigned char *)sp->u.buf->item; + input_length = sp->u.buf->size; + } else { +#endif + str = (const unsigned char *)sp->u.string; + input_length = SVALUE_STRLEN(sp); +#ifndef NO_BUFFER_TYPE + } +#endif + + i = input_length % 64; + + /* Copy partial block into 'final' */ + memcpy(final, str + input_length - i, i); + + /* Terminate with a '1' bit, then decide whether an additional + * block is needed. + */ + final[i] = 0x80; + final_length = (i > 55) ? 128 : 64; + + /* Write the 64-bit bit count in big-endian order */ + final[final_length - 5] = (input_length >> 29) & 0x7; + final[final_length - 4] = (input_length >> 21) & 0xff; + final[final_length - 3] = (input_length >> 13) & 0xff; + final[final_length - 2] = (input_length >> 5) & 0xff; + final[final_length - 1] = (input_length << 3) & 0xff; + + /* Trim the extra bytes off of the input length so that + * input rounds off to the nearest complete block + */ + input_length -= i; + + /* Initialize the hash */ + h0 = 0x67452301; + h1 = 0xEFCDAB89; + h2 = 0x98BADCFE; + h3 = 0x10325476; + h4 = 0xC3D2E1F0; + + /* Hash all complete input blocks */ + for (i = 0; i < input_length; i += 64) { + sha1_hash_block(str + i, &h0, &h1, &h2, &h3, &h4); + } + + /* Hash the 1 or 2 final padded blocks */ + sha1_hash_block(final, &h0, &h1, &h2, &h3, &h4); + if (final_length == 128) { + sha1_hash_block(final + 64, &h0, &h1, &h2, &h3, &h4); + } + + sprintf((char *)final, "%08x%08x%08x%08x%08x", h0, h1, h2, h3, h4); + pop_stack(); + push_malloced_string(string_copy((char *)final, "f_sha1")); +} +#endif diff --git a/src/packages/sha1_spec.c b/src/packages/sha1_spec.c index 7d57ed7af..b645b70ec 100755 --- a/src/packages/sha1_spec.c +++ b/src/packages/sha1_spec.c @@ -1,3 +1,3 @@ #include "spec.h" -string sha1(string); +string sha1(string|buffer); diff --git a/src/patchlevel.h b/src/patchlevel.h index ffb30cb91..be2cd7249 100644 --- a/src/patchlevel.h +++ b/src/patchlevel.h @@ -1 +1 @@ -#define PATCH_LEVEL "v2.24" +#define PATCH_LEVEL "v2.27" diff --git a/src/portability.h b/src/portability.h index a5bd8b24a..28af2ded3 100644 --- a/src/portability.h +++ b/src/portability.h @@ -15,6 +15,11 @@ #ifndef PORTABILITY_H #define PORTABILITY_H +/* CYGWIN with old POSIX needs this. */ +#ifdef __CYGWIN__ +#undef __STRICT_ANSI__ +#endif + /* define this if you have an Ultrix system that the driver won't otherwise compile on (doesn't seem to be needed for DECstations). */ @@ -120,7 +125,7 @@ #define SIGNAL_FUNC_TAKES_INT defined(_AIX) || defined(NeXT) \ || defined(_SEQUENT_) || defined(SVR4) \ || defined(__386BSD__) || defined(apollo) || defined(cray) \ - || defined(SunOS_5) || defined(__bsdi__) || defined(linux) + || defined(SunOS_5) || defined(__bsdi__) || defined(__linux__) /* Define MEMPAGESIZE to be some value if you wish to use BSDMALLOC * _and_ your system does not support the getpagesize() system call. @@ -131,7 +136,7 @@ * * FIXME: configure should check for getpagesize(). */ -#if !defined(linux) && !defined(__386BSD__) && !defined(__FreeBSD__) \ +#if !defined(__linux__) && !defined(__386BSD__) && !defined(__FreeBSD__) \ && !defined(OSF) && !defined(SunOS_4) && !defined(sgi) # ifdef _SC_PAGE_SIZE # define MEMPAGESIZE sysconf(_SC_PAGE_SIZE) @@ -151,7 +156,7 @@ /* otherwise make_func will break */ #ifndef _FUNC_SPEC_ /* these should be obtained from .h files when Linux .h structure stabilizes */ -# if defined(linux) || defined(_M_UNIX) +# if defined(__linux__) || defined(_M_UNIX) /* This has FD_SETSIZE on some Linux's (Linuces?) */ # include # include diff --git a/src/posix_timers.c b/src/posix_timers.c new file mode 100644 index 000000000..1f846950f --- /dev/null +++ b/src/posix_timers.c @@ -0,0 +1,105 @@ +#include "std.h" +#include +#include +#include "comm.h" +#include "posix_timers.h" +#include "eval.h" +#include "backend.h" + +static timer_t eval_timer_id, hb_timer_id; +/* + * SIGALRM handler. + */ +#ifdef SIGNAL_FUNC_TAKES_INT +void sigalrm_handler (int sig, siginfo_t *si, void *uc) +#else +void sigalrm_handler() +#endif +{ +#ifndef POSIX_TIMERS + outoftime = 1; +#else + if(!si->si_value.sival_ptr) + outoftime = 1; + else{ + if(si->si_value.sival_ptr == call_heart_beat){ + time_for_hb++; + } + } +#endif +} /* sigalrm_handler() */ +#ifdef POSIX_TIMERS +/* Called by main() to initialize all timers (currently only eval_cost) */ +void init_posix_timers(void) +{ + struct sigevent sev; + struct sigaction sa; + int i; + + /* This mimics the behavior of setitimer in uvalarm.c */ + memset(&sev, 0, sizeof(sev)); + sev.sigev_signo = SIGVTALRM; + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_value.sival_ptr = NULL; +#ifndef __CYGWIN__ + i = timer_create(CLOCK_THREAD_CPUTIME_ID, &sev, &eval_timer_id); +#else + i = timer_create(CLOCK_REALTIME, &sev, &eval_timer_id); +#endif + if (i < 0) { + perror("init_posix_timers: timer_create"); + exit(-1); + } + + sa.sa_sigaction = sigalrm_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + + i = sigaction(SIGVTALRM, &sa, NULL); + if (i < 0) { + perror("init_posix_timers: sigaction"); + exit(-1); + } + double interv = HEARTBEAT_INTERVAL; + struct itimerspec it; + it.it_interval.tv_sec = (int)interv; + it.it_interval.tv_nsec = (interv-(double)it.it_interval.tv_sec)*1000000000; + it.it_value.tv_sec = 0; + it.it_value.tv_nsec = 1; + sev.sigev_value.sival_ptr = call_heart_beat; + i = timer_create(CLOCK_MONOTONIC, &sev, &hb_timer_id); + if (i < 0) { + perror("init_posix_timers: timer_create"); + exit(-1); + } + timer_settime(hb_timer_id, 0, &it, NULL); +} + +/* Set the eval_timer to the given number of microseconds */ +void posix_eval_timer_set(int micros) +{ + struct itimerspec it; + + it.it_interval.tv_sec = 0; + it.it_interval.tv_nsec = 0; + + it.it_value.tv_sec = micros / 1000000; + it.it_value.tv_nsec = micros % 1000000 * 1000; + + timer_settime(eval_timer_id, 0, &it, NULL); +} + +/* Return the number of microseconds remaining on the eval_timer */ +int posix_eval_timer_get(void) +{ + struct itimerspec it; + + if (timer_gettime(eval_timer_id, &it) < 0) { + return 100; + } + + return it.it_value.tv_sec * 1000000 + it.it_value.tv_nsec / 1000; +} + + +#endif diff --git a/src/posix_timers.h b/src/posix_timers.h new file mode 100644 index 000000000..0c8ffdf6b --- /dev/null +++ b/src/posix_timers.h @@ -0,0 +1,14 @@ +#ifndef POSIX_TIMERS_H +#define POSIX_TIMERS_H +#ifdef SIGNAL_FUNC_TAKES_INT +void sigalrm_handler (int, siginfo_t *, void *); +#else +void sigalrm_handler (void); +#endif +#ifdef POSIX_TIMERS +void init_posix_timers(void); +void posix_eval_timer_set(int micros); +int posix_eval_timer_get(void); +#endif + +#endif diff --git a/src/preprocess.c b/src/preprocess.c index b2bc02e35..f126aa37c 100644 --- a/src/preprocess.c +++ b/src/preprocess.c @@ -1,7 +1,7 @@ /* WARNING: This file is #included into two places, since the definition of malloc() differs. Be careful. */ -static int cond_get_exp (int); +static long cond_get_exp (int); static void handle_cond (int); #ifndef LEXER @@ -111,7 +111,7 @@ static void handle_elif() if (iftop) { if (iftop->state == EXPECT_ELSE) { /* last cond was false... */ - int cond; + long cond; ifstate_t *p = iftop; /* pop previous condition */ @@ -206,10 +206,10 @@ static char optab2[] = #define optab1 (_optab-' ') -static int cond_get_exp (int priority) +static long cond_get_exp (int priority) { int c; - int value, value2, x; + long value, value2, x; #ifdef LEXER do diff --git a/src/program.h b/src/program.h index 79afa882e..a2f9e8986 100644 --- a/src/program.h +++ b/src/program.h @@ -201,7 +201,7 @@ typedef struct program_s { unsigned short last_inherited; unsigned PROG_REF_TYPE ref; /* Reference count */ unsigned short func_ref; -#ifdef DEBUG +#ifdef DEBUGMALLOC_EXTENSIONS int extra_ref; /* Used to verify ref count */ int extra_func_ref; #endif diff --git a/src/rc.c b/src/rc.c index 2354b6b02..da378181a 100644 --- a/src/rc.c +++ b/src/rc.c @@ -25,49 +25,49 @@ static int scan_config_line (const char *, void *, int); static void config_init (void); /* don't ask */ static void config_init() { - int i; + int i; - for (i = 0; i < NUM_CONFIG_INTS; i++) { - config_int[i] = 0; - } - for (i = 0; i < NUM_CONFIG_STRS; i++) { - config_str[i] = 0; - } + for (i = 0; i < NUM_CONFIG_INTS; i++) { + config_int[i] = 0; + } + for (i = 0; i < NUM_CONFIG_STRS; i++) { + config_str[i] = 0; + } } static void read_config_file (FILE * file) { - char str[MAX_LINE_LENGTH * 4]; - int size = 2, len, tmp; - char *p; - - buff_size = MAX_LINE_LENGTH * (NUM_CONFIG_INTS + 1) * (NUM_CONFIG_STRS + 1); - p = buff = CALLOCATE(buff_size, char, TAG_CONFIG, "read_config_file: 1"); - *p++ = '\n'; - - while (1) { - if (fgets(str, MAX_LINE_LENGTH * 4, file) == NULL) - break; - len = strlen(str); /* ACK! */ - if (len > MAX_LINE_LENGTH) { - fprintf(stderr, "*Error in config file: line too long:\n%s...\n", str); - exit(-1); - } - if (str[0] != '#' && str[0] != '\n') { - size += len + 1; - if (size > buff_size) { - tmp = p - buff; - buff = RESIZE(buff, buff_size *= 2, char, - TAG_CONFIG, "read_config_file: 2"); - p = buff + tmp; - } - strncpy(p, str, len); - p += len; - *p++ = '\n'; + char str[MAX_LINE_LENGTH * 4]; + int size = 2, len, tmp; + char *p; + + buff_size = MAX_LINE_LENGTH * (NUM_CONFIG_INTS + 1) * (NUM_CONFIG_STRS + 1); + p = buff = CALLOCATE(buff_size, char, TAG_CONFIG, "read_config_file: 1"); + *p++ = '\n'; + + while (1) { + if (fgets(str, MAX_LINE_LENGTH * 4, file) == NULL) + break; + len = strlen(str); /* ACK! */ + if (len > MAX_LINE_LENGTH) { + fprintf(stderr, "*Error in config file: line too long:\n%s...\n", str); + exit(-1); + } + if (str[0] != '#' && str[0] != '\n') { + size += len + 1; + if (size > buff_size) { + tmp = p - buff; + buff = RESIZE(buff, buff_size *= 2, char, + TAG_CONFIG, "read_config_file: 2"); + p = buff + tmp; + } + strncpy(p, str, len); + p += len; + *p++ = '\n'; + } } - } - *p = 0; + *p = 0; } @@ -82,302 +82,302 @@ static void read_config_file (FILE * file) -1 : warn if missing */ static int scan_config_line (const char * fmt, void * dest, int required) { - char *tmp, *end; - char missing_line[MAX_LINE_LENGTH]; + char *tmp, *end; + char missing_line[MAX_LINE_LENGTH]; - /* zero the destination. It is either a pointer to an int or a char + /* zero the destination. It is either a pointer to an int or a char buffer, so this will work */ - *((int *)dest) = 0; - tmp = buff; - while (tmp) { - while ((tmp = (char *) strchr(tmp, '\n'))) { - if (*(++tmp) == fmt[0]) break; - } - /* don't allow sscanf() to scan to next line for blank entries */ - end = (tmp ? strchr(tmp, '\n') : 0); - if (end) *end = '\0'; - if (tmp && sscanf(tmp, fmt, dest) == 1) { - if (end) *end = '\n'; - break; + *((int *)dest) = 0; + tmp = buff; + while (tmp) { + while ((tmp = (char *) strchr(tmp, '\n'))) { + if (*(++tmp) == fmt[0]) break; + } + /* don't allow sscanf() to scan to next line for blank entries */ + end = (tmp ? strchr(tmp, '\n') : 0); + if (end) *end = '\0'; + if (tmp && sscanf(tmp, fmt, dest) == 1) { + if (end) *end = '\n'; + break; + } + if (end) *end = '\n'; } - if (end) *end = '\n'; - } - if (!tmp) { - strcpy(missing_line, fmt); - tmp = (char *) strchr(missing_line, ':'); - *tmp = '\0'; - if (required == -1) { - fprintf(stderr, "*Warning: Missing line in config file:\n\t%s\n", - missing_line); - return 0; + if (!tmp) { + strcpy(missing_line, fmt); + tmp = (char *) strchr(missing_line, ':'); + *tmp = '\0'; + if (required == -1) { + fprintf(stderr, "*Warning: Missing line in config file:\n\t%s\n", + missing_line); + return 0; + } + if (!required) return 0; + fprintf(stderr, "*Error in config file. Missing line:\n\t%s\n", + missing_line); + exit(-1); } - if (!required) return 0; - fprintf(stderr, "*Error in config file. Missing line:\n\t%s\n", - missing_line); - exit(-1); - } - return 1; + return 1; } #if 0 static char *process_config_string(char *str) { - char *p = str; - char *q; - int n; - - while (*p && isspace(*p)) - p++; - n = strlen(p); - if (!n) return alloc_cstring("", "config_file: blank string"); - - q = p + n - 1; - while (q > p && isspace(*q)) - q--; - q[1] = 0; - return alloc_cstring(p, "process_config_string()"); + char *p = str; + char *q; + int n; + + while (*p && isspace(*p)) + p++; + n = strlen(p); + if (!n) return alloc_cstring("", "config_file: blank string"); + + q = p + n - 1; + while (q > p && isspace(*q)) + q--; + q[1] = 0; + return alloc_cstring(p, "process_config_string()"); } #endif void set_defaults (char * filename) { - FILE *def; - char defaults[SMALL_STRING_SIZE]; - char *p; - char tmp[MAX_LINE_LENGTH]; - char kind[MAX_LINE_LENGTH]; - int i, port, port_start = 0; - - max_string_length = 120; /* needed for string_copy() below */ - config_init(); - def = fopen(filename, "r"); - if (def) { - fprintf(stderr, "using config file: %s\n", filename); - } else { - sprintf(defaults, "%s/%s", CONFIG_FILE_DIR, filename); - def = fopen(defaults, "r"); + FILE *def; + char defaults[SMALL_STRING_SIZE]; + char *p; + char tmp[MAX_LINE_LENGTH]; + char kind[MAX_LINE_LENGTH]; + int i, port, port_start = 0; + + max_string_length = 120; /* needed for string_copy() below */ + config_init(); + def = fopen(filename, "r"); if (def) { - fprintf(stderr, "using config file: %s\n", defaults); + fprintf(stderr, "using config file: %s\n", filename); + } else { + sprintf(defaults, "%s/%s", CONFIG_FILE_DIR, filename); + def = fopen(defaults, "r"); + if (def) { + fprintf(stderr, "using config file: %s\n", defaults); + } } - } - if (!def) { - fprintf(stderr, "*Error: couldn't find or open config file: '%s'\n", filename); - exit(-1); - } - read_config_file(def); - - scan_config_line("global include file : %[^\n]", tmp, 0); - p = CONFIG_STR(__GLOBAL_INCLUDE_FILE__) = alloc_cstring(tmp, "config file: gif"); - - /* check if the global include file is quoted */ - if (*p && *p != '"' && *p != '<') { - char *ptr; - - fprintf(stderr, "Missing '\"' or '<' around global include file name; adding quotes.\n"); - for (ptr = p; *ptr; ptr++) - ; - ptr[2] = 0; - ptr[1] = '"'; - while (ptr > p) { - *ptr = ptr[-1]; - ptr--; + if (!def) { + fprintf(stderr, "*Error: couldn't find or open config file: '%s'\n", filename); + exit(-1); } - *p = '"'; - } - - scan_config_line("name : %[^\n]", tmp, 1); - CONFIG_STR(__MUD_NAME__) = alloc_cstring(tmp, "config file: mn"); - scan_config_line("address server ip : %[^\n]", tmp, 0); - CONFIG_STR(__ADDR_SERVER_IP__) = alloc_cstring(tmp, "config file: asi"); - - scan_config_line("mudlib directory : %[^\n]", tmp, 1); - CONFIG_STR(__MUD_LIB_DIR__) = alloc_cstring(tmp, "config file: mld"); - scan_config_line("binary directory : %[^\n]", tmp, 1); - CONFIG_STR(__BIN_DIR__) = alloc_cstring(tmp, "config file: bd"); - - scan_config_line("log directory : %[^\n]", tmp, 1); - CONFIG_STR(__LOG_DIR__) = alloc_cstring(tmp, "config file: ld"); - scan_config_line("include directories : %[^\n]", tmp, 1); - CONFIG_STR(__INCLUDE_DIRS__) = alloc_cstring(tmp, "config file: id"); - scan_config_line("master file : %[^\n]", tmp, 1); - CONFIG_STR(__MASTER_FILE__) = alloc_cstring(tmp, "config file: mf"); - scan_config_line("simulated efun file : %[^\n]", tmp, 0); - CONFIG_STR(__SIMUL_EFUN_FILE__) = alloc_cstring(tmp, "config file: sef"); - scan_config_line("swap file : %[^\n]", tmp, 1); - CONFIG_STR(__SWAP_FILE__) = alloc_cstring(tmp, "config file: sf"); - scan_config_line("debug log file : %[^\n]", tmp, -1); - CONFIG_STR(__DEBUG_LOG_FILE__) = alloc_cstring(tmp, "config file: dlf"); - - scan_config_line("default error message : %[^\n]", tmp, 0); - CONFIG_STR(__DEFAULT_ERROR_MESSAGE__) = alloc_cstring(tmp, "config file: dem"); - scan_config_line("default fail message : %[^\n]", tmp, 0); - CONFIG_STR(__DEFAULT_FAIL_MESSAGE__) = alloc_cstring(tmp, "config file: dfm"); - - scan_config_line("mud ip : %[^\n]", tmp, 0); - CONFIG_STR(__MUD_IP__) = alloc_cstring(tmp, "config file: mi"); - - if (scan_config_line("fd6 kind : %[^\n]", tmp, 0)) { - if (!strcasecmp(tmp, "telnet")) - FD6_KIND = PORT_TELNET; - else if (!strcasecmp(tmp, "mud")) - FD6_KIND = PORT_MUD; - else if (!strcasecmp(tmp, "ascii")) - FD6_KIND = PORT_ASCII; - else if (!strcasecmp(tmp, "binary")) - FD6_KIND = PORT_BINARY; - else { - fprintf(stderr, "Unknown port type for fd6 kind. fd6 support disabled.\n"); - FD6_KIND = PORT_UNDEFINED; + read_config_file(def); + + scan_config_line("global include file : %[^\n]", tmp, 0); + p = CONFIG_STR(__GLOBAL_INCLUDE_FILE__) = alloc_cstring(tmp, "config file: gif"); + + /* check if the global include file is quoted */ + if (*p && *p != '"' && *p != '<') { + char *ptr; + + fprintf(stderr, "Missing '\"' or '<' around global include file name; adding quotes.\n"); + for (ptr = p; *ptr; ptr++) + ; + ptr[2] = 0; + ptr[1] = '"'; + while (ptr > p) { + *ptr = ptr[-1]; + ptr--; + } + *p = '"'; } - } else { - FD6_KIND = PORT_UNDEFINED; - } - if (scan_config_line("port number : %d\n", &CONFIG_INT(__MUD_PORT__), 0)) { - external_port[0].port = PORTNO; - external_port[0].kind = PORT_TELNET; - port_start = 1; - } + scan_config_line("name : %[^\n]", tmp, 1); + CONFIG_STR(__MUD_NAME__) = alloc_cstring(tmp, "config file: mn"); + scan_config_line("address server ip : %[^\n]", tmp, 0); + CONFIG_STR(__ADDR_SERVER_IP__) = alloc_cstring(tmp, "config file: asi"); + + scan_config_line("mudlib directory : %[^\n]", tmp, 1); + CONFIG_STR(__MUD_LIB_DIR__) = alloc_cstring(tmp, "config file: mld"); + scan_config_line("binary directory : %[^\n]", tmp, 1); + CONFIG_STR(__BIN_DIR__) = alloc_cstring(tmp, "config file: bd"); + + scan_config_line("log directory : %[^\n]", tmp, 1); + CONFIG_STR(__LOG_DIR__) = alloc_cstring(tmp, "config file: ld"); + scan_config_line("include directories : %[^\n]", tmp, 1); + CONFIG_STR(__INCLUDE_DIRS__) = alloc_cstring(tmp, "config file: id"); + + scan_config_line("master file : %[^\n]", tmp, 1); + CONFIG_STR(__MASTER_FILE__) = alloc_cstring(tmp, "config file: mf"); + scan_config_line("simulated efun file : %[^\n]", tmp, 0); + CONFIG_STR(__SIMUL_EFUN_FILE__) = alloc_cstring(tmp, "config file: sef"); + scan_config_line("swap file : %[^\n]", tmp, 1); + CONFIG_STR(__SWAP_FILE__) = alloc_cstring(tmp, "config file: sf"); + scan_config_line("debug log file : %[^\n]", tmp, -1); + CONFIG_STR(__DEBUG_LOG_FILE__) = alloc_cstring(tmp, "config file: dlf"); + CONFIG_STR(__PLACEHOLDER1__) = alloc_cstring("__placeholder", "config file: placeholder"); + scan_config_line("default error message : %[^\n]", tmp, 0); + CONFIG_STR(__DEFAULT_ERROR_MESSAGE__) = alloc_cstring(tmp, "config file: dem"); + scan_config_line("default fail message : %[^\n]", tmp, 0); + CONFIG_STR(__DEFAULT_FAIL_MESSAGE__) = alloc_cstring(tmp, "config file: dfm"); + + scan_config_line("mud ip : %[^\n]", tmp, 0); + CONFIG_STR(__MUD_IP__) = alloc_cstring(tmp, "config file: mi"); + + if (scan_config_line("fd6 kind : %[^\n]", tmp, 0)) { + if (!strcasecmp(tmp, "telnet")) + FD6_KIND = PORT_TELNET; + else if (!strcasecmp(tmp, "mud")) + FD6_KIND = PORT_MUD; + else if (!strcasecmp(tmp, "ascii")) + FD6_KIND = PORT_ASCII; + else if (!strcasecmp(tmp, "binary")) + FD6_KIND = PORT_BINARY; + else { + fprintf(stderr, "Unknown port type for fd6 kind. fd6 support disabled.\n"); + FD6_KIND = PORT_UNDEFINED; + } + } else { + FD6_KIND = PORT_UNDEFINED; + } - scan_config_line("address server port : %d\n", - &CONFIG_INT(__ADDR_SERVER_PORT__), 0); + if (scan_config_line("port number : %d\n", &CONFIG_INT(__MUD_PORT__), 0)) { + external_port[0].port = PORTNO; + external_port[0].kind = PORT_TELNET; + port_start = 1; + } + + scan_config_line("address server port : %d\n", + &CONFIG_INT(__ADDR_SERVER_PORT__), 0); - scan_config_line("fd6 port : %d\n", &CONFIG_INT(__FD6_PORT__), 0); + scan_config_line("fd6 port : %d\n", &CONFIG_INT(__FD6_PORT__), 0); - scan_config_line("time to clean up : %d\n", - &CONFIG_INT(__TIME_TO_CLEAN_UP__), 1); - scan_config_line("time to reset : %d\n", - &CONFIG_INT(__TIME_TO_RESET__), 1); - scan_config_line("time to swap : %d\n", - &CONFIG_INT(__TIME_TO_SWAP__), 1); + scan_config_line("time to clean up : %d\n", + &CONFIG_INT(__TIME_TO_CLEAN_UP__), 1); + scan_config_line("time to reset : %d\n", + &CONFIG_INT(__TIME_TO_RESET__), 1); + scan_config_line("time to swap : %d\n", + &CONFIG_INT(__TIME_TO_SWAP__), 1); #if 0 - /* - * not currently used...see options.h - */ - scan_config_line("evaluator stack size : %d\n", - &CONFIG_INT(__EVALUATOR_STACK_SIZE__), 0); - scan_config_line("maximum local variables : %d\n", - &CONFIG_INT(__MAX_LOCAL_VARIABLES__), 0); - scan_config_line("maximum call depth : %d\n", - &CONFIG_INT(__MAX_CALL_DEPTH__), 0); - scan_config_line("living hash table size : %d\n", - &CONFIG_INT(__LIVING_HASH_TABLE_SIZE__), 0); + /* + * not currently used...see options.h + */ + scan_config_line("evaluator stack size : %d\n", + &CONFIG_INT(__EVALUATOR_STACK_SIZE__), 0); + scan_config_line("maximum local variables : %d\n", + &CONFIG_INT(__MAX_LOCAL_VARIABLES__), 0); + scan_config_line("maximum call depth : %d\n", + &CONFIG_INT(__MAX_CALL_DEPTH__), 0); + scan_config_line("living hash table size : %d\n", + &CONFIG_INT(__LIVING_HASH_TABLE_SIZE__), 0); #endif - scan_config_line("inherit chain size : %d\n", - &CONFIG_INT(__INHERIT_CHAIN_SIZE__), 1); - scan_config_line("maximum evaluation cost : %d\n", - &CONFIG_INT(__MAX_EVAL_COST__), 1); + scan_config_line("inherit chain size : %d\n", + &CONFIG_INT(__INHERIT_CHAIN_SIZE__), 1); + scan_config_line("maximum evaluation cost : %d\n", + &CONFIG_INT(__MAX_EVAL_COST__), 1); - scan_config_line("maximum array size : %d\n", - &CONFIG_INT(__MAX_ARRAY_SIZE__), 1); + scan_config_line("maximum array size : %d\n", + &CONFIG_INT(__MAX_ARRAY_SIZE__), 1); #ifndef NO_BUFFER_TYPE - scan_config_line("maximum buffer size : %d\n", - &CONFIG_INT(__MAX_BUFFER_SIZE__), 1); + scan_config_line("maximum buffer size : %d\n", + &CONFIG_INT(__MAX_BUFFER_SIZE__), 1); #endif - scan_config_line("maximum mapping size : %d\n", - &CONFIG_INT(__MAX_MAPPING_SIZE__), 1); - scan_config_line("maximum string length : %d\n", - &CONFIG_INT(__MAX_STRING_LENGTH__), 1); - scan_config_line("maximum bits in a bitfield : %d\n", - &CONFIG_INT(__MAX_BITFIELD_BITS__), 1); - - scan_config_line("maximum byte transfer : %d\n", - &CONFIG_INT(__MAX_BYTE_TRANSFER__), 1); - scan_config_line("maximum read file size : %d\n", - &CONFIG_INT(__MAX_READ_FILE_SIZE__), 1); - - scan_config_line("reserved size : %d\n", - &CONFIG_INT(__RESERVED_MEM_SIZE__), 0); - - scan_config_line("hash table size : %d\n", - &CONFIG_INT(__SHARED_STRING_HASH_TABLE_SIZE__), 1); - scan_config_line("object table size : %d\n", - &CONFIG_INT(__OBJECT_HASH_TABLE_SIZE__), 1); - - /* check for ports */ - if (port_start == 1) { - if (scan_config_line("external_port_1 : %[^\n]", tmp, 0)) { - int port = CONFIG_INT(__MUD_PORT__); - fprintf(stderr, "Warning: external_port_1 already defined to be 'telnet %i' by the line\n 'port number : %i'; ignoring the line 'external_port_1 : %s'\n", port, port, tmp); + scan_config_line("maximum mapping size : %d\n", + &CONFIG_INT(__MAX_MAPPING_SIZE__), 1); + scan_config_line("maximum string length : %d\n", + &CONFIG_INT(__MAX_STRING_LENGTH__), 1); + scan_config_line("maximum bits in a bitfield : %d\n", + &CONFIG_INT(__MAX_BITFIELD_BITS__), 1); + + scan_config_line("maximum byte transfer : %d\n", + &CONFIG_INT(__MAX_BYTE_TRANSFER__), 1); + scan_config_line("maximum read file size : %d\n", + &CONFIG_INT(__MAX_READ_FILE_SIZE__), 1); + + scan_config_line("reserved size : %d\n", + &CONFIG_INT(__RESERVED_MEM_SIZE__), 0); + + scan_config_line("hash table size : %d\n", + &CONFIG_INT(__SHARED_STRING_HASH_TABLE_SIZE__), 1); + scan_config_line("object table size : %d\n", + &CONFIG_INT(__OBJECT_HASH_TABLE_SIZE__), 1); + + /* check for ports */ + if (port_start == 1) { + if (scan_config_line("external_port_1 : %[^\n]", tmp, 0)) { + int port = CONFIG_INT(__MUD_PORT__); + fprintf(stderr, "Warning: external_port_1 already defined to be 'telnet %i' by the line\n 'port number : %i'; ignoring the line 'external_port_1 : %s'\n", port, port, tmp); + } } - } - for (i = port_start; i < 5; i++) { - external_port[i].kind = 0; - external_port[i].fd = -1; - sprintf(kind, "external_port_%i : %%[^\n]", i + 1); - if (scan_config_line(kind, tmp, 0)) { - if (sscanf(tmp, "%s %d", kind, &port) == 2) { - external_port[i].port = port; - if (!strcmp(kind, "telnet")) - external_port[i].kind = PORT_TELNET; - else - if (!strcmp(kind, "binary")) { + for (i = port_start; i < 5; i++) { + external_port[i].kind = 0; + external_port[i].fd = -1; + sprintf(kind, "external_port_%i : %%[^\n]", i + 1); + if (scan_config_line(kind, tmp, 0)) { + if (sscanf(tmp, "%s %d", kind, &port) == 2) { + external_port[i].port = port; + if (!strcmp(kind, "telnet")) + external_port[i].kind = PORT_TELNET; + else if (!strcmp(kind, "binary")) { #ifdef NO_BUFFER_TYPE - fprintf(stderr, "binary ports unavailable with NO_BUFFER_TYPE defined.\n"); - exit(-1); + fprintf(stderr, "binary ports unavailable with NO_BUFFER_TYPE defined.\n"); + exit(-1); #endif - external_port[i].kind = PORT_BINARY; - } else - if (!strcmp(kind, "ascii")) - external_port[i].kind = PORT_ASCII; - else - if (!strcmp(kind, "MUD")) - external_port[i].kind = PORT_MUD; - else - { - fprintf(stderr, "Unknown kind of external port: %s\n", - kind); - exit(-1); + external_port[i].kind = PORT_BINARY; + } else if (!strcmp(kind, "ascii")) + external_port[i].kind = PORT_ASCII; + else if (!strcmp(kind, "MUD")) + external_port[i].kind = PORT_MUD; + else if(!strcmp(kind, "websocket")) + external_port[i].kind = PORT_WEBSOCKET; + else + { + fprintf(stderr, "Unknown kind of external port: %s\n", + kind); + exit(-1); + } + } else { + fprintf(stderr, "Syntax error in port specification\n"); + exit(-1); + } } - } else { - fprintf(stderr, "Syntax error in port specification\n"); - exit(-1); - } } - } #ifdef PACKAGE_EXTERNAL - /* check for commands */ - for (i = 0; i < NUM_EXTERNAL_CMDS; i++) { - sprintf(kind, "external_cmd_%i : %%[^\n]", i + 1); - if (scan_config_line(kind, tmp, 0)) - external_cmd[i] = alloc_cstring(tmp, "external cmd"); - else - external_cmd[i] = 0; - } + /* check for commands */ + for (i = 0; i < NUM_EXTERNAL_CMDS; i++) { + sprintf(kind, "external_cmd_%i : %%[^\n]", i + 1); + if (scan_config_line(kind, tmp, 0)) + external_cmd[i] = alloc_cstring(tmp, "external cmd"); + else + external_cmd[i] = 0; + } #endif - FREE(buff); - fclose(def); + FREE(buff); + fclose(def); - /* - * from options.h - */ - config_int[__EVALUATOR_STACK_SIZE__ - BASE_CONFIG_INT] = CFG_EVALUATOR_STACK_SIZE; - config_int[__MAX_LOCAL_VARIABLES__ - BASE_CONFIG_INT] = CFG_MAX_LOCAL_VARIABLES; - config_int[__MAX_CALL_DEPTH__ - BASE_CONFIG_INT] = CFG_MAX_CALL_DEPTH; - config_int[__LIVING_HASH_TABLE_SIZE__ - BASE_CONFIG_INT] = CFG_LIVING_HASH_SIZE; + /* + * from options.h + */ + config_int[__EVALUATOR_STACK_SIZE__ - BASE_CONFIG_INT] = CFG_EVALUATOR_STACK_SIZE; + config_int[__MAX_LOCAL_VARIABLES__ - BASE_CONFIG_INT] = CFG_MAX_LOCAL_VARIABLES; + config_int[__MAX_CALL_DEPTH__ - BASE_CONFIG_INT] = CFG_MAX_CALL_DEPTH; + config_int[__LIVING_HASH_TABLE_SIZE__ - BASE_CONFIG_INT] = CFG_LIVING_HASH_SIZE; } int get_config_item (svalue_t * res, svalue_t * arg) { - int num; - - num = arg->u.number; - - if (num < 0 || num >= RUNTIME_CONFIG_NEXT) { - return 0; - } - if (num >= BASE_CONFIG_INT) { - res->type = T_NUMBER; - res->u.number = config_int[num - BASE_CONFIG_INT]; - } else { - if(!config_str[num]) //obsolete value, less muds break if we don't renumber! - return 0; - res->type = T_STRING; - res->subtype = STRING_CONSTANT; - res->u.string = config_str[num]; - } - - return 1; + int num; + + num = arg->u.number; + + if (num < 0 || num >= RUNTIME_CONFIG_NEXT) { + return 0; + } + if (num >= BASE_CONFIG_INT) { + res->type = T_NUMBER; + res->u.number = config_int[num - BASE_CONFIG_INT]; + } else { + if(!config_str[num]) //obsolete value, less muds break if we don't renumber! + return 0; + res->type = T_STRING; + res->subtype = STRING_CONSTANT; + res->u.string = config_str[num]; + } + + return 1; } diff --git a/src/regexp.c b/src/regexp.c index 9474edd8f..580a40414 100644 --- a/src/regexp.c +++ b/src/regexp.c @@ -192,7 +192,7 @@ * Just use 8 bits for now. */ #if 0 -#if defined(linux) +#if defined(__linux__) # ifndef CHARBITS # define CHARBITS 0xff # endif @@ -1211,12 +1211,12 @@ void regdump (regexp * r) s = r->program + 1; while (op != END) { /* While that wasn't END last time... */ op = OP(s); - printf("%2d%s", (s - r->program), regprop(s)); /* Where, what. */ + printf("%2ld%s", (s - r->program), regprop(s)); /* Where, what. */ nxt = regnext(s); if (nxt == (char *) NULL) /* nxt ptr. */ printf("(0)"); else - printf("(%d)", ((s - r->program) + (nxt - s))); + printf("(%ld)", ((s - r->program) + (nxt - s))); s += 3; if (op == ANYOF || op == ANYBUT || op == EXACTLY) { /* Literal string, where present. */ diff --git a/src/simulate.c b/src/simulate.c index 7e4df133e..e24745b1f 100644 --- a/src/simulate.c +++ b/src/simulate.c @@ -367,7 +367,7 @@ int strip_name (const char * src, char * dest, int size) { * it. * */ -object_t *int_load_object (const char * lname) +object_t *int_load_object (const char * lname, int callcreate) { int f; program_t *prog; @@ -516,7 +516,7 @@ object_t *int_load_object (const char * lname) error("master object: %s() denied permission to load '/%s'.\n", applies_table[APPLY_VALID_OBJECT], name); } - if (init_object(ob)) + if (init_object(ob) && callcreate) call_create(ob, 0); if (!(ob->flags & O_DESTRUCTED) && function_exists(APPLY_CLEAN_UP, ob, 1)) { diff --git a/src/simulate.h b/src/simulate.h index a3acc69b8..c4671270e 100644 --- a/src/simulate.h +++ b/src/simulate.h @@ -45,8 +45,8 @@ int get_char (svalue_t *, int, int, svalue_t *); int strip_name (const char *, char *, int); char *check_name (char *); -#define load_object(x, y) int_load_object(x) -object_t *int_load_object (const char *); +#define load_object(x, y) int_load_object(x, 1) +object_t *int_load_object (const char *, int); object_t *clone_object (const char *, int); object_t *environment (svalue_t *); object_t *first_inventory (svalue_t *); diff --git a/src/smalloc.c b/src/smalloc.c index 119e3b956..b0d4ebff0 100644 --- a/src/smalloc.c +++ b/src/smalloc.c @@ -1034,7 +1034,7 @@ static char *esbrk (u size) #else -#ifndef linux +#ifndef __linux__ extern char *sbrkx(); #endif /* linux */ diff --git a/src/socket_efuns.c b/src/socket_efuns.c index 20b1d0ee8..ec089baae 100644 --- a/src/socket_efuns.c +++ b/src/socket_efuns.c @@ -370,7 +370,7 @@ int socket_bind (int fd, int port, const char * addr) #ifdef IPV6 char tmp[INET6_ADDRSTRLEN]; debug(sockets, ("socket_bind: bound socket %d to %s.%d\n", - fd, inet_ntop(AF_INET6, &lpc_socks[fd].l_addr.sin6_addr, &tmp, INET6_ADDRSTRLEN), + fd, inet_ntop(AF_INET6, &lpc_socks[fd].l_addr.sin6_addr, (char *)&tmp, INET6_ADDRSTRLEN), ntohs(lpc_socks[fd].l_addr.sin6_port))); #else @@ -477,8 +477,6 @@ int socket_accept (int fd, svalue_t * read_callback, svalue_t * write_callback) i = find_new_socket(); if (i >= 0) { fd_set wmask; - struct timeval t; - int nb; lpc_socks[i].fd = accept_fd; lpc_socks[i].flags = S_HEADER | @@ -486,13 +484,7 @@ int socket_accept (int fd, svalue_t * read_callback, svalue_t * write_callback) FD_ZERO(&wmask); FD_SET(accept_fd, &wmask); - t.tv_sec = 0; - t.tv_usec = 1; //give the kernel some time to open the socket, but not too much! -#ifndef hpux - nb = select(accept_fd+1, (fd_set *) 0, &wmask, (fd_set *) 0, &t); -#else - nb = select(accept_fd+1, (int *) 0, (int *) &wmask, (int *) 0, &t); -#endif + if (!(FD_ISSET(accept_fd, &wmask))) lpc_socks[i].flags |= S_BLOCKED; @@ -655,7 +647,7 @@ int socket_write (int fd, svalue_t * message, const char * name) DMALLOC(len + 5, TAG_TEMPORARY, "socket_write: default"); if (buf == NULL) fatal("Out of memory"); - *(INT_32 *) buf = htonl((long) len); + *(uint32_t *) buf = htonl((uint32_t) len); len += 4; buf[4] = '\0'; p = buf + 4; @@ -947,7 +939,7 @@ void socket_read_select_handler (int fd) DMALLOC(lpc_socks[fd].r_len + 1, TAG_TEMPORARY, "socket_read_select_handler"); if (lpc_socks[fd].r_buf == NULL) fatal("Out of memory"); - debug(sockets, ("read_socket_handler: svalue len is %lu\n", + debug(sockets, ("read_socket_handler: svalue len is %d.\n", lpc_socks[fd].r_len)); } if (lpc_socks[fd].r_off < lpc_socks[fd].r_len) { diff --git a/src/sprintf.c b/src/sprintf.c index dc1140870..1c9857298 100644 --- a/src/sprintf.c +++ b/src/sprintf.c @@ -412,9 +412,7 @@ void svalue_to_string (svalue_t * obj, outbuffer_t * outbuf, int indent, int tra #endif case T_FUNCTION: { - svalue_t tmp; object_t *ob; - tmp.type = T_ARRAY; outbuf_add(outbuf, "(: "); switch (obj->u.fp->hdr.type) { diff --git a/src/std_incl.h b/src/std_incl.h index d6fea6ab1..7c6127284 100644 --- a/src/std_incl.h +++ b/src/std_incl.h @@ -28,9 +28,6 @@ #ifdef INCL_DOS_H # include #endif -#ifdef INCL_SYS_TIMES_H -# include -#endif #ifdef INCL_USCLKC_H # include #endif @@ -50,6 +47,9 @@ #ifdef INCL_LIMITS_H # include #endif +#ifdef INCL_FLOAT_H +# include +#endif #ifdef INCL_MALLOC_H # include #endif diff --git a/src/stralloc.c b/src/stralloc.c index 658cdcc97..938498d66 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -192,7 +192,7 @@ char * } else { if (REFS(b)) REFS(b)++; - //no we don't! ADD_STRING(SIZE(b)); + ADD_STRING(SIZE(b)); } NDBG(b); return (STRING(b)); diff --git a/src/testsuite/command/crasher.c b/src/testsuite/command/crasher.c new file mode 100644 index 000000000..0d1bd175b --- /dev/null +++ b/src/testsuite/command/crasher.c @@ -0,0 +1,478 @@ +// crahser, calling random efun with random argument hope to crash the driver. + +nosave mixed *_efuns = ({ + ({ "abs", (: abs :) }), + ({ "acos", (: acos :) }), + ({ "act_mxp", (: act_mxp :) }), + ({ "add_action", (: add_action :) }), + ({ "all_inventory", (: all_inventory :) }), + ({ "all_previous_objects", (: all_previous_objects :) }), + ({ "allocate", (: allocate :) }), + ({ "allocate_buffer", (: allocate_buffer :) }), + ({ "allocate_mapping", (: allocate_mapping :) }), + ({ "angle", (: angle :) }), + ({ "arr_to_str", (: arr_to_str :) }), + ({ "arrayp", (: arrayp :) }), + ({ "asin", (: asin :) }), + ({ "assemble_class", (: assemble_class :) }), + ({ "async_read", (: async_read :) }), + ({ "async_write", (: async_write :) }), + ({ "atan", (: atan :) }), + ({ "author_stats", (: author_stats :) }), + ({ "base_name", (: base_name :) }), + ({ "bind", (: bind :) }), + ({ "bufferp", (: bufferp :) }), + ({ "cache_stats", (: cache_stats :) }), + ({ "call_other", (: call_other :) }), + ({ "call_out", (: call_out :) }), + ({ "call_out_info", (: call_out_info :) }), + ({ "call_stack", (: call_stack :) }), + ({ "capitalize", (: capitalize :) }), + ({ "ceil", (: ceil :) }), + ({ "children", (: children :) }), + ({ "classes", (: classes :) }), + ({ "classp", (: classp :) }), + ({ "clear_bit", (: clear_bit :) }), +#ifdef HAS_DEBUG_LEVEL + ({ "clear_debug_level", (: clear_debug_level :) }), +#endif + ({ "clone_object", (: clone_object :) }), + ({ "clonep", (: clonep :) }), + ({ "command", (: command :) }), + ({ "commands", (: commands :) }), + ({ "compress", (: compress :) }), + ({ "compress_file", (: compress_file :) }), + ({ "compressedp", (: compressedp :) }), + ({ "copy", (: copy :) }), + ({ "cos", (: cos :) }), + ({ "cp", (: cp :) }), + ({ "crc32", (: crc32 :) }), + ({ "crypt", (: crypt :) }), + ({ "ctime", (: ctime :) }), + ({ "debug_info", (: debug_info :) }), +#ifdef HAS_DEBUG_LEVEL + ({ "debug_levels", (: debug_levels :) }), +#endif + ({ "debug_message", (: debug_message :) }), + ({ "deep_inherit_list", (: deep_inherit_list :) }), + ({ "deep_inventory", (: deep_inventory :) }), + ({ "defer", (: defer :) }), + ({ "destruct", (: destruct :) }), +#ifdef __PACKAGE_DEVELOP__ + ({ "destructed_objects", (: destructed_objects :) }), +#endif + // ({ "disable_commands", (: disable_commands :) }), + ({ "disable_wizard", (: disable_wizard :) }), + ({ "disassemble_class", (: disassemble_class :) }), + ({ "distance", (: distance :) }), + ({ "domain_stats", (: domain_stats :) }), + ({ "dotprod", (: dotprod :) }), + ({ "dump_file_descriptors", (: dump_file_descriptors :) }), + ({ "dump_prog", (: dump_prog :) }), + ({ "dumpallobj", (: dumpallobj :) }), + ({ "ed", (: ed :) }), + ({ "element_of", (: element_of :) }), + // ({ "enable_commands", (: enable_commands :) }), + ({ "enable_wizard", (: enable_wizard :) }), + ({ "environment", (: environment :) }), + ({ "error", (: error :) }), + ({ "eval_cost", (: eval_cost :) }), + ({ "evaluate", (: evaluate :) }), + ({ "event", (: event :) }), + ({ "exec", (: exec :) }), + ({ "exp", (: exp :) }), + ({ "explode", (: explode :) }), + ({ "export_uid", (: export_uid :) }), + ({ "external_start", (: external_start :) }), + ({ "fetch_class_member", (: fetch_class_member :) }), + ({ "fetch_variable", (: fetch_variable :) }), + ({ "file_length", (: file_length :) }), + ({ "file_name", (: file_name :) }), + ({ "file_size", (: file_size :) }), + ({ "filter", (: filter :) }), + ({ "filter_array", (: filter_array :) }), + ({ "filter_mapping", (: filter_mapping :) }), + ({ "find_call_out", (: find_call_out :) }), + ({ "find_living", (: find_living :) }), + ({ "find_object", (: find_object :) }), + ({ "find_player", (: find_player :) }), + ({ "first_inventory", (: first_inventory :) }), + ({ "floatp", (: floatp :) }), + ({ "floor", (: floor :) }), + ({ "flush_messages", (: flush_messages :) }), + ({ "function_exists", (: function_exists :) }), + ({ "function_owner", (: function_owner :) }), + ({ "functionp", (: functionp :) }), + ({ "functions", (: functions :) }), + ({ "get_char", (: get_char :) }), + ({ "get_config", (: get_config :) }), + ({ "get_dir", (: get_dir :) }), + ({ "get_garbage", (: get_garbage :) }), + ({ "geteuid", (: geteuid :) }), + ({ "getuid", (: getuid :) }), + ({ "has_gmcp", (: has_gmcp :) }), + ({ "has_mxp", (: has_mxp :) }), + ({ "has_zmp", (: has_zmp :) }), + ({ "heart_beats", (: heart_beats :) }), + ({ "id_matrix", (: id_matrix :) }), + ({ "implode", (: implode :) }), + ({ "in_edit", (: in_edit :) }), + ({ "in_input", (: in_input :) }), + ({ "inherit_list", (: inherit_list :) }), + ({ "inherits", (: inherits :) }), + ({ "input_to", (: input_to :) }), + ({ "interactive", (: interactive :) }), + ({ "intp", (: intp :) }), + ({ "is_daylight_savings_time", (: is_daylight_savings_time :) }), + ({ "keys", (: keys :) }), + ({ "link", (: link :) }), + ({ "living", (: living :) }), + ({ "livings", (: livings :) }), + ({ "load_object", (: load_object :) }), + ({ "localtime", (: localtime :) }), + ({ "log", (: log :) }), + ({ "log10", (: log10 :) }), + ({ "log2", (: log2 :) }), + ({ "lookat_rotate", (: lookat_rotate :) }), + ({ "lower_case", (: lower_case :) }), + ({ "malloc_status", (: malloc_status :) }), + ({ "map", (: map :) }), + ({ "map_array", (: map_array :) }), + ({ "map_delete", (: map_delete :) }), + ({ "map_mapping", (: map_mapping :) }), + ({ "mapp", (: mapp :) }), + ({ "master", (: master :) }), + ({ "match_path", (: match_path :) }), + ({ "max", (: max :) }), + ({ "max_eval_cost", (: max_eval_cost :) }), + ({ "member_array", (: member_array :) }), + ({ "memory_info", (: memory_info :) }), + ({ "memory_summary", (: memory_summary :) }), + ({ "message", (: message :) }), + ({ "min", (: min :) }), + ({ "mkdir", (: mkdir :) }), + ({ "move_object", (: move_object :) }), + ({ "mud_status", (: mud_status :) }), + ({ "named_livings", (: named_livings :) }), + ({ "network_stats", (: network_stats :) }), + ({ "next_bit", (: next_bit :) }), + ({ "next_inventory", (: next_inventory :) }), + ({ "norm", (: norm :) }), + ({ "notify_fail", (: notify_fail :) }), + ({ "nullp", (: nullp :) }), + ({ "num_classes", (: num_classes :) }), + ({ "objectp", (: objectp :) }), + ({ "objects", (: objects :) }), + ({ "oldcrypt", (: oldcrypt :) }), + ({ "origin", (: origin :) }), + ({ "pluralize", (: pluralize :) }), + ({ "pointerp", (: pointerp :) }), + ({ "pow", (: pow :) }), + ({ "present", (: present :) }), + ({ "previous_object", (: previous_object :) }), + ({ "printf", (: printf :) }), + ({ "program_info", (: program_info :) }), + ({ "query_charmode", (: query_charmode :) }), + ({ "query_heart_beat", (: query_heart_beat :) }), + ({ "query_host_name", (: query_host_name :) }), + ({ "query_idle", (: query_idle :) }), + ({ "query_ip_name", (: query_ip_name :) }), + ({ "query_ip_number", (: query_ip_number :) }), + ({ "query_ip_port", (: query_ip_port :) }), + ({ "query_load_average", (: query_load_average :) }), + ({ "query_notify_fail", (: query_notify_fail :) }), + ({ "query_num", (: query_num :) }), + ({ "query_replaced_program", (: query_replaced_program :) }), + ({ "query_shadowing", (: query_shadowing :) }), + ({ "query_snoop", (: query_snoop :) }), + ({ "query_snooping", (: query_snooping :) }), + ({ "query_verb", (: query_verb :) }), + ({ "random", (: random :) }), + ({ "read_buffer", (: read_buffer :) }), + ({ "read_bytes", (: read_bytes :) }), + ({ "read_file", (: read_file :) }), + ({ "real_time", (: real_time :) }), + ({ "receive", (: receive :) }), + ({ "reclaim_objects", (: reclaim_objects :) }), + ({ "refs", (: refs :) }), + ({ "reg_assoc", (: reg_assoc :) }), + ({ "regexp", (: regexp :) }), + ({ "reload_object", (: reload_object :) }), + ({ "remove_action", (: remove_action :) }), + ({ "remove_call_out", (: remove_call_out :) }), + ({ "remove_charmode", (: remove_charmode :) }), + ({ "remove_get_char", (: remove_get_char :) }), + ({ "remove_interactive", (: remove_interactive :) }), + ({ "remove_shadow", (: remove_shadow :) }), + ({ "rename", (: rename :) }), + ({ "repeat_string", (: repeat_string :) }), + ({ "replace_program", (: replace_program :) }), + ({ "replace_string", (: replace_string :) }), + ({ "replaceable", (: replaceable :) }), + ({ "request_term_size", (: request_term_size :) }), + ({ "request_term_type", (: request_term_type :) }), + ({ "reset_eval_cost", (: reset_eval_cost :) }), + ({ "resolve", (: resolve :) }), + ({ "restore_from_string", (: restore_from_string :) }), + ({ "restore_object", (: restore_object :) }), + ({ "restore_variable", (: restore_variable :) }), + ({ "rm", (: rm :) }), + ({ "rmdir", (: rmdir :) }), + ({ "rotate_x", (: rotate_x :) }), + ({ "rotate_y", (: rotate_y :) }), + ({ "rotate_z", (: rotate_z :) }), + ({ "round", (: round :) }), + ({ "rusage", (: rusage :) }), + ({ "save_object", (: save_object :) }), + ({ "save_variable", (: save_variable :) }), + ({ "say", (: say :) }), + ({ "scale", (: scale :) }), + ({ "send_gmcp", (: send_gmcp :) }), + ({ "send_nullbyte", (: send_nullbyte :) }), + ({ "send_zmp", (: send_zmp :) }), + ({ "set_author", (: set_author :) }), + ({ "set_bit", (: set_bit :) }), + ({ "set_debug_level", (: set_debug_level :) }), + ({ "set_encoding", (: set_encoding :) }), + ({ "set_eval_limit", (: set_eval_limit :) }), + ({ "set_heart_beat", (: set_heart_beat :) }), + ({ "set_hide", (: set_hide :) }), + ({ "set_living_name", (: set_living_name :) }), + ({ "set_reset", (: set_reset :) }), + ({ "seteuid", (: seteuid :) }), + ({ "shadow", (: shadow :) }), + ({ "shallow_inherit_list", (: shallow_inherit_list :) }), + ({ "shout", (: shout :) }), + ({ "shuffle", (: shuffle :) }), + // ({ "shutdown", (: shutdown :) }), + ({ "sin", (: sin :) }), + ({ "sizeof", (: sizeof :) }), + ({ "snoop", (: snoop :) }), + ({ "socket_accept", (: socket_accept :) }), + ({ "socket_acquire", (: socket_acquire :) }), + ({ "socket_address", (: socket_address :) }), + ({ "socket_bind", (: socket_bind :) }), + ({ "socket_close", (: socket_close :) }), + ({ "socket_connect", (: socket_connect :) }), + ({ "socket_create", (: socket_create :) }), + ({ "socket_error", (: socket_error :) }), + ({ "socket_listen", (: socket_listen :) }), + ({ "socket_release", (: socket_release :) }), + ({ "socket_status", (: socket_status :) }), + ({ "socket_write", (: socket_write :) }), + ({ "sort_array", (: sort_array :) }), + ({ "sprintf", (: sprintf :) }), + ({ "sqrt", (: sqrt :) }), + ({ "start_request_term_type", (: start_request_term_type :) }), + ({ "stat", (: stat :) }), + ({ "store_class_member", (: store_class_member :) }), + ({ "store_variable", (: store_variable :) }), + ({ "str_to_arr", (: str_to_arr :) }), + ({ "strcmp", (: strcmp :) }), + ({ "string_difference", (: string_difference :) }), + ({ "stringp", (: stringp :) }), + ({ "strlen", (: strlen :) }), + ({ "strsrch", (: strsrch :) }), + ({ "strwidth", (: strwidth :) }), + ({ "tan", (: tan :) }), + ({ "tell_object", (: tell_object :) }), + ({ "tell_room", (: tell_room :) }), + ({ "terminal_colour", (: terminal_colour :) }), + ({ "test_bit", (: test_bit :) }), + ({ "this_interactive", (: this_interactive :) }), + ({ "this_object", (: this_object :) }), + ({ "this_player", (: this_player :) }), + ({ "this_user", (: this_user :) }), + ({ "throw", (: throw :) }), + ({ "time", (: time :) }), + ({ "to_float", (: to_float :) }), + ({ "to_int", (: to_int :) }), + ({ "to_utf8", (: to_utf8 :) }), + ({ "trace", (: trace :) }), + ({ "traceprefix", (: traceprefix :) }), + ({ "translate", (: translate :) }), + ({ "typeof", (: typeof :) }), + ({ "uncompress", (: uncompress :) }), + ({ "uncompress_file", (: uncompress_file :) }), + ({ "undefinedp", (: undefinedp :) }), + ({ "unique_array", (: unique_array :) }), + ({ "unique_mapping", (: unique_mapping :) }), + ({ "upper_case", (: upper_case :) }), + ({ "uptime", (: uptime :) }), + ({ "userp", (: userp :) }), + ({ "users", (: users :) }), + ({ "utf8_to", (: utf8_to :) }), + ({ "values", (: values :) }), + ({ "variables", (: variables :) }), + ({ "virtualp", (: virtualp :) }), + ({ "wizardp", (: wizardp :) }), + ({ "write", (: write :) }), + ({ "write_buffer", (: write_buffer :) }), + ({ "write_bytes", (: write_bytes :) }), + ({ "write_file", (: write_file :) }), + ({ "zonetime", (: zonetime :) }), + + // operators + ({ "+", (: $1 + $2 :) }), + ({ "-", (: $1 - $2 :) }), + ({ "*", (: $1 * $2 :) }), + ({ "/", (: $1 / $2 :) }), + ({ "^", (: $1 ^ $2 :) }), + ({ "^", (: $1 ^ $2 :) }), + + ({ ">", (: $1 > $2 :) }), + ({ "<", (: $1 < $2 :) }), + ({ ">=", (: $1 >= $2 :) }), + ({ "<=", (: $1 <= $2 :) }), + ({ "==", (: $1 == $2 :) }), + + ({ "&&", (: $1 && $2 :) }), + ({ "||", (: $1 || $2 :) }), + ({ "!", (: !($1) :) }), + ({ "~", (: ~($1) :) }), + + ({ ">>", (: $1 >> $2 :) }), + ({ "<<", (: $1 << $2 :) }), + + ({ "?", (: $1 ? 0 : 1 :) }), +}); + +nosave mixed *_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", + "", + " ", + "_", + "^^^^^^", + "#^# #^#", + " ^", + "^ ", + " - - - - ", + "? ? ? ? ? ? ????? ???? ??", + "°°°°°°°°°°°°°°°°°°°°°", + "\\/ ", + " !", + + /* --- Objekte: --- */ + clone_object("/clone/login.c"), + this_object(), + previous_object(), + find_object("/single/master.c"), + + /* --- Closures: --- */ + (: 0 :), + (: (: 1 :) :), + (: sizeof :), + (: efun::input_to :), + (: error("123") :), + (: clone_object("/clone/login.c") :), + + /* --- Arrays: --- */ + ({ }), + ({ 0 }), + ({ "" }), + ({ ({ }) }), + ({ ([ ]) }), + ({ (: 1 :) }), + (: clone_object("/clone/login.c") :), + + //allocate(3000), + + /* --- Mappings: --- */ + ([ ]), + ([ 1 : (: 1 :) ]), + ([ clone_object("/clone/login.c"): (: sizeof :) ]), + + //allocate_mapping(200), +}); + +int main(string arg) { + mixed ob; + + write("Ok, let's try to crash the driver...\n"); + + ob = clone_object(this_object()); + ob->move(this_player()); +} + +mixed do_eval(mixed func, mixed* args) { + switch(sizeof(args)) { + case 0: + return evaluate(func); + case 1: + return evaluate(func, args[0]); + case 2: + return evaluate(func, args[0], args[1]); + case 3: + return evaluate(func, args[0], args[1], args[2]); + case 4: + return evaluate(func, args[0], args[1], args[2], args[3]); + } +} + +void create() { + mixed *args = ({ }); + mixed func, arg, result; + string func_name, log; + int i,j; + + set_living_name("crasher"); + + for(i=0; i<50; i++) { + + args = ({ }); + for(j=0; j<4; j++) { + if(random(2)) { + if(random(5)) { + args += ({ _values[random(sizeof(_values))] }); + } else { + args += ({ _efuns[random(sizeof(_efuns))][1] }); + } + } + } + + j = random(sizeof(_efuns)); + func_name = _efuns[j][0]; + func = _efuns[j][1]; + + log = sprintf("calling %s with ({ \n", func_name); + foreach( arg in args) { + log += sprintf(" %s: %O \n", typeof(arg), arg); + } + + log += "}) \n"; + + write_file("/log/crasher", log); + + catch(write("test... " + i + " " + log)); + + set_eval_limit(0x7fffffff); + + catch(do_eval(func, args)); + } + + call_out("create", 1); +} diff --git a/src/testsuite/command/speed.c b/src/testsuite/command/speed.c index 320039966..2701aca28 100644 --- a/src/testsuite/command/speed.c +++ b/src/testsuite/command/speed.c @@ -169,8 +169,8 @@ int main() { TIME("call_other (miss)",50000,this_object()->doesnt_exist()); TIME("inherited call",100000,ifun()); TIME("explicit inherited",100000,inh::ifun()); - TIME("save_object",300,save_object("/tmp/tmp")); - TIME("restore_object",1000,restore_object("/tmp/tmp")); + TIME("save_object",300,save_object("/tmp")); + TIME("restore_object",1000,restore_object("/tmp")); SAVETIME(ss, 1000000, save = 0); SAVETIME(sm, 1000000, save = 1); save = 0; diff --git a/src/testsuite/command/tests.c b/src/testsuite/command/tests.c index 2ead6c55e..33103719e 100644 --- a/src/testsuite/command/tests.c +++ b/src/testsuite/command/tests.c @@ -14,7 +14,7 @@ void recurse(string dir) { if (subdir == "fail") { foreach (string fn in get_dir(dir + "fail/*.c")) { ASSERT2(catch(load_object(dir+"fail/"+fn)), "fail/" + fn + " loaded"); -#if defined(__DEBUGMALLOC_EXTENSIONS__) && defined(__CHECK_MEMORY__) +#if defined(__DEBUGMALLOC__) && defined(__DEBUGMALLOC_EXTENSIONS__) && defined(__CHECK_MEMORY__) leaks = check_memory(); if (sizeof(filter(explode(leaks, "\n"), (: $1 && $1[0] :))) != 1) { write("After trying to compile: " + dir + "fail/" + fn + "\n"); @@ -40,10 +40,18 @@ main(string fun) write("Checks succeeded.\n"); return 1; } + + set_eval_limit(0x7fffffff); + reset_eval_cost(); + fun->do_tests(); + + set_eval_limit(0x7fffffff); + reset_eval_cost(); + if (tp != this_player()) error("Bad this_player() after calling " + fun + "\n"); -#if defined(__DEBUGMALLOC_EXTENSIONS__) && defined(__CHECK_MEMORY__) +#if defined(__DEBUGMALLOC__) && defined(__DEBUGMALLOC_EXTENSIONS__) && defined(__CHECK_MEMORY__) leaks = check_memory(); if (sizeof(filter(explode(leaks, "\n"), (: $1 && $1[0] :))) != 1) { write("After calling: " + fun + "\n"); diff --git a/src/testsuite/crasher/1 b/src/testsuite/crasher/1 new file mode 100644 index 000000000..f654c17c5 --- /dev/null +++ b/src/testsuite/crasher/1 @@ -0,0 +1,4 @@ +calling send_gmcp with ({ /* sizeof() == 1 */ + "^^^^^^" +}) + diff --git a/src/testsuite/crasher/11 b/src/testsuite/crasher/11 new file mode 100644 index 000000000..c10c16be6 --- /dev/null +++ b/src/testsuite/crasher/11 @@ -0,0 +1,3 @@ +calling localtime with ({ /* sizeof() == 1 */ + 9223372036854775807 +}) diff --git a/src/testsuite/crasher/12 b/src/testsuite/crasher/12 new file mode 100644 index 000000000..921fdca11 --- /dev/null +++ b/src/testsuite/crasher/12 @@ -0,0 +1,6 @@ +calling unique_mapping with ({ /* sizeof() == 2 */ + ({ /* sizeof() == 1 */ + ([ ]) + }), + "_" +}) diff --git a/src/testsuite/crasher/13 b/src/testsuite/crasher/13 new file mode 100644 index 000000000..1a149342d --- /dev/null +++ b/src/testsuite/crasher/13 @@ -0,0 +1,6 @@ +calling terminal_colour with ({ /* sizeof() == 4 */ + " - - - - ", + ([ ]), + (: shout :), + -5050211 +}) diff --git a/src/testsuite/crasher/14 b/src/testsuite/crasher/14 new file mode 100644 index 000000000..88d4d5710 --- /dev/null +++ b/src/testsuite/crasher/14 @@ -0,0 +1,4 @@ +calling save_object with ({ /* sizeof() == 2 */ + 32, + 40 +}) diff --git a/src/testsuite/crasher/16 b/src/testsuite/crasher/16 new file mode 100644 index 000000000..272cbffbc --- /dev/null +++ b/src/testsuite/crasher/16 @@ -0,0 +1,3 @@ +calling remove_get_char with ({ /* sizeof() == 1 */ + /clone/login#2 +}) diff --git a/src/testsuite/crasher/17 b/src/testsuite/crasher/17 new file mode 100644 index 000000000..adebafe9d --- /dev/null +++ b/src/testsuite/crasher/17 @@ -0,0 +1,4 @@ +calling zonetime with ({ +string: "" +int: 9223372036854775807 +}) diff --git a/src/testsuite/crasher/2 b/src/testsuite/crasher/2 new file mode 100644 index 000000000..07275b1c4 --- /dev/null +++ b/src/testsuite/crasher/2 @@ -0,0 +1,3 @@ +calling clear_debug_level with ({ /* sizeof() == 1 */ + "%d %q %T" +}) diff --git a/src/testsuite/crasher/4 b/src/testsuite/crasher/4 new file mode 100644 index 000000000..7c57f03c8 --- /dev/null +++ b/src/testsuite/crasher/4 @@ -0,0 +1,6 @@ +calling unique_mapping with ({ /* sizeof() == 2 */ + ({ /* sizeof() == 1 */ + (: () :) + }), + "#^# #^#" +}) diff --git a/src/testsuite/crasher/5 b/src/testsuite/crasher/5 new file mode 100644 index 000000000..2c4777df1 --- /dev/null +++ b/src/testsuite/crasher/5 @@ -0,0 +1,4 @@ +calling zonetime with ({ /* sizeof() == 2 */ + " ", + -9223372036854775807 +}) diff --git a/src/testsuite/crasher/7 b/src/testsuite/crasher/7 new file mode 100644 index 000000000..1ca0607e1 --- /dev/null +++ b/src/testsuite/crasher/7 @@ -0,0 +1,5 @@ +calling save_object with ({ /* sizeof() == 2 */ + -40, + -32 +}) + diff --git a/src/testsuite/crasher/8 b/src/testsuite/crasher/8 new file mode 100644 index 000000000..272cbffbc --- /dev/null +++ b/src/testsuite/crasher/8 @@ -0,0 +1,3 @@ +calling remove_get_char with ({ /* sizeof() == 1 */ + /clone/login#2 +}) diff --git a/src/testsuite/crasher/9 b/src/testsuite/crasher/9 new file mode 100644 index 000000000..4a8dc8245 --- /dev/null +++ b/src/testsuite/crasher/9 @@ -0,0 +1,7 @@ +calling ed with ({ /* sizeof() == 4 */ + -5050211, + " ^", + "°°°°°°°°°°°°°°°°°°°°°", + 1 +}) + diff --git a/src/testsuite/data/sha1/README b/src/testsuite/data/sha1/README new file mode 100644 index 000000000..b67642c15 --- /dev/null +++ b/src/testsuite/data/sha1/README @@ -0,0 +1,3 @@ +The files in this directory came from: + + http://www.nsrl.nist.gov/testdata/NSRLvectors.zip diff --git a/src/testsuite/data/sha1/Readme.txt b/src/testsuite/data/sha1/Readme.txt new file mode 100644 index 000000000..99d14c907 --- /dev/null +++ b/src/testsuite/data/sha1/Readme.txt @@ -0,0 +1,25 @@ + +File formats: + +There are two files included for this byte-oriented test. +One file contains the messages and the other file contains the hashes. + +The message files provided use "compact strings" to store the message values. +Compact strings are used to represented the messages in a compact form. +A compact string has the form + z || b || n(1) || n(2) || ... || n(z) +where z>=0 that represents the number of n, b is either 0 or 1, and +each n(i) is a decimal integer representing a positive number. +The length of the compact string is given by the summation of the n(i). + +The compact string is interpreted as the representation of the bit string +consisting of b repeated n(1) times, followed by 1-b repeated n(2) times, +followed by b repeated n(3) times, and so on. + +Example: + M = 5 1 7 13 5 1 2 + where z = 5 and b = 1. Then the compact string M represents the bit string + 1111111000000000000011111011 + where 1 is repeated 7 times, 0 is repeated 13 times, 1 is repeated 5 times, + 0 is repeated 1 time, and 1 is repeated 2 times. + diff --git a/src/testsuite/data/sha1/byte-hashes.sha1 b/src/testsuite/data/sha1/byte-hashes.sha1 new file mode 100644 index 000000000..fdd503ec2 --- /dev/null +++ b/src/testsuite/data/sha1/byte-hashes.sha1 @@ -0,0 +1,204 @@ +# Configuration information for "SHA-1 Test" +# SHA tests are configured for BYTE oriented implementations +H>SHS Type 1 Hashes +DA39A3EE5E6B4B0D3255BFEF95601890AFD80709 ^ +3CDF2936DA2FC556BFA533AB1EB59CE710AC80E5 ^ +19C1E2048FA7393CFBF2D310AD8209EC11D996E5 ^ +CA775D8C80FAA6F87FA62BECA6CA6089D63B56E5 ^ +71AC973D0E4B50AE9E5043FF4D615381120A25A0 ^ +A6B5B9F854CFB76701C3BDDBF374B3094EA49CBA ^ +D87A0EE74E4B9AD72E6847C87BDEEB3D07844380 ^ +1976B8DD509FE66BF09C9A8D33534D4EF4F63BFD ^ +5A78F439B6DB845BB8A558E4CEB106CD7B7FF783 ^ +F871BCE62436C1E280357416695EE2EF9B83695C ^ +62B243D1B780E1D31CF1BA2DE3F01C72AEEA0E47 ^ +1698994A273404848E56E7FDA4457B5900DE1342 ^ +056F4CDC02791DA7ED1EB2303314F7667518DEEF ^ +9FE2DA967BD8441EEA1C32DF68DDAA9DC1FC8E4B ^ +73A31777B4ACE9384EFA8BBEAD45C51A71ABA6DD ^ +3F9D7C4E2384EDDABFF5DD8A31E23DE3D03F42AC ^ +4814908F72B93FFD011135BEE347DE9A08DA838F ^ +0978374B67A412A3102C5AA0B10E1A6596FC68EB ^ +44AD6CB618BD935460D46D3F921D87B99AB91C1E ^ +02DC989AF265B09CF8485640842128DCF95E9F39 ^ +67507B8D497B35D6E99FC01976D73F54AECA75CF ^ +1EAE0373C1317CB60C36A42A867B716039D441F5 ^ +9C3834589E5BFFAC9F50950E0199B3EC2620BEC8 ^ +209F7ABC7F3B878EE46CDF3A1FBB9C21C3474F32 ^ +05FC054B00D97753A9B3E2DA8FBBA3EE808CEF22 ^ +0C4980EA3A46C757DFBFC5BAA38AC6C8E72DDCE7 ^ +96A460D2972D276928B69864445BEA353BDCFFD2 ^ +F3EF04D8FA8C6FA9850F394A4554C080956FA64B ^ +F2A31D875D1D7B30874D416C4D2EA6BAF0FFBAFE ^ +F4942D3B9E9588DCFDC6312A84DF75D05F111C20 ^ +310207DF35B014E4676D30806FA34424813734DD ^ +4DA1955B2FA7C7E74E3F47D7360CE530BBF57CA3 ^ +74C4BC5B26FB4A08602D40CCEC6C6161B6C11478 ^ +0B103CE297338DFC7395F7715EE47539B556DDB6 ^ +EFC72D99E3D2311CE14190C0B726BDC68F4B0821 ^ +660EDAC0A8F4CE33DA0D8DBAE597650E97687250 ^ +FE0A55A988B3B93946A63EB36B23785A5E6EFC3E ^ +0CBDF2A5781C59F907513147A0DE3CC774B54BF3 ^ +663E40FEE5A44BFCB1C99EA5935A6B5BC9F583B0 ^ +00162134256952DD9AE6B51EFB159B35C3C138C7 ^ +CEB88E4736E354416E2010FC1061B3B53B81664B ^ +A6A2C4B6BCC41DDC67278F3DF4D8D0B9DD7784EF ^ +C23D083CD8820B57800A869F5F261D45E02DC55D ^ +E8AC31927B78DDEC41A31CA7A44EB7177165E7AB ^ +E864EC5DBAB0F9FF6984AB6AD43A8C9B81CC9F9C ^ +CFED6269069417A84D6DE2347220F4B858BCD530 ^ +D9217BFB46C96348722C3783D29D4B1A3FEDA38C ^ +DEC24E5554F79697218D317315FA986229CE3350 ^ +83A099DF7071437BA5495A5B0BFBFEFE1C0EF7F3 ^ +AA3198E30891A83E33CE3BFA0587D86A197D4F80 ^ +9B6ACBEB4989CBEE7015C7D515A75672FFDE3442 ^ +B021EB08A436B02658EAA7BA3C88D49F1219C035 ^ +CAE36DAB8AEA29F62E0855D9CB3CD8E7D39094B1 ^ +02DE8BA699F3C1B0CB5AD89A01F2346E630459D7 ^ +88021458847DD39B4495368F7254941859FAD44B ^ +91A165295C666FE85C2ADBC5A10329DAF0CB81A0 ^ +4B31312EAF8B506811151A9DBD162961F7548C4B ^ +3FE70971B20558F7E9BAC303ED2BC14BDE659A62 ^ +93FB769D5BF49D6C563685954E2AECC024DC02D6 ^ +BC8827C3E614D515E83DEA503989DEA4FDA6EA13 ^ +E83868DBE4A389AB48E61CFC4ED894F32AE112AC ^ +55C95459CDE4B33791B4B2BCAAF840930AF3F3BD ^ +36BB0E2BA438A3E03214D9ED2B28A4D5C578FCAA ^ +3ACBF874199763EBA20F3789DFC59572ACA4CF33 ^ +86BE037C4D509C9202020767D860DAB039CADACE ^ +51B57D7080A87394EEC3EB2E0B242E553F2827C9 ^ +1EFBFA78866315CE6A71E457F3A750A38FACAB41 ^ +57D6CB41AEEC20236F365B3A490C61D0CFA39611 ^ +C532CB64B4BA826372BCCF2B4B5793D5B88BB715 ^ +15833B5631032663E783686A209C6A2B47A1080E ^ +D04F2043C96E10CD83B574B1E1C217052CD4A6B2 ^ +E8882627C64DB743F7DB8B4413DD033FC63BEB20 ^ +CD2D32286B8867BC124A0AF2236FC74BE3622199 ^ +019B70D745375091ED5C7B218445EC986D0F5A82 ^ +E5FF5FEC1DADBAED02BF2DAD4026BE6A96B3F2AF ^ +6F4E23B3F2E2C068D13921FE4E5E053FFED4E146 ^ +25E179602A575C915067566FBA6DA930E97F8678 ^ +67DED0E68E235C8A523E051E86108EEB757EFBFD ^ +AF78536EA83C822796745556D62A3EE82C7BE098 ^ +64D7AC52E47834BE72455F6C64325F9C358B610D ^ +9D4866BAA3639C13E541F250FFA3D8BC157A491F ^ +2E258811961D3EB876F30E7019241A01F9517BEC ^ +8E0EBC487146F83BC9077A1630E0FB3AB3C89E63 ^ +CE8953741FFF3425D2311FBBF4AB481B669DEF70 ^ +789D1D2DAB52086BD90C0E137E2515ED9C6B59B5 ^ +B76CE7472700DD68D6328B7AA8437FB051D15745 ^ +F218669B596C5FFB0B1C14BD03C467FC873230A0 ^ +1FF3BDBE0D504CB0CDFAB17E6C37ABA6B3CFFDED ^ +2F3CBACBB14405A4652ED52793C1814FD8C4FCE0 ^ +982C8AB6CE164F481915AF59AAED9FFF2A391752 ^ +5CD92012D488A07ECE0E47901D0E083B6BD93E3F ^ +69603FEC02920851D4B3B8782E07B92BB2963009 ^ +3E90F76437B1EA44CF98A08D83EA24CECF6E6191 ^ +34C09F107C42D990EB4881D4BF2DDDCAB01563AE ^ +474BE0E5892EB2382109BFC5E3C8249A9283B03D ^ +A04B4F75051786682483252438F6A75BF4705EC6 ^ +BE88A6716083EB50ED9416719D6A247661299383 ^ +C67E38717FEE1A5F65EC6C7C7C42AFC00CD37F04 ^ +959AC4082388E19E9BE5DE571C047EF10C174A8D ^ +BAA7AA7B7753FA0ABDC4A541842B5D238D949F0A ^ +351394DCEBC08155D100FCD488578E6AE71D0E9C ^ +AB8BE94C5AF60D9477EF1252D604E58E27B2A9EE ^ +3429EC74A695FDD3228F152564952308AFE0680A ^ +907FA46C029BC67EAA8E4F46E3C2A232F85BD122 ^ +2644C87D1FBBBC0FC8D65F64BCA2492DA15BAAE4 ^ +110A3EEB408756E2E81ABAF4C5DCD4D4C6AFCF6D ^ +CD4FDC35FAC7E1ADB5DE40F47F256EF74D584959 ^ +8E6E273208AC256F9ECCF296F3F5A37BC8A0F9F7 ^ +FE0606100BDBC268DB39B503E0FDFE3766185828 ^ +6C63C3E58047BCDB35A17F74EEBA4E9B14420809 ^ +BCC2BD305F0BCDA8CF2D478EF9FE080486CB265F ^ +CE5223FD3DD920A3B666481D5625B16457DCB5E8 ^ +948886776E42E4F5FAE1B2D0C906AC3759E3F8B0 ^ +4C12A51FCFE242F832E3D7329304B11B75161EFB ^ +C54BDD2050504D92F551D378AD5FC72C9ED03932 ^ +8F53E8FA79EA09FD1B682AF5ED1515ECA965604C ^ +2D7E17F6294524CE78B33EAB72CDD08E5FF6E313 ^ +64582B4B57F782C9302BFE7D07F74AA176627A3A ^ +6D88795B71D3E386BBD1EB830FB9F161BA98869F ^ +86AD34A6463F12CEE6DE9596ABA72F0DF1397FD1 ^ +7EB46685A57C0D466152DC339C8122548C757ED1 ^ +E7A98FB0692684054407CC221ABC60C199D6F52A ^ +34DF1306662206FD0A5FC2969A4BEEC4EB0197F7 ^ +56CF7EBF08D10F0CB9FE7EE3B63A5C3A02BCB450 ^ +3BAE5CB8226642088DA760A6F78B0CF8EDDEA9F1 ^ +6475DF681E061FA506672C27CBABFA9AA6DDFF62 ^ +79D81991FA4E4957C8062753439DBFD47BBB277D ^ +BAE224477B20302E881F5249F52EC6C34DA8ECEF ^ +EDE4DEB4293CFE4138C2C056B7C46FF821CC0ACC ^ +SHS Type 2 Hashes +A771FA5C812BD0C9596D869EC99E4F4AC988B13F ^ +E99D566212BBBCEEE903946F6100C9C96039A8F4 ^ +B48CE6B1D13903E3925AE0C88CB931388C013F9C ^ +E647D5BAF670D4BF3AFC0A6B72A2424B0C64F194 ^ +65C1CD932A06B05CD0B43AFB3BC7891F6BCEF45C ^ +70FFAE353A5CD0F8A65A8B2746D0F16281B25EC7 ^ +CC8221F2B829B8CF39646BF46888317C3EB378EA ^ +26ACCC2D6D51FF7BF3E5895588907765111BB69B ^ +01072915B8E868D9B28E759CF2BC1AEA4BB92165 ^ +3016115711D74236ADF0C371E47992F87A428598 ^ +BF30417999C1368F008C1F19FECA4D18A5E1C3C9 ^ +62BA49087185F2742C26E1C1F4844112178BF673 ^ +E1F6B9536F384DD3098285BBFD495A474140DC5A ^ +B522DAE1D67726EBA7C4136D4E2F6D6D645AC43E ^ +E9A021C3EB0B9F2C710554D4BF21B19F78E09478 ^ +DF13573188F3BF705E697A3E1F580145F2183377 ^ +188835CFE52ECFA0C4135C2825F245DC29973970 ^ +41B615A34EE2CEC9D84A91B141CFAB115821950B ^ +AB3DD6221D2AFE6613B815DA1C389EEC74AA0337 ^ +0706D414B4AA7FB4A9051AA70D6856A7264054FB ^ +3CBF8151F3A00B1D5A809CBB8C4F3135055A6BD1 ^ +DA5D6A0319272BBCCEA63ACFA6799756FFDA6840 ^ +FB4429C95F6277B346D3B389413758DFFFEEDC98 ^ +2C6E30D9C895B42DCCCFC84C906EC88C09B20DE1 ^ +3DE3189A5E19F225CDCE254DFF23DACD22C61363 ^ +93530A9BC9A817F6922518A73A1505C411D05DA2 ^ +E31354345F832D31E05C1B842D405D4BD4588EC8 ^ +3FF76957E80B60CF74D015AD431FCA147B3AF232 ^ +34AE3B806BE143A84DCE82E4B830EB7D3D2BAC69 ^ +D7447E53D66BB5E4C26E8B41F83EFD107BF4ADDA ^ +77DD2A4482705BC2E9DC96EC0A13395771AC850C ^ +EAA1465DB1F59DE3F25EB8629602B568E693BB57 ^ +9329D5B40E0DC43AA25FED69A0FA9C211A948411 ^ +E94C0B6AA62AA08C625FAF817DDF8F51EC645273 ^ +7FF02B909D82AD668E31E547E0FB66CB8E213771 ^ +5BB3570858FA1744123BAC2873B0BB9810F53FA1 ^ +905F43940B3591CE39D1145ACB1ECA80AB5E43CD ^ +336C79FBD82F33E490C577E3F791C3CBFE842AFF ^ +5C6D07A6B44F7A75A64F6CE592F3BAE91E022210 ^ +7E0D3E9D33127F4A30EB8D9C134A58409FA8695B ^ +9A5F50DFCFB19286206C229019F0ABF25283028C ^ +DCA737E269F9D8626D488988C996E06B352C0708 ^ +B8FFC1D4972FCE63241E0E77850AC46DDE75DBFA ^ +E9C9BF41C8549354151B977003CE1D830BE667DB ^ +0942908960B54F96CB43452E583F4F9CB66E398A ^ +FCE34051C34D4B81B85DDC4B543CDE8007E284B3 ^ +61E8916532503627F4024D13884640A46F1D61D4 ^ +F008D5D7853B6A17B7466CD9E18BD135E520FAF4 ^ +BD8D2E873CF659B5C77AAC1616827EF8A3B1A3B3 ^ +B25A04DD425302ED211A1C2412D2410FA10C63B6 ^ +A404E21588123E0893718B4B44E91414A785B91F ^ +A1E13BC55BF6DAD83CF3AABDA3287AD68681EA64 ^ +D5FD35FFABED6733C92365929DF0FB4CAE864D15 ^ +C12E9C280EE9C079E0506FF89F9B20536E0A83EF ^ +E22769DC00748A9BBD6C05BBC8E81F2CD1DC4E2D ^ +F29835A93475740E888E8C14318F3CA45A3C8606 ^ +1A1D77C6D0F97C4B620FAA90F3F8644408E4B13D ^ +4EC84870E9BDD25F523C6DFB6EDD605052CA4EAA ^ +D689513FED08B80C39B67371959BC4E3FECB0537 ^ +C4FED58F209FC3C34AD19F86A6DACADC86C04D33 ^ +051888C6D00029C176DE792B84DECE2DC1C74B00 ^ +1A3540BEE05518505827954F58B751C475AEECE0 ^ +DFA19180359D5A7A38E842F172359CAF4208FC05 ^ +7B0FA84EBBCFF7D7F4500F73D79660C4A3431B67 ^ +9E886081C9ACAAD0F97B10810D1DE6FCDCE6B5F4 ^ +A4D46E4BA0AE4B012F75B1B50D0534D578AE9CB6 ^ +6342B199EE64C7B2C9CBCD4F2DCB65ACEF51516F ^ +SHS Type 1 Strings +0 1 ^ +5 0 2 1 2 1 2 ^ +5 0 1 3 4 4 4 ^ +7 0 4 3 4 4 1 4 4 ^ +10 0 4 1 5 3 4 4 3 1 3 4 ^ +10 0 3 1 6 5 5 1 3 6 6 4 ^ +13 1 3 2 5 3 3 3 4 6 6 1 4 6 2 ^ +16 1 3 5 5 1 2 1 3 3 6 3 5 2 3 5 7 2 ^ +15 1 8 1 5 3 2 7 4 5 6 7 3 3 1 6 3 ^ +15 1 4 6 8 2 1 4 2 5 1 6 8 8 6 4 7 ^ +18 1 1 2 7 3 8 6 7 5 4 3 4 3 5 3 3 2 6 8 ^ +16 0 9 8 1 8 1 7 6 7 7 1 2 6 9 5 4 7 ^ +18 0 7 1 7 3 9 4 7 7 5 2 8 1 7 8 2 7 2 9 ^ +19 1 2 3 1 8 8 6 9 10 3 10 8 9 2 4 1 5 1 5 9 ^ +19 1 8 5 4 8 1 3 9 5 7 7 2 7 2 7 8 7 4 8 10 ^ +20 1 1 9 7 4 1 4 5 1 10 8 6 4 4 9 9 9 8 2 9 10 ^ +19 1 11 6 7 7 2 6 2 6 10 6 9 10 5 11 1 6 8 11 4 ^ +22 0 10 5 10 3 7 8 9 9 1 1 1 10 2 1 5 10 2 9 9 9 7 8 ^ +21 0 1 10 1 6 9 4 2 5 2 11 8 12 12 9 8 1 3 10 7 11 12 ^ +24 1 3 9 5 12 3 4 2 9 12 11 6 6 1 1 9 5 9 1 4 9 4 10 8 9 ^ +25 1 3 2 3 11 1 12 5 6 2 7 8 4 8 8 9 9 8 4 9 1 4 8 10 9 9 ^ +23 0 11 10 7 10 10 6 10 9 4 5 10 5 8 4 1 10 12 4 6 1 8 11 6 ^ +22 0 12 8 10 4 3 8 5 5 7 11 13 11 12 11 4 12 3 6 5 11 10 5 ^ +26 1 10 9 6 9 7 2 10 4 4 5 5 2 12 13 5 3 1 10 1 4 7 8 13 13 12 9 ^ +31 0 2 6 5 4 7 3 10 6 13 6 3 9 6 2 10 5 3 8 4 1 11 3 5 3 7 11 1 12 9 12 5 ^ +27 1 14 5 1 3 7 2 3 9 3 4 14 4 4 10 8 5 14 1 11 12 12 10 4 13 7 11 9 ^ +30 1 4 9 5 5 8 9 5 10 4 2 4 7 9 9 6 3 5 1 8 3 2 13 3 14 9 8 9 10 14 10 ^ +27 0 12 9 5 8 7 2 14 12 3 8 14 6 6 4 7 5 7 10 7 11 10 1 9 6 7 12 14 ^ +24 0 12 9 9 2 11 13 12 11 11 6 14 13 10 5 6 8 10 4 3 11 11 14 5 14 ^ +24 0 15 4 5 3 8 12 15 8 14 15 9 12 12 3 10 13 6 11 10 4 13 14 8 8 ^ +28 1 1 8 1 5 11 4 9 12 4 13 15 5 9 11 7 14 11 1 11 7 8 8 11 1 13 15 12 13 ^ +32 1 5 8 3 8 10 7 8 1 5 13 12 14 5 3 6 4 12 15 6 6 10 11 13 9 1 11 6 10 3 7 14 2 ^ +31 0 10 3 5 1 14 11 11 16 1 2 2 11 6 13 15 12 6 5 16 2 14 2 10 12 2 5 5 6 10 13 15 ^ +34 0 3 10 8 16 9 5 12 15 4 11 13 3 6 5 10 8 1 3 9 3 11 1 2 16 12 10 6 1 9 1 16 5 6 14 ^ +30 1 1 12 4 4 2 15 13 15 11 15 5 11 9 7 15 16 6 16 12 3 2 10 16 5 5 7 1 7 11 16 ^ +34 0 7 9 11 2 5 5 5 4 13 13 14 4 7 12 6 4 8 2 9 9 13 13 3 3 6 7 16 7 6 15 5 8 15 14 ^ +36 1 4 6 16 15 11 14 14 4 7 10 3 4 10 3 6 7 14 4 6 6 5 2 7 8 16 2 12 16 10 14 3 2 3 7 14 3 ^ +32 0 15 10 9 1 14 10 14 6 6 16 3 2 3 8 3 12 8 11 17 3 9 7 16 14 4 11 15 5 13 9 5 17 ^ +30 0 17 17 13 8 2 6 8 16 1 12 5 17 2 9 8 10 13 14 11 17 12 5 14 9 11 9 11 4 11 12 ^ +30 1 16 6 10 5 8 3 17 16 14 1 15 15 15 6 13 2 11 6 13 11 13 4 6 7 11 11 12 16 13 16 ^ +33 1 16 16 14 16 2 4 16 11 6 15 7 4 17 6 5 7 6 3 14 16 5 17 11 13 1 1 14 13 3 6 14 5 16 ^ +39 1 2 16 13 7 8 6 2 15 1 9 12 4 4 11 13 7 2 11 9 18 4 5 4 8 2 14 9 9 1 8 13 11 15 8 5 9 10 16 7 ^ +34 0 2 7 1 1 17 13 6 11 10 8 5 12 15 6 15 10 12 4 18 1 2 8 11 12 16 10 12 18 11 16 12 11 17 6 ^ +34 1 4 7 13 7 10 7 10 6 1 12 7 18 11 18 2 10 15 10 14 8 18 9 9 12 12 3 13 12 6 4 9 17 13 17 ^ +40 0 5 7 3 2 1 17 14 4 16 6 13 1 13 6 6 10 1 3 18 3 11 7 9 5 7 11 17 1 9 16 5 15 10 17 3 8 15 17 8 12 ^ +40 0 11 3 15 17 11 1 1 4 3 14 18 4 2 18 8 15 6 4 6 3 15 11 16 10 17 17 9 6 3 2 6 16 4 9 12 6 8 1 11 17 ^ +37 1 2 19 12 8 16 14 2 9 16 2 6 6 7 9 10 9 11 9 14 11 15 5 16 9 2 17 2 8 15 8 4 3 14 14 16 16 12 ^ +37 1 11 10 16 12 11 7 14 14 14 6 10 10 1 6 13 19 5 6 4 7 12 12 10 5 10 15 15 8 5 13 17 13 5 6 14 1 19 ^ +38 1 2 6 5 17 9 11 18 18 8 6 13 15 3 3 15 5 13 18 3 2 5 5 14 7 13 4 17 7 2 17 3 18 15 7 15 16 18 11 ^ +38 1 12 8 6 3 17 12 13 19 15 9 7 17 16 15 3 11 11 5 2 13 19 16 2 4 16 7 8 1 2 9 17 12 3 5 18 19 11 9 ^ +39 1 14 16 14 8 9 16 5 1 6 3 17 18 16 9 1 15 9 10 9 19 1 3 3 20 11 13 17 1 19 8 3 4 3 7 1 14 19 19 19 ^ +37 1 18 13 11 5 18 4 19 10 6 19 11 17 10 10 7 9 13 16 9 10 18 4 12 5 16 5 20 12 3 8 10 1 18 1 6 20 14 ^ +36 0 8 9 6 12 11 7 7 3 17 13 6 20 17 9 20 16 10 12 17 8 11 8 11 10 5 10 14 18 8 19 9 12 12 2 20 19 ^ +39 0 12 16 20 3 9 9 19 17 13 13 4 17 2 11 7 14 3 6 16 13 10 13 5 16 10 2 8 2 17 19 4 17 7 19 6 9 15 15 6 ^ +43 0 7 2 18 5 7 18 5 2 15 7 11 10 9 3 2 14 19 3 11 8 18 15 5 3 5 12 15 16 10 17 7 19 16 2 1 16 6 3 19 12 5 18 16 ^ +49 1 9 11 2 1 12 11 14 12 14 10 4 11 6 8 16 7 5 11 20 8 17 4 14 4 15 3 2 2 4 3 2 3 14 15 10 2 12 7 3 7 20 20 19 10 2 3 1 10 20 ^ +36 0 19 20 12 5 19 21 5 21 11 14 19 1 17 8 9 4 19 3 17 1 14 21 14 7 6 5 20 14 21 20 4 6 21 7 11 12 ^ +41 0 12 9 11 6 16 18 18 10 11 20 6 12 11 5 7 21 19 18 6 15 21 10 4 14 9 19 10 3 3 5 13 1 8 12 3 13 9 7 10 17 14 ^ +45 0 10 6 8 3 17 18 3 21 19 6 17 15 4 9 15 9 15 14 4 7 14 8 10 13 4 11 10 7 6 21 1 14 5 11 7 7 2 13 13 3 9 13 8 14 20 ^ +39 1 3 7 18 4 9 9 5 15 13 17 10 15 16 20 8 19 9 10 9 1 19 14 21 2 18 13 10 4 18 16 4 21 15 10 18 19 3 12 18 ^ +41 0 14 4 13 11 1 11 1 10 2 12 4 21 10 21 18 9 2 16 7 20 6 7 12 19 20 1 13 12 10 8 21 15 7 19 13 6 8 19 20 18 19 ^ +37 0 11 18 1 17 14 15 20 16 20 8 2 17 10 4 21 5 19 19 14 22 21 18 13 14 1 3 12 11 11 4 22 13 5 18 7 21 21 ^ +48 0 9 22 19 12 8 16 5 17 5 9 1 2 9 6 12 6 1 7 4 3 15 1 14 1 12 3 10 2 10 14 21 13 17 6 6 17 1 21 2 14 16 17 9 11 20 21 11 18 ^ +50 1 12 8 20 13 2 9 20 9 14 10 1 16 2 22 6 4 16 14 15 1 12 4 14 9 21 3 3 9 8 21 15 14 8 4 14 4 2 3 8 12 8 6 1 2 18 20 15 3 19 10 ^ +44 0 10 20 14 6 3 4 21 1 12 4 18 2 6 7 6 9 20 14 10 10 19 17 21 12 15 17 7 10 11 8 10 12 1 19 19 9 18 21 4 18 11 9 22 5 ^ +47 0 15 8 15 3 5 6 2 19 12 17 4 20 8 11 20 2 18 4 16 20 12 9 9 6 16 21 16 3 16 18 3 19 5 16 2 4 2 12 11 15 11 14 17 2 10 18 8 ^ +48 1 5 13 3 21 5 3 6 18 18 10 1 21 21 7 1 13 12 19 1 14 6 8 21 19 21 11 19 13 2 13 4 1 10 22 16 4 9 4 10 16 3 7 15 11 9 13 17 12 ^ +45 0 14 7 6 2 20 3 6 19 19 10 2 22 12 17 12 1 20 7 7 15 20 6 18 8 3 14 23 18 15 4 7 5 23 15 7 14 10 10 19 17 2 4 15 17 21 ^ +45 1 15 11 8 9 17 5 12 18 14 6 20 17 21 12 16 9 22 9 20 15 2 22 11 2 6 11 9 8 2 4 14 19 3 21 21 23 8 2 11 4 8 4 20 22 11 ^ +38 0 21 18 22 10 19 9 14 17 23 21 10 7 15 13 16 5 4 10 13 14 20 23 12 20 23 18 10 12 8 21 11 6 12 7 19 14 18 17 ^ +40 0 18 22 6 9 22 5 23 13 6 8 23 20 22 5 22 15 19 20 9 9 1 13 13 10 14 13 5 22 14 21 9 21 19 14 14 4 18 13 12 14 ^ +48 1 7 3 15 5 17 14 23 14 5 17 22 11 1 8 13 23 6 21 3 6 11 7 23 8 6 21 4 4 22 19 13 8 5 19 7 5 23 1 4 19 11 23 11 21 14 1 3 21 ^ +43 0 22 14 11 7 18 16 17 24 12 12 3 13 19 16 22 4 16 4 6 23 8 18 11 2 3 20 22 9 21 8 23 1 23 20 7 16 13 23 4 13 3 7 22 ^ +47 1 23 6 13 19 2 3 7 2 9 9 15 6 13 4 22 6 19 20 1 9 7 14 1 15 3 23 24 22 18 12 12 17 19 10 8 11 22 12 10 2 20 15 18 17 18 7 19 ^ +47 1 12 21 6 12 4 7 18 17 3 2 14 24 14 1 23 1 11 15 10 6 18 20 7 1 8 1 16 6 20 23 23 21 10 10 12 24 10 11 23 2 12 23 9 3 24 24 10 ^ +52 0 14 10 18 15 14 5 16 11 22 2 15 24 8 22 1 4 24 9 10 15 3 9 5 4 17 15 9 12 19 19 1 3 10 6 8 3 17 8 18 24 19 3 4 15 4 9 2 24 5 20 13 13 ^ +42 0 20 17 19 22 13 8 10 19 15 11 1 14 17 20 22 10 7 11 16 9 21 22 17 23 12 15 4 24 7 21 18 2 21 16 1 19 18 20 11 3 15 17 ^ +50 0 18 1 6 14 5 5 5 19 13 10 24 19 16 24 15 13 2 19 15 24 21 17 4 13 17 1 1 9 1 10 2 18 1 21 19 5 18 12 2 22 16 23 15 19 6 18 9 1 23 5 ^ +51 0 21 13 14 11 18 12 13 3 19 9 20 22 20 2 11 12 6 1 12 16 18 2 9 8 4 3 11 17 11 5 4 19 16 11 23 13 18 1 20 8 2 16 16 21 4 19 5 5 20 24 16 ^ +53 1 20 25 17 11 8 4 19 25 17 7 16 21 6 4 8 2 15 9 2 9 19 3 6 3 3 10 25 13 15 7 8 20 21 12 10 12 5 24 11 20 3 13 13 16 9 13 10 3 9 16 3 7 25 ^ +49 1 9 9 14 2 13 17 25 2 18 5 19 23 9 25 9 10 23 12 12 7 13 8 15 7 1 6 21 2 8 7 6 16 14 14 12 15 13 24 10 15 11 10 8 14 15 21 25 21 25 ^ +47 0 9 18 20 22 21 20 11 14 23 22 10 13 14 8 19 12 2 11 20 23 13 4 10 6 5 7 23 11 3 16 8 21 4 8 18 5 12 14 8 6 20 19 24 8 23 17 23 ^ +48 1 7 19 1 18 1 14 22 13 14 5 8 22 18 14 25 17 11 12 22 2 12 12 16 12 13 18 17 12 17 14 18 8 25 9 23 5 3 8 14 24 17 7 3 3 23 17 22 19 ^ +51 1 19 17 16 22 24 14 16 20 23 20 9 19 16 7 12 16 5 8 9 7 10 21 24 10 11 19 1 21 14 14 19 3 22 8 12 20 1 18 5 6 5 12 14 1 1 11 9 22 3 24 4 ^ +52 1 6 1 11 16 1 12 8 11 11 17 10 22 7 3 10 2 6 4 24 16 24 19 4 5 18 11 12 9 20 21 25 2 21 18 10 20 25 21 3 17 17 5 8 22 25 19 8 10 19 7 11 18 ^ +44 0 26 14 21 25 25 4 9 13 5 8 9 21 8 12 26 24 9 24 15 1 23 22 16 14 8 22 15 19 24 20 7 8 15 24 12 4 4 23 21 13 19 15 21 12 ^ +59 1 15 7 3 21 20 8 22 14 23 26 19 2 10 18 3 5 3 1 9 15 15 3 7 13 23 9 7 1 13 17 14 25 9 16 2 2 6 13 7 19 25 17 1 5 21 2 7 22 5 6 25 3 12 19 6 2 4 24 17 ^ +60 0 9 18 20 19 4 11 14 1 6 8 26 6 9 22 4 10 2 7 21 9 8 24 25 14 22 12 22 3 23 3 3 20 6 11 23 6 1 7 5 18 5 15 25 26 1 1 10 11 11 4 12 11 20 3 14 2 3 2 23 15 ^ +49 0 12 17 24 11 8 6 24 16 15 22 21 14 6 12 20 19 5 5 12 11 6 23 2 16 23 7 24 6 21 2 17 17 5 25 11 25 20 25 24 18 6 12 19 25 7 6 5 2 25 ^ +54 1 12 16 1 15 7 1 26 19 19 13 20 11 17 6 20 5 24 24 1 21 11 9 20 21 15 10 19 26 3 2 6 7 12 9 10 8 14 10 15 5 17 8 21 1 20 25 6 19 8 3 22 16 16 20 ^ +63 0 17 13 11 10 17 15 12 6 13 14 17 4 12 10 24 5 13 24 3 5 2 5 11 14 8 5 10 17 16 8 4 14 21 15 3 6 17 25 8 2 3 3 19 10 13 22 22 8 2 13 25 17 2 1 19 1 14 20 2 5 4 15 24 ^ +49 0 14 20 7 25 20 26 20 16 7 17 17 22 1 13 6 5 1 18 14 15 23 15 10 5 19 18 18 26 12 13 3 25 12 21 16 24 4 16 3 6 26 26 10 20 13 1 20 24 15 ^ +56 0 3 8 14 5 5 7 11 13 11 26 11 4 26 17 20 19 11 10 3 10 14 9 6 9 7 16 10 4 4 19 19 2 26 13 19 17 15 24 15 4 21 22 13 13 12 22 2 14 20 5 18 7 17 24 20 20 ^ +58 1 6 17 9 20 2 10 19 3 22 4 1 11 3 5 3 21 11 15 12 23 26 5 2 27 6 5 16 6 3 2 23 5 3 20 20 4 24 2 18 21 7 14 10 27 23 6 24 6 19 23 3 9 22 16 21 17 19 23 ^ +58 1 17 7 21 19 6 16 15 15 20 14 2 25 19 14 18 19 7 9 1 14 11 10 16 3 23 14 26 10 11 1 18 1 12 24 19 19 1 7 2 3 24 7 12 9 2 8 16 20 24 5 26 26 4 9 2 7 25 17 ^ +54 1 8 12 18 14 26 7 17 18 4 20 1 16 14 21 26 4 6 8 24 11 25 15 24 16 23 4 10 23 21 24 15 10 9 26 7 14 24 21 6 20 5 17 16 17 1 3 12 1 4 13 3 9 21 26 ^ +56 1 7 18 11 1 19 20 23 12 12 27 13 13 15 16 13 1 16 15 12 26 3 16 16 8 17 13 21 4 6 5 19 14 16 4 16 11 14 18 18 27 9 13 21 3 26 22 3 7 6 4 26 3 15 8 25 21 ^ +50 1 20 13 9 11 20 6 11 21 27 25 20 7 4 18 26 16 27 5 12 19 7 23 6 25 25 2 11 13 25 21 18 17 6 12 14 13 24 11 14 19 26 27 25 6 1 15 4 7 27 15 ^ +51 0 15 16 26 27 23 14 12 28 22 15 8 19 2 20 13 1 24 2 25 1 6 19 19 8 11 24 24 21 13 27 5 11 28 17 7 25 6 23 24 14 25 12 5 13 26 2 5 8 10 16 17 ^ +58 1 5 26 18 19 21 3 12 11 13 4 14 22 22 14 16 13 3 22 16 23 5 19 6 13 10 26 17 27 26 4 3 25 6 14 2 3 5 7 23 11 22 8 25 2 9 25 18 17 8 2 14 4 19 1 5 27 13 24 ^ +53 0 2 27 28 2 17 23 10 27 18 26 7 22 16 3 27 1 26 21 28 10 3 6 2 2 10 17 13 16 6 17 21 23 13 20 22 5 6 11 12 12 8 23 13 17 9 23 20 3 28 27 12 17 22 ^ +59 0 28 19 5 21 4 27 8 1 19 14 20 6 7 9 1 6 22 3 19 26 14 8 6 7 19 15 23 1 17 16 6 26 14 5 22 25 4 7 10 16 21 10 18 19 24 16 23 8 3 17 28 18 10 2 5 3 21 21 15 ^ +58 0 6 24 1 4 24 18 10 22 1 21 12 5 4 4 20 25 24 26 8 25 11 2 7 27 22 19 4 18 27 10 28 4 12 24 8 16 12 11 16 17 25 8 12 16 1 9 9 10 5 24 23 18 5 14 18 8 4 28 ^ +61 0 5 17 8 28 1 22 4 11 3 2 17 3 14 9 27 13 18 24 9 8 7 28 25 14 21 27 24 6 18 16 2 12 15 9 14 10 1 8 17 4 6 15 26 11 15 2 28 20 26 16 3 7 5 8 9 26 10 12 25 11 22 ^ +53 0 9 13 24 15 20 2 4 8 2 22 20 19 4 15 14 28 13 25 10 10 12 28 24 22 26 28 15 9 11 26 19 22 27 2 21 8 20 23 26 12 10 21 9 15 13 25 7 26 1 13 5 9 20 ^ +58 0 3 9 21 22 7 1 23 28 1 2 8 22 12 18 28 5 18 14 7 11 17 20 20 7 21 13 8 28 21 22 2 16 20 15 28 9 3 22 13 10 23 4 16 11 14 1 10 8 14 14 15 18 13 12 21 18 25 28 ^ +60 1 29 20 2 29 22 8 16 20 4 12 9 6 12 16 16 7 9 20 29 11 9 4 1 15 25 16 29 10 22 7 2 8 5 18 14 23 24 4 6 26 3 11 6 12 1 7 14 24 14 6 10 21 16 23 29 25 6 14 17 24 ^ +64 0 12 10 5 10 15 25 8 15 3 7 13 25 16 14 1 29 22 26 15 27 9 1 8 8 28 6 13 5 13 3 15 5 23 8 23 2 5 5 4 17 13 14 7 17 12 27 3 18 5 7 5 26 18 15 22 28 16 13 7 2 23 19 25 15 ^ +56 1 17 7 16 25 23 11 11 15 2 13 9 26 2 24 26 7 28 11 2 29 7 22 23 5 28 19 1 27 29 1 24 11 18 20 3 13 11 7 3 15 17 24 1 18 13 6 3 25 27 16 28 18 24 8 23 22 ^ +51 1 29 28 6 28 14 12 28 27 22 4 14 25 1 3 9 7 11 14 15 16 10 19 12 19 11 20 13 28 4 27 28 7 27 12 4 28 21 17 22 20 17 15 15 23 22 13 12 21 22 21 29 ^ +64 1 12 14 12 18 27 8 7 4 9 14 16 15 8 11 21 20 10 10 21 23 20 2 11 23 1 11 1 5 3 23 16 15 27 14 5 16 3 22 2 3 24 3 19 29 4 4 10 8 20 14 15 1 26 12 27 25 4 28 22 11 19 19 24 9 ^ +60 1 20 8 9 5 25 19 17 19 15 7 24 24 21 3 20 16 8 3 17 28 18 29 9 23 9 10 29 4 12 24 15 5 8 22 17 29 12 3 8 29 15 21 21 4 7 20 7 10 7 26 10 16 24 6 7 12 8 12 15 17 ^ +60 0 9 17 11 28 12 26 26 6 29 13 10 20 6 23 10 4 3 26 26 14 20 20 25 14 13 15 24 14 11 4 23 27 24 20 9 16 17 24 13 12 6 1 14 26 25 7 8 21 1 19 3 2 2 17 21 13 5 9 21 11 ^ +54 0 25 1 27 24 6 23 16 5 1 20 29 22 25 9 25 10 3 28 28 25 19 18 16 24 14 15 5 28 12 28 26 29 2 15 15 9 5 18 19 22 12 15 4 6 15 24 16 9 4 26 25 18 27 12 ^ +61 1 20 4 26 12 3 22 1 22 30 3 28 10 9 24 14 29 6 30 3 10 20 14 6 3 19 21 21 28 16 18 11 30 11 20 30 1 9 8 11 5 19 10 24 4 22 4 2 26 5 15 20 8 3 13 30 18 8 1 25 28 19 ^ +56 1 20 15 21 18 18 12 16 13 24 9 21 2 28 6 1 23 9 18 27 27 4 9 13 10 8 14 16 15 12 11 14 21 14 10 11 25 17 17 30 21 13 27 26 26 22 14 13 17 21 19 9 9 20 23 13 28 ^ +59 1 10 28 24 10 22 27 23 27 8 17 14 6 4 21 26 15 1 8 29 27 6 28 15 3 27 25 25 14 19 13 29 8 24 2 8 2 4 12 19 11 10 6 26 14 22 24 30 10 11 12 2 12 17 23 8 8 12 28 12 ^ +56 0 14 28 2 17 4 8 3 26 9 23 21 30 30 20 4 13 28 29 9 3 17 7 19 30 28 1 2 20 9 12 24 15 30 20 27 3 23 11 6 29 25 23 26 17 20 10 22 15 23 6 25 5 4 30 2 29 ^ +63 1 23 15 27 14 26 1 1 7 19 12 7 6 20 18 14 4 15 17 28 7 11 7 8 9 22 17 12 5 23 18 25 18 6 12 26 30 12 30 14 3 1 18 10 20 27 21 8 6 24 26 20 11 24 7 2 4 18 15 14 30 16 19 14 ^ +52 0 27 15 4 19 25 29 29 7 14 18 9 11 9 27 11 15 29 9 28 20 2 30 26 21 17 8 28 17 22 29 24 8 11 18 29 15 6 7 27 27 17 24 18 23 11 19 8 30 5 24 22 24 ^ +66 1 25 15 28 23 5 10 21 5 8 7 3 10 19 17 6 9 15 29 10 7 4 1 16 21 16 29 13 18 5 3 8 15 8 21 29 20 5 27 2 13 27 7 7 30 2 18 26 10 2 5 29 21 15 25 26 24 8 12 20 3 9 10 30 7 12 29 ^ +53 1 30 26 20 11 22 19 27 2 16 10 6 4 24 17 20 25 20 15 8 23 23 20 30 18 16 3 30 15 26 23 28 7 21 8 7 31 31 14 26 18 3 1 26 28 15 25 11 31 3 25 9 21 30 ^ +67 0 2 6 14 4 9 5 28 8 17 22 1 4 8 7 10 14 19 10 14 8 27 9 24 26 4 30 11 8 19 5 21 7 2 27 20 16 20 20 22 14 13 16 26 14 10 3 25 22 25 23 21 10 15 15 29 8 13 4 2 13 22 20 7 4 20 31 23 ^ +65 0 2 2 28 13 19 14 12 23 27 6 2 14 2 22 6 25 30 29 31 13 14 16 31 12 16 30 5 14 31 11 4 1 1 25 21 13 26 22 21 5 22 14 29 1 21 3 14 30 4 2 29 12 15 23 3 15 5 1 6 23 22 13 1 14 23 ^ +59 1 25 5 15 6 13 3 22 11 23 31 24 6 5 20 4 14 3 29 8 29 19 7 29 23 25 28 19 11 15 27 21 14 1 19 20 26 12 7 12 1 18 13 29 28 23 29 14 23 7 1 9 29 24 5 30 18 5 25 30 ^ +55 1 31 25 13 7 24 25 24 1 12 19 9 7 6 28 20 14 28 21 19 31 20 20 6 24 18 27 24 4 18 21 1 31 15 1 15 2 27 4 26 25 4 23 19 2 31 22 30 21 22 5 27 12 30 28 31 ^ +62 0 27 15 18 14 25 15 17 7 28 11 28 29 30 1 17 12 10 2 18 20 21 2 11 12 5 4 12 25 14 5 5 24 22 18 31 15 22 29 11 3 21 31 21 27 3 28 7 10 25 2 15 30 9 30 7 22 15 9 3 20 24 14 ^ +60 0 28 14 18 9 27 14 22 27 31 10 8 14 7 15 7 20 5 26 1 29 7 17 17 8 3 13 27 18 8 31 27 28 22 22 17 19 18 18 11 19 13 25 10 19 6 28 4 31 23 10 18 26 31 5 10 13 12 8 15 27 ^ +60 1 24 22 4 29 22 31 28 20 4 16 21 3 1 15 5 15 6 30 3 29 29 7 27 20 2 20 31 22 26 9 29 16 4 26 32 17 20 14 28 17 19 6 24 11 26 28 5 18 15 8 16 20 21 4 9 12 4 8 17 29 ^ +SHS Type 2 Strings +69 1 5 3 11 15 12 24 31 23 1 6 28 2 8 31 6 7 30 5 19 23 12 6 9 31 19 17 24 25 22 6 12 16 3 7 9 9 11 29 4 11 2 5 13 29 10 12 30 32 18 28 18 27 3 30 4 4 26 6 13 31 13 2 11 7 24 4 17 29 12 ^ +95 0 21 19 21 23 11 42 36 2 13 4 1 33 22 16 27 9 4 33 16 3 30 15 11 32 13 17 38 32 9 38 4 36 15 32 27 19 42 18 6 36 22 10 29 12 25 40 15 29 23 28 30 4 8 11 24 9 10 31 28 43 23 16 29 33 5 40 26 3 19 12 36 43 5 35 37 5 14 11 45 35 16 10 8 32 4 15 35 26 2 39 22 37 22 30 29 ^ +106 1 18 14 51 2 6 32 51 9 32 50 44 46 51 8 11 53 45 55 16 10 3 52 8 20 20 46 46 13 32 2 46 50 43 25 54 9 31 29 2 47 15 29 24 45 44 18 37 14 28 39 36 44 47 16 50 10 44 24 53 35 22 40 20 15 51 22 18 22 42 6 54 49 38 21 7 13 30 16 7 52 16 22 13 38 7 11 44 33 9 25 13 37 42 14 45 53 30 38 5 25 5 35 38 22 28 53 ^ +127 0 58 35 43 28 5 28 63 8 12 25 9 47 53 29 62 7 37 2 3 48 5 12 55 56 28 35 12 63 6 58 27 27 48 44 35 14 17 22 56 10 8 1 16 15 42 63 14 51 57 19 41 7 8 56 47 34 52 22 48 60 43 9 1 52 4 21 49 61 18 50 23 13 46 62 23 45 62 9 56 18 23 31 8 30 27 36 13 38 4 58 53 47 24 18 41 58 19 12 18 52 42 29 44 45 26 63 34 32 41 64 15 26 55 19 2 49 6 30 53 13 54 12 53 37 12 37 43 ^ +148 0 60 4 51 47 58 38 17 63 33 23 28 43 12 69 70 33 17 12 50 18 18 36 45 2 67 4 45 20 4 33 38 29 45 8 22 58 39 71 38 32 53 35 19 53 31 29 51 35 4 63 18 33 26 47 70 9 64 62 63 30 15 1 35 28 16 40 20 14 50 33 19 38 30 27 55 10 16 46 47 7 55 12 53 26 56 33 29 55 25 17 48 43 21 43 18 24 63 27 68 46 38 33 35 10 18 11 27 5 9 58 35 70 36 36 39 47 2 10 66 47 5 18 21 44 71 51 57 3 22 7 56 55 28 25 14 40 16 24 48 37 66 50 24 45 18 39 53 55 ^ +165 1 15 62 35 29 15 40 19 76 67 4 5 71 46 61 26 8 77 48 1 23 12 60 40 24 44 33 29 42 73 66 49 61 20 30 1 54 52 42 39 64 23 65 37 24 20 11 26 66 22 77 22 57 7 38 57 33 61 73 7 64 1 49 35 76 14 27 21 45 68 38 58 73 13 72 47 73 33 8 66 23 38 4 56 77 47 10 71 13 20 31 41 6 51 3 18 17 61 47 14 48 76 46 28 34 43 1 56 4 25 7 65 41 1 34 37 23 59 59 27 26 13 15 14 75 60 14 1 28 59 26 65 61 16 23 17 28 6 19 2 35 49 30 29 48 2 63 73 59 1 3 76 41 11 19 18 43 54 63 67 51 4 9 78 60 66 ^ +181 0 18 19 84 17 12 10 57 18 77 51 52 16 39 74 49 52 63 38 72 2 15 64 83 62 49 56 11 26 68 58 83 33 23 50 63 71 53 27 84 22 39 41 52 58 11 64 7 60 45 70 22 5 73 38 30 30 48 21 75 80 40 21 8 53 9 26 30 34 81 71 71 51 23 75 33 41 23 32 5 8 66 40 72 40 16 66 45 14 48 34 21 41 27 3 55 27 37 23 41 65 4 57 51 74 22 19 75 42 16 19 46 16 10 48 20 19 37 41 14 57 9 17 55 38 5 60 7 46 20 43 36 39 52 20 10 62 45 23 46 7 35 75 29 70 35 36 34 25 12 15 84 26 10 6 71 29 79 33 32 25 59 76 82 64 58 7 8 19 41 74 2 53 65 24 1 55 51 36 21 79 7 ^ +184 1 60 66 66 6 3 9 73 12 7 40 70 18 71 70 65 51 14 14 27 50 9 87 81 50 22 19 40 37 16 79 12 34 37 76 82 10 61 7 81 49 67 26 45 82 50 81 63 45 69 31 31 76 51 9 59 34 51 54 34 83 10 33 51 86 81 82 69 18 8 22 64 19 86 62 58 33 37 17 34 5 29 83 42 76 50 54 66 39 9 1 36 43 17 65 6 35 56 72 71 83 88 10 1 8 87 22 6 21 78 25 89 43 62 40 55 85 31 89 74 63 46 28 24 26 31 17 7 8 27 19 12 85 17 20 27 77 10 2 54 80 17 52 74 76 69 78 11 20 80 4 29 24 85 75 18 39 23 70 83 29 57 67 72 70 33 4 15 46 42 2 69 13 53 33 69 64 33 64 14 40 69 59 78 54 ^ +193 1 68 43 95 53 38 58 55 28 20 16 67 48 17 86 32 44 68 67 28 16 14 79 25 15 72 67 50 80 18 30 10 75 1 60 45 87 78 28 95 49 63 70 59 26 6 51 73 60 65 18 26 8 87 5 58 31 25 57 40 46 78 57 34 78 61 36 66 57 38 80 22 32 68 71 30 74 37 81 66 77 66 55 2 51 24 93 61 40 68 45 61 12 63 24 89 59 52 72 43 20 20 69 36 40 88 46 9 62 55 77 84 20 18 6 77 15 52 39 75 3 26 4 85 17 62 29 11 92 46 58 29 59 28 42 80 71 96 2 49 85 37 63 4 61 14 2 53 87 25 86 6 75 76 93 41 39 93 92 42 56 41 63 26 28 18 77 11 50 78 79 1 12 12 91 29 13 58 5 56 92 66 59 4 39 47 95 5 5 62 33 13 80 27 ^ +203 1 35 28 11 7 20 7 17 3 3 30 89 13 65 56 66 63 22 82 16 31 55 56 77 91 91 71 101 13 10 85 101 95 17 99 98 91 33 14 20 48 32 7 64 29 38 35 25 4 95 23 34 1 85 81 23 31 96 71 84 50 15 79 47 25 51 45 35 66 19 61 60 9 31 93 64 70 30 42 86 53 1 71 46 42 22 38 96 10 99 34 76 26 55 73 63 63 97 23 92 81 64 46 1 30 31 35 86 91 88 64 87 16 37 69 84 94 60 100 3 47 52 8 71 87 57 29 76 43 18 45 46 15 65 12 44 42 66 60 15 68 19 58 39 62 76 9 92 101 57 32 4 34 15 41 62 32 89 71 43 35 31 41 21 17 82 33 96 27 62 29 82 57 46 62 15 24 99 37 83 40 52 46 56 80 98 3 91 74 6 27 7 58 94 10 41 79 97 84 77 74 26 99 35 ^ +212 1 26 101 17 91 45 97 80 59 102 30 68 4 85 9 4 39 16 18 85 70 11 87 62 72 78 38 3 41 53 82 82 35 18 13 94 64 52 39 77 59 26 9 65 46 64 98 32 29 86 79 16 63 54 76 56 98 16 98 78 22 72 33 103 104 52 84 12 65 15 85 101 97 84 31 51 26 100 100 38 80 13 2 78 7 24 44 84 103 27 7 28 16 33 99 25 103 54 14 42 62 87 92 27 22 42 5 52 100 84 73 72 63 24 48 56 52 23 5 17 76 31 1 95 58 43 60 50 62 30 23 35 79 20 35 3 72 32 45 51 87 41 84 27 79 77 70 102 15 54 15 100 8 52 69 105 3 30 84 42 93 66 89 69 74 24 33 42 97 4 38 99 106 13 93 6 106 74 100 54 45 21 59 56 37 9 50 32 75 79 31 77 9 61 1 8 68 6 60 81 7 100 99 14 61 48 25 73 26 70 72 94 34 ^ +233 0 11 98 110 88 35 110 35 64 49 88 93 28 85 6 78 65 90 52 24 97 51 39 51 59 23 1 3 49 33 11 78 27 35 55 64 5 102 4 70 25 56 58 38 66 11 31 96 66 104 59 41 86 58 29 79 41 40 72 51 12 92 34 52 44 69 104 21 97 89 96 48 21 4 61 40 28 67 34 23 85 44 22 62 52 33 84 23 30 73 74 4 79 12 81 47 80 53 47 89 40 19 80 62 34 61 29 41 95 43 1 70 63 55 53 18 19 13 48 10 19 89 49 4 52 53 56 76 10 8 104 77 15 28 38 75 109 3 85 90 8 40 8 93 90 43 39 14 60 17 36 78 56 105 80 35 75 36 58 82 50 100 98 45 74 13 66 95 72 71 95 34 14 98 72 33 38 37 52 6 14 107 59 3 29 61 67 98 92 5 93 17 98 36 87 41 75 71 57 88 17 25 91 84 3 58 20 92 69 51 50 36 31 14 25 18 30 18 1 41 104 30 82 59 87 70 34 96 28 47 62 81 103 48 ^ +234 1 63 90 108 108 102 64 82 88 4 111 76 97 22 1 108 41 34 91 33 20 25 24 26 8 83 11 31 7 85 109 106 4 105 85 68 28 33 99 53 8 16 12 11 74 17 83 66 70 16 30 9 67 68 34 24 81 47 92 72 47 37 33 38 92 17 8 28 88 22 62 69 32 89 75 3 72 96 85 13 105 24 38 37 94 115 83 72 108 114 24 93 76 103 60 99 102 9 43 10 59 95 46 33 93 15 26 69 44 2 86 107 55 45 61 65 92 66 9 55 39 70 83 29 98 67 13 111 15 20 31 62 8 2 51 20 19 33 44 14 115 71 112 97 10 41 28 53 51 26 57 15 38 98 55 106 22 56 31 50 95 107 110 84 70 10 108 96 73 100 25 36 55 88 71 63 96 30 90 96 79 22 7 30 23 28 59 89 8 51 99 47 86 34 18 43 65 98 104 107 49 7 79 71 8 57 21 29 80 2 74 78 44 57 9 61 22 13 68 52 91 74 98 43 30 58 68 95 101 72 102 76 42 99 61 ^ +249 0 27 117 45 119 80 2 59 52 8 76 20 94 102 69 96 42 46 106 67 9 110 89 71 69 34 31 15 85 16 29 100 82 37 62 68 95 108 44 23 114 34 36 56 93 11 30 96 12 31 67 14 114 14 66 70 30 81 46 53 119 85 6 104 47 92 72 70 5 70 15 115 68 105 33 97 13 85 106 14 61 29 22 86 45 57 69 91 38 38 28 66 13 60 95 103 3 15 5 113 38 23 62 5 65 94 107 73 104 37 47 102 117 3 78 35 7 95 56 78 45 52 28 46 43 37 32 53 19 55 29 47 97 76 115 83 71 11 45 62 73 99 116 2 24 116 7 28 41 2 29 37 52 23 5 118 79 31 57 89 61 24 101 78 50 93 73 41 7 33 45 47 24 1 48 73 36 3 25 87 46 28 108 54 68 53 67 119 28 36 118 104 42 88 27 112 4 74 85 1 63 39 97 71 74 75 76 10 49 12 79 11 50 103 118 94 117 118 37 27 12 94 60 28 51 47 82 110 17 15 105 23 52 43 12 21 22 81 41 12 74 90 42 108 117 98 67 4 69 85 ^ +243 0 76 81 26 101 13 68 62 106 87 19 98 32 81 63 79 93 31 121 123 75 52 11 66 41 54 87 38 5 104 62 51 38 55 29 31 120 44 16 48 94 46 105 91 66 78 27 43 6 64 2 55 79 75 84 113 22 4 113 109 31 33 17 96 11 29 63 98 103 107 116 34 14 9 95 38 18 51 75 33 109 118 55 66 4 76 7 75 70 82 74 23 1 26 69 40 112 99 47 65 31 70 119 52 103 88 85 86 28 16 12 76 25 22 78 64 21 86 27 61 77 72 108 2 18 106 119 121 54 16 85 72 2 73 26 88 66 60 80 35 24 117 63 24 44 67 52 122 119 33 72 16 99 98 69 54 19 42 28 53 114 32 117 81 100 57 49 123 56 21 68 80 53 95 1 45 95 107 98 87 1 27 24 99 116 16 67 1 113 91 84 25 40 25 72 3 28 90 87 112 80 16 117 45 77 36 90 105 59 88 122 64 108 108 71 98 18 50 115 93 105 77 35 6 46 55 47 102 4 26 87 111 120 81 113 4 57 105 3 84 94 115 61 73 ^ +255 1 91 47 51 9 57 9 55 94 61 61 68 46 107 6 35 81 114 78 96 74 14 89 73 67 67 69 113 107 11 98 113 109 20 92 17 67 70 88 57 10 124 9 60 122 93 91 45 7 15 24 51 5 98 115 24 49 90 104 117 66 128 94 64 80 12 43 91 46 111 59 58 77 30 14 88 60 123 68 41 44 68 40 104 118 41 43 93 90 105 92 16 127 26 54 125 114 79 71 24 48 21 25 118 40 103 49 91 44 67 65 25 119 109 18 48 23 69 112 38 61 64 87 84 104 119 110 122 92 22 1 8 83 34 100 32 62 41 46 112 34 102 76 56 39 4 127 30 13 19 110 124 7 16 128 95 4 124 11 104 116 126 49 95 3 55 96 70 90 101 4 122 96 75 118 39 128 99 92 18 42 20 87 83 35 75 111 61 67 71 28 101 9 56 34 105 95 71 23 73 71 26 57 15 23 76 55 99 89 128 98 117 68 43 88 62 38 62 39 2 83 36 15 26 60 128 96 73 74 10 1 12 42 22 2 77 33 33 32 57 13 14 82 57 12 39 3 58 80 14 87 85 44 69 109 119 ^ +283 0 102 55 53 41 60 88 25 67 58 76 44 22 68 118 108 40 95 96 81 90 85 28 77 18 11 37 72 93 60 110 124 119 95 131 91 37 109 126 8 73 69 72 80 17 83 5 76 20 32 15 10 1 103 18 22 116 98 9 51 104 102 44 33 15 12 24 31 89 1 6 28 101 8 64 72 106 30 5 52 89 111 39 108 64 85 17 57 124 22 105 78 115 3 40 108 66 108 77 128 103 44 35 38 13 95 10 111 63 98 117 61 51 126 69 96 70 70 59 39 13 97 33 112 2 77 7 123 70 83 29 66 67 49 79 19 104 115 14 60 2 55 40 71 33 28 114 51 91 17 46 45 128 57 87 62 25 115 38 50 55 90 74 8 51 102 79 43 94 36 122 94 12 41 36 25 104 91 24 7 99 80 30 126 32 63 122 107 114 27 28 79 41 12 35 51 115 122 70 22 79 65 2 88 27 17 59 15 23 44 57 5 65 6 26 78 80 125 93 84 100 45 22 129 68 36 111 74 118 11 50 42 120 47 21 8 86 112 26 67 60 99 45 93 47 8 38 59 52 56 124 20 82 18 117 24 18 46 106 19 117 26 41 47 45 130 7 15 1 4 5 100 10 85 50 44 11 48 92 119 108 42 118 125 ^ +272 0 8 61 99 70 96 20 87 123 134 82 22 2 110 118 33 86 5 7 5 94 56 15 60 96 54 13 22 55 99 4 25 105 17 37 69 10 38 117 117 30 70 13 9 109 115 62 94 52 66 117 100 135 7 75 23 5 81 110 31 118 29 1 62 11 41 88 109 119 102 37 3 30 123 47 31 56 134 29 124 116 118 99 21 56 77 91 23 37 135 81 44 51 67 95 51 133 30 57 67 116 122 48 100 7 132 97 106 69 93 4 95 125 102 103 119 81 57 133 96 37 118 50 117 113 81 127 17 45 103 32 121 129 60 43 65 127 30 36 132 110 52 53 35 71 12 76 22 72 130 112 99 76 26 21 73 63 63 97 23 58 115 132 114 1 132 31 35 18 23 54 30 53 118 37 35 84 94 60 100 3 47 18 110 105 87 57 63 76 43 52 45 46 49 65 12 10 42 66 60 117 34 19 92 5 28 76 9 126 101 125 32 38 34 15 7 62 32 21 3 43 69 31 109 123 51 116 135 130 129 130 63 14 57 80 62 15 126 31 105 83 108 120 80 124 46 98 105 91 6 6 27 7 58 128 78 7 79 63 84 77 74 128 65 61 95 121 17 24 123 117 51 122 ^ +284 0 44 71 43 20 126 58 53 47 98 18 19 119 93 29 70 39 94 112 44 115 135 98 82 10 67 29 102 113 68 80 19 75 1 91 114 87 80 7 40 37 86 120 16 104 136 117 82 138 32 65 114 119 137 121 8 12 46 126 26 119 73 130 60 76 113 100 14 133 26 116 34 120 80 95 84 53 15 24 44 51 4 10 23 77 24 99 66 37 54 63 42 136 21 34 76 5 17 128 101 1 59 40 113 112 32 97 31 93 105 79 91 18 39 1 103 132 51 68 124 111 13 97 43 128 69 84 85 72 15 12 26 87 16 16 92 101 13 77 4 118 89 103 56 42 16 60 44 39 126 46 18 83 93 41 105 3 82 106 115 91 6 4 54 115 15 120 109 113 48 41 9 95 20 62 67 105 111 25 132 7 116 46 138 44 83 61 124 131 35 107 6 109 81 114 67 41 137 77 56 74 73 34 12 14 69 52 11 98 47 54 83 81 6 1 15 88 35 139 80 83 49 89 27 47 130 92 133 87 51 112 76 49 109 49 57 93 73 22 117 50 64 58 97 139 36 131 111 133 58 33 8 88 55 38 90 46 30 118 57 29 82 74 41 117 38 46 94 92 5 105 15 117 70 103 68 60 120 48 21 110 85 40 81 66 ^ +291 0 46 113 52 134 79 74 64 57 18 23 9 52 8 16 103 57 138 59 59 65 92 2 7 130 92 8 34 40 86 131 140 100 112 4 42 1 110 108 43 37 15 67 19 35 94 61 130 98 35 88 34 65 104 56 126 118 50 87 10 81 109 90 86 118 32 6 114 88 39 38 39 62 3 12 134 72 137 35 75 81 115 106 140 112 11 123 41 103 45 95 84 71 107 13 26 110 96 62 16 109 84 59 53 38 27 8 28 13 32 137 17 138 41 122 36 99 65 99 83 36 112 29 49 70 96 126 136 131 116 3 18 17 126 142 14 37 141 141 123 42 13 20 83 42 139 83 54 49 58 42 7 137 29 48 16 121 127 34 52 140 106 128 58 36 124 83 24 69 54 61 112 17 6 95 97 24 57 86 124 59 71 119 67 1 109 54 68 49 57 132 32 5 71 113 40 80 104 75 106 133 31 126 130 104 62 9 39 44 66 116 141 135 96 132 19 41 121 126 124 77 8 4 60 82 6 101 124 89 51 123 48 40 85 77 21 112 10 69 66 115 87 16 108 30 84 65 80 103 32 131 134 73 47 10 63 39 50 93 37 135 114 69 48 34 58 23 27 133 37 9 40 98 41 115 99 70 83 29 42 67 133 55 79 80 91 122 12 2 115 112 47 ^ +293 1 33 13 99 138 1 42 89 118 87 113 99 12 134 142 100 38 5 55 75 14 110 108 42 64 130 79 138 62 64 69 57 11 123 25 59 16 111 94 24 65 30 51 119 48 107 92 84 69 28 136 143 54 20 6 70 47 142 64 4 65 59 73 99 134 146 102 125 116 57 137 137 72 48 128 78 5 80 63 54 85 30 22 129 68 21 21 74 28 128 107 27 60 2 93 95 71 37 11 37 15 39 102 3 104 65 80 59 52 113 34 20 67 60 27 81 135 46 106 106 102 68 128 17 15 100 124 15 43 136 122 100 67 142 35 14 53 120 2 89 93 99 73 9 122 39 77 15 96 90 43 79 134 60 92 105 55 96 31 119 77 97 72 23 140 38 30 43 83 136 88 107 117 72 109 118 58 91 119 73 95 100 59 138 123 54 49 143 50 133 66 106 45 80 88 42 93 5 59 77 101 74 110 104 40 92 19 77 76 86 102 129 3 144 101 139 134 56 90 18 91 94 85 55 10 137 11 58 1 107 113 70 22 7 56 29 143 111 8 46 45 116 122 129 89 7 121 53 95 14 49 118 62 125 91 37 97 15 35 100 63 140 63 50 51 58 26 127 6 45 59 102 121 114 85 141 135 10 72 19 106 66 66 41 53 13 38 1 21 103 50 108 46 119 ^ +297 1 46 31 132 112 28 63 124 97 129 43 40 72 99 107 132 137 96 139 99 145 121 144 118 37 81 39 94 60 55 109 47 109 110 75 42 12 139 137 43 128 106 107 19 126 12 101 148 127 15 117 125 125 62 96 13 76 70 96 101 110 138 8 95 76 143 17 32 97 79 149 39 31 94 123 21 41 135 55 84 70 33 135 118 50 62 121 81 1 45 144 93 60 5 64 137 8 105 91 82 67 27 113 119 53 18 98 79 48 84 32 135 128 5 1 20 76 17 85 108 72 36 141 140 49 150 105 104 3 149 14 54 18 148 64 49 125 37 28 28 101 22 104 91 32 82 117 12 114 69 58 2 58 115 9 108 47 59 65 14 92 7 4 86 98 16 82 92 95 38 94 10 10 48 97 104 66 115 97 142 115 122 119 40 97 16 32 47 34 88 89 26 50 12 76 80 51 40 9 133 24 44 40 122 84 108 22 142 140 99 44 15 54 8 42 125 150 130 21 79 124 62 46 119 15 29 91 57 150 42 138 71 61 68 80 114 6 1 70 121 18 35 113 56 87 86 10 73 14 29 41 72 89 1 133 87 101 123 59 90 142 77 133 52 78 48 34 138 134 27 17 60 131 147 61 93 148 39 132 49 62 71 36 91 4 139 49 100 120 43 113 144 30 94 73 127 40 125 ^ +313 1 35 97 95 76 105 88 32 138 30 69 61 40 47 21 107 6 39 81 114 53 125 53 147 14 4 73 146 96 98 13 136 11 98 117 138 153 67 146 71 99 88 7 139 24 13 35 47 97 145 74 36 119 3 51 84 48 119 53 49 15 79 17 120 103 148 64 30 41 97 120 75 111 63 58 131 134 18 13 10 48 18 16 48 43 15 54 18 41 47 122 144 80 92 145 77 1 33 89 54 46 78 48 21 54 43 40 53 24 16 73 42 94 29 44 34 151 152 23 123 12 142 140 43 37 88 29 19 35 72 96 151 130 62 112 34 36 91 120 50 112 138 2 105 60 68 137 131 5 17 19 139 74 11 120 78 149 58 128 15 104 16 126 78 20 57 134 71 49 90 76 108 126 100 54 68 39 132 153 42 147 146 124 62 87 35 75 61 65 46 100 82 105 113 31 63 5 95 54 71 77 127 150 80 36 144 2 130 59 74 39 3 152 121 122 18 117 12 117 141 118 135 62 36 69 5 39 53 150 52 153 143 30 66 96 126 131 56 137 8 7 86 142 14 7 111 141 93 136 137 134 43 12 89 23 44 9 152 146 121 97 19 38 110 91 67 14 32 110 66 68 8 130 84 73 118 59 24 41 72 121 150 55 37 138 27 104 66 124 9 51 109 47 125 109 148 8 29 47 72 146 149 61 93 10 20 54 15 76 133 125 106 110 67 ^ +330 0 23 9 26 136 27 51 115 122 44 106 6 146 108 113 85 51 8 96 47 56 137 62 59 89 143 71 140 14 85 156 139 99 154 30 53 115 35 147 108 148 58 52 28 103 19 92 95 152 152 10 11 13 155 67 11 83 101 69 153 152 45 141 14 120 129 140 119 59 2 89 73 70 83 29 16 67 81 29 1 54 65 96 117 2 37 47 128 33 3 89 108 98 139 49 78 27 103 39 119 94 132 90 38 132 55 65 131 90 58 2 54 100 69 118 22 44 19 7 148 93 25 29 123 81 64 131 55 30 1 89 38 97 82 64 9 28 86 123 151 10 133 40 154 102 4 111 65 9 63 59 124 116 72 105 76 57 137 97 32 145 108 78 112 50 43 34 75 20 22 129 68 11 118 74 125 118 57 17 20 129 53 65 61 144 1 17 142 156 52 100 54 15 20 59 52 63 131 20 57 124 31 125 46 106 76 92 8 98 154 152 80 114 15 140 136 112 100 17 92 25 151 150 80 99 69 83 49 43 156 102 19 57 122 96 30 3 39 134 40 32 75 5 76 127 138 99 17 57 52 150 130 18 127 33 23 116 107 78 77 77 42 69 68 48 41 69 33 75 40 49 128 103 4 146 93 10 83 66 96 152 30 38 12 33 5 39 47 41 34 60 74 20 42 156 67 46 56 102 89 3 124 81 99 104 56 50 8 61 74 55 15 87 108 28 138 47 93 60 2 124 46 126 103 91 145 36 25 116 122 51 ^ +322 0 75 7 107 158 81 105 154 90 20 125 77 114 69 92 7 58 21 98 154 50 128 149 117 127 153 45 3 18 121 86 29 71 79 101 2 5 22 143 10 27 53 146 157 148 112 33 22 80 123 24 147 1 112 82 159 63 74 97 109 33 151 32 89 87 132 117 46 129 59 115 91 114 118 37 21 9 94 60 25 89 47 79 110 55 12 143 99 87 43 88 56 57 160 76 12 71 128 77 146 117 95 105 42 66 3 76 20 76 101 100 118 149 45 26 143 148 32 57 39 129 19 31 84 123 1 152 135 5 54 30 13 125 68 30 62 101 51 142 5 94 83 20 116 24 107 109 105 91 42 17 27 93 69 3 139 68 79 38 84 2 85 128 126 122 131 46 17 35 98 42 26 111 100 29 120 55 84 114 109 145 14 18 138 14 9 85 7 18 129 91 2 94 51 133 82 87 123 64 39 8 103 38 75 110 78 7 9 45 115 42 138 135 86 78 16 62 52 75 159 54 151 121 149 77 74 16 85 47 102 105 82 119 10 67 137 153 148 135 28 49 26 151 153 36 80 11 130 113 24 44 30 102 24 58 133 122 140 99 24 156 54 119 42 115 140 90 132 19 94 2 157 99 136 19 71 7 130 153 108 51 21 58 70 74 137 1 40 111 149 5 103 6 27 76 141 23 125 140 1 72 29 152 103 87 51 93 29 80 132 77 123 153 68 159 14 98 114 158 121 158 81 131 ^ +322 0 35 93 109 125 119 10 10 19 135 26 4 74 135 35 120 129 113 92 17 29 47 88 14 159 149 87 45 36 75 68 22 138 20 59 61 144 151 11 107 6 153 81 114 43 85 157 97 148 118 73 126 56 58 137 96 11 98 67 98 103 57 146 21 59 88 151 139 148 127 25 17 47 115 34 160 109 107 51 64 28 69 13 49 149 69 141 90 93 118 64 10 1 67 80 35 111 13 58 101 124 132 147 154 18 162 6 162 33 5 34 142 41 161 82 114 70 92 145 57 155 137 114 79 44 36 48 48 21 14 13 40 33 14 150 33 32 54 143 14 4 101 142 23 93 136 132 120 147 17 38 163 143 5 52 46 151 130 32 72 34 124 150 51 100 112 128 126 65 10 28 87 81 159 131 19 99 54 125 110 58 119 28 78 129 104 140 126 38 154 27 114 61 153 90 66 98 76 50 158 48 39 82 123 22 147 136 114 52 37 35 75 41 15 150 60 52 55 103 21 23 129 95 24 71 47 97 130 50 140 144 106 100 9 64 19 117 122 71 92 8 77 156 97 121 98 85 2 36 39 109 143 23 120 156 133 93 154 36 66 116 131 160 127 162 161 46 142 14 141 81 141 63 86 117 104 3 146 39 127 34 133 102 106 91 57 9 28 60 61 7 158 12 80 26 8 122 80 44 63 68 49 158 21 32 81 150 15 141 108 161 64 46 124 123 31 99 27 105 109 98 112 144 ^ +336 1 34 161 107 149 48 67 138 109 156 104 37 133 60 80 84 81 160 9 16 96 164 1 95 112 4 86 163 116 98 103 55 31 8 56 37 36 127 32 9 89 103 31 100 161 85 106 119 89 154 43 115 162 137 108 128 38 42 155 103 9 62 65 102 122 10 138 160 125 47 158 43 91 69 123 132 35 121 4 110 89 130 69 29 139 69 53 70 83 29 163 67 41 9 108 34 45 76 87 2 144 164 98 33 160 79 78 48 89 9 38 134 93 146 79 54 122 80 38 112 55 55 101 70 8 129 44 70 59 98 149 24 136 124 138 63 25 166 83 51 34 91 45 30 118 59 28 87 72 44 116 28 36 103 101 113 10 114 62 111 71 65 126 53 19 114 86 42 85 36 57 137 57 159 95 88 78 72 20 23 14 65 10 22 129 68 1 68 74 75 108 7 7 147 109 13 35 51 104 158 164 122 126 2 50 4 132 127 59 52 13 81 20 47 107 74 148 115 46 106 46 82 115 68 144 142 60 104 15 90 136 102 100 134 42 15 141 100 40 49 49 73 166 13 156 82 166 37 82 96 137 130 166 134 20 139 45 122 56 107 98 79 124 17 32 130 120 165 77 23 130 96 67 68 47 37 12 29 18 38 158 19 160 55 147 39 118 83 121 96 43 137 33 66 86 112 147 155 149 140 5 19 17 148 161 10 44 159 146 57 16 26 102 49 3 104 61 59 74 56 10 165 31 54 25 142 157 37 58 165 128 154 73 50 149 94 137 ^ +330 1 61 51 65 132 23 169 116 122 14 66 7 98 131 72 69 127 72 163 125 68 69 51 47 159 31 164 71 118 50 83 113 81 127 153 45 137 134 121 68 163 26 43 65 127 166 138 98 144 18 53 137 139 148 76 158 4 62 78 167 102 144 94 55 141 63 29 97 91 24 115 166 80 69 132 99 1 120 23 88 64 87 118 37 137 152 94 60 168 71 47 52 110 37 155 125 63 42 43 52 11 12 151 31 12 44 110 32 128 117 68 87 24 39 164 76 145 58 101 91 100 140 151 143 130 32 21 3 111 1 31 75 123 153 116 135 130 27 164 165 116 23 12 62 83 24 133 139 49 74 154 80 158 80 64 105 91 6 142 27 75 24 128 112 41 79 29 84 145 40 128 99 95 95 19 17 160 89 15 17 84 64 11 93 10 66 78 73 127 148 18 129 139 143 49 150 9 84 82 154 85 15 88 82 60 87 19 12 133 58 20 39 65 51 141 134 27 70 167 120 117 86 60 16 44 16 57 132 18 142 85 104 59 47 141 58 2 66 96 46 119 153 40 110 126 103 90 144 13 26 106 144 80 145 134 103 95 24 44 21 84 140 13 97 104 140 99 6 147 54 83 42 106 131 54 96 135 67 118 121 81 109 10 53 132 112 117 81 33 155 49 61 38 119 1 13 102 131 148 94 131 143 67 123 148 89 104 135 72 145 152 76 87 6 66 2 71 123 77 114 108 59 123 166 62 96 140 94 149 116 169 ^ +349 0 125 17 93 82 80 110 156 147 156 99 154 4 29 90 163 120 84 113 56 8 157 29 61 169 141 113 78 48 50 13 138 11 50 61 99 106 2 107 6 117 81 114 34 49 112 52 130 82 73 108 20 22 110 60 11 98 22 62 58 48 146 149 23 88 142 139 121 91 16 163 2 88 171 133 100 62 51 46 10 24 150 49 131 60 114 63 84 91 64 165 138 40 44 172 111 141 58 74 115 96 129 145 164 153 170 126 24 169 16 115 41 125 46 87 61 92 145 39 155 92 78 70 35 27 21 48 21 151 159 40 15 5 132 170 23 18 107 160 150 56 133 23 66 109 123 102 102 172 166 145 116 151 34 1 151 130 5 36 34 97 114 15 82 128 112 119 99 29 138 165 42 36 159 95 19 63 36 89 101 40 92 1 33 93 104 113 126 2 136 96 52 108 90 57 89 31 5 113 30 39 37 96 4 147 127 105 43 165 35 75 23 143 105 24 25 10 94 12 160 102 95 170 71 20 70 112 23 95 144 61 73 137 55 1 81 95 26 65 172 41 147 79 103 80 40 121 36 12 64 98 169 93 111 115 48 127 9 39 107 131 115 118 162 161 10 142 14 123 54 141 36 41 99 77 140 128 167 82 25 106 57 70 64 21 19 15 34 126 149 167 53 163 127 86 35 8 54 23 40 140 3 169 45 150 152 96 81 143 28 28 124 87 13 90 9 87 109 53 67 164 28 131 89 149 42 55 126 79 132 74 19 133 30 68 72 75 148 9 10 72 152 144 83 106 153 74 163 98 152 ^ +375 1 94 28 13 8 20 28 18 118 5 140 89 67 171 64 152 85 61 101 80 154 149 34 115 135 128 108 110 20 33 128 103 35 38 57 95 10 111 151 98 29 149 7 82 69 96 114 26 103 171 101 53 121 24 2 121 51 35 70 83 29 154 67 5 167 63 16 27 58 60 2 99 128 71 33 160 70 51 3 44 149 2 89 84 101 43 18 113 71 38 94 55 46 74 52 139 102 35 43 50 80 122 6 100 88 129 36 25 148 47 24 7 55 36 30 82 32 19 78 63 26 71 28 167 85 56 167 95 159 78 26 66 35 65 90 44 159 105 59 15 67 57 137 21 132 50 70 78 36 169 5 172 56 1 22 129 68 168 23 74 30 99 138 174 120 91 153 8 42 68 158 155 104 99 133 5 135 96 82 59 52 144 36 20 38 62 29 112 106 46 106 19 73 70 41 135 133 42 95 15 45 136 93 100 98 173 6 132 55 4 4 31 64 130 162 156 64 157 19 46 96 92 103 139 134 2 94 18 86 38 89 62 61 79 157 14 112 111 156 32 14 85 78 31 59 20 1 161 169 149 29 122 150 133 37 102 30 109 65 85 51 174 110 164 66 77 76 111 119 131 95 5 1 166 103 134 141 17 158 123 137 48 165 175 102 13 3 86 43 23 47 56 150 165 4 36 174 115 157 168 13 147 119 109 55 41 140 67 27 31 27 53 126 17 163 116 122 160 60 7 92 113 66 45 109 60 151 125 62 39 39 17 153 13 152 53 94 50 53 89 57 127 153 45 119 104 121 56 145 172 19 41 103 166 108 68 126 12 53 131 127 148 52 134 168 50 48 155 72 132 82 37 129 63 175 160 ^ +366 1 73 15 79 139 71 51 132 81 135 111 166 61 37 60 118 37 92 134 94 60 150 53 47 25 110 19 137 107 27 176 43 16 145 146 142 165 12 17 92 166 110 117 41 69 6 12 164 76 109 40 101 82 82 131 134 115 143 112 32 164 146 93 162 31 66 123 144 80 135 94 137 156 107 157 173 62 65 176 124 112 4 65 127 44 131 53 19 105 91 149 106 27 57 158 92 85 14 79 20 84 127 174 128 72 68 59 171 17 124 80 167 8 57 28 172 66 144 48 42 37 109 121 18 120 103 116 13 132 39 73 145 76 158 43 82 33 51 153 164 97 13 2 3 20 24 114 98 9 25 131 102 99 86 42 16 26 159 39 105 161 133 49 59 41 20 105 31 136 30 87 10 119 135 13 83 99 58 45 99 156 26 61 135 143 80 118 107 76 77 24 44 12 66 95 147 61 86 140 99 167 138 54 47 42 97 122 18 60 90 40 73 85 63 82 1 35 96 94 81 54 15 128 40 52 2 101 1 165 93 113 130 85 95 98 58 105 112 53 68 108 72 100 152 49 87 140 39 154 62 114 77 105 63 50 87 157 26 78 122 67 140 71 170 119 5 93 64 50 104 144 129 138 75 130 4 178 60 139 120 54 113 32 2 133 17 43 163 129 89 72 149 155 30 38 7 138 5 44 61 69 76 175 107 6 93 81 114 28 25 82 22 118 58 73 96 175 177 92 36 11 98 171 38 28 42 146 125 178 88 136 139 103 67 10 151 151 70 153 115 94 32 51 34 177 173 132 49 119 54 96 45 78 73 64 159 120 22 20 154 111 117 58 56 109 72 143 ^ +372 1 136 146 144 170 90 15 169 180 88 41 89 10 60 52 92 145 21 155 47 42 61 26 18 176 48 21 124 141 40 179 178 114 143 14 164 71 142 132 11 124 23 39 82 114 84 57 163 130 127 89 133 16 138 151 130 160 34 70 78 161 64 92 112 110 72 175 102 138 179 173 159 59 19 27 18 53 92 22 65 156 170 57 104 86 126 148 118 155 78 43 63 90 48 80 168 142 68 12 39 174 69 168 147 118 96 34 129 35 75 5 107 60 170 180 147 85 3 133 75 95 152 71 175 43 94 178 50 144 16 46 101 46 165 45 68 163 38 172 5 138 61 85 62 177 76 36 167 19 53 151 66 66 97 3 100 164 12 98 131 70 109 162 161 156 142 14 105 27 141 9 178 81 50 113 110 131 37 16 79 12 34 37 167 173 10 152 7 81 140 158 26 136 82 50 172 154 45 160 31 122 167 142 9 150 125 51 54 125 174 10 124 51 177 81 173 69 109 8 22 155 19 86 62 149 33 37 108 34 96 29 174 133 167 50 54 66 130 9 1 36 134 108 65 97 126 56 163 71 83 88 10 1 8 178 22 6 112 169 116 89 43 153 40 146 85 31 89 74 154 137 28 115 117 122 108 98 8 27 110 103 176 17 20 27 77 10 93 145 80 17 143 165 76 69 78 102 20 91 171 95 29 115 176 166 109 39 23 70 83 29 148 67 163 161 33 4 15 46 42 2 69 104 53 33 160 64 33 155 14 131 160 59 78 71 19 176 107 65 38 82 55 40 56 40 115 84 29 25 44 68 104 176 76 64 123 18 25 136 23 6 171 31 30 30 58 14 13 72 57 14 41 177 ^ +363 0 135 69 16 167 79 143 46 178 26 3 65 58 36 135 97 35 175 51 152 57 137 173 108 10 54 78 4 153 173 164 48 177 22 129 68 168 167 74 174 91 106 174 96 75 129 168 34 36 158 147 88 75 101 149 103 64 42 59 52 112 180 20 30 22 173 80 98 46 106 179 65 30 17 127 125 26 87 15 5 136 85 100 66 141 182 124 15 156 148 15 56 98 146 156 48 149 3 14 96 52 79 115 134 170 54 178 54 22 73 30 45 39 133 182 96 103 148 176 6 45 62 183 51 180 153 145 145 117 21 90 118 109 21 62 22 101 49 53 11 142 86 132 66 69 44 79 87 115 55 5 169 150 63 110 109 177 150 91 129 40 149 159 102 165 3 70 27 175 23 56 126 165 164 20 158 91 157 136 157 131 111 69 39 33 132 43 19 175 179 37 118 9 155 116 122 128 52 7 84 89 58 13 85 44 135 125 54 183 23 161 145 173 136 29 62 50 13 57 25 127 153 45 95 64 121 40 121 140 171 9 71 166 68 28 102 4 53 123 111 148 20 102 160 34 8 139 32 116 66 13 113 63 143 97 63 10 59 124 66 41 132 71 115 106 151 46 22 45 118 37 67 124 94 60 140 43 47 10 110 9 127 97 7 156 43 180 125 126 137 145 12 2 82 146 100 117 26 59 180 181 164 76 89 30 101 77 72 126 114 95 143 102 32 149 131 83 157 31 61 123 139 60 135 74 169 122 151 102 137 168 62 55 166 119 97 163 60 112 24 116 38 178 105 91 134 86 27 47 138 72 70 183 79 15 84 117 154 128 57 53 39 161 88 ^ +393 1 92 72 151 33 183 164 42 112 32 10 5 93 97 18 112 71 92 168 116 179 186 65 137 68 134 3 82 9 19 121 148 65 160 173 158 167 90 66 180 172 99 86 83 86 26 16 10 135 23 81 137 125 17 19 25 183 73 7 104 185 79 165 119 119 176 59 75 18 5 59 132 26 21 127 119 80 94 83 52 61 24 44 4 50 55 115 29 70 140 99 159 130 54 15 42 89 114 173 28 50 16 33 53 47 58 180 19 64 78 49 30 186 104 32 44 157 85 1 149 85 97 114 77 63 58 50 89 80 21 36 84 72 60 152 25 87 108 15 138 54 106 77 97 23 42 55 149 181 62 106 43 132 31 138 111 176 93 40 10 96 128 105 114 43 98 4 146 20 107 120 14 113 181 101 1 19 155 113 57 64 117 131 6 22 186 138 184 36 61 29 36 175 107 6 61 81 114 20 180 42 169 102 26 73 80 151 153 68 4 11 98 139 6 175 34 146 93 154 88 128 139 79 35 2 135 119 46 129 91 86 179 51 18 169 141 108 49 103 46 72 21 70 49 64 151 96 185 175 130 111 85 58 32 101 40 101 131 136 139 170 70 10 169 175 73 41 69 177 45 47 92 145 11 155 22 22 56 21 13 166 48 21 109 131 40 174 178 104 128 9 149 51 132 122 173 119 23 24 67 109 74 32 158 110 117 74 123 6 118 151 130 150 167 34 55 58 146 54 72 112 105 57 160 82 123 159 153 159 39 19 7 8 33 87 12 50 146 150 37 104 71 126 133 108 145 68 38 38 90 43 75 148 122 43 2 39 154 54 163 147 113 91 29 109 35 75 182 87 35 155 170 127 80 185 118 60 95 142 71 165 28 84 168 25 144 178 31 81 41 160 25 53 143 ^ +381 1 14 172 163 130 45 69 46 145 36 36 151 169 13 135 42 26 81 153 76 148 178 90 131 30 101 162 161 132 142 14 89 3 141 175 146 65 26 89 94 99 187 8 55 162 2 13 143 173 2 120 173 41 132 150 2 112 42 18 140 130 37 128 23 106 159 118 167 150 101 11 30 109 150 184 124 19 169 73 165 53 109 158 172 147 11 46 38 149 25 21 92 184 64 179 158 133 135 34 38 58 114 9 183 4 118 76 49 89 102 40 163 47 75 80 176 175 8 154 14 180 104 153 84 89 11 129 8 138 85 181 73 66 154 121 20 115 93 114 108 82 182 19 86 103 176 183 186 177 53 10 69 137 56 1 135 141 68 69 54 86 12 75 171 87 187 107 144 150 93 23 7 70 83 29 140 67 139 153 183 178 189 30 18 2 29 72 29 33 160 56 9 123 164 107 136 19 70 31 177 152 99 57 38 66 55 32 32 24 83 60 21 1 36 52 80 168 44 32 115 184 25 120 181 172 155 189 22 30 26 180 5 64 49 188 1 28 111 57 176 167 67 131 22 160 186 169 65 34 30 117 91 17 163 39 134 57 137 155 90 170 42 78 170 141 167 158 42 177 22 129 68 168 143 74 150 85 82 174 78 63 111 156 28 12 158 141 76 57 77 125 79 40 12 59 52 88 156 20 24 182 149 56 92 46 106 167 59 189 121 119 14 81 15 165 136 79 100 42 117 182 118 175 138 124 3 50 74 134 156 36 143 181 180 96 22 61 97 134 164 24 166 30 10 61 6 33 9 115 176 84 97 142 152 15 50 165 45 168 135 133 127 93 15 66 94 91 9 32 16 95 37 29 171 118 68 108 66 63 20 55 186 ^ +396 1 97 10 5 160 132 18 83 73 159 141 55 120 31 131 141 102 138 3 52 9 148 189 56 99 165 146 2 140 64 157 100 121 113 102 24 21 24 123 16 10 139 152 19 109 146 116 122 92 43 7 75 62 49 170 58 26 117 125 45 147 5 125 136 155 118 2 26 50 161 21 182 127 153 45 68 19 121 22 94 104 144 166 35 166 23 176 75 188 53 114 93 148 177 66 151 16 156 121 180 98 48 179 95 63 107 97 45 1 23 97 57 23 132 53 79 97 124 19 188 18 118 37 22 106 94 60 122 25 47 176 110 184 109 79 164 120 43 153 89 90 128 109 12 168 64 110 82 117 192 41 171 163 164 76 53 12 101 68 54 117 78 59 143 84 32 122 104 65 148 31 52 123 130 24 135 38 151 95 142 93 101 159 62 37 148 110 70 127 51 85 181 89 11 142 105 91 107 50 27 29 102 36 43 165 79 6 84 99 118 128 30 26 3 143 17 68 66 139 187 15 165 158 24 88 20 179 174 81 79 18 106 47 74 150 104 179 162 59 131 62 116 166 82 184 188 97 136 41 136 167 140 143 175 72 42 174 148 75 74 71 86 14 16 191 117 11 63 119 119 186 182 13 171 49 182 80 167 73 147 119 107 164 41 57 181 168 29 114 26 184 121 101 80 76 65 34 49 24 44 191 38 25 91 5 58 140 99 153 124 54 184 42 83 108 155 4 20 191 3 29 35 40 180 7 40 66 25 12 180 86 26 38 139 73 1 137 79 85 102 71 39 28 44 77 56 190 12 66 72 30 152 7 87 84 190 126 48 100 77 91 186 36 31 143 163 50 94 25 126 1 114 105 170 93 22 173 90 116 87 96 19 74 4 122 183 83 120 177 113 169 181 77 182 1 149 186 ^ +384 1 25 56 85 107 177 6 186 138 184 28 61 184 191 175 107 6 29 81 114 12 156 2 137 86 189 73 64 127 129 44 167 11 98 107 169 143 26 146 61 130 88 120 139 55 3 189 119 87 22 105 67 78 147 51 2 161 109 84 49 87 38 48 192 62 25 64 143 72 169 151 106 111 53 58 8 93 8 85 123 120 131 170 38 2 169 167 49 41 37 153 21 39 92 145 190 155 177 185 48 13 5 150 48 21 85 115 40 166 178 88 104 1 125 19 116 106 141 111 23 43 101 58 187 150 78 101 50 107 185 86 151 130 134 143 34 31 26 122 38 40 112 97 33 136 50 99 127 121 159 7 19 170 187 1 79 191 26 130 118 5 104 47 126 109 92 129 52 30 193 90 35 67 116 90 3 181 39 122 30 155 147 105 83 21 77 35 75 174 55 190 131 154 95 72 185 94 36 95 126 71 149 4 68 152 180 144 146 7 49 33 152 188 29 111 194 172 148 125 35 59 36 125 11 36 141 149 183 125 27 1 71 133 61 138 168 85 131 5 96 162 161 117 142 14 79 183 141 165 126 55 11 74 84 79 167 3 40 142 177 193 128 173 192 100 163 16 127 145 182 97 17 193 120 115 32 108 18 96 154 103 152 150 86 181 15 99 135 179 124 194 164 68 160 43 109 138 152 142 6 21 23 149 20 11 82 164 44 159 148 133 115 24 28 53 104 9 183 179 108 56 39 84 87 30 163 32 70 75 166 170 8 139 9 175 99 143 64 89 186 114 183 133 85 161 63 61 154 111 15 115 78 109 108 72 177 14 71 103 176 173 176 157 38 10 54 132 41 186 130 126 63 69 39 76 7 65 171 82 172 102 124 140 83 113 ^ +396 1 189 70 83 29 132 67 115 145 151 170 181 14 192 2 187 40 5 33 160 48 183 91 132 83 112 177 62 189 153 128 91 49 38 50 55 24 8 8 51 36 13 175 28 36 56 160 12 107 168 25 104 157 156 139 165 14 30 192 164 195 56 41 180 159 28 79 41 144 167 51 115 188 136 154 145 65 2 22 93 83 191 147 23 110 57 137 131 66 138 26 78 146 125 159 150 34 177 22 129 68 168 111 74 118 77 50 174 54 47 87 140 20 178 158 133 60 33 45 93 47 8 170 59 52 56 124 20 16 150 117 24 84 46 106 151 51 158 173 113 111 196 73 15 133 136 71 100 10 85 182 110 143 114 92 185 42 42 118 156 20 135 173 156 96 180 37 73 134 156 182 150 196 192 45 172 17 167 91 168 68 89 134 120 190 173 34 141 37 152 111 117 103 61 7 34 62 67 191 190 8 87 21 195 139 86 44 76 66 55 186 23 31 87 183 5 155 122 191 68 53 149 136 35 115 26 121 131 102 123 3 42 197 133 179 56 84 165 136 190 130 49 157 80 101 103 97 197 11 19 118 1 5 119 137 9 104 193 141 116 122 72 38 7 70 47 44 155 43 16 107 125 40 127 193 105 131 145 108 185 6 50 141 1 167 127 153 45 53 192 121 12 79 84 129 151 15 166 196 156 60 188 53 109 83 148 162 46 146 6 136 111 160 88 38 169 85 63 87 97 35 194 3 82 52 13 132 43 59 92 109 4 178 3 118 37 195 96 94 60 112 15 47 166 110 179 99 69 149 100 43 138 69 70 123 89 12 158 54 90 72 117 182 31 166 153 164 76 33 2 101 63 44 112 58 39 143 74 32 107 89 55 143 31 47 123 125 4 135 18 141 80 137 88 81 154 187 ^ +406 0 23 134 103 49 99 44 64 160 68 190 114 105 91 86 22 27 15 74 8 22 151 79 199 84 85 90 128 9 5 175 129 17 40 59 125 187 194 144 151 3 60 6 158 153 67 58 18 99 19 53 129 90 179 134 52 124 55 95 138 82 170 167 69 122 13 108 160 119 115 161 51 14 167 120 47 60 57 86 16 184 96 197 42 98 112 165 154 199 157 21 168 52 146 66 126 119 93 150 20 36 153 140 194 93 26 156 114 80 80 55 44 13 35 24 44 191 24 190 63 177 44 140 99 146 117 54 163 42 76 101 134 176 185 177 168 1 21 19 180 193 12 52 197 191 173 65 19 31 118 59 1 123 72 71 88 64 11 193 37 63 28 169 184 45 72 195 152 186 87 56 176 112 41 93 77 84 158 29 3 136 142 36 80 4 119 166 86 98 163 93 1 145 83 102 66 75 191 46 4 94 155 55 120 149 113 148 181 49 175 180 142 87 5 51 65 92 167 196 186 138 184 23 61 164 171 175 107 6 9 81 114 7 141 177 117 76 174 73 54 112 114 29 152 11 98 87 154 123 21 146 41 115 88 115 139 40 183 189 109 67 7 90 52 73 127 51 192 156 89 69 49 77 33 33 182 57 10 64 138 57 159 136 91 111 33 58 193 88 188 75 118 110 126 170 18 197 169 162 34 41 17 138 6 34 92 145 185 155 157 170 43 8 140 48 21 70 105 40 161 178 78 89 196 110 199 106 96 121 106 23 185 28 96 48 167 145 58 91 35 97 180 66 151 130 124 128 34 16 6 107 28 20 112 92 18 121 30 84 107 101 159 187 19 155 182 181 74 186 11 120 98 185 104 32 126 94 82 119 42 25 173 90 30 62 96 70 178 176 39 102 15 150 147 100 78 16 57 35 75 169 35 170 116 144 75 146 ^ +409 1 185 70 12 95 110 71 133 183 52 136 148 144 114 186 17 25 144 164 5 79 178 172 124 117 19 43 20 93 174 36 125 117 151 109 3 164 55 101 37 122 152 77 131 168 88 162 161 93 142 14 63 167 141 149 94 39 190 50 68 47 135 198 16 110 153 177 104 173 192 68 147 179 119 137 166 73 180 169 88 91 24 76 10 80 146 79 128 150 62 149 194 83 111 171 124 170 156 60 152 27 109 106 120 134 201 184 202 149 12 198 66 132 12 127 132 133 83 8 12 45 88 9 183 155 92 24 23 76 63 14 163 8 62 67 150 162 8 115 1 167 91 127 32 89 162 90 159 125 85 129 47 53 154 95 7 115 54 101 108 56 169 6 47 103 176 157 160 125 14 10 30 124 17 178 122 102 55 69 15 60 202 49 171 74 148 94 92 124 67 200 184 70 83 29 127 67 100 140 131 165 176 4 182 2 167 20 193 33 160 43 173 71 112 68 97 157 57 169 138 113 86 44 38 40 55 19 196 201 31 21 8 165 23 26 41 155 195 183 102 158 25 94 142 146 129 150 9 30 177 154 195 51 36 175 139 28 59 31 124 167 41 105 173 121 134 130 65 185 17 78 78 181 137 13 95 57 137 116 51 118 16 78 131 115 154 145 29 177 22 129 68 168 91 74 98 72 30 174 39 37 72 130 15 163 158 128 50 18 25 73 27 191 150 59 52 36 104 20 11 130 97 4 79 46 106 141 46 138 163 108 106 191 68 15 113 136 66 100 193 65 182 105 123 99 72 180 37 22 108 156 10 130 168 141 96 160 22 58 134 151 162 140 181 187 35 157 7 147 76 163 58 84 129 100 190 153 24 126 32 142 96 107 88 41 2 14 42 52 186 170 3 82 11 180 119 66 29 56 66 50 171 3 11 77 163 5 150 112 128 ^ +413 1 47 25 135 129 7 108 19 107 117 102 102 3 28 190 112 165 56 63 165 122 183 116 28 157 52 73 89 90 169 202 12 111 185 203 91 116 200 97 193 134 116 122 44 31 7 63 26 37 134 22 2 93 125 33 99 186 77 124 131 94 171 183 50 113 178 146 127 153 45 32 164 121 203 58 56 108 130 192 166 168 128 39 188 53 102 69 148 141 18 139 197 108 97 132 74 24 155 71 63 59 97 21 194 180 61 45 204 132 29 31 85 88 188 164 187 118 37 167 82 94 60 98 1 47 152 110 172 85 55 128 72 43 117 41 42 116 61 12 144 40 62 58 117 168 17 159 139 164 76 5 193 101 56 30 105 30 11 143 60 32 86 68 41 136 31 40 123 118 181 135 195 127 59 130 81 53 147 62 13 124 98 34 79 39 49 145 53 180 94 105 91 71 2 27 5 54 193 7 141 79 199 84 75 70 128 199 195 160 119 17 20 54 115 187 184 129 146 193 40 201 143 138 57 43 18 94 204 38 114 80 179 114 47 119 50 80 118 82 160 152 49 112 198 88 155 104 95 151 36 199 162 100 27 50 47 86 195 16 179 81 192 27 83 107 150 134 194 147 1 158 32 131 61 111 119 83 140 5 21 133 120 174 78 26 136 109 65 80 40 29 203 25 24 44 191 14 170 43 162 34 140 99 141 112 54 148 42 71 96 119 161 165 167 148 186 11 4 180 188 197 42 182 181 168 50 14 26 103 49 1 113 67 61 78 59 196 173 32 53 8 154 169 30 72 175 152 176 87 36 166 102 36 88 77 79 138 24 188 131 127 26 70 194 114 146 66 93 158 93 191 125 78 92 51 60 176 26 4 74 135 35 120 129 113 133 181 29 170 170 137 77 190 46 45 77 157 191 186 138 184 18 61 144 151 175 107 6 194 81 114 2 126 110 ^ +427 1 85 60 150 73 38 88 90 5 128 11 98 55 130 91 13 146 9 91 88 107 139 16 159 189 93 35 191 66 28 65 95 51 184 148 57 45 49 61 25 9 166 49 194 64 130 33 143 112 67 111 1 58 177 80 164 59 110 94 118 170 194 197 169 154 10 41 193 114 190 26 92 145 177 155 125 146 35 200 124 48 21 46 89 40 153 178 62 65 196 86 175 90 80 89 98 23 169 4 88 32 135 137 26 75 11 81 172 34 151 130 108 104 34 200 182 83 12 196 112 84 202 97 206 60 75 69 159 163 19 131 174 157 66 178 195 104 66 161 104 8 126 70 66 103 26 17 141 90 22 54 64 38 146 168 39 70 199 142 147 92 70 8 25 35 75 161 3 138 92 128 43 59 185 55 205 95 100 71 123 173 42 126 128 144 94 176 205 20 139 149 198 59 168 172 109 112 9 33 10 73 154 36 115 97 131 99 196 144 45 81 22 112 142 72 131 148 83 162 161 78 142 14 53 157 141 139 74 29 180 35 58 27 115 198 1 90 138 167 89 173 192 48 137 159 114 132 156 58 160 154 68 76 19 56 5 70 141 64 113 150 47 129 184 73 96 166 124 155 151 55 147 17 109 86 100 129 201 164 192 149 7 193 56 112 200 107 122 133 63 206 2 40 78 9 183 140 82 4 13 71 48 4 163 201 57 62 140 157 8 100 204 162 86 117 12 89 147 75 144 120 85 109 37 48 154 85 2 115 39 96 108 46 164 1 32 103 176 147 150 105 207 10 15 119 2 173 117 87 50 69 50 202 39 171 69 133 89 72 114 57 195 179 70 83 29 122 67 85 135 111 160 171 202 172 2 147 183 33 160 38 163 51 92 53 82 137 52 149 123 98 81 39 38 30 55 14 186 196 11 6 3 155 18 16 26 150 180 168 97 148 25 84 127 136 119 135 4 30 162 144 195 46 31 170 119 28 190 ^ +443 1 17 96 167 27 91 152 100 106 109 65 164 10 57 71 167 123 209 74 57 137 95 30 90 2 78 110 101 147 138 22 177 22 129 68 168 63 74 70 65 2 174 18 23 51 116 8 142 158 121 36 207 207 45 209 170 122 59 52 8 76 20 4 102 69 186 72 46 106 127 39 110 149 101 99 184 61 15 85 136 59 100 172 37 182 98 95 78 44 173 30 204 94 156 206 123 161 120 96 132 1 37 134 144 134 126 160 180 21 136 203 119 55 156 44 77 122 72 190 125 10 105 25 128 75 93 67 13 205 196 14 31 179 142 206 75 207 159 91 38 8 28 66 43 150 185 193 63 135 5 143 98 143 32 5 125 124 197 103 14 97 107 102 87 3 18 185 97 155 56 48 165 112 178 106 13 157 32 53 79 85 149 197 7 106 175 203 71 101 195 92 193 129 116 122 24 26 7 58 11 32 119 7 202 83 125 28 79 181 57 119 121 84 161 168 50 93 163 131 127 153 45 17 144 121 198 43 36 93 115 177 166 148 108 24 188 53 97 59 148 126 208 134 192 88 87 112 64 14 145 61 63 39 97 11 194 165 46 40 199 132 19 11 80 73 178 154 177 118 37 147 72 94 60 88 201 47 142 110 167 75 45 113 52 43 102 21 22 111 41 12 134 30 42 48 117 158 7 154 129 164 76 195 188 101 51 20 100 10 201 143 50 32 71 53 31 131 31 35 123 113 166 135 180 117 44 125 76 33 142 62 3 114 93 19 59 34 34 130 38 170 74 105 91 56 192 27 205 34 178 202 131 79 199 84 65 50 128 189 185 145 109 17 49 105 187 174 114 141 183 20 196 128 123 47 28 18 89 189 23 99 70 179 94 42 114 45 65 98 82 150 137 29 102 183 68 150 89 75 141 21 184 157 80 7 40 37 86 190 16 174 66 187 12 68 102 135 114 189 137 191 148 12 116 56 96 119 73 130 200 6 113 100 154 63 26 116 104 50 80 25 14 193 83 ^ +436 1 24 44 191 211 138 11 138 18 140 99 133 104 54 124 42 63 88 95 137 133 151 116 162 208 193 180 180 173 26 158 165 160 26 6 18 79 33 1 97 59 45 62 51 172 141 24 37 189 130 145 6 72 143 152 160 87 4 150 86 28 80 77 71 106 16 164 123 103 10 54 178 106 114 34 85 150 93 175 93 70 76 27 36 152 207 4 42 103 3 120 97 113 109 181 210 162 154 129 61 166 38 13 53 141 183 186 138 184 10 61 112 119 175 107 6 170 81 114 207 102 125 65 50 135 73 28 73 75 203 113 11 98 35 115 71 8 146 202 76 88 102 139 1 144 189 83 15 181 51 13 60 75 51 179 143 37 30 49 51 20 207 156 44 184 64 125 18 133 97 52 111 194 58 167 75 149 49 105 84 113 170 179 197 169 149 208 41 178 99 180 21 92 145 172 155 105 131 30 208 200 114 48 21 31 79 40 148 178 52 50 196 71 160 80 70 69 93 23 159 202 83 22 115 132 6 65 209 71 167 14 151 130 98 89 34 190 167 68 2 181 112 79 192 82 191 45 55 49 159 148 19 116 169 142 61 173 185 94 46 146 104 206 126 55 56 93 16 12 121 90 17 49 44 18 126 163 39 50 189 137 147 87 65 3 5 35 75 156 196 118 77 118 23 54 185 40 195 95 90 71 113 163 32 116 108 144 74 166 190 15 134 134 188 39 158 172 94 107 212 23 53 134 36 105 77 111 89 186 124 35 61 7 102 132 67 131 128 78 162 161 63 142 14 43 147 141 129 54 19 170 20 48 7 95 198 199 70 123 157 74 173 192 28 127 139 109 127 146 43 140 139 48 61 14 36 60 136 49 98 150 32 109 174 63 81 161 124 140 146 50 142 7 109 66 80 124 201 144 182 149 2 188 46 92 185 87 112 133 43 201 205 35 68 9 183 125 72 197 3 66 33 207 163 191 52 57 130 152 8 85 204 157 81 107 205 187 ^ +462 1 126 54 123 113 85 81 23 41 154 71 210 115 18 89 108 32 157 209 11 103 176 133 136 77 193 10 209 112 196 166 110 66 43 69 194 36 202 25 171 62 112 82 44 100 43 188 172 70 83 29 115 67 64 128 83 153 164 195 158 2 119 187 169 33 160 31 149 23 64 32 61 109 45 121 102 77 74 32 38 16 55 7 172 189 198 200 211 141 11 2 5 143 159 147 90 134 25 70 106 122 105 114 212 30 141 130 195 39 24 163 91 28 11 7 76 167 17 81 137 85 86 94 65 149 5 42 66 157 113 204 59 57 137 80 15 70 207 78 95 91 142 133 17 177 22 129 68 168 43 74 50 60 197 174 3 13 36 106 3 127 158 116 26 197 192 25 194 155 102 59 52 203 56 20 214 82 49 171 67 46 106 117 34 90 139 96 94 179 56 15 65 136 54 100 157 17 182 93 75 63 24 168 25 189 84 156 201 118 156 105 96 112 201 22 134 139 114 116 145 175 11 121 198 99 40 151 34 72 117 52 190 105 90 20 118 60 83 52 208 205 181 209 16 174 122 206 70 202 144 71 18 208 8 66 38 135 170 178 53 115 5 138 88 123 17 200 115 119 182 98 9 87 97 102 72 3 8 180 82 145 56 33 165 102 173 96 213 157 12 33 69 80 129 192 2 101 165 203 51 86 190 87 193 124 116 122 4 21 7 53 211 27 104 207 197 73 125 23 59 176 37 114 111 74 151 153 50 73 148 116 127 153 45 2 124 121 193 28 16 78 100 162 166 128 88 9 188 53 92 49 148 111 193 129 187 68 77 92 54 4 135 51 63 19 97 1 194 150 31 35 194 132 9 206 75 58 168 144 167 118 37 127 62 94 60 78 196 47 132 110 162 65 35 98 32 43 87 1 2 106 21 12 124 20 22 38 117 148 212 149 119 164 76 180 183 101 46 10 95 205 186 143 40 32 56 38 21 126 31 30 123 108 151 135 165 107 29 120 71 13 137 62 208 104 88 4 39 29 19 115 23 160 54 105 91 41 177 27 200 14 163 124 ^ +453 0 115 79 199 84 49 18 128 173 169 121 93 17 186 41 89 187 158 90 133 167 206 188 104 99 31 4 18 81 165 217 75 54 179 62 34 106 37 41 66 82 134 113 215 86 159 36 142 65 43 125 215 160 149 48 193 24 21 86 182 16 166 42 179 206 44 94 111 82 181 121 167 132 198 92 48 72 119 57 114 184 200 81 68 122 39 26 84 96 26 80 1 208 177 217 24 44 191 206 118 209 123 8 140 99 128 99 54 109 42 58 83 80 122 113 141 96 147 203 183 180 175 158 16 143 155 155 11 1 13 64 23 1 87 54 35 52 46 157 121 19 27 174 115 130 209 72 123 152 150 87 202 140 76 23 75 77 66 86 11 149 118 88 44 168 101 94 14 80 145 93 165 73 65 66 12 21 137 192 4 22 83 201 120 77 113 94 181 195 157 144 124 51 151 33 211 38 131 178 186 138 184 5 61 92 99 175 107 6 155 81 114 207 87 105 45 40 120 73 18 58 60 193 98 11 98 15 100 51 3 146 187 61 88 97 139 204 129 189 73 213 171 36 216 55 55 51 174 138 17 15 49 41 15 197 146 39 174 64 120 3 123 82 37 111 179 58 157 70 134 39 100 74 108 170 164 197 169 144 198 41 163 84 170 16 92 145 167 155 85 116 25 208 200 104 48 21 16 69 40 143 178 42 35 196 56 145 70 60 49 88 23 149 192 78 12 95 127 204 55 199 61 162 212 151 130 88 74 34 180 152 53 210 166 112 74 182 67 176 30 35 29 159 133 19 101 164 127 56 168 175 84 26 131 104 196 126 40 46 83 6 7 101 90 12 44 24 216 106 158 39 30 179 132 147 82 60 216 203 35 75 151 181 98 62 108 3 49 185 25 185 95 80 71 103 153 22 106 88 144 54 156 175 10 129 119 178 19 148 172 79 102 207 13 208 33 114 36 95 57 91 79 176 104 25 41 210 92 122 62 131 108 73 162 161 48 142 14 33 137 141 119 34 9 160 5 38 205 75 198 189 50 108 112 ^ +454 1 53 173 192 113 111 102 120 132 22 112 118 20 40 7 8 213 46 129 28 77 150 11 81 160 49 60 154 124 119 139 43 135 213 109 38 52 117 201 116 168 149 215 181 32 64 164 59 98 133 15 194 198 28 54 9 183 104 58 176 209 59 12 200 163 177 45 50 116 145 8 64 204 150 74 93 184 89 111 39 108 108 85 61 13 36 154 61 210 115 3 84 108 22 152 209 216 103 176 123 126 57 183 10 199 107 186 161 105 51 38 69 184 26 202 15 171 57 97 77 24 90 33 183 167 70 83 29 110 67 49 123 63 148 159 190 148 2 99 172 159 33 160 26 139 3 44 17 46 89 40 101 87 62 69 27 38 6 55 2 162 184 183 190 211 131 6 212 210 138 144 132 85 124 25 60 91 112 95 99 212 30 126 120 195 34 19 158 71 28 211 217 56 167 7 71 122 70 66 79 65 134 27 61 147 103 199 44 57 137 65 50 202 78 80 81 137 128 12 177 22 129 68 168 23 74 30 55 182 174 208 3 21 96 218 112 158 111 16 187 177 5 179 140 82 59 52 188 36 20 214 62 29 156 62 46 106 107 29 70 129 91 89 174 51 15 45 136 49 100 142 217 182 88 55 48 4 163 20 174 74 156 196 113 151 90 96 92 191 7 134 134 94 106 130 170 1 106 193 79 25 146 24 67 112 32 190 85 210 75 15 108 45 73 37 193 205 166 194 1 169 102 206 65 197 129 51 218 198 208 66 33 120 155 163 43 95 5 133 78 103 2 185 105 114 167 93 4 77 87 102 57 3 218 175 67 135 56 18 165 92 168 86 203 157 212 13 59 75 109 187 217 96 155 203 31 71 185 82 193 119 116 122 204 16 7 48 201 22 89 197 192 63 125 18 39 171 17 109 101 64 141 138 50 53 133 101 127 153 45 207 104 121 188 13 216 63 85 147 166 108 68 214 188 53 87 39 148 96 178 124 182 48 67 72 44 214 125 41 63 219 97 211 194 135 16 30 189 132 219 191 70 43 158 181 ^ +475 0 153 118 37 99 48 94 60 64 189 47 118 110 155 51 21 77 4 43 66 195 196 99 215 12 110 6 216 24 117 134 205 142 105 164 76 159 176 101 39 218 88 184 165 143 26 32 35 17 7 119 31 23 123 101 130 135 144 93 8 113 64 207 130 62 201 90 81 205 11 22 220 94 2 146 26 105 91 20 156 27 193 208 142 178 107 79 199 84 41 2 128 165 161 109 85 17 174 37 81 187 150 78 129 159 194 184 92 87 23 214 18 77 153 209 63 46 179 46 30 102 33 29 50 82 126 101 203 78 147 20 138 53 27 117 207 148 145 32 181 16 13 86 178 16 162 30 175 198 32 90 99 66 177 113 155 124 186 80 44 60 119 49 106 176 192 65 52 106 27 26 68 92 14 80 211 200 169 213 24 44 191 202 102 197 111 140 99 124 95 54 97 42 54 79 68 110 97 133 80 135 199 175 180 171 146 8 131 147 151 221 219 9 52 15 1 79 50 27 44 42 145 105 15 19 162 103 118 201 72 107 152 142 87 190 132 68 19 71 77 62 70 7 137 114 76 214 36 160 97 78 220 76 141 93 157 57 61 58 9 125 180 4 6 67 189 120 61 113 82 181 183 153 136 120 43 139 29 199 26 123 174 186 138 184 1 61 76 83 175 107 6 143 81 114 207 75 89 29 32 108 73 10 46 48 185 86 11 98 221 88 35 221 146 175 49 88 93 139 196 117 189 65 201 163 24 208 51 39 51 170 134 1 3 49 33 11 189 138 35 166 64 116 213 115 70 25 111 167 58 149 66 122 31 96 66 104 170 152 197 169 140 190 41 151 72 162 12 92 145 163 155 69 104 21 208 200 96 48 21 4 61 40 139 178 34 23 196 44 133 62 52 33 84 23 141 184 74 4 79 123 192 47 191 53 158 200 151 130 80 62 34 172 140 41 206 154 112 70 174 55 164 18 19 13 159 121 19 89 160 115 52 164 167 76 10 119 104 188 126 28 38 75 220 3 85 90 8 40 8 204 90 154 39 14 171 128 147 78 56 216 191 35 75 147 169 82 50 100 209 45 185 13 177 95 150 ^ +471 0 71 89 139 8 92 60 144 26 142 154 3 122 98 164 216 134 172 58 95 200 224 201 5 86 36 81 29 63 65 162 76 11 13 196 78 108 55 131 80 66 162 161 27 142 14 19 123 141 105 6 220 146 209 24 184 47 198 175 22 87 133 38 173 192 205 103 91 97 115 122 7 92 103 25 2 213 213 36 124 13 62 150 221 61 150 39 45 149 124 104 134 38 130 208 109 18 32 112 201 96 158 149 215 176 22 44 149 39 88 133 220 189 193 23 44 9 183 89 48 161 204 54 222 195 163 167 40 45 106 140 8 49 204 145 69 83 169 89 96 24 93 103 85 41 3 31 154 51 210 115 213 79 108 12 147 209 206 103 176 113 116 37 173 10 189 102 176 156 100 36 33 69 174 16 202 5 171 52 82 72 4 80 23 178 162 70 83 29 105 67 34 118 43 143 154 185 138 2 79 157 149 33 160 21 129 208 24 2 31 69 35 81 72 47 64 22 38 221 55 222 152 179 168 180 211 121 1 207 200 133 129 117 80 114 25 50 76 102 85 84 212 30 111 110 195 29 14 153 51 28 196 212 36 167 222 61 107 55 46 64 65 119 220 12 56 137 93 194 29 57 137 50 210 30 197 78 65 71 132 123 7 177 22 129 68 168 3 74 10 50 167 174 198 218 6 86 218 97 158 106 6 177 162 210 164 125 62 59 52 173 16 20 214 42 9 141 57 46 106 97 24 50 119 86 84 169 46 15 25 136 44 100 127 202 182 83 35 33 209 158 15 159 64 156 191 108 146 75 96 72 181 217 134 129 74 96 115 165 216 91 188 59 10 141 14 62 107 12 190 65 205 60 10 98 30 63 22 178 205 151 179 211 164 82 206 60 192 114 31 203 188 193 66 28 105 140 148 33 75 5 128 68 83 212 170 95 109 152 88 224 67 77 102 42 3 213 170 52 125 56 3 165 82 163 76 193 157 197 218 49 70 89 182 217 91 145 203 11 56 180 77 193 114 116 122 189 11 7 43 191 17 74 187 187 53 125 13 19 166 222 104 91 54 131 123 50 33 118 86 127 167 ^ +480 1 45 193 76 121 181 219 195 42 64 126 166 80 40 200 188 53 80 25 148 75 157 117 175 20 53 44 30 207 111 27 63 198 97 204 194 114 222 23 182 132 212 170 63 22 144 120 143 118 37 79 38 94 60 54 184 47 108 110 150 41 11 62 211 43 51 180 181 94 200 12 100 223 201 14 117 124 200 137 95 164 76 144 171 101 34 213 83 169 150 143 16 32 20 2 224 114 31 18 123 96 115 135 129 83 220 108 59 192 125 62 196 80 76 195 218 17 210 79 214 136 6 105 91 5 141 27 188 193 127 168 97 79 199 84 31 209 128 155 151 94 75 17 159 32 71 187 140 63 124 149 179 179 77 72 13 204 18 72 138 199 48 36 179 26 25 97 28 14 30 82 116 86 188 68 132 133 38 7 107 197 133 140 12 166 6 3 86 173 16 157 15 170 188 17 85 84 46 172 103 140 114 171 65 39 45 119 39 96 166 182 45 32 86 12 26 48 87 226 80 201 190 159 208 24 44 191 197 82 182 96 217 140 99 119 90 54 82 42 49 74 53 95 77 123 60 120 194 165 180 166 131 225 116 137 146 211 219 4 37 5 1 69 45 17 34 37 130 85 10 9 147 88 103 191 72 87 152 132 87 175 122 58 14 66 77 57 50 2 122 109 61 209 26 150 92 58 205 71 136 93 147 37 56 48 212 221 110 165 4 213 47 174 120 41 113 67 181 168 148 126 115 33 124 24 184 11 113 169 186 138 184 223 61 56 63 175 107 6 128 81 114 207 60 69 9 22 93 73 31 33 175 71 11 98 206 73 15 221 146 160 34 88 88 139 186 102 189 55 186 153 9 198 46 19 51 165 129 208 215 49 23 6 179 128 30 156 64 111 203 105 55 10 111 152 58 139 61 107 21 91 56 99 170 137 197 169 135 180 41 136 57 152 7 92 145 158 155 49 89 16 208 200 86 48 21 216 51 40 134 178 24 8 196 29 118 52 42 13 79 23 131 174 69 221 59 118 177 37 181 43 153 185 151 130 70 47 34 162 125 26 201 139 112 65 164 40 149 3 226 220 159 106 19 74 155 100 47 159 157 193 ^ +471 0 211 98 104 174 126 7 24 61 213 225 57 90 1 33 209 183 62 147 39 215 157 121 147 71 49 216 170 35 75 140 148 54 29 86 188 38 185 221 163 95 58 71 81 131 84 44 144 10 134 142 228 118 86 156 204 126 172 46 91 196 220 197 218 70 36 73 13 47 57 154 60 3 226 188 70 100 51 131 64 62 162 161 15 142 14 11 115 141 97 219 216 138 201 16 172 31 198 167 6 75 125 26 173 192 193 95 75 93 111 114 224 76 91 213 13 227 201 213 28 120 1 50 150 213 45 142 31 33 145 124 92 130 34 126 204 109 2 16 108 201 80 150 149 215 172 14 28 137 23 80 133 208 185 189 19 36 9 183 77 40 149 200 50 214 191 163 159 36 41 98 136 8 37 204 141 65 75 157 89 84 12 81 99 85 25 224 27 154 43 210 115 205 75 108 4 143 209 198 103 176 105 108 21 165 10 181 98 168 152 96 24 29 69 166 8 202 226 171 48 70 68 217 72 15 174 158 70 83 29 101 67 22 114 27 139 150 181 130 2 63 145 141 33 160 17 121 196 8 219 19 53 31 65 60 35 60 18 38 217 55 222 144 175 156 172 211 113 226 203 192 129 117 105 76 106 25 42 64 94 77 72 212 30 99 102 195 25 10 149 35 28 184 208 20 167 218 53 95 43 30 52 65 107 220 52 129 85 190 17 57 137 38 202 14 193 78 53 63 128 119 3 177 22 129 68 168 216 74 223 46 155 174 190 214 223 78 218 85 158 102 227 169 150 198 152 113 46 59 52 161 20 214 26 222 129 53 46 106 89 20 34 111 82 80 165 42 15 9 136 40 100 115 190 182 79 19 21 197 154 11 147 56 156 187 104 142 63 96 56 173 209 134 125 58 88 103 161 212 79 184 43 227 137 6 58 103 225 190 49 201 48 6 90 18 55 10 166 205 139 167 203 160 66 206 56 188 102 15 191 180 181 66 24 93 128 136 25 59 5 124 60 67 204 158 87 105 140 84 224 59 69 102 30 3 209 166 40 117 56 220 165 74 159 68 185 157 185 206 41 66 167 ^ +490 1 176 217 85 133 203 218 38 174 71 193 108 116 122 171 5 7 37 179 11 56 175 181 41 125 7 226 160 204 98 79 42 119 105 50 9 100 68 127 153 45 185 60 121 177 211 183 30 52 114 166 64 24 192 188 53 76 17 148 63 145 113 171 4 45 28 22 203 103 19 63 186 97 200 194 102 214 19 178 132 208 158 59 10 136 112 135 118 37 63 30 94 60 46 180 47 100 110 146 33 3 50 199 43 39 168 169 90 188 12 92 219 189 6 117 116 196 133 87 164 76 132 167 101 30 209 79 157 138 143 8 32 8 221 220 110 31 14 123 92 103 135 117 75 212 104 55 180 121 62 192 72 72 187 206 13 202 67 206 128 221 105 91 224 129 27 184 181 115 160 89 79 199 84 23 197 128 147 143 82 67 17 147 28 63 187 132 51 120 141 167 175 65 60 5 196 18 68 126 191 36 28 179 10 21 93 24 2 14 82 108 74 176 60 120 215 129 26 222 99 189 121 136 227 154 229 226 86 169 16 153 3 166 180 5 81 72 30 168 95 128 106 159 53 35 33 119 31 88 158 174 29 16 70 26 32 83 218 80 193 182 151 204 24 44 191 193 66 170 84 213 140 99 115 86 54 70 42 45 70 41 83 61 115 44 108 190 157 180 162 119 221 104 129 142 203 219 25 228 1 61 41 9 26 33 118 69 6 1 135 76 91 183 72 71 152 124 87 163 114 50 10 62 77 53 34 229 110 105 49 205 18 142 88 42 193 67 132 93 139 21 52 40 204 213 98 153 4 201 31 162 120 25 113 55 181 156 144 118 111 25 112 20 172 230 105 165 186 138 184 223 61 40 47 175 107 6 116 81 114 207 48 53 224 14 81 73 223 19 21 167 59 11 98 194 61 230 221 146 148 22 88 84 139 178 90 189 47 174 145 228 190 42 3 51 161 125 196 207 49 15 2 171 120 26 148 64 107 195 97 43 229 111 140 58 131 57 95 13 87 48 95 170 125 197 169 131 172 41 124 45 144 3 92 145 154 155 33 77 12 208 200 78 48 21 208 43 40 130 178 16 227 196 17 106 44 34 228 75 23 123 166 65 217 43 114 165 29 173 35 200 ^ +479 0 167 151 130 58 29 34 150 107 8 195 121 112 59 152 22 131 218 208 202 159 88 19 56 149 82 41 153 145 54 199 86 104 166 126 228 16 53 209 225 41 90 230 29 197 171 46 143 39 203 149 117 147 67 45 216 158 35 75 136 136 38 17 78 176 34 185 213 155 95 50 71 73 123 225 76 28 144 227 126 130 228 114 74 148 192 118 172 34 87 192 216 193 206 54 36 65 230 31 49 146 44 228 214 180 62 92 47 131 48 58 162 161 3 142 14 3 107 141 89 207 212 130 193 8 160 15 198 159 223 63 117 14 173 192 181 87 59 89 107 106 216 60 79 201 1 227 189 213 20 116 222 38 150 205 29 134 23 21 141 124 80 126 30 122 200 109 219 104 201 64 142 149 215 168 6 12 125 7 72 133 196 181 185 15 28 9 183 65 32 137 196 46 206 187 163 151 32 37 90 132 8 25 204 137 61 67 145 89 72 69 95 85 9 220 23 154 35 210 115 197 71 108 229 139 209 190 103 176 97 100 5 157 10 173 94 160 148 92 12 25 69 158 202 222 171 44 58 64 205 64 7 170 154 70 83 29 97 67 10 110 11 135 146 177 122 2 47 133 133 33 160 13 113 184 225 211 7 37 27 49 48 23 56 14 38 213 55 222 136 171 144 164 211 105 226 199 184 125 105 93 72 98 25 34 52 86 69 60 212 30 87 94 195 21 6 145 19 28 172 204 4 167 214 45 83 31 14 40 65 95 220 221 48 121 77 186 5 57 137 26 194 231 189 78 41 55 124 115 232 177 22 129 68 168 204 74 211 42 143 174 182 210 215 70 218 73 158 98 223 161 138 186 140 101 30 59 52 149 217 20 214 10 210 117 49 46 106 81 16 18 103 78 76 161 38 15 226 136 36 100 103 178 182 75 3 9 185 150 7 135 48 156 183 100 138 51 96 40 165 201 134 121 42 80 91 157 208 67 180 27 219 133 231 54 99 213 190 33 197 36 2 82 6 47 231 154 205 127 155 195 156 50 206 52 184 90 232 179 172 169 66 20 81 116 124 17 43 5 120 52 51 196 146 79 101 128 80 224 65 ^ +503 1 55 102 9 3 202 159 19 103 56 206 165 60 152 54 171 157 164 185 27 59 45 171 217 80 123 203 203 23 169 66 193 103 116 122 156 7 32 169 6 41 165 176 31 125 2 211 155 189 93 69 32 109 90 50 225 85 53 127 153 45 175 40 121 172 201 168 15 37 99 166 44 4 182 188 53 71 7 148 48 130 108 166 220 35 8 12 198 93 9 63 171 97 195 194 87 204 14 173 132 203 143 54 231 126 102 125 118 37 43 20 94 60 36 175 47 90 110 141 23 229 35 184 43 24 153 154 85 173 12 82 214 174 232 117 106 191 128 77 164 76 117 162 101 25 204 74 142 123 143 234 32 229 211 215 105 31 9 123 87 88 135 102 65 202 99 50 165 116 62 187 62 67 177 191 8 192 52 196 118 206 105 91 214 114 27 179 166 100 150 79 79 199 84 13 182 128 137 133 67 57 17 132 23 53 187 122 36 115 131 152 170 50 45 231 186 18 63 111 181 21 18 179 226 16 88 19 223 230 82 98 59 161 50 105 200 124 11 207 89 179 106 131 212 139 224 221 86 164 16 148 224 161 170 226 76 57 10 163 85 113 96 144 38 30 18 119 21 78 148 164 9 232 50 221 26 12 78 208 80 183 172 141 199 24 44 191 188 46 155 69 208 140 99 110 81 54 55 42 40 65 26 68 41 105 24 93 185 147 180 157 104 216 89 119 137 193 219 231 10 223 1 51 36 235 16 28 103 49 1 227 120 61 76 173 72 51 152 114 87 148 104 40 5 57 77 48 14 229 95 100 34 200 8 132 83 22 178 62 127 93 129 1 47 30 194 203 83 138 4 186 11 147 120 5 113 40 181 141 139 108 106 15 97 15 157 220 95 160 186 138 184 223 61 20 27 175 107 6 101 81 114 207 33 33 209 4 66 73 218 4 6 157 44 11 98 179 46 215 221 146 133 7 88 79 139 168 75 189 37 159 135 218 180 37 219 51 156 120 181 197 49 5 233 161 110 21 138 64 102 185 87 28 219 111 125 58 121 52 80 3 82 38 90 170 110 197 169 126 162 41 109 30 134 234 92 145 149 155 13 62 7 208 200 68 48 21 198 33 40 125 178 6 217 196 2 91 34 24 213 70 23 113 161 ^ +470 0 58 210 15 107 144 15 159 21 142 152 151 130 48 14 34 140 92 231 190 106 112 54 142 7 116 208 193 187 159 73 19 41 144 67 36 148 135 44 184 71 104 156 126 218 6 43 204 225 21 90 230 24 182 156 26 138 39 188 139 112 147 62 40 216 143 35 75 131 121 18 2 68 161 29 185 203 145 95 40 71 63 113 220 66 8 144 212 116 115 228 109 59 138 177 108 172 19 82 187 211 188 191 34 36 55 215 11 39 136 24 223 199 170 52 82 42 131 28 53 162 161 226 142 14 231 97 141 79 192 207 120 183 236 145 233 198 149 208 48 107 237 173 192 166 77 39 84 102 96 206 40 64 186 224 227 174 213 10 111 212 23 150 195 9 124 13 6 136 124 65 121 25 117 195 109 204 218 99 201 44 132 149 215 163 234 230 110 225 62 133 181 176 180 10 18 9 183 50 22 122 191 41 196 182 163 141 27 32 80 127 8 10 204 132 56 57 130 89 57 223 54 90 85 227 215 18 154 25 210 115 187 66 108 224 134 209 180 103 176 87 90 223 147 10 163 89 150 143 87 235 20 69 148 228 202 217 171 39 43 59 190 54 235 165 149 70 83 29 92 67 233 105 229 130 141 172 112 2 27 118 123 33 160 8 103 169 210 201 230 17 22 29 33 8 51 9 38 208 55 222 126 166 129 154 211 95 226 194 174 120 90 78 67 88 25 24 37 76 59 45 212 30 72 84 195 16 1 140 237 28 157 199 222 167 209 35 68 16 232 25 65 80 220 211 43 111 67 181 228 57 137 11 184 216 184 78 26 45 119 110 232 177 22 129 68 168 189 74 196 37 128 174 172 205 205 60 218 58 158 93 218 151 123 171 125 86 10 59 52 134 202 20 214 228 195 102 44 46 106 71 11 236 93 73 71 156 33 15 211 136 31 100 88 163 182 70 221 232 170 145 2 120 38 156 178 95 133 36 96 20 155 191 134 116 22 70 76 152 203 52 175 7 209 128 226 49 94 198 190 13 192 21 235 72 229 37 221 139 205 112 140 185 151 30 206 47 179 75 217 101 ^ +502 0 158 148 66 13 60 95 103 3 15 5 113 38 23 182 125 65 94 107 73 224 37 47 102 237 3 198 155 7 95 56 198 165 52 148 46 163 157 152 173 19 55 29 167 217 76 115 203 191 11 165 62 193 99 116 122 144 236 7 28 161 2 29 157 172 23 125 238 199 151 177 89 61 24 101 78 50 213 73 41 127 153 45 167 24 121 168 193 156 3 25 87 166 28 228 174 188 53 67 239 148 36 118 104 162 208 27 232 4 194 85 1 63 159 97 191 194 75 196 10 169 132 199 131 50 223 118 94 117 118 37 27 12 94 60 28 171 47 82 110 137 15 225 23 172 43 12 141 142 81 161 12 74 210 162 228 117 98 187 124 69 164 76 105 158 101 21 200 70 130 111 143 230 32 221 203 211 101 31 5 123 83 76 135 90 57 194 95 46 153 112 62 183 54 63 169 179 4 184 40 188 110 194 105 91 206 102 27 175 154 88 142 71 79 199 84 5 170 128 129 125 55 49 17 120 19 45 187 114 24 111 123 140 166 38 33 227 178 18 59 99 173 9 10 179 214 12 84 15 215 218 82 90 47 149 42 93 188 120 239 195 81 171 94 127 200 127 220 217 86 160 16 144 216 157 162 218 72 45 234 159 77 101 88 132 26 26 6 119 13 70 140 156 233 220 34 213 26 236 74 200 80 175 164 133 195 24 44 191 184 30 143 57 204 140 99 106 77 54 43 42 36 61 14 56 25 97 8 81 181 139 180 153 92 212 77 111 133 185 219 231 238 219 1 43 32 231 8 24 91 33 237 223 108 49 64 165 72 35 152 106 87 136 96 32 1 53 77 44 238 229 83 96 22 196 124 79 6 166 58 123 93 121 225 43 22 186 195 71 126 4 174 235 135 120 229 113 28 181 129 135 100 102 7 85 11 145 212 87 156 186 138 184 223 61 4 11 175 107 6 89 81 114 207 21 17 197 236 54 73 214 232 234 149 32 11 98 167 34 203 221 146 121 235 88 75 139 160 63 189 29 147 127 210 172 33 207 51 152 116 169 189 49 237 233 153 102 17 130 64 98 177 79 16 211 111 113 58 113 48 68 235 78 30 86 170 98 197 169 122 154 41 97 18 126 234 92 145 145 155 237 50 209 ^ +481 1 208 200 56 48 21 186 21 40 119 178 236 205 196 226 73 22 12 195 64 23 101 144 54 206 241 103 132 7 151 13 138 140 151 130 40 2 34 132 80 223 186 94 112 50 134 237 104 200 181 175 159 61 19 29 140 55 32 144 127 36 172 59 104 148 126 210 240 35 200 225 5 90 230 20 170 144 10 134 39 176 131 108 147 58 36 216 131 35 75 127 109 2 232 60 149 25 185 195 137 95 32 71 55 105 216 58 234 144 200 108 103 228 105 47 130 165 100 172 7 78 183 207 184 179 18 36 47 203 237 31 128 8 219 187 162 44 74 38 131 12 49 162 161 218 142 14 227 89 141 71 180 203 112 175 232 133 221 198 141 196 36 99 229 173 192 154 69 23 80 98 88 198 24 52 174 216 227 162 213 2 107 204 11 150 187 235 116 5 236 132 124 53 117 21 113 191 109 192 206 95 201 28 124 149 215 159 230 218 98 213 54 133 169 172 176 6 10 9 183 38 14 110 187 37 188 178 163 133 23 28 72 123 8 240 204 128 52 49 118 89 45 215 42 86 85 215 211 14 154 17 210 115 179 62 108 220 130 209 172 103 176 79 82 211 139 10 155 85 142 139 83 227 16 69 140 224 202 213 171 35 31 55 178 46 231 161 145 70 83 29 88 67 225 101 217 126 137 168 104 2 11 106 115 33 160 4 95 157 198 193 222 1 18 13 21 238 47 5 38 204 55 222 118 162 117 146 211 87 226 190 166 116 78 66 63 80 25 16 25 68 51 33 212 30 60 76 195 12 239 136 225 28 145 195 210 167 205 27 56 4 220 13 65 68 220 203 39 103 59 177 220 57 137 241 176 204 180 78 14 37 115 106 232 177 22 129 68 168 177 74 184 33 116 174 164 201 197 52 218 46 158 89 214 143 111 159 113 74 236 59 52 122 190 20 214 216 183 90 40 46 106 63 7 224 85 69 67 152 29 15 199 136 27 100 76 151 182 66 209 224 158 141 240 108 30 156 174 91 129 24 96 4 147 183 134 112 6 62 64 148 199 40 171 233 201 124 222 45 90 186 190 239 188 9 235 64 221 29 213 127 178 ^ +508 1 94 122 173 145 6 206 41 173 57 199 146 150 136 66 9 48 83 91 239 243 5 109 30 7 174 113 57 90 95 69 224 29 39 102 229 3 194 151 239 87 56 190 165 44 144 38 155 157 140 161 11 51 13 163 217 72 107 203 179 243 161 58 193 95 116 122 132 236 7 24 153 242 17 149 168 15 125 238 187 147 165 85 53 16 93 66 50 201 61 29 127 153 45 159 8 121 164 185 144 235 13 75 166 12 216 166 188 53 63 235 148 24 106 100 158 196 19 220 240 190 77 237 63 147 97 187 194 63 188 6 165 132 195 119 46 215 110 86 109 118 37 11 4 94 60 20 167 47 74 110 133 7 221 11 160 43 129 130 77 149 12 66 206 150 224 117 90 183 120 61 164 76 93 154 101 17 196 66 118 99 143 226 32 213 195 207 97 31 1 123 79 64 135 78 49 186 91 42 141 108 62 179 46 59 161 167 176 28 180 102 182 105 91 198 90 27 171 142 76 134 63 79 199 84 241 158 128 121 117 43 41 17 108 15 37 187 106 12 107 115 128 162 26 21 223 170 18 55 87 165 241 2 179 202 8 80 11 207 206 82 82 35 137 34 81 176 116 231 183 73 163 82 123 188 115 216 213 86 156 16 140 208 153 154 210 68 33 222 155 69 89 80 120 14 22 238 119 5 62 132 148 221 208 18 205 26 224 70 192 80 167 156 125 191 24 44 191 180 14 131 45 200 140 99 102 73 54 31 42 32 57 2 44 9 89 236 69 177 131 180 149 80 208 65 103 129 177 219 231 230 215 1 35 28 227 20 79 17 237 219 96 37 52 157 72 19 152 98 87 124 88 24 241 49 77 40 226 229 71 92 10 192 236 116 75 234 154 54 119 93 113 213 39 14 178 187 59 114 4 162 223 123 120 217 113 16 181 117 131 92 98 243 73 7 133 204 79 152 186 138 184 223 61 232 239 175 107 6 77 81 114 207 9 1 185 232 42 73 210 224 226 141 20 11 98 155 22 191 221 146 109 227 88 71 139 152 51 189 21 135 119 202 164 29 195 51 148 112 157 181 49 233 233 145 94 13 122 64 94 169 71 4 203 111 101 58 105 44 56 231 74 22 82 170 86 197 169 118 146 41 85 6 118 234 92 145 141 149 ^ +484 1 219 32 243 208 200 48 48 21 178 13 40 115 178 232 197 196 218 61 14 4 183 60 23 93 136 50 202 229 99 120 245 143 5 134 128 151 130 32 236 34 124 68 215 182 82 112 46 126 229 92 192 169 163 159 49 19 17 136 43 28 140 119 28 160 47 104 140 126 202 236 27 196 225 235 90 230 16 158 132 240 130 39 164 123 104 147 54 32 216 119 35 75 123 97 232 224 52 137 21 185 187 129 95 24 71 47 97 212 50 222 144 188 100 91 228 101 35 122 153 92 172 241 74 179 203 180 167 2 36 39 191 225 23 120 238 215 175 154 36 66 34 131 242 45 162 161 210 142 14 223 81 141 63 168 199 104 167 228 121 209 198 133 184 24 91 221 173 192 142 61 7 76 94 80 190 8 40 162 208 227 150 213 240 103 196 245 150 179 223 108 243 228 128 124 41 113 17 109 187 109 180 194 91 201 12 116 149 215 155 226 206 86 201 46 133 157 168 172 2 2 9 183 26 6 98 183 33 180 174 163 125 19 24 64 119 8 232 204 124 48 41 106 89 33 207 30 82 85 203 207 10 154 9 210 115 171 58 108 216 126 209 164 103 176 71 74 199 131 10 147 81 134 135 79 219 12 69 132 220 202 209 171 31 19 51 166 38 227 157 141 70 83 29 84 67 217 97 205 122 133 164 96 2 241 94 107 33 160 87 145 186 185 214 231 14 243 9 230 43 1 38 200 55 222 110 158 105 138 211 79 226 186 158 112 66 54 59 72 25 8 13 60 43 21 212 30 48 68 195 8 239 132 213 28 133 191 198 167 201 19 44 238 208 1 65 56 220 195 35 95 51 173 212 57 137 233 168 192 176 78 2 29 111 102 232 177 22 129 68 168 165 74 172 29 104 174 156 197 189 44 218 34 158 85 210 135 99 147 101 62 224 59 52 110 178 20 214 204 171 78 36 46 106 55 3 212 77 65 63 148 25 15 187 136 23 100 64 139 182 62 197 216 146 137 240 96 22 156 170 87 125 12 96 234 139 175 134 108 236 54 52 144 195 28 167 221 193 120 218 41 86 174 190 227 184 243 235 56 213 21 205 115 205 71 ^ +506 0 110 165 141 238 206 37 169 45 187 134 142 124 66 5 36 71 79 235 231 5 105 22 239 166 101 49 86 83 65 224 21 31 102 221 3 190 147 231 79 56 182 165 36 140 30 147 157 128 149 3 47 245 159 217 68 99 203 167 235 157 54 193 91 116 122 120 236 7 20 145 242 5 141 164 7 125 238 175 143 153 81 45 8 85 54 50 189 49 17 127 153 45 151 240 121 160 177 132 227 1 63 166 244 204 158 188 53 59 231 148 12 94 96 154 184 11 208 236 186 69 233 63 135 97 183 194 51 180 2 161 132 191 107 42 207 102 78 101 118 37 243 244 94 60 12 163 47 66 110 129 247 217 247 148 43 236 117 118 73 137 12 58 202 138 220 117 82 179 116 53 164 76 81 150 101 13 192 62 106 87 143 222 32 205 187 203 93 31 245 123 75 52 135 66 41 178 87 38 129 104 62 175 38 55 153 155 244 168 16 172 94 170 105 91 190 78 27 167 130 64 126 55 79 199 84 237 146 128 113 109 31 33 17 96 11 29 187 98 103 107 116 158 14 9 219 162 18 51 75 157 233 242 179 190 4 76 7 199 194 82 74 23 125 26 69 164 112 223 171 65 155 70 119 176 103 212 209 86 152 16 136 200 149 146 202 64 21 210 151 61 77 72 108 2 18 230 119 245 54 124 140 209 196 2 197 26 212 66 184 80 159 148 117 187 24 44 191 176 246 119 33 196 140 99 98 69 54 19 42 28 53 238 32 241 81 224 57 173 123 180 145 68 204 53 95 125 169 219 231 222 211 1 27 24 223 240 16 67 1 237 215 84 25 40 149 72 3 152 90 87 112 80 16 241 45 77 36 214 229 59 88 246 188 232 108 71 222 142 50 115 93 105 201 35 6 170 179 47 102 4 150 211 111 120 205 113 4 181 105 127 84 94 239 61 3 121 196 71 148 186 138 184 223 61 220 227 175 107 6 65 81 114 207 245 233 173 228 30 73 206 216 218 133 8 11 98 143 10 179 221 146 97 219 88 67 139 144 39 189 13 123 111 194 156 25 183 51 144 108 145 173 49 229 233 137 86 9 114 64 90 161 63 240 195 111 89 58 97 40 44 227 70 14 78 170 74 197 169 114 138 41 73 242 110 234 177 ^ +491 0 145 135 155 207 20 243 208 200 40 48 21 170 5 40 111 178 228 189 196 210 49 6 246 171 56 23 85 128 46 198 217 95 108 241 135 247 130 116 151 130 24 228 34 116 56 207 178 70 112 42 118 221 80 184 157 151 159 37 19 5 132 31 24 136 111 20 148 35 104 132 126 194 232 19 192 225 223 90 230 12 146 120 228 126 39 152 115 100 147 50 28 216 107 35 75 119 85 220 216 44 125 17 185 179 121 95 16 71 39 89 208 42 210 144 176 92 79 228 97 23 114 141 84 172 233 70 175 199 176 155 236 36 31 179 213 15 112 226 211 163 146 28 58 30 131 230 41 162 161 202 142 14 219 73 141 55 156 195 96 159 224 109 197 198 125 172 12 83 213 173 192 130 53 241 72 90 72 182 242 28 150 200 227 138 213 236 99 188 237 150 171 211 100 239 220 124 124 29 109 13 105 183 109 168 182 87 201 246 108 149 215 151 222 194 74 189 38 133 145 164 168 248 244 9 183 14 248 86 179 29 172 170 163 117 15 20 56 115 8 224 204 120 44 33 94 89 21 199 18 78 85 191 203 6 154 1 210 115 163 54 108 212 122 209 156 103 176 63 66 187 123 10 139 77 126 131 75 211 8 69 124 216 202 205 171 27 7 47 154 30 223 153 137 70 83 29 80 67 209 93 193 118 129 160 88 2 229 82 99 33 160 246 79 133 174 177 206 219 10 231 247 222 39 247 38 196 55 222 102 154 93 130 211 71 226 182 150 108 54 42 55 64 25 1 52 35 9 212 30 36 60 195 4 239 128 201 28 121 187 186 167 197 11 32 230 196 239 65 44 220 187 31 87 43 169 204 57 137 225 160 180 172 78 240 21 107 98 232 177 22 129 68 168 153 74 160 25 92 174 148 193 181 36 218 22 158 81 206 127 87 135 89 50 212 59 52 98 166 20 214 192 159 66 32 46 106 47 249 200 69 61 59 144 21 15 175 136 19 100 52 127 182 58 185 208 134 133 240 84 14 156 166 83 121 96 222 131 167 134 104 224 46 40 140 191 16 163 209 185 116 214 37 82 162 190 215 180 235 235 48 205 13 197 103 205 76 104 161 139 232 146 ^ +516 0 33 165 33 175 122 134 112 66 1 24 59 67 231 219 5 101 14 227 158 89 41 82 71 61 224 13 23 102 213 3 186 143 223 71 56 174 165 28 136 22 139 157 116 137 247 43 233 155 217 64 91 203 155 227 153 50 193 87 116 122 108 236 7 16 137 242 245 133 160 251 125 238 163 139 141 77 37 77 42 50 177 37 5 127 153 45 143 228 121 156 169 120 219 241 51 166 232 192 150 188 53 55 227 148 82 92 150 172 3 196 232 182 61 229 63 123 97 179 194 39 172 250 157 132 187 95 38 199 94 70 93 118 37 231 240 94 60 4 159 47 58 110 125 243 213 239 136 43 228 105 106 69 125 12 50 198 126 216 117 74 175 112 45 164 76 69 146 101 9 188 58 94 75 143 218 32 197 179 199 89 31 245 123 71 40 135 54 33 170 83 34 117 100 62 171 30 51 145 143 244 160 4 164 86 158 105 91 182 66 27 163 118 52 118 47 79 199 84 233 134 128 105 101 19 25 17 84 7 21 187 90 240 99 99 104 154 2 249 215 154 18 47 63 149 225 238 179 178 72 3 191 182 82 66 11 113 18 57 152 108 215 159 57 147 58 115 164 91 208 205 86 148 16 132 192 145 138 194 60 9 198 147 53 65 64 96 242 14 222 119 241 46 116 132 197 184 238 189 26 200 62 176 80 151 140 109 183 24 44 191 172 234 107 21 192 140 99 94 65 54 7 42 24 49 230 20 229 73 212 45 169 115 180 141 56 200 41 87 121 161 219 231 214 207 1 19 20 219 236 12 55 237 237 211 72 13 28 141 72 239 152 82 87 100 72 8 241 41 77 32 202 229 47 84 238 184 228 100 67 210 130 46 111 93 97 189 31 250 162 171 35 90 4 138 199 99 120 193 113 244 181 93 123 76 90 235 49 251 109 188 63 144 186 138 184 223 61 208 215 175 107 6 53 81 114 207 237 221 161 224 18 73 202 208 210 125 248 11 98 131 250 167 221 146 85 211 88 63 139 136 27 189 5 111 103 186 148 21 171 51 140 104 133 165 49 225 233 129 78 5 106 64 86 153 55 232 187 111 77 58 89 36 32 223 66 6 74 170 62 197 169 110 130 41 61 234 102 234 92 145 133 155 201 14 243 208 200 36 48 21 166 1 40 109 178 147 ^ +522 0 179 196 200 34 251 241 156 51 23 75 118 41 193 202 90 93 236 125 242 125 101 151 130 14 218 34 106 41 197 173 55 112 37 108 211 65 174 142 136 159 22 19 245 127 16 19 131 101 10 133 20 104 122 126 184 227 9 187 225 208 90 230 7 131 105 213 121 39 137 105 95 147 45 23 216 92 35 75 114 70 205 206 34 110 12 185 169 111 95 6 71 29 79 203 32 195 144 161 82 64 228 92 8 104 126 74 172 223 65 170 194 171 140 221 36 21 164 198 5 102 211 206 148 136 18 48 25 131 215 36 162 161 192 142 14 214 63 141 45 141 190 86 149 219 94 182 198 115 157 252 73 203 173 192 115 43 226 67 85 62 172 227 13 135 190 227 123 213 231 94 178 227 150 161 196 90 234 210 119 124 14 104 8 100 178 109 153 167 82 201 231 98 149 215 146 217 179 59 174 28 133 130 159 163 248 239 9 183 254 243 71 174 24 162 165 163 107 10 15 46 110 8 214 204 115 39 23 79 89 6 189 3 73 85 176 198 1 154 246 210 115 153 49 108 207 117 209 146 103 176 53 56 172 113 10 129 72 116 126 70 201 3 69 114 211 202 200 171 22 247 42 139 20 218 148 132 70 83 29 75 67 199 88 178 113 124 155 78 2 214 67 89 33 160 246 69 118 159 167 196 204 5 216 237 212 34 247 38 191 55 222 92 149 78 120 211 61 226 177 140 103 39 27 50 54 25 245 241 42 25 249 212 30 21 50 195 254 239 123 186 28 106 182 171 167 192 1 17 220 181 229 65 29 220 177 26 77 33 164 194 57 137 215 150 165 167 78 230 11 102 93 232 177 22 129 68 168 138 74 145 20 77 174 138 188 171 26 218 7 158 76 201 117 72 120 74 35 197 59 52 83 151 20 214 177 144 51 27 46 106 37 249 185 59 56 54 139 16 15 160 136 14 100 37 112 182 53 170 198 119 128 240 69 4 156 161 78 116 240 96 207 121 157 134 99 209 36 25 135 186 1 158 194 175 111 209 32 77 147 190 200 175 225 235 38 195 3 187 88 205 61 89 151 134 217 206 30 162 24 166 113 128 103 66 253 15 50 58 228 210 5 98 8 218 152 80 35 79 62 58 224 7 17 102 207 3 183 140 217 65 56 168 165 22 133 16 133 157 107 128 244 12 ^ +517 1 218 150 217 59 81 203 140 217 148 45 193 82 116 122 93 236 7 11 127 242 235 123 155 246 125 238 148 134 126 72 27 247 67 27 50 162 22 247 127 153 45 133 213 121 151 159 105 209 231 36 166 217 177 140 188 53 50 222 148 242 67 87 145 157 250 181 227 177 51 224 63 108 97 174 194 24 162 250 152 132 182 80 33 189 84 60 83 118 37 216 235 94 60 251 154 47 48 110 120 238 208 229 121 43 218 90 91 64 110 12 40 193 111 211 117 64 170 107 35 164 76 54 141 101 4 183 53 79 60 143 213 32 187 169 194 84 31 245 123 66 25 135 39 23 160 78 29 102 95 62 166 20 46 135 128 244 150 246 154 76 143 105 91 172 51 27 158 103 37 108 37 79 199 84 228 119 128 95 91 4 15 17 69 2 11 187 80 230 94 89 89 149 244 239 210 144 18 42 48 139 215 233 179 163 252 67 255 181 167 82 56 253 98 8 42 137 103 205 144 47 137 43 110 149 76 203 200 86 143 16 127 182 140 128 184 55 251 183 142 43 50 54 81 232 9 212 119 236 36 106 122 182 169 223 179 26 185 57 166 80 141 130 99 178 24 44 191 167 219 92 6 187 140 99 89 60 54 249 42 19 44 220 5 214 63 197 30 164 105 180 136 41 195 26 77 116 151 219 231 204 202 1 9 15 214 231 7 40 222 237 206 57 255 13 131 72 224 152 72 87 85 62 255 241 36 77 27 187 229 32 79 228 179 223 90 62 195 115 41 106 93 87 174 26 245 152 161 20 75 4 123 184 84 120 178 113 234 181 78 118 66 85 230 34 251 94 178 53 139 186 138 184 223 61 193 200 175 107 6 38 81 114 207 227 206 146 219 3 73 197 198 200 115 238 11 98 116 240 152 221 146 70 201 88 58 139 126 12 189 252 96 93 176 138 16 156 51 135 99 118 155 49 220 233 119 68 96 64 81 143 45 222 177 111 62 58 79 31 17 218 61 253 69 170 47 197 169 105 120 41 46 224 92 234 92 145 128 155 186 256 243 208 200 26 48 21 156 248 40 104 178 221 175 196 196 28 249 239 150 49 23 71 114 39 191 196 88 87 234 121 240 123 95 151 130 10 214 34 102 35 193 171 49 112 35 104 207 59 170 136 130 159 16 19 241 125 213 ^ +529 1 15 127 93 2 121 8 104 114 126 176 223 1 183 225 196 90 230 3 119 93 201 117 39 125 97 91 147 41 19 216 80 35 75 110 58 193 198 26 98 8 185 161 103 95 257 71 21 71 199 24 183 144 149 74 52 228 88 255 96 114 66 172 215 61 166 190 167 128 209 36 13 152 186 256 94 199 202 136 128 10 40 21 131 203 32 162 161 184 142 14 210 55 141 37 129 186 78 141 215 82 170 198 107 145 244 65 195 173 192 103 35 214 63 81 54 164 215 1 123 182 227 111 213 227 90 170 219 150 153 184 82 230 202 115 124 2 100 4 96 174 109 141 155 78 201 219 90 149 215 142 213 167 47 162 20 133 118 155 159 248 235 9 183 246 239 59 170 20 154 161 163 99 6 11 38 106 8 206 204 111 35 15 67 89 253 181 250 69 85 164 194 256 154 242 210 115 145 45 108 203 113 209 138 103 176 45 48 160 105 10 121 68 108 122 66 193 258 69 106 207 202 196 171 18 239 38 127 12 214 144 128 70 83 29 71 67 191 84 166 109 120 151 70 2 202 55 81 33 160 246 61 106 147 159 188 192 1 204 229 204 30 247 38 187 55 222 84 145 66 112 211 53 226 173 132 99 27 15 46 46 25 241 233 34 17 241 212 30 9 42 195 254 239 119 174 28 94 178 159 167 188 252 5 212 169 221 65 17 220 169 22 69 25 160 186 57 137 207 142 153 163 78 222 3 98 89 232 177 22 129 68 168 126 74 133 16 65 174 130 184 163 18 218 254 158 72 197 109 60 108 62 23 185 59 52 71 139 20 214 165 132 39 23 46 106 29 249 173 51 52 50 135 12 15 148 136 10 100 25 100 182 49 158 190 107 124 240 57 255 156 157 74 112 232 96 195 113 149 134 95 197 28 13 131 182 248 154 182 167 107 205 28 73 135 190 188 171 217 235 30 187 254 179 76 205 49 77 143 130 205 206 26 158 12 154 101 120 91 66 253 3 38 46 224 198 5 94 206 144 68 27 75 50 54 224 258 9 102 199 3 179 136 209 57 56 160 165 14 129 8 125 157 95 116 240 36 212 148 217 57 77 203 134 213 146 43 193 80 116 122 87 236 7 9 123 242 231 119 153 244 125 238 142 132 120 70 23 245 63 21 50 156 16 243 127 153 45 129 207 121 149 155 99 205 227 30 166 211 57 ^ +548 0 134 188 53 47 219 148 236 58 84 142 148 247 172 224 174 45 221 63 99 97 171 194 15 156 250 149 132 179 71 30 183 78 54 77 118 37 207 232 94 60 248 151 47 42 110 117 235 205 223 112 43 212 81 82 61 101 12 34 190 102 208 117 58 167 104 29 164 76 45 138 101 1 180 50 70 51 143 210 32 181 163 191 81 31 245 123 63 16 135 30 17 154 75 26 93 92 62 163 14 43 129 119 244 144 240 148 70 134 105 91 166 42 27 155 94 28 102 31 79 199 84 225 110 128 89 85 255 9 17 60 259 5 187 74 224 91 83 80 146 238 233 207 138 18 39 39 133 209 230 179 154 252 64 255 175 158 82 50 247 89 2 33 128 100 199 135 41 131 34 107 140 67 200 197 86 140 16 124 176 137 122 178 52 245 174 139 37 41 48 72 226 6 206 119 233 30 100 116 173 160 214 173 26 176 54 160 80 135 124 93 175 24 44 191 164 210 83 257 184 140 99 86 57 54 243 42 16 41 214 256 205 57 188 21 161 99 180 133 32 192 17 71 113 145 219 231 198 199 1 3 12 211 228 4 31 213 237 203 48 249 4 125 72 215 152 66 87 76 56 252 241 33 77 24 178 229 23 76 222 176 220 84 59 186 106 38 103 93 81 165 23 242 146 155 11 66 4 114 175 75 120 169 113 228 181 69 115 60 82 227 25 251 85 172 47 136 186 138 184 223 61 184 191 175 107 6 29 81 114 207 221 197 137 216 254 73 194 192 194 109 232 11 98 107 234 143 221 146 61 195 88 55 139 120 3 189 249 87 87 170 132 13 147 51 132 96 109 149 49 217 233 113 62 257 90 64 78 137 39 216 171 111 53 58 73 28 8 215 58 250 66 170 38 197 169 102 114 41 37 218 86 234 92 145 125 155 177 250 243 208 200 20 48 21 150 245 40 101 178 218 169 196 190 19 246 236 141 46 23 65 108 36 188 187 85 78 231 115 237 120 86 151 130 4 208 34 96 26 187 168 40 112 32 98 201 50 164 127 121 159 7 19 235 122 1 14 126 91 118 5 104 112 126 174 222 259 182 225 193 90 230 2 116 90 198 116 39 122 95 90 147 40 18 216 77 35 75 109 55 190 196 24 95 7 185 159 101 95 256 71 19 69 198 22 180 144 146 72 49 228 87 253 94 111 64 172 213 60 165 189 166 125 206 36 11 149 183 255 92 196 201 133 126 8 38 20 131 213 ^ +547 0 29 162 161 178 142 14 207 49 141 31 120 183 72 135 212 73 161 198 101 136 238 59 189 173 192 94 29 205 60 78 48 158 206 254 114 176 227 102 213 224 87 164 213 150 147 175 76 227 196 112 124 255 97 1 93 171 109 132 146 75 201 210 84 149 215 139 210 158 38 153 14 133 109 152 156 248 232 9 183 240 236 50 167 17 148 158 163 93 3 8 32 103 8 200 204 108 32 9 58 89 247 175 244 66 85 155 191 256 154 239 210 115 139 42 108 200 110 209 132 103 176 39 42 151 99 10 115 65 102 119 63 187 258 69 100 204 202 193 171 15 233 35 118 6 211 141 125 70 83 29 68 67 185 81 157 106 117 148 64 2 193 46 75 33 160 246 55 97 138 153 182 183 260 195 223 198 27 247 38 184 55 222 78 142 57 106 211 47 226 170 126 96 18 6 43 40 25 238 227 28 11 235 212 30 36 195 254 239 116 165 28 85 175 150 167 185 249 258 206 160 215 65 8 220 163 19 63 19 157 180 57 137 201 136 144 160 78 216 259 95 86 232 177 22 129 68 168 117 74 124 13 56 174 124 181 157 12 218 248 158 69 194 103 51 99 53 14 176 59 52 62 130 20 214 156 123 30 20 46 106 23 249 164 45 49 47 132 9 15 139 136 7 100 16 91 182 46 149 184 98 121 240 48 252 156 154 71 109 226 96 186 107 143 134 92 188 22 4 128 179 242 151 173 161 104 202 25 70 126 190 179 168 211 235 24 181 251 173 67 205 40 68 137 127 196 206 23 155 3 145 92 114 82 66 253 256 29 37 221 189 5 91 256 197 138 59 21 72 41 51 224 255 3 102 193 3 176 133 203 51 56 154 165 8 126 2 119 157 86 107 237 33 203 145 217 54 71 203 125 207 143 40 193 77 116 122 78 236 7 6 117 242 225 113 150 241 125 238 133 129 111 67 17 242 57 12 50 147 7 237 127 153 45 123 198 121 146 149 90 199 221 21 166 202 162 130 188 53 45 217 148 232 52 82 140 142 245 166 222 172 41 219 63 93 97 169 194 9 152 250 147 132 177 65 28 179 74 50 73 118 37 201 230 94 60 246 149 47 38 110 115 233 203 219 106 43 208 75 76 59 95 12 30 188 96 206 117 54 165 102 25 164 76 39 136 101 261 178 48 64 45 143 208 32 177 159 189 79 31 245 123 61 10 135 24 13 150 73 24 87 90 62 161 10 41 125 209 ^ + +global include file : # if an object is left alone for a certain time, then the # function clean_up will be called. This function can do anything, @@ -73,7 +73,8 @@ maximum local variables : 30 # Maximum amount of "eval cost" per thread - execution is halted when # it is exceeded. -maximum evaluation cost : 500000 +# This must be reasonably small for the call_out tests to finish. +maximum evaluation cost : 0x7fffffff # This is the maximum array size allowed for one single array. maximum array size : 15000 diff --git a/src/testsuite/etc/motd b/src/testsuite/etc/motd index 0ed9b5caa..3f2de64a2 100644 --- a/src/testsuite/etc/motd +++ b/src/testsuite/etc/motd @@ -4,4 +4,9 @@ The only commands in this little mudlib are: All of update, dest, ed, and rm require full pathnames as arguments. +More commands: +tests : run a series test to validate driver function. +speed : run a benchmark. +crasher: calling efun with random argument, attempt to crash driver. + Have fun. diff --git a/src/testsuite/include/tests.h b/src/testsuite/include/tests.h index b8d0f2ce6..643fc0c57 100644 --- a/src/testsuite/include/tests.h +++ b/src/testsuite/include/tests.h @@ -1,8 +1,17 @@ #ifndef TESTS_H #define TESTS_H -#define ASSERT(x) if (!(x)) { error(file_name() + ": Check failed.\n"); } -#define ASSERT2(x, r) if (!(x)) { error(file_name() + ":" + r + ", Check failed.\n"); } +#define SAFE(x) do {x} while(0) + +#define OUTPUT(x) SAFE(write(catch(error(x))); \ + if(!this_player()) { shutdown(-1); }) +#define WHERE __FILE__ + ":" + __LINE__ + +#define ASSERT(x) if (!(x)) { OUTPUT(WHERE + ", Check failed.\n"); } +#define ASSERT2(x, r) if (!(x)) { OUTPUT(WHERE + ", Check failed: " + r + ".\n"); } +#define ASSERT_EQ(x, y) if ((x) != (y) ) { \ + OUTPUT(WHERE + ", Check Failed: \n" + \ + "Expected: " + (x) + "Actual: " + (y) + "\n"); } #define SAVETP tp = this_player() #define RESTORETP { if (tp) evaluate(bind( (: enable_commands :), tp)); else { object youd_never_use_this_as_a_var = new("/single/void"); evaluate(bind( (: enable_commands :), youd_never_use_this_as_a_var)); destruct(youd_never_use_this_as_a_var); } } diff --git a/src/testsuite/inherit/master/valid.c b/src/testsuite/inherit/master/valid.c index 5ae5bf81c..70ed98ea9 100644 --- a/src/testsuite/inherit/master/valid.c +++ b/src/testsuite/inherit/master/valid.c @@ -15,7 +15,7 @@ valid_shadow(object ob) { #ifdef __PACKAGE_UIDS__ if (getuid(ob) == ROOT_UID) { - return 0; + return 1; /* for test */ } #endif if (ob->query_prevent_shadow(previous_object())) { diff --git a/src/testsuite/log/author_stats b/src/testsuite/log/author_stats deleted file mode 100644 index 9afd74b92..000000000 --- a/src/testsuite/log/author_stats +++ /dev/null @@ -1,2 +0,0 @@ -Root 0 0 -NONAME 0 0 diff --git a/src/testsuite/log/domain_stats b/src/testsuite/log/domain_stats deleted file mode 100644 index f8bc232d9..000000000 --- a/src/testsuite/log/domain_stats +++ /dev/null @@ -1,4 +0,0 @@ -Root 0 0 -Backbone 0 0 -BACKBONE 0 0 -NONAME 0 0 diff --git a/src/testsuite/single/inh.c b/src/testsuite/single/inh.c index 0516ea6dc..9fa61cb03 100644 --- a/src/testsuite/single/inh.c +++ b/src/testsuite/single/inh.c @@ -1,2 +1,3 @@ +/* this file is used by commands/speed.c */ void ifun() { } diff --git a/src/testsuite/single/tests/compiler/64bit.c b/src/testsuite/single/tests/compiler/64bit.c new file mode 100644 index 000000000..17da9de46 --- /dev/null +++ b/src/testsuite/single/tests/compiler/64bit.c @@ -0,0 +1,198 @@ +// These tests can only performed if the driver is compiled for a LP64 +// platform. Tests borrowed from LDMUD. +// https://raw.github.com/ldmud/ldmud/master/test/t-LP64-issues.c +#if MAX_INT > 2147483647 +mixed* func1() { + return ({ "0000770-1 (bitwise AND)", 0, + ((0x1000000000 & 0x1000000000) == 0x1000000000) + }); +} + +mixed* func2() { + int i = 0x1000000000; + i &= 0x1000000000; + + return ({ "0000770-2 (bitwise AND assignment)", 0, + (i == 0x1000000000) + }); +} + +mixed* func3() { + return ({ "0000770-3 (bitwise OR)", 0, + ((0x1000000000 | 0x0) == 0x1000000000) + }); +} + +mixed* func4() { + int i = 0x1000000000; + i |= 0x0; + + return ({ "0000770-4 (bitwise OR assignment)", 0, + (i == 0x1000000000) + }); +} + +mixed* func5() { + return ({ "0000770-5 (Modulus)", 0, + ((216681099904 % 100000000000) == 16681099904) + }); +} + +mixed* func6() { + int i = 216681099904; + i %= 100000000000; + + return ({ "0000770-6 (Modulus assignment)", 0, + (i == 16681099904) + }); +} + +mixed* func7() { + return ({ "0000770-7 (bitwise XOR)", 0, + ((0x10000000000 ^ 0x01000000000) == 0x11000000000) + }); +} + +mixed* func8() { + int i = 0x10000000000; + i ^= 0x01000000000; + return ({ "0000770-8 (bitwise XOR assignment)", 0, + (i == 0x11000000000) + }); +} +#endif + +#if defined(MAX_FLOAT) +mixed* func_f1() { + return ({ "float is C double:", 0, + sprintf("%.16f", + (1.0 / 3.0)) == + "0.3333333333333333" + }); +} + +mixed* func_f2() { + float i = 1.0; + i /= 3.0; + return ({ "float is C double", 0, + (sprintf("%.16f", i) == + "0.3333333333333333") + }); +} + +mixed* func_f3() { + return ({ "float literal is C double", 0, + (sprintf("%.16f", 1.0000000000000002) == + "1.0000000000000002") + }); +} + +mixed* func_f4() { + float i = 1.0000000000000002; + return ({ "float literal is C double", 0, + (sprintf("%.16f", i) == + "1.0000000000000002") + }); +} + +mixed* func_f5() { + // "int plus float" + ASSERT_EQ(2.00000000000002, + 1 + 1.00000000000002); +} + +mixed* func_f6() { + // "float plus float" + ASSERT_EQ(4.00000000000000, + 3.00000000000000 + + 1.00000000000000); +} + +mixed* func_constant_overflow1() { + // "constant int overflow", 0, + ASSERT_EQ(0x7fffffffffffffff, MAX_INT); + // Bug: When mudos parse LPC file, it treats '-123' + // as '-1 * 123'. when reading MIN_INT '-9223372036854775808' + // it will be parsed as -1 * 9223372036854775808. + // and 9223372036854775808 will cause overflow in strtoll(), + // which will return 9223372036854775807 (INT_MAX) instead. + // So MIN_INT == -1 * MAX_INT. + ASSERT_EQ(-0x7fffffffffffffff, -MAX_INT); + ASSERT_EQ("-9223372036854775807", sprintf("%d", MIN_INT)); + ASSERT(MIN_INT != MAX_INT + 1); + ASSERT(MIN_INT == -1 * MAX_INT); + ASSERT_EQ("-9223372036854775808", sprintf("%d", MAX_INT + 1)); + ASSERT_EQ("-9223372036854775807", sprintf("%d", -0x7fffffffffffffff)); + + // FluffOS use strtoll to parse constant, + // which always returns MAX_INT / MIN_INT when that happens. + ASSERT_EQ(-0x7fffffffffffffff1234, MIN_INT); + ASSERT_EQ(0x7fffffffffffffff1234, MAX_INT); + + ASSERT_EQ(8142508126285861427, 0x70ffffffffffffff + 0x1234); + ASSERT_EQ(9223372036854771149, -0x7fffffffffffffff - 0x1234); + + ASSERT_EQ(sprintf("%d", MAX_INT), "" + MAX_INT); + ASSERT_EQ(sprintf("%d", MIN_INT), "" + MIN_INT); +} + +mixed* func_constant_overflow2() { + float max_float = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000; + + ASSERT_EQ(max_float, MAX_FLOAT); + ASSERT_EQ(-max_float, -MAX_FLOAT); + ASSERT_EQ(sprintf("%f", MAX_FLOAT), "" + MAX_FLOAT); + ASSERT_EQ(sprintf("%f", MIN_FLOAT), "" + MIN_FLOAT); +} + +mixed* func_sscanf() { + int s = 0; + string res = "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000"; + float f; + + sscanf("9223372036854775807", "%d", s); + ASSERT_EQ(MAX_INT, s); + sscanf("1000009223372036854775807", "%d", s); + ASSERT_EQ(MAX_INT, s); + + sscanf("-9223372036854775807", "%d", s); + ASSERT_EQ(-1 * MAX_INT, s); + + sscanf("-9223372036854775807", "%d", s); + ASSERT_EQ(-1 * MAX_INT, s); + + sscanf(res, "%f", f); + ASSERT_EQ(MAX_FLOAT, f); +>>>>>>> f9cdbcf... Include #ifndef routine in auto generated header. +} +#endif + +nosave mixed *tests = ({ +#if MAX_INT > 2147483647 + (: func1 :), + (: func2 :), + (: func3 :), + (: func4 :), + (: func5 :), + (: func6 :), + (: func7 :), + (: func8 :), +#endif +#if defined(MAX_FLOAT) + (: func_f1 :), + (: func_f2 :), + (: func_f3 :), + (: func_f4 :), +#endif +}); + +void do_tests() { +#if MAX_INT <= 2147483647 + write("LPC int is not 64 bit, test not run: MAX_INT:" + MAX_INT + "\n"); +#else + foreach(mixed test in tests) { + mixed* result = evaluate(test); + ASSERT2(result[2], result[0]); + } +#endif +} diff --git a/src/testsuite/single/tests/compiler/constant_expr.c b/src/testsuite/single/tests/compiler/constant_expr.c index 849859e88..bc741325c 100644 --- a/src/testsuite/single/tests/compiler/constant_expr.c +++ b/src/testsuite/single/tests/compiler/constant_expr.c @@ -1,6 +1,7 @@ void do_tests() { mixed code; +#ifdef __DEBUG__ // array constants code = __TREE__ ( sizeof( ({ 1, 3, 3 }) ) ); ASSERT(same(code, ({ "number", 3 }))); @@ -34,4 +35,5 @@ void do_tests() { ASSERT(1/8.0 == 0.125); ASSERT(1.0/2 == 0.5); ASSERT(1.0/2.0 == 0.5); +#endif } diff --git a/src/testsuite/single/tests/compiler/fail/missing_type.c b/src/testsuite/single/tests/compiler/fail/missing_type.c index e901f01b4..920950343 100644 --- a/src/testsuite/single/tests/compiler/fail/missing_type.c +++ b/src/testsuite/single/tests/compiler/fail/missing_type.c @@ -1 +1,3 @@ +#pragma strict_types + foo; diff --git a/src/testsuite/single/tests/efuns/call_out.c b/src/testsuite/single/tests/efuns/call_out.c index f1dc9b995..ef3c43038 100644 --- a/src/testsuite/single/tests/efuns/call_out.c +++ b/src/testsuite/single/tests/efuns/call_out.c @@ -32,6 +32,12 @@ void finish() { void do_tests() { mixed calls, call; + if (busy) { + write("The call_out test is busy. Try again later!\n"); + return; + } + busy = 1; + tp = this_player(); called = 0; call_out( (: no_args :), 1); @@ -40,7 +46,19 @@ void do_tests() { call_out( "one_arg", 4, 1); call_out( (: two_arg, 1 :), 5, 2); call_out( "two_arg", 6, 1, 2); - call_out( "finish", 10); + + // FIXME: move the recursive test out functional test. */ + /* All call_outs set up here should be called sucessfully */ + // call_out( "spin", 0); + // call_out( "spin", 0); + + /* Only one of the recursively created call_outs should succeed */ + // call_out( "call_multiple", 0, "spin", 5); + + /* This should eventually time out */ + // call_out( "call_out_recursive_setup", 1, 0); + + // call_out( "finish", 7); calls = call_out_info(); foreach(call in calls) { diff --git a/src/testsuite/single/tests/efuns/find_call_out.c b/src/testsuite/single/tests/efuns/find_call_out.c index a539c36b6..3dde07800 100644 --- a/src/testsuite/single/tests/efuns/find_call_out.c +++ b/src/testsuite/single/tests/efuns/find_call_out.c @@ -3,4 +3,5 @@ void do_tests() { call_out("foo", 10); ASSERT(find_call_out("foo") == 10); ASSERT(find_call_out("bar") == -1); + remove_call_out("foo"); } diff --git a/src/testsuite/single/tests/efuns/read_file.c b/src/testsuite/single/tests/efuns/read_file.c index d2a547ba9..7da6d012c 100644 --- a/src/testsuite/single/tests/efuns/read_file.c +++ b/src/testsuite/single/tests/efuns/read_file.c @@ -1,10 +1,13 @@ void do_tests() { string foo = read_bytes("/testfile"); - string mid = implode(explode(foo, "\n")[99..198], "\n") + "\n"; - + string mid = implode(explode(foo, "\n")[9..18], "\n") + "\n"; + string all = implode(explode(foo, "\n")[9..<1], "\n") + "\n"; + ASSERT(!read_file("/single", 10, 10)); - ASSERT(read_file("/testfile") == foo); - ASSERT(read_file("/testfile", 100, 100) == mid); + ASSERT(foo == read_file("/testfile")); + ASSERT_EQ(mid, read_file("/testfile", 10, 10)); + // if we are asking more lines than in the file, return whole file + ASSERT(all == read_file("/testfile", 10, 0x7fffffff)); ASSERT(!read_file("/does_not_exist")); ASSERT(!read_file("/testfile", 10000, 1)); } diff --git a/src/testsuite/single/tests/efuns/restore_variable.c b/src/testsuite/single/tests/efuns/restore_variable.c index cca4cbe30..738913454 100644 --- a/src/testsuite/single/tests/efuns/restore_variable.c +++ b/src/testsuite/single/tests/efuns/restore_variable.c @@ -1,5 +1,5 @@ -#define ERR(x) ASSERT2(catch(restore_variable(x)), sprintf("%O", x)) -#define IS(x, y) ASSERT2(same(restore_variable(x),y), sprintf("%O", x)) +#define ERR(x) ASSERT2(catch(restore_variable(x)), sprintf("unexpected successful restore: %O ", x)) +#define IS(x, y) ASSERT2(same(restore_variable(x),y), sprintf("expected: %O, actual: %O", y, restore_variable(x))) string *value_errs = ({ "\"\"x", "\"\\", "\"\\x\\", "\"\\x\"x", "-x" }); diff --git a/src/testsuite/single/tests/efuns/save_object.c b/src/testsuite/single/tests/efuns/save_object.c index 0c4c095d3..272cdea40 100644 --- a/src/testsuite/single/tests/efuns/save_object.c +++ b/src/testsuite/single/tests/efuns/save_object.c @@ -11,4 +11,8 @@ void do_tests() { ASSERT(read_file("/sf.o") == "#" + __FILE__ + "\ny 1\n"); save_object("/sf", 1); ASSERT(read_file("/sf.o") == "#" + __FILE__ + "\nx 0\ny 1\n"); + + // Fluffos new behavior. + ASSERT(save_object(0) == "#" + __FILE__ + "\ny 1\n"); + ASSERT(save_object(1) == "#" + __FILE__ + "\nx 0\ny 1\n"); } diff --git a/src/testsuite/single/tests/efuns/sha1.c b/src/testsuite/single/tests/efuns/sha1.c new file mode 100644 index 000000000..f97b2a5ce --- /dev/null +++ b/src/testsuite/single/tests/efuns/sha1.c @@ -0,0 +1,102 @@ +#ifdef __PACKAGE_SHA1__ + +#define MESSAGE_FILE "/data/sha1/byte-messages.sha1" +#define HASH_FILE "/data/sha1/byte-hashes.sha1" + +string * read_data(string filename); +buffer uncompact(string input); + +void do_tests() +{ + string *messages, *hashes; + + /* Validate the hashes in http://www.nsrl.nist.gov/testdata/NSRLvectors.zip */ + messages = read_data(MESSAGE_FILE); + messages = map(messages, (: uncompact :)); + + hashes = read_data(HASH_FILE); + hashes = map(hashes, (: lower_case :)); + + ASSERT(sizeof(messages) > 0); + ASSERT_EQ(sizeof(messages), sizeof(hashes)); + + for (int i = 0; i < sizeof(messages); i++) { + ASSERT_EQ(sha1(messages[i]), hashes[i]); + } + + /* Verify that strings work too. These examples were taken from: + * http://en.wikipedia.org/wiki/SHA-1 + * http://www.nsrl.nist.gov/testdata/ + */ + ASSERT_EQ(sha1(""), + "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + ASSERT_EQ(sha1("The quick brown fox jumps over the lazy dog"), + "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"); + ASSERT_EQ(sha1("The quick brown fox jumps over the lazy cog"), + "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"); + ASSERT_EQ(sha1("abc"), + "a9993e364706816aba3e25717850c26c9cd0d89d"); + ASSERT_EQ(sha1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"), + "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); +} + +string * read_data(string filename) +{ + string contents, *lines; + + contents = read_file(filename); + contents = replace_string(contents, "\r", ""); + + lines = explode(contents, "\n"); + lines = filter(lines, (: $1[<2..] == " ^" :)); + lines = map(lines, (: $1[0..<3] :)); + + return lines; +} + +/* See /data/sha1/Readme.txt for details on string compaction */ +buffer uncompact(string input) +{ + int *counts, b, bits, char, index, count; + buffer result; + + /* Split up fields; get initial bit value (0 or 1) and array of counts */ + counts = map(explode(input, " "), (: to_int :)); + b = !!counts[1]; + counts = counts[2..]; + + /* Count how long the result will be, and allocate a buffer. Using + * buffers instead of strings because we need to support '\0' + */ + foreach (count in counts) { + bits += count; + } + result = allocate_buffer(bits / 8); + bits = 0; + + foreach (count in counts) { + while (count > 0) { + /* Optimize for all-zero or all-one bytes -- big speedup here */ + while (count >= 8 && bits == 0) { + result[index++] = b && 0xff; + count -= 8; + } + + /* Add bits individually */ + if (count--) { + char = (char << 1) | b; + if (++bits == 8) { + result[index++] = char & 0xff; + bits = 0; + } + } + } + + /* Toggle the current bit */ + b = !b; + } + + return result; +} + +#endif diff --git a/src/testsuite/single/tests/efuns/sprintf.c b/src/testsuite/single/tests/efuns/sprintf.c index 2e855aef2..cc03246df 100644 --- a/src/testsuite/single/tests/efuns/sprintf.c +++ b/src/testsuite/single/tests/efuns/sprintf.c @@ -201,7 +201,7 @@ mixed make_arg(int x, int trail) { void do_tests() { int x; mixed *mx; - string format, shouldbe; + string format, shouldbe, actual; string hmm; while (1) { @@ -209,7 +209,8 @@ void do_tests() { format = "$" + mx[0] + "^"; shouldbe = "$" + mx[1] + "^"; - ASSERT2(sprintf(format, mx[2..]...) == shouldbe, shouldbe); + actual = sprintf(format, mx[2..]...); + ASSERT2(shouldbe == actual, "expected: " + shouldbe + ", actual: " + actual); } hmm = sprintf("xxx%#-20.5s\n", "This\nis\na\ntest\nof\nsprintf\ntable\nmode\n"); diff --git a/src/trees.c b/src/trees.c index 3e8bc8b4a..38b0deb1d 100644 --- a/src/trees.c +++ b/src/trees.c @@ -343,7 +343,7 @@ parse_node_t *insert_pop_value (parse_node_t * expr) { break; case F_ASSIGN: if (IS_NODE(expr->r.expr, NODE_OPCODE_1, F_LOCAL_LVALUE)) { - long tmp = expr->r.expr->l.number; + LPC_INT tmp = expr->r.expr->l.number; expr->kind = NODE_UNARY_OP_1; expr->r.expr = expr->l.expr; expr->v.number = F_VOID_ASSIGN_LOCAL; @@ -421,7 +421,7 @@ parse_node_t *optimize_loop_test (parse_node_t * pn) { ret = pn; } else if (IS_NODE(pn, NODE_UNARY_OP, F_POST_DEC) && IS_NODE(pn->r.expr, NODE_OPCODE_1, F_LOCAL_LVALUE)) { - long lvar = pn->r.expr->l.number; + LPC_INT lvar = pn->r.expr->l.number; CREATE_OPCODE_1(ret, F_WHILE_DEC, 0, lvar); } else ret = pn; diff --git a/src/trees.h b/src/trees.h index 0870c17cc..59d957fa8 100644 --- a/src/trees.h +++ b/src/trees.h @@ -5,6 +5,7 @@ #ifndef _TREES_H #define _TREES_H #include "std.h" +#include "lpc_incl.h" #define NODES_PER_BLOCK 256 enum node_type { @@ -25,8 +26,8 @@ enum control_jump_type { }; union parse_value { - long number; - double real; + LPC_INT number; + LPC_FLOAT real; struct parse_node_s *expr; };