summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwrog <wrog>2004-05-22 01:25:43 (GMT)
committerwrog <wrog>2004-05-22 01:25:43 (GMT)
commiteb039bfdc08bd288a779014d4f0216048c789a70 (patch)
tree7851d677083d0756f183aae465eed9b6bd8a5c57
parent9305c9aa5c57241080e5d0c9029498234def197a (diff)
downloadmoo-cvs-eb039bfdc08bd288a779014d4f0216048c789a70.zip
moo-cvs-eb039bfdc08bd288a779014d4f0216048c789a70.tar.gz
moo-cvs-eb039bfdc08bd288a779014d4f0216048c789a70.tar.bz2
moo-cvs-eb039bfdc08bd288a779014d4f0216048c789a70.tar.xz
merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
-rw-r--r--Makefile.in17
-rw-r--r--config.h.in7
-rwxr-xr-xconfigure45
-rw-r--r--configure.in13
-rw-r--r--db.h35
-rw-r--r--db_file.c196
-rw-r--r--execute.c36
-rw-r--r--execute.h22
-rw-r--r--log.c20
-rw-r--r--log.h12
-rw-r--r--my-in.h14
-rw-r--r--my-string.h7
-rw-r--r--net_bsd_tcp.c69
-rw-r--r--net_multi.c80
-rw-r--r--net_single.c34
-rw-r--r--net_sysv_tcp.c85
-rw-r--r--net_tcp.c89
-rw-r--r--network.c25
-rw-r--r--options.h60
-rw-r--r--parser.y6
-rw-r--r--server.c68
-rw-r--r--server.h87
-rw-r--r--tasks.c321
-rw-r--r--tasks.h8
-rw-r--r--version.c2
25 files changed, 968 insertions, 390 deletions
diff --git a/Makefile.in b/Makefile.in
index 585ad0a..9bc4fae 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -39,6 +39,7 @@ CSRCS = ast.c code_gen.c db_file.c db_io.c db_objects.c db_properties.c \
OPT_NET_SRCS = net_single.c net_multi.c \
net_mp_selct.c net_mp_poll.c net_mp_fake.c \
+ net_tcp.c \
net_bsd_tcp.c net_bsd_lcl.c net_sysv_tcp.c net_sysv_lcl.c
OPT_NET_OBJS = $(OPT_NET_SRCS:.c=.o)
@@ -48,6 +49,7 @@ OPT_CSRCS = gnu-malloc.c $(OPT_NET_SRCS)
YSRCS = parser.y
HDRS = ast.h bf_register.h code_gen.h db.h db_io.h db_private.h decompile.h \
+ db_tune.h \
disassemble.h eval_env.h eval_vm.h exceptions.h execute.h functions.h \
getpagesize.h keywords.h list.h log.h match.h md5.h name_lookup.h \
network.h net_mplex.h net_multi.h net_proto.h numbers.h opcode.h \
@@ -137,7 +139,7 @@ tags:
etags -t $(SRCS)
clean:
- rm -f $(OBJS) core y.tab.c y.tab.h y.output makedep eddep
+ rm -f $(OBJS) $(OPT_NET_OBJS) core y.tab.c y.tab.h y.output makedep eddep
distclean: clean
rm -f config.h Makefile config.status
@@ -154,6 +156,12 @@ depend: ${ALL_CSRCS}
###############################################################################
# $Log$
+# Revision 1.9 2004/05/22 01:25:43 wrog
+# merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+#
+# Revision 1.8.10.1 2003/06/01 12:33:07 wrog
+# added net_tcp.c; (put db_tune.h in HDRS); ran makedepend
+#
# Revision 1.8 2000/05/11 06:32:27 xythian
# fixed bloody "suspicious line 293" emacs warning when saving Makefile.in
# by tweaking quotes
@@ -398,7 +406,7 @@ net_proto.o: net_proto.c options.h config.h net_bsd_tcp.c my-inet.h \
my-in.h my-types.h my-socket.h my-stdlib.h my-string.h my-unistd.h \
list.h structures.h my-stdio.h log.h name_lookup.h net_proto.h \
server.h network.h streams.h timers.h my-time.h utils.h execute.h \
- db.h program.h version.h opcode.h parse_cmd.h
+ db.h program.h version.h opcode.h parse_cmd.h net_tcp.c exceptions.h
numbers.o: numbers.c my-math.h my-stdlib.h config.h my-string.h \
my-time.h functions.h my-stdio.h execute.h db.h program.h \
structures.h version.h opcode.h options.h parse_cmd.h log.h random.h \
@@ -478,11 +486,12 @@ net_mp_selct.o: net_mp_selct.c my-string.h config.h my-sys-time.h \
options.h my-types.h log.h my-stdio.h structures.h net_mplex.h
net_mp_poll.o: net_mp_poll.c my-poll.h config.h log.h my-stdio.h \
structures.h net_mplex.h storage.h ref_count.h
+net_tcp.o: net_tcp.c
net_bsd_tcp.o: net_bsd_tcp.c my-inet.h config.h my-in.h my-types.h \
my-socket.h my-stdlib.h my-string.h my-unistd.h list.h structures.h \
my-stdio.h log.h name_lookup.h net_proto.h options.h server.h \
network.h streams.h timers.h my-time.h utils.h execute.h db.h \
- program.h version.h opcode.h parse_cmd.h
+ program.h version.h opcode.h parse_cmd.h net_tcp.c exceptions.h
net_bsd_lcl.o: net_bsd_lcl.c my-socket.h config.h my-stdio.h \
my-string.h my-unistd.h log.h structures.h net_proto.h options.h \
storage.h ref_count.h utils.h execute.h db.h program.h version.h \
@@ -491,7 +500,7 @@ net_sysv_tcp.o: net_sysv_tcp.c my-inet.h config.h my-fcntl.h my-in.h \
my-types.h my-ioctl.h my-socket.h my-stdlib.h my-string.h \
my-stropts.h my-tiuser.h my-unistd.h log.h my-stdio.h structures.h \
name_lookup.h net_proto.h options.h server.h network.h streams.h \
- timers.h my-time.h
+ timers.h my-time.h net_tcp.c exceptions.h
net_sysv_lcl.o: net_sysv_lcl.c my-fcntl.h config.h my-stat.h \
my-stdio.h my-stdlib.h my-unistd.h exceptions.h list.h structures.h \
log.h net_multi.h net_proto.h options.h storage.h ref_count.h \
diff --git a/config.h.in b/config.h.in
index ef89701..17d3871 100644
--- a/config.h.in
+++ b/config.h.in
@@ -60,6 +60,7 @@
#undef NDECL_TOLOWER /* <ctype.h> */
#undef NDECL_FCNTL /* <fcntl.h> */
#undef NDECL_HTONL /* <netinet/in.h> */
+#undef NDECL_IN_ADDR_T /* <netinet/in.h> */
#undef NDECL_IOCTL /* <sys/ioctl.h> */
#undef NDECL_POLL /* <poll.h> */
#undef NDECL_KILL /* <signal.h> */
@@ -272,6 +273,12 @@
/*
* $Log$
+ * Revision 1.3 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.2.10.1 2003/06/01 12:39:27 wrog
+ * ensure definitions for in_addr_t, INADDR_NONE
+ *
* Revision 1.2 1998/12/29 05:26:51 nop
* Fixed one more Log keyword that slipped by.
*
diff --git a/configure b/configure
index 6878b69..4884870 100755
--- a/configure
+++ b/configure
@@ -1614,6 +1614,41 @@ done
trfrom='[a-z]' trto='[A-Z]'
+for var in in_addr_t
+do
+echo "checking whether $var is declared in netinet/in.h"
+
+pattern="[^_a-zA-Z0-9]$var"
+cat > conftest.c <<EOF
+#include "confdefs.h"
+
+#include <netinet/in.h>
+
+
+EOF
+eval "$CPP conftest.c > conftest.out 2>&1"
+if egrep "$pattern" conftest.out >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ {
+test -n "$verbose" && \
+echo " defining NDECL_`echo $var | tr "$trfrom" "$trto"`"
+echo "#define" NDECL_`echo $var | tr "$trfrom" "$trto"` 1 >> confdefs.h
+DEFS="$DEFS -DNDECL_`echo $var | tr "$trfrom" "$trto"`=1"
+SEDDEFS="${SEDDEFS}\${SEDdA}NDECL_`echo $var | tr "$trfrom" "$trto"`\${SEDdB}NDECL_`echo $var | tr "$trfrom" "$trto"`\${SEDdC}1\${SEDdD}
+\${SEDuA}NDECL_`echo $var | tr "$trfrom" "$trto"`\${SEDuB}NDECL_`echo $var | tr "$trfrom" "$trto"`\${SEDuC}1\${SEDuD}
+\${SEDeA}NDECL_`echo $var | tr "$trfrom" "$trto"`\${SEDeB}NDECL_`echo $var | tr "$trfrom" "$trto"`\${SEDeC}1\${SEDeD}
+"
+}
+
+fi
+rm -f conftest*
+
+done
+
+
+trfrom='[a-z]' trto='[A-Z]'
for func in ioctl
do
echo "checking whether $func is declared in sys/ioctl.h"
@@ -2838,8 +2873,14 @@ ${CONFIG_SHELL-/bin/sh} config.status
# $Log$
-# Revision 1.1 1997/03/03 03:45:05 nop
-# Initial revision
+# Revision 1.2 2004/05/22 01:25:43 wrog
+# merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+#
+# Revision 1.1.1.1.12.1 2003/06/01 12:39:27 wrog
+# ensure definitions for in_addr_t, INADDR_NONE
+#
+# Revision 1.1.1.1 1997/03/03 03:45:05 nop
+# LambdaMOO 1.8.0p5
#
# Revision 2.8 1996/03/19 07:16:46 pavel
# Added one more option for trying to enable ANSI C compilation.
diff --git a/configure.in b/configure.in
index d814f46..d8fe691 100644
--- a/configure.in
+++ b/configure.in
@@ -321,6 +321,9 @@ AC_HAVE_FUNCS(random lrand48 wait3 wait2 sigsetmask sigprocmask sigrelse)
MOO_NDECL_FUNCS(ctype.h, tolower)
MOO_NDECL_FUNCS(fcntl.h, fcntl)
MOO_NDECL_FUNCS(netinet/in.h, htonl)
+dnl *** this next should really be some variety of AC_CHECK_TYPE
+dnl *** but this is just a grep test anyway --wrog
+MOO_NDECL_VARS(netinet/in.h, in_addr_t)
MOO_NDECL_FUNCS(sys/ioctl.h, ioctl)
MOO_NDECL_FUNCS(poll.h, poll)
MOO_NDECL_FUNCS(signal.h, kill sigemptyset sigprocmask sigrelse)
@@ -518,8 +521,14 @@ echo "----------------------------------------------------------------------"
AC_OUTPUT(Makefile)
# $Log$
-# Revision 1.1 1997/03/03 03:45:05 nop
-# Initial revision
+# Revision 1.2 2004/05/22 01:25:43 wrog
+# merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+#
+# Revision 1.1.1.1.12.1 2003/06/01 12:39:27 wrog
+# ensure definitions for in_addr_t, INADDR_NONE
+#
+# Revision 1.1.1.1 1997/03/03 03:45:05 nop
+# LambdaMOO 1.8.0p5
#
# Revision 2.8 1996/03/19 07:16:46 pavel
# Added one more option for trying to enable ANSI C compilation.
diff --git a/db.h b/db.h
index c239445..96743a1 100644
--- a/db.h
+++ b/db.h
@@ -161,13 +161,30 @@ extern int db_for_all_contents(Objid,
*/
extern void db_change_location(Objid oid, Objid location);
-/* NOTE: New flags must always be added to the end of this list, rather than
- * replacing one of the obsolete ones, since old databases might have
- * old objects around that still have that flag set.
- */
typedef enum {
- FLAG_USER, FLAG_PROGRAMMER, FLAG_WIZARD, FLAG_OBSOLETE_1,
- FLAG_READ, FLAG_WRITE, FLAG_OBSOLETE_2, FLAG_FERTILE
+ /* Permanent flags */
+ FLAG_USER,
+ FLAG_PROGRAMMER,
+ FLAG_WIZARD,
+ FLAG_OBSOLETE_1,
+ FLAG_READ,
+ FLAG_WRITE,
+ FLAG_OBSOLETE_2,
+ FLAG_FERTILE,
+ /* NOTE: New permanent flags must always be added here, rather
+ * than replacing one of the obsolete ones, since old
+ * databases might have old objects around that still have
+ * that flag set.
+ */
+
+ /* Temporary flags.
+ * (not saved; can be renumbered with impunity)
+ * make sure FLAG_FIRST_TEMP > last permanent flag
+ */
+ FLAG_FIRST_TEMP = 14,
+ /* allows space for the 2 needed by validate_hierarchies(),
+ * just in case int is only 16 bits
+ */
} db_object_flag;
extern int db_object_has_flag(Objid, db_object_flag);
@@ -518,6 +535,12 @@ extern void db_delete_verb(db_verb_handle);
/*
* $Log$
+ * Revision 1.5 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.4.10.1 2003/06/03 12:18:00 wrog
+ * allow temporary flags on objects
+ *
* Revision 1.4 2001/01/29 08:38:44 bjj
* Fix Sourceforge Bug #127620: add_verb() should return verbindex
* And now it does. Old servers always returned 0, new servers will always
diff --git a/db_file.c b/db_file.c
index 78f94f1..0918286 100644
--- a/db_file.c
+++ b/db_file.c
@@ -221,24 +221,22 @@ write_object(Objid oid)
static int
validate_hierarchies()
{
- Objid oid, log_oid;
+ Objid oid;
Objid size = db_last_used_objid() + 1;
int broken = 0;
int fixed_nexts = 0;
oklog("VALIDATING the object hierarchies ...\n");
-# define PROGRESS_INTERVAL 10000
# define MAYBE_LOG_PROGRESS \
{ \
- if (oid == log_oid) { \
- log_oid += PROGRESS_INTERVAL; \
+ if (log_report_progress()) { \
oklog("VALIDATE: Done through #%d ...\n", oid); \
} \
}
oklog("VALIDATE: Phase 1: Check for invalid objects ...\n");
- for (oid = 0, log_oid = PROGRESS_INTERVAL; oid < size; oid++) {
+ for (oid = 0; oid < size; oid++) {
Object *o = dbpriv_find_object(oid);
MAYBE_LOG_PROGRESS;
@@ -273,24 +271,28 @@ validate_hierarchies()
fixed_nexts);
oklog("VALIDATE: Phase 2: Check for cycles ...\n");
- for (oid = 0, log_oid = PROGRESS_INTERVAL; oid < size; oid++) {
+ for (oid = 0; oid < size; oid++) {
Object *o = dbpriv_find_object(oid);
MAYBE_LOG_PROGRESS;
if (o) {
-# define CHECK(start, field, name) \
- { \
- Objid oid2 = start; \
- int count = 0; \
- for (; oid2 != NOTHING \
- ; oid2 = dbpriv_find_object(oid2)->field) { \
- if (++count > size) { \
- errlog("VALIDATE: Cycle in `%s' chain of #%d\n",\
- name, oid); \
- broken = 1; \
- break; \
- } \
- } \
+# define CHECK(start, field, name) \
+ { \
+ Objid slower = start; \
+ Objid faster = slower; \
+ while (faster != NOTHING) { \
+ faster = dbpriv_find_object(faster)->field; \
+ if (faster == NOTHING) \
+ break; \
+ faster = dbpriv_find_object(faster)->field; \
+ slower = dbpriv_find_object(slower)->field; \
+ if (faster == slower) { \
+ errlog("VALIDATE: Cycle in `%s' chain of #%d\n", \
+ name, oid); \
+ broken = 1; \
+ break; \
+ } \
+ } \
}
CHECK(o->parent, parent, "parent");
@@ -299,62 +301,72 @@ validate_hierarchies()
CHECK(o->contents, next, "contents");
# undef CHECK
+
+ /* setup for phase 3: set two temp flags on every object */
+ o->flags |= (3<<FLAG_FIRST_TEMP);
}
}
if (broken) /* Can't continue if cycles found */
return 0;
- oklog("VALIDATE: Phase 3: Check for inconsistencies ...\n");
- for (oid = 0, log_oid = PROGRESS_INTERVAL; oid < size; oid++) {
+ oklog("VALIDATE: Phase 3a: Finding delusional parents ...\n");
+ for (oid = 0; oid < size; oid++) {
Object *o = dbpriv_find_object(oid);
MAYBE_LOG_PROGRESS;
if (o) {
-# define CHECK(up, up_name, down, down_name, across) \
- { \
- Objid up = o->up; \
- Objid oid2; \
- \
- /* Is oid in its up's down list? */ \
- if (up != NOTHING) { \
- for (oid2 = dbpriv_find_object(up)->down; \
- oid2 != NOTHING; \
- oid2 = dbpriv_find_object(oid2)->across) { \
- if (oid2 == oid) /* found it */ \
- break; \
- } \
- if (oid2 == NOTHING) { /* didn't find it */ \
- errlog("VALIDATE: #%d not in %s (#%d)'s %s list.\n", \
- oid, up_name, up, down_name); \
- broken = 1; \
- } \
- } \
+# define CHECK(up, down, down_name, across, FLAG) \
+ { \
+ Objid oidkid; \
+ Object *okid; \
+ \
+ for (oidkid = o->down; \
+ oidkid != NOTHING; \
+ oidkid = okid->across) { \
+ \
+ okid = dbpriv_find_object(oidkid); \
+ if (okid->up != oid) { \
+ errlog( \
+ "VALIDATE: #%d erroneously on #%d's %s list.\n", \
+ oidkid, oid, down_name); \
+ broken = 1; \
+ } \
+ else { \
+ /* mark okid as properly claimed */ \
+ okid->flags &= ~(1<<(FLAG)); \
+ } \
+ } \
}
- CHECK(parent, "parent", child, "child", sibling);
- CHECK(location, "location", contents, "contents", next);
+ CHECK(parent, child, "child", sibling, FLAG_FIRST_TEMP);
+ CHECK(location, contents, "contents", next, FLAG_FIRST_TEMP+1);
# undef CHECK
+ }
+ }
-# define CHECK(up, down, down_name, across) \
+ oklog("VALIDATE: Phase 3b: Finding delusional children ...\n");
+ for (oid = 0; oid < size; oid++) {
+ Object *o = dbpriv_find_object(oid);
+
+ MAYBE_LOG_PROGRESS;
+ if (o) {
+# define CHECK(up, up_name, down_name, FLAG) \
{ \
- Objid oid2; \
- \
- for (oid2 = o->down; \
- oid2 != NOTHING; \
- oid2 = dbpriv_find_object(oid2)->across) { \
- if (dbpriv_find_object(oid2)->up != oid) { \
- errlog( \
- "VALIDATE: #%d erroneously on #%d's %s list.\n", \
- oid2, oid, down_name); \
- broken = 1; \
- } \
+ /* If oid is unclaimed, up must be NOTHING */ \
+ if ((o->flags & (1<<(FLAG))) && o->up != NOTHING) { \
+ errlog("VALIDATE: #%d not in %s (#%d)'s %s list.\n", \
+ oid, up_name, o->up, down_name); \
+ broken = 1; \
} \
}
- CHECK(parent, child, "child", sibling);
- CHECK(location, contents, "contents", next);
+ CHECK(parent, "parent", "child", FLAG_FIRST_TEMP);
+ CHECK(location, "location", "contents", FLAG_FIRST_TEMP+1);
+
+ /* clear temp flags */
+ o->flags &= ~(3<<FLAG_FIRST_TEMP);
# undef CHECK
}
@@ -419,7 +431,7 @@ read_db_file(void)
errlog("READ_DB_FILE: Bad object #%d.\n", i - 1);
return 0;
}
- if (i % 10000 == 0 || i == nobjs)
+ if (i == nobjs || log_report_progress())
oklog("LOADING: Done reading %d objects ...\n", i);
}
@@ -449,7 +461,7 @@ read_db_file(void)
return 0;
}
db_set_verb_program(h, program);
- if (i % 5000 == 0 || i == nprogs)
+ if (i == nprogs || log_report_progress())
oklog("LOADING: Done reading %d verb programs...\n", i);
}
@@ -489,38 +501,39 @@ write_db_file(const char *reason)
user_list = db_all_users();
- TRY
+ TRY {
dbio_printf(header_format_string, current_version);
- dbio_printf("%d\n%d\n%d\n%d\n",
- max_oid + 1, nprogs, 0, user_list.v.list[0].v.num);
- for (i = 1; i <= user_list.v.list[0].v.num; i++)
- dbio_write_objid(user_list.v.list[i].v.obj);
- oklog("%s: Writing %d objects...\n", reason, max_oid + 1);
- for (oid = 0; oid <= max_oid; oid++) {
- write_object(oid);
- if ((oid + 1) % 10000 == 0 || oid == max_oid)
- oklog("%s: Done writing %d objects...\n", reason, oid + 1);
- }
- oklog("%s: Writing %d MOO verb programs...\n", reason, nprogs);
- for (i = 0, oid = 0; oid <= max_oid; oid++)
- if (valid(oid)) {
- int vcount = 0;
-
- for (v = dbpriv_find_object(oid)->verbdefs; v; v = v->next) {
- if (v->program) {
- dbio_printf("#%d:%d\n", oid, vcount);
- dbio_write_program(v->program);
- if (++i % 5000 == 0 || i == nprogs)
- oklog("%s: Done writing %d verb programs...\n",
- reason, i);
+ dbio_printf("%d\n%d\n%d\n%d\n",
+ max_oid + 1, nprogs, 0, user_list.v.list[0].v.num);
+ for (i = 1; i <= user_list.v.list[0].v.num; i++)
+ dbio_write_objid(user_list.v.list[i].v.obj);
+ oklog("%s: Writing %d objects...\n", reason, max_oid + 1);
+ for (oid = 0; oid <= max_oid; oid++) {
+ write_object(oid);
+ if (oid == max_oid || log_report_progress())
+ oklog("%s: Done writing %d objects...\n", reason, oid + 1);
+ }
+ oklog("%s: Writing %d MOO verb programs...\n", reason, nprogs);
+ for (i = 0, oid = 0; oid <= max_oid; oid++)
+ if (valid(oid)) {
+ int vcount = 0;
+
+ for (v = dbpriv_find_object(oid)->verbdefs; v; v = v->next) {
+ if (v->program) {
+ dbio_printf("#%d:%d\n", oid, vcount);
+ dbio_write_program(v->program);
+ if (++i == nprogs || log_report_progress())
+ oklog("%s: Done writing %d verb programs...\n",
+ reason, i);
+ }
+ vcount++;
}
- vcount++;
}
- }
- oklog("%s: Writing forked and suspended tasks...\n", reason);
- write_task_queue();
- oklog("%s: Writing list of formerly active connections...\n", reason);
- write_active_connections();
+ oklog("%s: Writing forked and suspended tasks...\n", reason);
+ write_task_queue();
+ oklog("%s: Writing list of formerly active connections...\n", reason);
+ write_active_connections();
+ }
EXCEPT(dbpriv_dbio_failed)
success = 0;
ENDTRY;
@@ -722,6 +735,15 @@ char rcsid_db_file[] = "$Id$";
/*
* $Log$
+ * Revision 1.5 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.4.8.2 2003/06/03 12:21:17 wrog
+ * new validation algorithms for cycle-detection and hierarchy checking
+ *
+ * Revision 1.4.8.1 2003/06/01 12:27:35 wrog
+ * added braces and fixed indentation on TRY
+ *
* Revision 1.4 1998/12/14 13:17:33 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/execute.c b/execute.c
index 114fa1d..10cb52c 100644
--- a/execute.c
+++ b/execute.c
@@ -58,7 +58,6 @@ static int ticks_remaining;
int task_timed_out;
static int interpreter_is_running = 0;
static Timer_ID task_alarm_id;
-static task_kind current_task_kind;
static const char *handler_verb_name; /* For in-DB traceback handling */
static Var handler_verb_args;
@@ -2128,7 +2127,8 @@ run_interpreter(char raise, enum error e,
if (do_db_tracebacks && h.ptr) {
ret = do_server_verb_task(SYSTEM_OBJECT, handler_verb_name,
var_ref(handler_verb_args), h,
- activ_stack[0].player, "", &handled, 0);
+ activ_stack[0].player, "", &handled,
+ 0/*no-traceback*/);
if ((ret == OUTCOME_DONE && is_true(handled))
|| ret == OUTCOME_BLOCKED) {
/* Assume the in-DB code handled it */
@@ -2182,13 +2182,12 @@ current_max_stack_size(void)
/* procedure to create a new task */
static enum outcome
-do_task(Program * prog, int which_vector, Var * result, int do_db_tracebacks)
+do_task(Program * prog, int which_vector, Var * result, int is_fg, int do_db_tracebacks)
{ /* which vector determines the vector for the root_activ.
a forked task can also have which_vector == MAIN_VECTOR.
this happens iff it is recovered from a read from disk,
because in that case the forked statement is parsed as
the main vector */
- int forked = (current_task_kind == TASK_FORKED);
RUN_ACTIV.prog = program_ref(prog);
@@ -2202,17 +2201,16 @@ do_task(Program * prog, int which_vector, Var * result, int do_db_tracebacks)
RUN_ACTIV.bi_func_pc = 0;
RUN_ACTIV.temp.type = TYPE_NONE;
- return run_interpreter(0, E_NONE, result, !forked, do_db_tracebacks);
+ return run_interpreter(0, E_NONE, result, is_fg, do_db_tracebacks);
}
/* procedure to resume an old task */
enum outcome
-resume_from_previous_vm(vm the_vm, Var v, task_kind kind, Var * result)
+resume_from_previous_vm(vm the_vm, Var v)
{
int i;
- current_task_kind = kind;
check_activ_stack_size(the_vm->max_stack_size);
top_activ_stack = the_vm->top_activ_stack;
root_activ_vector = the_vm->root_activ_vector;
@@ -2222,12 +2220,12 @@ resume_from_previous_vm(vm the_vm, Var v, task_kind kind, Var * result)
free_vm(the_vm, 0);
if (v.type == TYPE_ERR)
- return run_interpreter(1, v.v.err, result, 0, 1);
+ return run_interpreter(1, v.v.err, 0, 0/*bg*/, 1/*traceback*/);
else {
/* PUSH_REF(v) */
*(RUN_ACTIV.top_rt_stack++) = var_ref(v);
- return run_interpreter(0, E_NONE, result, 0, 1);
+ return run_interpreter(0, E_NONE, 0, 0/*bg*/, 1/*traceback*/);
}
}
@@ -2254,7 +2252,6 @@ do_server_program_task(Objid this, const char *verb, Var args, Objid vloc,
{
Var *env;
- current_task_kind = TASK_INPUT;
check_activ_stack_size(current_max_stack_size());
top_activ_stack = 0;
@@ -2279,7 +2276,7 @@ do_server_program_task(Objid this, const char *verb, Var args, Objid vloc,
set_rt_env_str(env, SLOT_VERB, str_ref(RUN_ACTIV.verb));
set_rt_env_var(env, SLOT_ARGS, args);
- return do_task(program, MAIN_VECTOR, result, do_db_tracebacks);
+ return do_task(program, MAIN_VECTOR, result, 1/*fg*/, do_db_tracebacks);
}
enum outcome
@@ -2288,7 +2285,6 @@ do_input_task(Objid user, Parsed_Command * pc, Objid this, db_verb_handle vh)
Program *prog = db_verb_program(vh);
Var *env;
- current_task_kind = TASK_INPUT;
check_activ_stack_size(current_max_stack_size());
top_activ_stack = 0;
@@ -2313,21 +2309,19 @@ do_input_task(Objid user, Parsed_Command * pc, Objid this, db_verb_handle vh)
set_rt_env_str(env, SLOT_VERB, str_ref(pc->verb));
set_rt_env_var(env, SLOT_ARGS, var_ref(pc->args));
- return do_task(prog, MAIN_VECTOR, 0, 1);
+ return do_task(prog, MAIN_VECTOR, 0, 1/*fg*/, 1/*traceback*/);
}
enum outcome
-do_forked_task(Program * prog, Var * rt_env, activation a, int f_id,
- Var * result)
+do_forked_task(Program * prog, Var * rt_env, activation a, int f_id)
{
- current_task_kind = TASK_FORKED;
check_activ_stack_size(current_max_stack_size());
top_activ_stack = 0;
RUN_ACTIV = a;
RUN_ACTIV.rt_env = rt_env;
- return do_task(prog, f_id, result, 1);
+ return do_task(prog, f_id, 0, 0/*bg*/, 1/*traceback*/);
}
/* this is called from bf_eval to set up stack for an eval call */
@@ -2878,9 +2872,17 @@ char rcsid_execute[] = "$Id$";
/*
* $Log$
+ * Revision 1.16 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
* Revision 1.15 2004/03/03 23:06:57 bjj
* Luke-Jr's patch for read_activ FUNC_NOT_FOUND
*
+ * Revision 1.14.2.1 2003/06/04 21:28:58 wrog
+ * removed useless arguments from resume_from_previous_vm(), do_forked_task();
+ * replaced current_task_kind with is_fg argument for do_task();
+ * made enum task_kind internal to tasks.c
+ *
* Revision 1.14 2002/09/15 23:21:01 xplat
* GNU indent normalization.
*
diff --git a/execute.h b/execute.h
index ec6d594..e394a62 100644
--- a/execute.h
+++ b/execute.h
@@ -70,10 +70,6 @@ typedef struct {
typedef vmstruct *vm;
-typedef enum {
- TASK_INPUT, TASK_FORKED, TASK_SUSPENDED
-} task_kind;
-
#define alloc_data(size) mymalloc(size, M_BI_FUNC_DATA)
#define free_data(ptr) myfree((void *) ptr, M_BI_FUNC_DATA)
@@ -96,13 +92,13 @@ enum outcome {
};
extern enum outcome do_forked_task(Program * prog, Var * rt_env,
- activation a, int f_id, Var * result);
+ activation a, int f_id);
extern enum outcome do_input_task(Objid user, Parsed_Command * pc,
Objid this, db_verb_handle vh);
extern enum outcome do_server_verb_task(Objid this, const char *verb,
Var args, db_verb_handle h,
Objid player, const char *argstr,
- Var * result, int do_db_tracebacks);
+ Var * result, int do_db_tracebacks);
extern enum outcome do_server_program_task(Objid this, const char *verb,
Var args, Objid vloc,
const char *verbname,
@@ -111,8 +107,7 @@ extern enum outcome do_server_program_task(Objid this, const char *verb,
const char *argstr,
Var * result,
int do_db_tracebacks);
-extern enum outcome resume_from_previous_vm(vm the_vm, Var value,
- task_kind tk, Var * result);
+extern enum outcome resume_from_previous_vm(vm the_vm, Var value);
extern int task_timed_out;
extern void abort_running_task(void);
@@ -135,6 +130,17 @@ extern int read_activ(activation * a, int which_vector);
/*
* $Log$
+ * Revision 1.8 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.7.2.2 2003/06/07 13:14:24 wrog
+ * fix log entry
+ *
+ * Revision 1.7.2.1 2003/06/04 21:28:59 wrog
+ * removed useless arguments from resume_from_previous_vm(), do_forked_task();
+ * replaced current_task_kind with is_fg argument for do_task();
+ * made enum task_kind internal to tasks.c
+ *
* Revision 1.7 2002/09/15 23:21:01 xplat
* GNU indent normalization.
*
diff --git a/log.c b/log.c
index baf7b1d..99dd0f0 100644
--- a/log.c
+++ b/log.c
@@ -38,14 +38,24 @@ set_log_file(FILE * f)
log_file = f;
}
+int log_pcount = 5000;
+static time_t log_prev = 0;
+int log_report_progress_cktime()
+{
+ time_t now = time(0);
+ log_pcount = 5000;
+ return ((now >= log_prev + 2) && (log_prev = now, 1));
+}
+
static void
do_log(const char *fmt, va_list args, const char *prefix)
{
FILE *f;
+ log_prev = time(0);
+ log_pcount = 5000;
if (log_file) {
- time_t now = time(0);
- char *nowstr = ctime(&now);
+ char *nowstr = ctime(&log_prev);
nowstr[19] = '\0'; /* kill the year and newline at the end */
f = log_file;
@@ -153,6 +163,12 @@ char rcsid_log[] = "$Id$";
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.3.10.1 2003/06/03 12:19:27 wrog
+ * added log_report_progress()
+ *
* Revision 1.3 1998/12/14 13:17:59 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/log.h b/log.h
index 2beb53e..6363fb4 100644
--- a/log.h
+++ b/log.h
@@ -30,8 +30,20 @@ extern void reset_command_history(void);
extern void log_command_history(void);
extern void add_command_to_history(Objid player, const char *command);
+
+#define log_report_progress() ((--log_pcount <= 0) && log_report_progress_cktime())
+
+extern int log_pcount;
+extern int log_report_progress_cktime();
+
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.3.10.1 2003/06/03 12:19:27 wrog
+ * added log_report_progress()
+ *
* Revision 1.3 1998/12/14 13:18:00 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/my-in.h b/my-in.h
index 1c33c25..c16b393 100644
--- a/my-in.h
+++ b/my-in.h
@@ -38,10 +38,24 @@ extern unsigned32 ntohl();
#endif
+# if NDECL_IN_ADDR_T
+typedef unsigned32 in_addr_t;
+# endif
+
+# ifndef INADDR_NONE
+# define INADDR_NONE ((in_addr_t)-1)
+# endif
+
#endif
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.3.10.1 2003/06/01 12:39:27 wrog
+ * ensure definitions for in_addr_t, INADDR_NONE
+ *
* Revision 1.3 1998/12/14 13:18:09 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/my-string.h b/my-string.h
index a95f6ca..a825f26 100644
--- a/my-string.h
+++ b/my-string.h
@@ -54,6 +54,7 @@ extern size_t strlen(const char *);
# if NDECL_MEMCPY
# include "my-types.h"
extern void *memcpy(void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t);
extern int memcmp(const void *, const void *, size_t);
# endif
# endif
@@ -87,6 +88,12 @@ extern void *memset(void *, int, size_t);
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.3.10.1 2003/06/11 10:36:14 wrog
+ * added memmove()
+ *
* Revision 1.3 1998/12/14 13:18:19 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/net_bsd_tcp.c b/net_bsd_tcp.c
index af36792..99a111b 100644
--- a/net_bsd_tcp.c
+++ b/net_bsd_tcp.c
@@ -41,37 +41,28 @@
#include "timers.h"
#include "utils.h"
+#include "net_tcp.c"
+
const char *
proto_name(void)
{
return "BSD/TCP";
}
-const char *
-proto_usage_string(void)
-{
- return "[port]";
-}
-
int
proto_initialize(struct proto *proto, Var * desc, int argc, char **argv)
{
int port = DEFAULT_PORT;
- char *p;
-
- initialize_name_lookup();
proto->pocket_size = 1;
proto->believe_eof = 1;
proto->eol_out_string = "\r\n";
- if (argc > 1)
+ if (!tcp_arguments(argc, argv, &port))
return 0;
- else if (argc == 1) {
- port = strtoul(argv[0], &p, 10);
- if (*p != '\0')
- return 0;
- }
+
+ initialize_name_lookup();
+
desc->type = TYPE_INT;
desc->v.num = port;
return 1;
@@ -103,7 +94,7 @@ proto_make_listener(Var desc, int *fd, Var * canon, const char **name)
return E_QUOTA;
}
address.sin_family = AF_INET;
- address.sin_addr.s_addr = htonl(INADDR_ANY);
+ address.sin_addr.s_addr = bind_local_ip;
address.sin_port = htons(port);
if (bind(s, (struct sockaddr *) &address, sizeof(address)) < 0) {
enum error e = E_QUOTA;
@@ -213,6 +204,9 @@ proto_open_connection(Var arglist, int *read_fd, int *write_fd,
static struct sockaddr_in addr;
static Stream *st1 = 0, *st2 = 0;
+ if (!outbound_network_enabled)
+ return E_PERM;
+
if (!st1) {
st1 = new_stream(20);
st2 = new_stream(50);
@@ -238,18 +232,39 @@ proto_open_connection(Var arglist, int *read_fd, int *write_fd,
log_perror("Making socket in proto_open_connection");
return E_QUOTA;
}
- TRY
+
+ if (bind_local_ip != INADDR_ANY) {
+ static struct sockaddr_in local_addr;
+
+ local_addr.sin_family = AF_INET;
+ local_addr.sin_addr.s_addr = bind_local_ip;
+ local_addr.sin_port = 0;
+ /* In theory, if the original listen() succeeded,
+ * then this should too, but who knows, really? */
+ if (bind(s, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0) {
+ enum error e = E_QUOTA;
+
+ log_perror("Binding local address in proto_open_connection");
+ if (errno == EACCES)
+ e = E_PERM;
+ close(s);
+ return e;
+ }
+ }
+ TRY {
id = set_timer(server_int_option("outbound_connect_timeout", 5),
timeout_proc, 0);
- result = connect(s, (struct sockaddr *) &addr, sizeof(addr));
- cancel_timer(id);
- EXCEPT(timeout_exception)
+ result = connect(s, (struct sockaddr *) &addr, sizeof(addr));
+ cancel_timer(id);
+ }
+ EXCEPT(timeout_exception) {
result = -1;
- errno = ETIMEDOUT;
- reenable_timers();
- ENDTRY
+ errno = ETIMEDOUT;
+ reenable_timers();
+ }
+ ENDTRY;
- if (result < 0) {
+ if (result < 0) {
close(s);
if (errno == EADDRNOTAVAIL ||
errno == ECONNREFUSED ||
@@ -281,6 +296,12 @@ char rcsid_net_bsd_tcp[] = "$Id$";
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.3.10.1 2003/06/01 12:42:30 wrog
+ * added cmdline options -a (source address) +O/-O (enable/disable outbound network)
+ *
* Revision 1.3 1998/12/14 13:18:27 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/net_multi.c b/net_multi.c
index 7f3d570..6608c2d 100644
--- a/net_multi.c
+++ b/net_multi.c
@@ -618,44 +618,19 @@ network_set_connection_binary(network_handle nh, int do_binary)
h->binary = do_binary;
}
-Var
-network_connection_options(network_handle nh, Var list)
-{
-#if NETWORK_PROTOCOL == NP_TCP
- nhandle *h = nh.ptr;
- Var pair;
-
- pair = new_list(2);
- pair.v.list[1].type = TYPE_STR;
- pair.v.list[1].v.str = str_dup("client-echo");
- pair.v.list[2].type = TYPE_INT;
- pair.v.list[2].v.num = h->client_echo;
- list = listappend(list, pair);
-#endif
-
- return list;
-}
-
-int
-network_connection_option(network_handle nh, const char *option, Var * value)
-{
-#if NETWORK_PROTOCOL == NP_TCP
- nhandle *h = nh.ptr;
-
- if (!mystrcasecmp(option, "client-echo")) {
- value->type = TYPE_INT;
- value->v.num = h->client_echo;
- return 1;
- }
-#endif
+#if NETWORK_PROTOCOL == NP_LOCAL
+# define NETWORK_CO_TABLE(DEFINE, nh, value, _)
+ /* No network-specific connection options */
- return 0;
-}
+#elif NETWORK_PROTOCOL == NP_TCP
+# define NETWORK_CO_TABLE(DEFINE, nh, value, _) \
+ DEFINE(client-echo, _, TYPE_INT, num, \
+ ((nhandle *)nh.ptr)->client_echo, \
+ network_set_client_echo(nh, is_true(value));) \
-int
-network_set_connection_option(network_handle nh, const char *option, Var value)
+void
+network_set_client_echo(network_handle nh, int is_on)
{
-#if NETWORK_PROTOCOL == NP_TCP
nhandle *h = nh.ptr;
/* These values taken from RFC 854 and RFC 857. */
@@ -664,25 +639,24 @@ network_set_connection_option(network_handle nh, const char *option, Var value)
#define TN_WONT 252
#define TN_ECHO 1
- {
- static char telnet_cmd[4] =
+ static char telnet_cmd[4] =
{TN_IAC, 0, TN_ECHO, 0};
- if (!mystrcasecmp(option, "client-echo")) {
- h->client_echo = is_true(value);
- if (h->client_echo)
- telnet_cmd[1] = TN_WONT;
- else
- telnet_cmd[1] = TN_WILL;
- enqueue_output(nh, telnet_cmd, 3, 0, 1);
- return 1;
- }
- }
-#endif
-
- return 0;
+ h->client_echo = is_on;
+ if (is_on)
+ telnet_cmd[1] = TN_WONT;
+ else
+ telnet_cmd[1] = TN_WILL;
+ enqueue_output(nh, telnet_cmd, 3, 0, 1);
}
+#else /* NETWORK_PROTOCOL == NP_SINGLE */
+
+# error "NP_SINGLE ???"
+
+#endif /* NETWORK_PROTOCOL */
+
+
#ifdef OUTBOUND_NETWORK
enum error
@@ -726,6 +700,12 @@ char rcsid_net_multi[] = "$Id$";
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:43 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.3.10.1 2003/06/07 12:59:04 wrog
+ * introduced connection_option macros
+ *
* Revision 1.3 1998/12/14 13:18:31 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/net_single.c b/net_single.c
index 9e20593..366870c 100644
--- a/net_single.c
+++ b/net_single.c
@@ -116,23 +116,9 @@ network_set_connection_binary(network_handle nh, int do_binary)
binary = do_binary;
}
-Var
-network_connection_options(network_handle nh, Var list)
-{
- return list;
-}
+#define NETWORK_CO_TABLE(DEFINE, nh, value, _)
+ /* No network-specific connection options */
-int
-network_connection_option(network_handle nh, const char *option, Var * value)
-{
- return 0;
-}
-
-int
-network_set_connection_option(network_handle nh, const char *option, Var value)
-{
- return 0;
-}
void
network_close(network_handle nh)
@@ -237,10 +223,20 @@ network_process_io(int timeout)
char rcsid_net_single[] = "$Id$";
-/* $Log$
-/* Revision 1.2 1997/03/03 04:19:07 nop
-/* GNU Indent normalization
/*
+ * $Log$
+ * Revision 1.3 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.2.12.2 2003/06/07 13:03:55 wrog
+ * deslashed log entries
+ *
+ * Revision 1.2.12.1 2003/06/07 12:59:04 wrog
+ * introduced connection_option macros
+ *
+ * Revision 1.2 1997/03/03 04:19:07 nop
+ * GNU Indent normalization
+ *
* Revision 1.1.1.1 1997/03/03 03:45:02 nop
* LambdaMOO 1.8.0p5
*
diff --git a/net_sysv_tcp.c b/net_sysv_tcp.c
index d6375d2..aea09c3 100644
--- a/net_sysv_tcp.c
+++ b/net_sysv_tcp.c
@@ -55,6 +55,8 @@
#include "structures.h"
#include "timers.h"
+#include "net_tcp.c"
+
static struct t_call *call = 0;
static void
@@ -72,31 +74,20 @@ proto_name(void)
return "SysV/TCP";
}
-const char *
-proto_usage_string(void)
-{
- return "[port]";
-}
-
int
proto_initialize(struct proto *proto, Var * desc, int argc, char **argv)
{
int port = DEFAULT_PORT;
- char *p;
-
- initialize_name_lookup();
proto->pocket_size = 1;
proto->believe_eof = 1;
proto->eol_out_string = "\r\n";
- if (argc > 1)
+ if (!tcp_arguments(argc, argv, &port))
return 0;
- else if (argc == 1) {
- port = strtoul(argv[0], &p, 10);
- if (*p != '\0')
- return 0;
- }
+
+ initialize_name_lookup();
+
desc->type = TYPE_INT;
desc->v.num = port;
return 1;
@@ -123,7 +114,7 @@ proto_make_listener(Var desc, int *fd, Var * canon, const char **name)
return E_QUOTA;
}
req_addr.sin_family = AF_INET;
- req_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ req_addr.sin_addr.s_addr = bind_local_ip;
req_addr.sin_port = htons(port);
requested.addr.maxlen = sizeof(req_addr);
@@ -143,7 +134,7 @@ proto_make_listener(Var desc, int *fd, Var * canon, const char **name)
if (t_errno == TACCES || (t_errno == TSYSERR && errno == EACCES))
e = E_PERM;
return e;
- } else if (port != 0 && rec_addr.sin_port != port) {
+ } else if (port != 0 && rec_addr.sin_port != htons(port)) {
errlog("Can't bind to requested port!\n");
t_close(s);
return E_QUOTA;
@@ -268,8 +259,8 @@ proto_open_connection(Var arglist, int *read_fd, int *write_fd,
* getting all those nasty little parameter-passing rules right. This
* function isn't recursive anyway, so it doesn't matter.
*/
- struct sockaddr_in rec_addr;
- struct t_bind received;
+ struct sockaddr_in rec_addr, req_addr;
+ struct t_bind received, requested, *p_requested;
static const char *host_name;
static int port;
static Timer_ID id;
@@ -278,6 +269,9 @@ proto_open_connection(Var arglist, int *read_fd, int *write_fd,
static struct sockaddr_in addr;
static Stream *st1 = 0, *st2 = 0;
+ if (!outbound_network_enabled)
+ return E_PERM;
+
if (!st1) {
st1 = new_stream(20);
st2 = new_stream(50);
@@ -304,11 +298,26 @@ proto_open_connection(Var arglist, int *read_fd, int *write_fd,
log_ti_error("Making endpoint in proto_open_connection");
return E_QUOTA;
}
+
+ if (bind_local_ip == INADDR_ANY) {
+ p_requested = 0;
+ }
+ else {
+ req_addr.sin_family = AF_INET;
+ req_addr.sin_addr.s_addr = bind_local_ip;
+ req_addr.sin_port = 0;
+
+ requested.addr.maxlen = sizeof(req_addr);
+ requested.addr.len = sizeof(req_addr);
+ requested.addr.buf = (void *) &req_addr;
+ p_requested = &requested;
+ }
+
received.addr.maxlen = sizeof(rec_addr);
received.addr.len = sizeof(rec_addr);
received.addr.buf = (void *) &rec_addr;
- if (t_bind(fd, 0, &received) < 0) {
+ if (t_bind(fd, p_requested, &received) < 0) {
log_ti_error("Binding outbound endpoint");
t_close(fd);
return E_QUOTA;
@@ -317,19 +326,21 @@ proto_open_connection(Var arglist, int *read_fd, int *write_fd,
call->addr.len = sizeof(addr);
call->addr.buf = (void *) &addr;
- TRY
+ TRY {
id = set_timer(server_int_option("outbound_connect_timeout", 5),
timeout_proc, 0);
- result = t_connect(fd, call, 0);
- cancel_timer(id);
- EXCEPT(timeout_exception)
+ result = t_connect(fd, call, 0);
+ cancel_timer(id);
+ }
+ EXCEPT(timeout_exception) {
result = -1;
- errno = ETIMEDOUT;
- t_errno = TSYSERR;
- reenable_timers();
- ENDTRY
+ errno = ETIMEDOUT;
+ t_errno = TSYSERR;
+ reenable_timers();
+ }
+ ENDTRY;
- if (result < 0) {
+ if (result < 0) {
t_close(fd);
log_ti_error("Connecting in proto_open_connection");
return E_QUOTA;
@@ -352,10 +363,20 @@ proto_open_connection(Var arglist, int *read_fd, int *write_fd,
char rcsid_net_sysv_tcp[] = "$Id$";
-/* $Log$
-/* Revision 1.2 1997/03/03 04:19:09 nop
-/* GNU Indent normalization
/*
+ * $Log$
+ * Revision 1.3 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.2.12.2 2003/06/01 13:15:18 wrog
+ * Fixed log / comment braindeath
+ *
+ * Revision 1.2.12.1 2003/06/01 12:42:30 wrog
+ * added cmdline options -a (source address) +O/-O (enable/disable outbound network)
+ *
+ * Revision 1.2 1997/03/03 04:19:09 nop
+ * GNU Indent normalization
+ *
* Revision 1.1.1.1 1997/03/03 03:45:02 nop
* LambdaMOO 1.8.0p5
*
diff --git a/net_tcp.c b/net_tcp.c
new file mode 100644
index 0000000..c1c5e13
--- /dev/null
+++ b/net_tcp.c
@@ -0,0 +1,89 @@
+/************
+ * net_tcp.c
+ *
+ * common code for
+ * multi-user networking protocol implementations for TCP/IP
+ * (net_bsd_tcp.c and net_sysv_tcp.c)
+ *
+ */
+
+#ifdef OUTBOUND_NETWORK
+static char outbound_network_enabled = OUTBOUND_NETWORK;
+#endif
+
+static in_addr_t bind_local_ip = INADDR_ANY;
+
+const char *
+proto_usage_string(void)
+{
+ return "[+O|-O] [-a ip_address] [[-p] port]";
+}
+
+
+static int
+tcp_arguments(int argc, char **argv, int *pport)
+{
+ char *p = 0;
+
+ for ( ; argc > 0; argc--, argv++) {
+ if (argc > 0
+ && (argv[0][0] == '-' || argv[0][0] == '+')
+ && argv[0][1] == 'O'
+ && argv[0][2] == 0
+ ) {
+#ifdef OUTBOUND_NETWORK
+ outbound_network_enabled = (argv[0][0] == '+');
+#else
+ if (argv[0][0] == '+') {
+ fprintf(stderr, "Outbound network not supported.\n");
+ oklog("CMDLINE: *** Ignoring %s (outbound network not supported)\n", argv[0]);
+ }
+#endif
+ }
+ else if (0 == strcmp(argv[0],"-a")) {
+ if (argc <= 1)
+ return 0;
+ argc--;
+ argv++;
+ bind_local_ip = inet_addr(argv[0]);
+ if (bind_local_ip == INADDR_NONE)
+ return 0;
+ oklog("CMDLINE: Source address restricted to %s\n", argv[0]);
+ }
+ else {
+ if (p != 0) /* strtoul always sets p */
+ return 0;
+ if (0 == strcmp(argv[0],"-p")) {
+ if (argc <= 1)
+ return 0;
+ argc--;
+ argv++;
+ }
+ *pport = strtoul(argv[0], &p, 10);
+ if (*p != '\0')
+ return 0;
+ oklog("CMDLINE: Initial port = %d\n", *pport);
+ }
+ }
+#ifdef OUTBOUND_NETWORK
+ oklog("CMDLINE: Outbound network connections %s.\n",
+ outbound_network_enabled ? "enabled" : "disabled");
+#endif
+ return 1;
+}
+
+char rcsid_net_tcp[] = "$Id$";
+
+/*
+ * $Log$
+ * Revision 1.2 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.1.2.2 2003/06/10 00:14:52 wrog
+ * fixed printf warning
+ *
+ * Revision 1.1.2.1 2003/06/01 12:42:30 wrog
+ * added cmdline options -a (source address) +O/-O (enable/disable outbound network)
+ *
+ *
+ */
diff --git a/network.c b/network.c
index dab4abf..8852f1c 100644
--- a/network.c
+++ b/network.c
@@ -23,8 +23,33 @@
# include "net_multi.c"
#endif
+Var
+network_connection_options(network_handle nh, Var list)
+{
+ CONNECTION_OPTION_LIST(NETWORK_CO_TABLE, nh, list);
+}
+
+int
+network_connection_option(network_handle nh, const char *option, Var * value)
+{
+ CONNECTION_OPTION_GET(NETWORK_CO_TABLE, nh, option, value);
+}
+
+int
+network_set_connection_option(network_handle nh, const char *option, Var value)
+{
+ CONNECTION_OPTION_SET(NETWORK_CO_TABLE, nh, option, value);
+}
+
+
/*
* $Log$
+ * Revision 1.3 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.2.10.1 2003/06/07 12:59:04 wrog
+ * introduced connection_option macros
+ *
* Revision 1.2 1998/12/14 13:18:35 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/options.h b/options.h
index 9a74658..fc518d1 100644
--- a/options.h
+++ b/options.h
@@ -53,6 +53,17 @@
#define OUT_OF_BAND_PREFIX "#$#"
/******************************************************************************
+ * If OUT_OF_BAND_QUOTE_PREFIX is defined as a non-empty string, then any
+ * lines of input from any player that begin with that prefix will be
+ * stripped of that prefix and processed normally (whether to be parsed a
+ * command or given to a pending read()ing task), even if the resulting line
+ * begins with OUT_OF_BAND_PREFIX. This provides a means of quoting lines
+ * that would otherwise spawn #0:do_out_of_band_command tasks
+ */
+
+#define OUT_OF_BAND_QUOTE_PREFIX "#$\""
+
+/******************************************************************************
* The following constants define the execution limits placed on all MOO tasks.
*
* DEFAULT_MAX_STACK_DEPTH is the default maximum depth allowed for the MOO
@@ -143,19 +154,31 @@
/* #define MPLEX_STYLE MP_POLL */
/******************************************************************************
- * Define OUTBOUND_NETWORK to enable the built-in MOO function
- * open_network_connection(), which allows (only) wizard-owned MOO code to make
- * outbound network connections from the server.
+ * The built-in MOO function open_network_connection(), when enabled,
+ * allows (only) wizard-owned MOO code to make outbound network connections
+ * from the server. When disabled, it raises E_PERM whenever called.
+ *
+ * The +O and -O command line options can explicitly enable and disable this
+ * function. If neither option is supplied, the definition given to
+ * OUTBOUND_NETWORK here determines the default behavior
+ * (use 0 to disable by default, 1 or blank to enable by default).
+ *
+ * If OUTBOUND_NETWORK is not defined at all,
+ * open_network_connection() is permanently disabled and +O is ignored.
+ *
* *** THINK VERY HARD BEFORE ENABLING THIS FUNCTION ***
- * In some contexts, this could represent a serious breach of security. By
- * default, the open_network_connection() function is disabled, always raising
- * E_PERM when called.
+ * In some contexts, this could represent a serious breach of security.
*
* Note: OUTBOUND_NETWORK may not be defined if NETWORK_PROTOCOL is either
* NP_SINGLE or NP_LOCAL.
*/
-/* #define OUTBOUND_NETWORK */
+/* disable by default, +O enables: */
+/* #define OUTBOUND_NETWORK 0 */
+
+/* enable by default, -O disables: */
+/* #define OUTBOUND_NETWORK 1 */
+
/******************************************************************************
* The following constants define certain aspects of the server's network
@@ -277,6 +300,9 @@
#ifndef OUT_OF_BAND_PREFIX
#define OUT_OF_BAND_PREFIX ""
#endif
+#ifndef OUT_OF_BAND_QUOTE_PREFIX
+#define OUT_OF_BAND_QUOTE_PREFIX ""
+#endif
#if PATTERN_CACHE_SIZE < 1
# error Illegal match() pattern cache size!
@@ -331,6 +357,14 @@
# error You cannot define "OUTBOUND_NETWORK" with that "NETWORK_PROTOCOL"
#endif
+/* make sure OUTBOUND_NETWORK has a value;
+ for backward compatibility, use 1 if none given */
+#if defined(OUTBOUND_NETWORK) && (( 0 * OUTBOUND_NETWORK - 1 ) == 0)
+#undef OUTBOUND_NETWORK
+#define OUTBOUND_NETWORK 1
+#endif
+
+
#if NETWORK_PROTOCOL != NP_LOCAL && NETWORK_PROTOCOL != NP_SINGLE && NETWORK_PROTOCOL != NP_TCP
# error Illegal value for "NETWORK_PROTOCOL"
#endif
@@ -350,6 +384,18 @@
/*
* $Log$
+ * Revision 1.9 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.8.10.3 2004/05/21 00:02:59 wrog
+ * allow for OUT_OF_BAND_QUOTE_PREFIX being undefined
+ *
+ * Revision 1.8.10.2 2003/06/11 10:36:45 wrog
+ * added OUT_OF_BAND_QUOTE_PREFIX
+ *
+ * Revision 1.8.10.1 2003/06/01 12:42:30 wrog
+ * added cmdline options -a (source address) +O/-O (enable/disable outbound network)
+ *
* Revision 1.8 2001/01/29 09:08:40 bjj
* Made STRING_INTERNING optional via options.h.
*
diff --git a/parser.y b/parser.y
index c3293d9..4e6bb14 100644
--- a/parser.y
+++ b/parser.y
@@ -1232,8 +1232,12 @@ char rcsid_parser[] = "$Id$";
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
* Revision 1.3 2004/04/09 19:52:52 bjj
- * Add missing ; to make newer bison happy.
+ * == Revision 1.2.8.1 2003/06/07 20:16:24 wrog
+ * fixed 6 rules that were missing final semicolons to make newer bison happy.
*
* Revision 1.2 1998/12/14 13:18:45 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
diff --git a/server.c b/server.c
index 5d47535..b38c1c7 100644
--- a/server.c
+++ b/server.c
@@ -559,42 +559,34 @@ init_cmdline(int argc, char *argv[])
cmdline_buflen = p - argv[0];
}
+#define SERVER_CO_TABLE(DEFINE, H, VALUE, _) \
+ DEFINE(binary, _, TYPE_INT, num, \
+ H->binary, \
+ { \
+ H->binary = is_true(VALUE); \
+ network_set_connection_binary(H->nhandle, H->binary); \
+ }) \
+
static int
server_set_connection_option(shandle * h, const char *option, Var value)
{
- if (!mystrcasecmp(option, "binary")) {
- h->binary = is_true(value);
- network_set_connection_binary(h->nhandle, h->binary);
- return 1;
- }
- return 0;
+ CONNECTION_OPTION_SET(SERVER_CO_TABLE, h, option, value);
}
static int
server_connection_option(shandle * h, const char *option, Var * value)
{
- if (!mystrcasecmp(option, "binary")) {
- value->type = TYPE_INT;
- value->v.num = h->binary;
- return 1;
- }
- return 0;
+ CONNECTION_OPTION_GET(SERVER_CO_TABLE, h, option, value);
}
static Var
server_connection_options(shandle * h, Var list)
{
- Var pair;
-
- pair = new_list(2);
- pair.v.list[1].type = TYPE_STR;
- pair.v.list[1].v.str = str_dup("binary");
- pair.v.list[2].type = TYPE_INT;
- pair.v.list[2].v.num = h->binary;
-
- return listappend(list, pair);
+ CONNECTION_OPTION_LIST(SERVER_CO_TABLE, h, list);
}
+#undef SERVER_CO_TABLE
+
static char *
read_stdin_line()
{
@@ -602,6 +594,7 @@ read_stdin_line()
char *line, buffer[1000];
int buflen;
+ fflush(stdout);
if (!s)
s = new_stream(100);
@@ -819,6 +812,7 @@ emergency_mode()
else
printf("%s\n", message);
} else if (!mystrcasecmp(command, "abort") && nargs == 0) {
+ printf("Bye. (%s)\n\n", "NOT saving database");
exit(1);
} else if (!mystrcasecmp(command, "quit") && nargs == 0) {
start_ok = 0;
@@ -870,6 +864,11 @@ emergency_mode()
}
}
+ printf("Bye. (%s)\n\n", start_ok ? "continuing" : "saving database");
+#if NETWORK_PROTOCOL != NP_SINGLE
+ fclose(stdout);
+#endif
+
free_stream(s);
in_emergency_mode = 0;
oklog("EMERGENCY_MODE: Leaving mode; %s continue...\n",
@@ -965,7 +964,7 @@ server_new_connection(server_listener sl, network_handle nh, int outbound)
h->print_messages = (!outbound && l->print_messages);
if (!outbound) {
- new_input_task(h->tasks, "");
+ new_input_task(h->tasks, "", 0);
/*
* Suspend input at the network level until the above input task
* is processed. At the point when it is dequeued, tasks.c will
@@ -1004,7 +1003,7 @@ server_receive_line(server_handle sh, const char *line)
shandle *h = (shandle *) sh.ptr;
h->last_activity_time = time(0);
- new_input_task(h->tasks, line);
+ new_input_task(h->tasks, line, h->binary);
}
void
@@ -1226,6 +1225,13 @@ main(int argc, char **argv)
this_program, db_usage_string(), network_usage_string());
exit(1);
}
+#if NETWORK_PROTOCOL != NP_SINGLE
+ if (!emergency)
+ fclose(stdout);
+#endif
+ if (log_file)
+ fclose(stderr);
+
oklog("STARTING: Version %s of the LambdaMOO server\n", server_version);
oklog(" (Using %s protocol)\n", network_protocol_name());
oklog(" (Task timeouts measured in %s seconds.)\n",
@@ -1747,9 +1753,25 @@ char rcsid_server[] = "$Id$";
/*
* $Log$
+ * Revision 1.7 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.5.10.4 2004/05/21 23:02:56 wrog
+ * NP_SINGLE needs to have stdout stay open
+ *
+ * Revision 1.5.10.3 2004/05/20 19:57:11 wrog
+ * fixed flushing issues w.r.t. emergency mode;
+ * close stdout and stderr when we are not using them
+ *
* Revision 1.6 2003/06/12 18:16:56 bjj
* Suspend input on connection until :do_login_command() can run.
*
+ * Revision 1.5.10.2 2003/06/11 10:40:16 wrog
+ * added binary argument to new_input_task()
+ *
+ * Revision 1.5.10.1 2003/06/07 12:59:04 wrog
+ * introduced connection_option macros
+ *
* Revision 1.5 1998/12/29 06:56:32 nop
* Fixed leak in onc().
*
diff --git a/server.h b/server.h
index e21811f..b3812f2 100644
--- a/server.h
+++ b/server.h
@@ -158,10 +158,97 @@ extern void boot_player(Objid player);
extern void write_active_connections(void);
extern int read_active_connections(void);
+
+
+/* Body for *_connection_option() */
+#define CONNECTION_OPTION_GET(TABLE,HANDLE,OPTION,VALUE) \
+ _STATEMENT({ \
+ TABLE(_CONNECT_OPTION_GET_SINGLE, (HANDLE), @, \
+ _RMPAREN2((OPTION),(VALUE))) \
+ return 0; \
+ })
+
+/* Body for *_set_connection_option() */
+#define CONNECTION_OPTION_SET(TABLE,HANDLE,OPTION,VALUE) \
+ _STATEMENT({ \
+ TABLE(_CONNECT_OPTION_SET_SINGLE, (HANDLE), (VALUE), \
+ _RMPAREN2((OPTION),(VALUE))) \
+ return 0; \
+ })
+
+/* Body for *_connection_options() */
+#define CONNECTION_OPTION_LIST(TABLE,HANDLE,LIST) \
+ _STATEMENT({ \
+ TABLE(_CONNECT_OPTION_LIST_SINGLE, (HANDLE), @, \
+ (LIST)) \
+ return (LIST); \
+ })
+
+/* All of the above require a TABLE of connection options #defined
+ * as follows
+ *
+ * #define TABLE(DEFINE, HANDLE, VALUE, _)
+ * DEFINE(<name>, _, TYPE_<foo>, <member>,
+ * <get-value-expression>,
+ * <set-value-statement>)
+ * ...
+ *
+ * where
+ * <get-value-expression>
+ * should extract from HANDLE a value for option <name>
+ * of type suitable for assignment to Var.v.<member>
+ * <set-value-expression>
+ * should do whatever needs to be done to HANDLE
+ * to reflect the new VALUE
+ */
+
+/*
+ * Helper macros for CONNECTION_OPTION_(GET|SET|LIST)
+ * (nothing should need to invoke these directly):
+ */
+#define _RMPAREN2(ARG1,ARG2) ARG1,ARG2
+#define _STATEMENT(STMT) do STMT while (0)
+
+#define _CONNECT_OPTION_GET_SINGLE(NAME, OPTION, VALUE, \
+ TYPE_FOO, VFOO_MEMBER, \
+ GETVALUE, SETVALUE) \
+ if (!mystrcasecmp(OPTION, #NAME)) { \
+ VALUE->type = (TYPE_FOO); \
+ VALUE->v.VFOO_MEMBER = (GETVALUE); \
+ return 1; \
+ }
+
+#define _CONNECT_OPTION_SET_SINGLE(NAME, OPTION, VALUE, \
+ TYPE_FOO, VFOO_MEMBER, \
+ GETVALUE, SETVALUE) \
+ if (!mystrcasecmp(OPTION, #NAME)) { \
+ SETVALUE; \
+ return 1; \
+ }
+
+#define _CONNECT_OPTION_LIST_SINGLE(NAME, LIST, \
+ TYPE_FOO, VFOO_MEMBER, \
+ GETVALUE, SETVALUE) \
+ { \
+ Var pair = new_list(2); \
+ pair.v.list[1].type = TYPE_STR; \
+ pair.v.list[1].v.str = str_dup(#NAME); \
+ pair.v.list[2].type = (TYPE_FOO); \
+ pair.v.list[2].v.VFOO_MEMBER = (GETVALUE); \
+ LIST = listappend(LIST, pair); \
+ } \
+
+
#endif /* Server_H */
/*
* $Log$
+ * Revision 1.4 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.3.10.1 2003/06/07 12:59:04 wrog
+ * introduced connection_option macros
+ *
* Revision 1.3 1998/12/14 13:18:58 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/tasks.c b/tasks.c
index 12a14f9..864d5ae 100644
--- a/tasks.c
+++ b/tasks.c
@@ -43,6 +43,17 @@
#include "verbs.h"
#include "version.h"
+typedef enum {
+ /* Input Tasks */
+ TASK_INBAND, /* vanilla in-band */
+ TASK_OOB, /* out-of-band unless disable_oob */
+ TASK_QUOTED, /* in-band; needs unquote unless disable-oob */
+ TASK_BINARY, /* in-band; binary mode string */
+ /* Background Tasks */
+ TASK_FORKED,
+ TASK_SUSPENDED,
+} task_kind;
+
typedef struct forked_task {
int id;
Program *program;
@@ -61,6 +72,7 @@ typedef struct suspended_task {
typedef struct {
char *string;
int length;
+ struct task *next_itail; /* see tqueue.first_itail */
} input_task;
typedef struct task {
@@ -88,7 +100,8 @@ typedef struct tqueue {
* negative `player' slots) are treated specially: they are passed to a
* particular verb on the system object. If that verb returns a valid
* player object number, then that is used as the new player number for the
- * connection.
+ * connection. (Note that none of this applies to tasks that are being
+ * read() or that are being handled as out-of-band commands.)
*
* The `connected' field is true iff this queue has an associated open
* network connection. Queues without such connections may nonetheless
@@ -102,20 +115,35 @@ typedef struct tqueue {
Objid handler;
int connected;
task *first_input, **last_input;
+ task *first_itail, **last_itail;
+ /* The input queue alternates between contiguous sequences of TASK_OOBs
+ * and sequences of non-TASK_OOBs; the "itail queue" is the queue of all
+ * sequence-ending tasks threaded along the next_itail pointers.
+ * first_itail is null iff first_input is null
+ * When the queue is nonempty,
+ * last_itail points to the penultimate .next_itail pointer slot
+ * unlike last_input which always points to the final (null)
+ * .next pointer slot
+ * For tasks not at the end of a sequence,
+ * the next_itail field is ignored and may be garbage.
+ */
int total_input_length;
int last_input_task_id;
int input_suspended;
+
task *first_bg, **last_bg;
int usage; /* a kind of inverted priority */
int num_bg_tasks; /* in either here or waiting_tasks */
- int hold_input; /* make input tasks wait for read() */
char *output_prefix, *output_suffix;
const char *flush_cmd;
Stream *program_stream;
Objid program_object;
const char *program_verb;
- char reading; /* boolean */
+ /* booleans */
+ char hold_input; /* input tasks must wait for read() */
+ char disable_oob; /* treat all input lines as inband */
+ char reading; /* some task is blocked on read() */
vm reading_vm;
} tqueue;
@@ -213,8 +241,9 @@ find_tqueue(Objid player, int create_if_not_found)
tq->handler = 0;
tq->connected = 0;
- tq->first_input = tq->first_bg = 0;
+ tq->first_input = tq->first_itail = tq->first_bg = 0;
tq->last_input = &(tq->first_input);
+ tq->last_itail = &(tq->first_itail);
tq->last_bg = &(tq->first_bg);
tq->total_input_length = tq->input_suspended = 0;
@@ -224,6 +253,7 @@ find_tqueue(Objid player, int create_if_not_found)
tq->reading = 0;
tq->hold_input = 0;
+ tq->disable_oob = 0;
tq->num_bg_tasks = 0;
tq->last_input_task_id = 0;
@@ -277,17 +307,52 @@ dequeue_bg_task(tqueue * tq)
return t;
}
+static char oob_quote_prefix[] = OUT_OF_BAND_QUOTE_PREFIX;
+#define oob_quote_prefix_length (sizeof(oob_quote_prefix) - 1)
+
+enum dequeue_how { DQ_FIRST = -1, DQ_OOB = 0, DQ_INBAND = 1 };
+
static task *
-dequeue_input_task(tqueue * tq)
+dequeue_input_task(tqueue * tq, enum dequeue_how how)
{
- task *t = tq->first_input;
+ task *t;
+ task **pt, **pitail;
+
+ if (tq->disable_oob) {
+ if (how == DQ_OOB)
+ return 0;
+ how = DQ_FIRST;
+ }
+
+ if (!tq->first_input)
+ return 0;
+ else if (how == (tq->first_input->kind == TASK_OOB)) {
+ pt = &(tq->first_itail->next);
+ pitail = &(tq->first_itail->t.input.next_itail);
+ }
+ else {
+ pt = &(tq->first_input);
+ pitail = &(tq->first_itail);
+ }
+ t = *pt;
if (t) {
- tq->first_input = t->next;
+ *pt = t->next;
if (t->next == 0)
- tq->last_input = &(tq->first_input);
+ tq->last_input = pt;
else
t->next = 0;
+
+ if (t == *pitail) {
+ *pitail = 0;
+ if (t->t.input.next_itail) {
+ tq->first_itail = t->t.input.next_itail;
+ t->t.input.next_itail = 0;
+ }
+ if (*(tq->last_itail) == 0)
+ tq->last_itail = &(tq->first_itail);
+ }
+
tq->total_input_length -= t->t.input.length;
if (tq->input_suspended
&& tq->connected
@@ -295,27 +360,34 @@ dequeue_input_task(tqueue * tq)
server_resume_input(tq->player);
tq->input_suspended = 0;
}
+
+ if (t->kind == TASK_OOB) {
+ if (tq->disable_oob)
+ t->kind = TASK_INBAND;
+ }
+ else if (t->kind == TASK_QUOTED) {
+ if (!tq->disable_oob)
+ memmove(t->t.input.string,
+ t->t.input.string + oob_quote_prefix_length,
+ 1 + strlen(t->t.input.string + oob_quote_prefix_length));
+ t->kind = TASK_INBAND;
+ }
}
return t;
}
-static task *
-dequeue_any_task(tqueue * tq)
-{
- task *t = dequeue_input_task(tq);
-
- if (t)
- return t;
- else
- return dequeue_bg_task(tq);
-}
-
static void
free_task(task * t, int strong)
{ /* for FORKED tasks, strong == 1 means free the rt_env also.
for SUSPENDED tasks, strong == 1 means free the vm also. */
switch (t->kind) {
- case TASK_INPUT:
+ default:
+ panic("Unknown task kind in free_task()");
+ break;
+ case TASK_BINARY:
+ case TASK_INBAND:
+ case TASK_QUOTED:
+ case TASK_OOB:
free_str(t->t.input.string);
break;
case TASK_FORKED:
@@ -570,11 +642,11 @@ do_login_task(tqueue * tq, char *command)
}
if (dead_tq) { /* Copy over tasks from old queue for player */
tq->num_bg_tasks = dead_tq->num_bg_tasks;
- while ((t = dequeue_any_task(dead_tq)) != 0) {
- if (t->kind == TASK_INPUT)
- free_task(t, 0);
- else /* FORKED or SUSPENDED */
- enqueue_bg_task(tq, t);
+ while ((t = dequeue_input_task(dead_tq, DQ_FIRST)) != 0) {
+ free_task(t, 0);
+ }
+ while ((t = dequeue_bg_task(dead_tq)) != 0) {
+ enqueue_bg_task(tq, t);
}
dead_tq->player = NOTHING; /* it'll be freed by run_ready_tasks */
dead_tq->num_bg_tasks = 0;
@@ -629,92 +701,104 @@ free_task_queue(task_queue q)
ensure_usage(tq);
}
+#define TASK_CO_TABLE(DEFINE, tq, value, _) \
+ DEFINE(flush-command, _, TYPE_STR, str, \
+ tq->flush_cmd ? str_ref(tq->flush_cmd) : str_dup(""), \
+ { \
+ if (tq->flush_cmd) \
+ free_str(tq->flush_cmd); \
+ if (value.type == TYPE_STR && value.v.str[0] != '\0') \
+ tq->flush_cmd = str_ref(value.v.str); \
+ else \
+ tq->flush_cmd = 0; \
+ }) \
+ \
+ DEFINE(hold-input, _, TYPE_INT, num, \
+ tq->hold_input, \
+ { \
+ tq->hold_input = is_true(value); \
+ /* Anything to be done? */ \
+ if (!tq->hold_input && tq->first_input) \
+ ensure_usage(tq); \
+ }) \
+ \
+ DEFINE(disable-oob, _, TYPE_INT, num, \
+ tq->disable_oob, \
+ { \
+ tq->disable_oob = is_true(value); \
+ /* Anything to be done? */ \
+ if (!tq->disable_oob && tq->first_input \
+ && (tq->first_itail->next \
+ || tq->first_input->kind == TASK_OOB)) \
+ ensure_usage(tq); \
+ }) \
+
int
tasks_set_connection_option(task_queue q, const char *option, Var value)
{
- tqueue *tq = q.ptr;
-
- if (!mystrcasecmp(option, "flush-command")) {
- if (tq->flush_cmd)
- free_str(tq->flush_cmd);
- if (value.type == TYPE_STR && value.v.str[0] != '\0')
- tq->flush_cmd = str_ref(value.v.str);
- else
- tq->flush_cmd = 0;
-
- return 1;
- }
- if (!mystrcasecmp(option, "hold-input")) {
- tq->hold_input = is_true(value);
- if (!tq->hold_input && tq->first_input) /* Anything to be done? */
- ensure_usage(tq);
- return 1;
- }
- return 0;
+ CONNECTION_OPTION_SET(TASK_CO_TABLE, (tqueue *)q.ptr, option, value);
}
int
tasks_connection_option(task_queue q, const char *option, Var * value)
{
- tqueue *tq = q.ptr;
-
- if (!mystrcasecmp(option, "flush-command")) {
- value->type = TYPE_STR;
- value->v.str = (tq->flush_cmd ? str_ref(tq->flush_cmd) : str_dup(""));
- return 1;
- }
- if (!mystrcasecmp(option, "hold-input")) {
- value->type = TYPE_INT;
- value->v.num = tq->hold_input;
- return 1;
- }
- return 0;
+ CONNECTION_OPTION_GET(TASK_CO_TABLE, (tqueue *)q.ptr, option, value);
}
Var
tasks_connection_options(task_queue q, Var list)
{
- tqueue *tq = q.ptr;
- Var pair;
-
- pair = new_list(2);
- pair.v.list[1].type = TYPE_STR;
- pair.v.list[1].v.str = str_dup("flush-command");
- pair.v.list[2].type = TYPE_STR;
- pair.v.list[2].v.str = (tq->flush_cmd ? str_ref(tq->flush_cmd)
- : str_dup(""));
- list = listappend(list, pair);
-
- pair = new_list(2);
- pair.v.list[1].type = TYPE_STR;
- pair.v.list[1].v.str = str_dup("hold-input");
- pair.v.list[2].type = TYPE_INT;
- pair.v.list[2].v.num = tq->hold_input;
- list = listappend(list, pair);
-
- return list;
+ CONNECTION_OPTION_LIST(TASK_CO_TABLE, (tqueue *)q.ptr, list);
}
+#undef TASK_CO_TABLE
+
static void
-enqueue_input_task(tqueue * tq, const char *input, int at_front)
+enqueue_input_task(tqueue * tq, const char *input, int at_front, int binary)
{
+ static char oob_prefix[] = OUT_OF_BAND_PREFIX;
task *t;
t = (task *) mymalloc(sizeof(task), M_TASK);
- t->kind = TASK_INPUT;
+ if (binary)
+ t->kind = TASK_BINARY;
+ else if (oob_quote_prefix_length > 0
+ && strncmp(oob_quote_prefix, input, oob_quote_prefix_length) == 0)
+ t->kind = TASK_QUOTED;
+ else if (sizeof(oob_prefix) > 1
+ && strncmp(oob_prefix, input, sizeof(oob_prefix) - 1) == 0)
+ t->kind = TASK_OOB;
+ else
+ t->kind = TASK_INBAND;
+
t->t.input.string = str_dup(input);
tq->total_input_length += (t->t.input.length = strlen(input));
+ t->t.input.next_itail = 0;
if (at_front && tq->first_input) { /* if nothing there, front == back */
+ if ((tq->first_input->kind == TASK_OOB) != (t->kind == TASK_OOB)) {
+ t->t.input.next_itail = tq->first_itail;
+ tq->first_itail = t;
+ if (tq->last_itail == &(tq->first_itail))
+ tq->last_itail = &(t->t.input.next_itail);
+ }
t->next = tq->first_input;
tq->first_input = t;
- } else {
+ }
+ else {
+ if (tq->first_input && (((*(tq->last_itail))->kind == TASK_OOB)
+ != (t->kind == TASK_OOB)))
+ tq->last_itail = &((*(tq->last_itail))->t.input.next_itail);
+ *(tq->last_itail) = t;
+
*(tq->last_input) = t;
tq->last_input = &(t->next);
t->next = 0;
}
- if (!tq->hold_input || tq->reading) /* Anything to do with this line? */
+ /* Anything to do with this line? */
+ if (!tq->hold_input || tq->reading
+ || (!tq->disable_oob && t->kind == TASK_OOB))
ensure_usage(tq);
if (!tq->input_suspended
@@ -745,7 +829,8 @@ flush_input(tqueue * tq, int show_messages)
if (show_messages)
notify(tq->player, ">> Flushing the following pending input:");
- while ((t = dequeue_input_task(tq)) != 0) {
+ while ((t = dequeue_input_task(tq, DQ_FIRST)) != 0) {
+ /* TODO*** flush only non-TASK_OOB tasks ??? */
if (show_messages) {
stream_printf(s, ">> %s", t->t.input.string);
notify(tq->player, reset_stream(s));
@@ -759,7 +844,7 @@ flush_input(tqueue * tq, int show_messages)
}
void
-new_input_task(task_queue q, const char *input)
+new_input_task(task_queue q, const char *input, int binary)
{
tqueue *tq = q.ptr;
@@ -767,7 +852,7 @@ new_input_task(task_queue q, const char *input)
flush_input(tq, 1);
return;
}
- enqueue_input_task(tq, input, 0);
+ enqueue_input_task(tq, input, 0/*at-rear*/, binary);
}
static void
@@ -921,7 +1006,7 @@ read_input_now(Objid connection)
if (!tq || is_out_of_input(tq)) {
r.type = TYPE_ERR;
r.v.err = E_INVARG;
- } else if (!(t = dequeue_input_task(tq))) {
+ } else if (!(t = dequeue_input_task(tq, DQ_INBAND))) {
r.type = TYPE_INT;
r.v.num = 0;
} else {
@@ -998,7 +1083,6 @@ run_ready_tasks(void)
{
int did_one = 0;
time_t start = time(0);
- static char oob_prefix[] = OUT_OF_BAND_PREFIX;
while (active_tqueues && !did_one) {
/* Loop over tqueues, looking for a task */
@@ -1011,33 +1095,36 @@ run_ready_tasks(void)
current_task_id = tq->reading_vm->task_id;
v.type = TYPE_ERR;
v.v.err = E_INVARG;
- resume_from_previous_vm(tq->reading_vm, v, TASK_INPUT, 0);
+ resume_from_previous_vm(tq->reading_vm, v);
did_one = 1;
}
while (!did_one) { /* Loop over tasks, looking for runnable one */
- if (tq->hold_input && !tq->reading)
+ t = dequeue_input_task(tq, ((tq->hold_input && !tq->reading)
+ ? DQ_OOB
+ : DQ_FIRST));
+ if (!t)
t = dequeue_bg_task(tq);
- else
- t = dequeue_any_task(tq);
if (!t)
break;
switch (t->kind) {
- case TASK_INPUT:
- if (sizeof(oob_prefix) > 1
- && !strncmp(oob_prefix, t->t.input.string,
- sizeof(oob_prefix) - 1)) {
- do_out_of_band_command(tq, t->t.input.string);
- did_one = 1;
- } else if (tq->reading) {
+ default:
+ panic("Unexpected task kind in run_ready_tasks()");
+ break;
+ case TASK_OOB:
+ do_out_of_band_command(tq, t->t.input.string);
+ did_one = 1;
+ break;
+ case TASK_BINARY:
+ case TASK_INBAND:
+ if (tq->reading) {
Var v;
tq->reading = 0;
current_task_id = tq->reading_vm->task_id;
v.type = TYPE_STR;
v.v.str = t->t.input.string;
- resume_from_previous_vm(tq->reading_vm, v, TASK_INPUT,
- 0);
+ resume_from_previous_vm(tq->reading_vm, v);
did_one = 1;
} else {
/* Used to insist on tq->connected here, but Pavel
@@ -1057,15 +1144,14 @@ run_ready_tasks(void)
ft = t->t.forked;
current_task_id = ft.id;
do_forked_task(ft.program, ft.rt_env, ft.a,
- ft.f_index, 0);
+ ft.f_index);
did_one = 1;
}
break;
case TASK_SUSPENDED:
current_task_id = t->t.suspended.the_vm->task_id;
resume_from_previous_vm(t->t.suspended.the_vm,
- t->t.suspended.value,
- TASK_SUSPENDED, 0);
+ t->t.suspended.value);
did_one = 1;
break;
}
@@ -1117,7 +1203,7 @@ run_server_task_setting_id(Objid player, Objid what, const char *verb,
h = db_find_callable_verb(what, verb);
if (h.ptr)
return do_server_verb_task(what, verb, args, h, player, argstr,
- result, 1);
+ result, 1/*traceback*/);
else {
/* simulate an empty verb */
if (result) {
@@ -1137,7 +1223,8 @@ run_server_program_task(Objid this, const char *verb, Var args, Objid vloc,
{
current_task_id = new_task_id();
return do_server_program_task(this, verb, args, vloc, verbname, program,
- progr, debug, player, argstr, result, 1);
+ progr, debug, player, argstr, result,
+ 1/*traceback*/);
}
void
@@ -1982,7 +2069,7 @@ bf_force_input(Var arglist, Byte next, void *vdata, Objid progr)
return make_error_pack(E_PERM);
}
tq = find_tqueue(conn, 1);
- enqueue_input_task(tq, line, at_front);
+ enqueue_input_task(tq, line, at_front, 0/*non-binary*/);
free_var(arglist);
return no_var_pack();
}
@@ -2024,9 +2111,35 @@ char rcsid_tasks[] = "$Id$";
/*
* $Log$
+ * Revision 1.12 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
+ * Revision 1.10.2.5 2004/05/20 19:40:32 wrog
+ * fixed force_input(,,1) bug
+ *
* Revision 1.11 2003/06/12 18:16:56 bjj
* Suspend input on connection until :do_login_command() can run.
*
+ * Revision 1.10.2.4 2003/06/11 10:57:27 wrog
+ * fixed non-blocking read() to only grab inband lines
+ * fixed "hold-input" to not hold up out-of-band lines
+ * fixed out-of-band line handling to not mess with binary input lines
+ * implemented quoting with OUT_OF_BAND_QUOTE_PREFIX
+ * TASK_INPUT differentiates into TASK_INBAND/OOB/QUOTED/BINARY
+ * input queue is now doubly threaded so that one can dequeue first available (non-)TASK_OOB even if it's not at the front
+ * new connection option "disable-oob"
+ *
+ * Revision 1.10.2.3 2003/06/07 14:34:14 wrog
+ * removed dequeue_any_task()
+ *
+ * Revision 1.10.2.2 2003/06/07 12:59:04 wrog
+ * introduced connection_option macros
+ *
+ * Revision 1.10.2.1 2003/06/04 21:28:59 wrog
+ * removed useless arguments from resume_from_previous_vm(), do_forked_task();
+ * replaced current_task_kind with is_fg argument for do_task();
+ * made enum task_kind internal to tasks.c
+ *
* Revision 1.10 2002/09/15 23:21:01 xplat
* GNU indent normalization.
*
diff --git a/tasks.h b/tasks.h
index e6ebfd8..91ae3b7 100644
--- a/tasks.h
+++ b/tasks.h
@@ -35,7 +35,7 @@ extern Var tasks_connection_options(task_queue, Var);
extern int tasks_set_connection_option(task_queue, const char *,
Var);
-extern void new_input_task(task_queue, const char *);
+extern void new_input_task(task_queue, const char *, int);
extern void task_suspend_input(task_queue);
extern enum error enqueue_forked_task2(activation a, int f_index,
unsigned after_seconds, int vid);
@@ -111,9 +111,15 @@ extern db_verb_handle find_verb_for_programming(Objid player,
/*
* $Log$
+ * Revision 1.5 2004/05/22 01:25:44 wrog
+ * merging in WROGUE changes (W_SRCIP, W_STARTUP, W_OOB)
+ *
* Revision 1.4 2003/06/12 18:16:57 bjj
* Suspend input on connection until :do_login_command() can run.
*
+ * Revision 1.3.10.1 2003/06/11 10:40:17 wrog
+ * added binary argument to new_input_task()
+ *
* Revision 1.3 1998/12/14 13:19:08 nop
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
*
diff --git a/version.c b/version.c
index 85157b2..b159856 100644
--- a/version.c
+++ b/version.c
@@ -40,7 +40,7 @@
#include "config.h"
#include "version.h"
-const char *server_version = "1.8.1";
+const char *server_version = "1.8.2";
int
check_version(DB_Version version)