lpmoo-1.2/etc/
lpmoo-1.2/mudlib/
lpmoo-1.2/mudlib/etc/
lpmoo-1.2/mudlib/include/
lpmoo-1.2/mudlib/include/moo/
lpmoo-1.2/mudlib/lpc/
lpmoo-1.2/mudlib/std/auto/
lpmoo-1.2/mudlib/std/bfuns/
dgd-net/   755    314      6           0  5640047605  10362 5ustar  mudusersdgd-net/src/   755    314      6           0  5701632062  11144 5ustar  mudusersdgd-net/src/Changelog.Net   644    314      6        2401  5701632062  13560 0ustar  mudusersEvery package has two version indicators: A dgd-net release number,
and a DGD version number. There is a loose correspondence between them,
because support for older DGD versions is often dropped in later releases.
Contact me if you need a particular release / version combination that
is not supported.

Release 1:
   - comm_receive condensed to a single loop
   - cleaned up buffer allocation
   - put SO_REUSEADDR back

Release 2:
   - fixed the call to setsockopt
   - made it compatible with precompilation

Release 3:
   - properly initialized usr->newlines (fixes crashing bug)
   - fixed bug where commands would only be executed if several were queued.

Release 4:
   - added LINEMODE patches from DGD 1.0.8.3 (+minor fix to SB/SE handling)
   - fixed send_message() for when the driver object doubles as a port object
   - reversed order of checking for errors and writability in conn_connected
   - an error is raised if a connect() fails right away (used to be silent)

Release 5:
   - Added config.c and comp/comp.c patches from DGD 1.0.8.8
   - Doc fix: accept() has been connection() since release 0.
   - Added checks for nusers < maxusers before calling comm_new
   - Made some error messages clearer
   - Made sure no writes are done to not yet connected sockets
dgd-net/src/comm.c   640    314      6       40472  5701631612  12346 0ustar  mudusers# define INCLUDE_TELNET
# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "interpret.h"
# include "comm.h"

# ifndef TELOPT_LINEMODE
# define TELOPT_LINEMODE       34      /* linemode option */
# define LM_MODE               1
# define MODE_EDIT             0x01
# endif

typedef struct _user_ {
    union {
	object *obj;		/* associated object */
	struct _user_ *next;	/* next in free list */
    } u;
    int inbufsz;		/* bytes in input buffer */
    int outbufsz;		/* bytes in output buffer */
    int newlines;               /* # of newlines in input buffer */
    char flags;			/* connection flags */
    char state;			/* telnet state */
    connection *conn;		/* connection */
    char *inbuf;                /* input buffer */
    char *outbuf;               /* output buffer */
} user;

/* flags */
# define CF_ECHO	0x01    /* client echoes input */
# define CF_TELNET	0x02    /* telnet connection */
# define CF_GA		0x04    /* send GA after prompt */
# define CF_SEENCR	0x08    /* just seen a CR */
# define CF_PORT        0x10    /* port connection */
# define CF_DATAGRAM    0x20    /* datagram connection */
# define CF_CONNECTING  0x40    /* connection being initiated */

/* state */
# define TS_DATA	0
# define TS_IAC		1
# define TS_DO		2
# define TS_DONT	3
# define TS_WILL        4
# define TS_WONT        5
# define TS_SB          6
# define TS_SE          7

static user **users;		/* array of users */
static int maxusers;		/* max # of users */
static int nusers;		/* # of users */
static int newlines;		/* # of newlines in all input buffers */
static object *this_user;	/* current user */

/*
 * NAME:	comm->init()
 * DESCRIPTION:	initialize communications
 */
void comm_init(cf_users)
int cf_users;
{
    register int i;
    register user **usr;

    conn_init(cf_users);
    users = ALLOC(user*, maxusers = cf_users);
    for (i = cf_users, usr = users; i > 0; --i, usr++) {
	*usr = (user *) NULL;
    }
}

/*
 * NAME:	comm->finish()
 * DESCRIPTION:	terminate connections
 */
void comm_finish()
{
    comm_flush(FALSE);
    conn_finish();
}

/*
 * NAME:	comm->new()
 * DESCRIPTION:	allocate and init a new user struct (assumes nusers < maxusers)
 */
static void comm_new(obj, conn, flags)
object *obj;
connection *conn;
int flags;
{
    static char give_lm[] = { IAC, DO, TELOPT_LINEMODE };
    static char echo_on[] = { IAC, WONT, TELOPT_ECHO };

    register user **usr;
    register int size;

    if (obj->flags & (O_USER | O_EDITOR)) {
	error("User object is already used for user or editor");
    }

    if (flags & CF_PORT) {
	size = sizeof(user);
    } else if (flags & CF_TELNET) {
	size = sizeof(user) + INBUF_SIZE + OUTBUF_SIZE;
    } else {
	size = sizeof(user) + OUTBUF_SIZE;
    }

    for (usr = users; *usr != (user *) NULL; usr++) ;
    mstatic();
    *usr = (user *)ALLOC(char, size);
    mdynamic();
    (*usr)->u.obj = obj;
    obj->flags |= O_USER;
    obj->etabi = usr - users;
    (*usr)->inbufsz = 0;
    (*usr)->outbufsz = 0;
    (*usr)->newlines = 0;
    (*usr)->conn = conn;
    (*usr)->flags = flags;
    if (flags & CF_PORT) {
	(*usr)->inbuf = (char *) NULL;
	(*usr)->outbuf = (char *) NULL;
    } else if (flags & CF_TELNET) {
	(*usr)->inbuf = (char *) *usr + sizeof(user);
	(*usr)->outbuf = (*usr)->inbuf + INBUF_SIZE;
	(*usr)->state = TS_DATA;
	if (!(flags & CF_CONNECTING)) {
	    if (flags & CF_ECHO) {
		conn_write(conn, echo_on, 3);
	    }
	    conn_write(conn, give_lm, 3);
	}
    } else {
	(*usr)->inbuf = (char *) NULL;
	(*usr)->outbuf = (char *) *usr + sizeof(user);
    }
    nusers++;
}

/*
 * NAME:	comm->del()
 * DESCRIPTION:	delete a connection
 */
static void comm_del(usr)
register user **usr;
{
    object *obj, *olduser;

    conn_del((*usr)->conn);
    if ((*usr)->flags & CF_TELNET) {
	newlines -= (*usr)->newlines;
    }
    obj = (*usr)->u.obj;
    obj->flags &= ~O_USER;
    FREE(*usr);
    *usr = (user *) NULL;
    --nusers;

    olduser = this_user;
    this_user = obj;
    if (i_call(obj, "close", TRUE, 0)) {
	i_del_value(sp++);
    }
    if (obj == olduser) {
	this_user = (object *) NULL;
    } else {
	this_user = olduser;
    }
}

/*
 * NAME:	comm->listen()
 * DESCRIPTION:	have an object listen to a port
 */
void comm_listen(obj, port, protocol)
object *obj;
int port, protocol;
{
    register connection *conn;
    int flags;

    if (nusers >= maxusers)
	error("Max number of connection/port objects exceeded");

    if (protocol == PRC_TELNET) {
	flags = CF_TELNET | CF_ECHO | CF_PORT;
	protocol = PRC_TCP;
    } else if (protocol == PRC_UDP) {
	flags = CF_DATAGRAM | CF_PORT;
    } else {
	flags = CF_PORT;
    }
    conn = conn_listen(port, protocol);
    if (conn != (connection *) NULL) {
	comm_new(obj, conn, flags);
    } else {
        error("Could not open port");
    }
    if (i_call(obj, "open", TRUE, 0)) {
        i_del_value(sp++);
    }
}

/*
 * NAME:	comm->connect()
 * DESCRIPTION:	initiate a telnet or tcp connection
 */
void comm_connect(obj, host, port, protocol)
object *obj;
char *host;
int port, protocol;
{
    register connection *conn;
    int flags;

    if (nusers >= maxusers)
	error("Max number of connection/port objects exceeded");

    if (protocol == PRC_TELNET) {
	flags = CF_TELNET | CF_CONNECTING;
	protocol = PRC_TCP;
    } else if (protocol == PRC_TCP) {
	flags = CF_CONNECTING;
    }
    conn = conn_connect(host, port, protocol);
    if (conn != (connection *) NULL) {
	comm_new(obj, conn, flags);
    } else {
	error("Could not initiate connection");
    }
}

/*
 * NAME:	comm->send()
 * DESCRIPTION:	send a message to a user
 */
void comm_send(obj, str)
object *obj;
string *str;
{
    register user *usr;
    register char *p, *q;
    register unsigned short len, size;

    usr = users[UCHAR(obj->etabi)];
    if (usr->flags & (CF_DATAGRAM | CF_PORT)) {
        error("Object is not a stream connection");
    }
    if (usr->flags & CF_CONNECTING) {
	error("Connection is not yet ready");
    }
    p = str->text;
    len = str->len;
    size = usr->outbufsz;
    q = usr->outbuf + size;
    if (usr->flags & CF_TELNET) {
	while (len != 0) {
	    if (UCHAR(*p) == IAC) {
		/*
		 * double the telnet IAC character
		 */
		if (size == OUTBUF_SIZE) {
		    conn_write(usr->conn, q = usr->outbuf, size);
		    size = 0;
		}
		*q++ = IAC;
		size++;
	    } else if (*p == LF) {
		/*
		 * insert CR before LF
		 */
		if (size == OUTBUF_SIZE) {
		    conn_write(usr->conn, q = usr->outbuf, size);
		    size = 0;
		}
		*q++ = CR;
		size++;
	    } else if ((*p & 0x7f) < ' ' && *p != HT && *p != BEL && *p != BS) {
		/*
		 * illegal character
		 */
		p++;
		--len;
		continue;
	    }
	    if (size == OUTBUF_SIZE) {
		conn_write(usr->conn, q = usr->outbuf, size);
		size = 0;
	    }
	    *q++ = *p++;
	    --len;
	    size++;
	}
    } else {
	/*
	 * binary connection
	 */
	while (size + len > OUTBUF_SIZE) {
	    memcpy(q, p, OUTBUF_SIZE - size);
	    p += OUTBUF_SIZE - size;
	    len -= OUTBUF_SIZE - size;
	    conn_write(usr->conn, q = usr->outbuf, OUTBUF_SIZE);
	    size = 0;
	}
	memcpy(q, p, len);
	size += len;
    }
    usr->outbufsz = size;
}

/*
 * NAME:	comm->sendto()
 * DESCRIPTION:	send a datagram
 */
void comm_sendto(obj, data, host, port)
object *obj;
string *data;
char *host;
int port;
{
    register user *usr;

    usr = users[UCHAR(obj->etabi)];
    if (usr->flags & CF_DATAGRAM == 0) {
	error("Object is not a datagram object");
    }
    conn_sendto(usr->conn, data->text, data->len, host, port);
}


/*
 * NAME:	comm->echo()
 * DESCRIPTION:	turn on/off input echoing for a user
 */
void comm_echo(obj, echo)
object *obj;
int echo;
{
    register user *usr;
    char buf[3];

    usr = users[UCHAR(obj->etabi)];
    if (usr->flags & CF_CONNECTING)
	error("Connection is not yet ready");
    if ((usr->flags & CF_TELNET) && echo != (usr->flags & CF_ECHO)) {
	buf[0] = IAC;
	buf[1] = (echo) ? WONT : WILL;
	buf[2] = TELOPT_ECHO;
	conn_write(usr->conn, buf, 3);
	usr->flags ^= CF_ECHO;
    }
}

/*
 * NAME:	comm->flush()
 * DESCRIPTION:	flush output to all users
 */
void comm_flush(prompt)
int prompt;
{
    register user **usr;
    register int i, size;
    register char *p;

    for (usr = users, i = maxusers; i > 0; usr++, --i) {
	if (*usr != (user *) NULL && (size=(*usr)->outbufsz) > 0) {
	    if (prompt && (*usr)->u.obj == this_user &&
		((*usr)->flags & (CF_TELNET | CF_GA)) == (CF_TELNET | CF_GA)) {
		/*
		 * append "go ahead" to indicate that the prompt has been sent
		 */
		if (size >= OUTBUF_SIZE - 2) {
		    conn_write((*usr)->conn, (*usr)->outbuf, size);
		    size = 0;
		}
		p = (*usr)->outbuf + size;
		*p++ = IAC;
		*p++ = GA;
		size += 2;
	    }
	    conn_write((*usr)->conn, (*usr)->outbuf, size);
	    (*usr)->outbufsz = 0;
	}
    }
    this_user = (object *) NULL;
}

/*
 * NAME:	comm->receive()
 * DESCRIPTION:	receive a message from a user
 */
void comm_receive()
{
    static int lastuser;
    connection *conn;
    object *o;
    register int n;
    register char *p, *q;

    this_user = (object *) NULL;
    n = conn_select(newlines == 0);
    if (n > 0 || newlines > 0) {
	static char intr[] =            { '\177' };
	static char brk[] =             { '\034' };
	static char tm[] =              { IAC, WILL, TELOPT_TM };
	static char will_sga[] =        { IAC, WILL, TELOPT_SGA };
	static char wont_sga[] =        { IAC, WONT, TELOPT_SGA };
	static char mode_edit[] =       { IAC, SB, TELOPT_LINEMODE, LM_MODE,
					  MODE_EDIT, IAC, SE };
	register user *usr;
	char buf[INBUF_SIZE];
	Int size;

	n = lastuser;
	for (;;) {
	    n = (n + 1) % maxusers;
	    usr = users[n];
	    if (usr != (user *) NULL) {
		if (usr->flags & CF_CONNECTING) {
		    int r;

		    r = conn_connected(usr->conn);
		    if (r == 1) {
			usr->flags &= ~CF_CONNECTING;
			this_user = usr->u.obj;
			if (i_call(this_user, "open", TRUE, 0)) {
			    i_del_value(sp++);
			}
			comm_flush(TRUE);
		    } else if (r == -1) {
			comm_del(&users[n]);
		    }
		} else if (usr->flags & CF_DATAGRAM) {
		    size = conn_recvfrom(usr->conn, buf, INBUF_SIZE);
		    if (size > 0) {
			lastuser = n;
			(--sp)->type = T_STRING;
			str_ref(sp->u.string = str_new(buf, (long) size));
			(--sp)->type = T_STRING;
			str_ref(sp->u.string = conn_ipnum(usr->conn));
			(--sp)->type = T_INT;
			sp->u.number = conn_port(usr->conn);
			this_user = usr->u.obj;
			if (i_call(this_user, "receive_datagram", TRUE, 3)) {
			    i_del_value(sp++);
			}
			return;
		    }
		} else if (usr->flags & CF_PORT) {
		    if (nusers < maxusers) {
			conn = conn_accept(usr->conn);
			if (conn != (connection *) NULL) {
			    (--sp)->type = T_STRING;
			    str_ref(sp->u.string = conn_ipnum(conn));
			    (--sp)->type = T_INT;
			    sp->u.number = conn_port(conn);
			    if (ec_push()) {
				conn_del(conn);
				error((char *) NULL);   /* pass on error */
			    }
			    this_user = usr->u.obj;
			    if (!i_call(this_user, "connection", TRUE, 2) ||
				sp->type != T_OBJECT) {
				error("connection() did not return an object");
			    }
			    ec_pop();
			    comm_new(o = o_object(sp->oindex, sp->u.objcnt),
				     conn, usr->flags & ~CF_PORT);
			    sp++;
			    this_user = o;
			    if (i_call(this_user, "open", TRUE, 0)) {
				i_del_value(sp++);
			    }
			    comm_flush(TRUE);
			}
		    }
		} else if (usr->flags & CF_TELNET) {
		    p = usr->inbuf + usr->inbufsz;
		    size = conn_read(usr->conn, p, INBUF_SIZE - usr->inbufsz);
		    if (size < 0) {
			/*
			 * bad connection
			 */
			comm_del(&users[n]);
			continue;
		    } else if (size > 0) {
			register int state, flags, nls;

			flags = usr->flags;
			state = usr->state;
			nls = usr->newlines;
			q = p;
			while (size > 0) {
			    switch (state) {
			    case TS_DATA:
				switch (UCHAR(*p)) {
				case IAC:
				    state = TS_IAC;
				    break;

				case BS:
			        case 0x7f:
				    if (q != usr->inbuf && q[-1] != LF) {
					--q;
				    }
				    flags &= ~CF_SEENCR;
				    break;

			        case CR:
				    nls++;
				    newlines++;
				    *q++ = LF;
				    flags |= CF_SEENCR;
				    break;

				case LF:
				    if ((flags & CF_SEENCR) != 0) {
					flags &= ~CF_SEENCR;
					break;
				    }
				    nls++;
				    newlines++;
				    /* fall through */
			        default:
				    *q++ = *p;
				    flags &= ~CF_SEENCR;
				    break;
			        }
				break;

			    case TS_IAC:
				switch (UCHAR(*p)) {
				case IAC:
				    *q++ = *p;
				    state = TS_DATA;
				    break;

			        case DO:
				    state = TS_DO;
				    break;

			        case DONT:
				    state = TS_DONT;
				    break;

			        case WILL:
				    state = TS_WILL;
				    break;

				case WONT:
				    state = TS_WONT;
				    break;

				case SB:
				    state = TS_SB;
				    break;

			        case IP:
				    conn_write(usr->conn, intr, 1);
				    state = TS_DATA;
				    break;

				case BREAK:
				    conn_write(usr->conn, brk, 1);
				    state = TS_DATA;
				    break;

			        default:
				    state = TS_DATA;
				    break;
				}
				break;

			    case TS_DO:
				if (UCHAR(*p) == TELOPT_TM) {
				    conn_write(usr->conn, tm, 3);
				} else if (UCHAR(*p) == TELOPT_SGA) {
				    flags &= ~CF_GA;
				    conn_write(usr->conn, will_sga, 3);
				}
				state = TS_DATA;
				break;

			    case TS_DONT:
				if (UCHAR(*p) == TELOPT_SGA) {
				    flags |= CF_GA;
				    conn_write(usr->conn, wont_sga, 3);
			        }
				state = TS_DATA;
				break;

			    case TS_WILL:
				if (UCHAR(*p) == TELOPT_LINEMODE) {
				    conn_write(usr->conn, mode_edit, 7);
				}
				/* fall through */
			    case TS_WONT:
				state = TS_DATA;
				break;

			    case TS_SB:
				/* skip to the end */
				if (UCHAR(*p) == IAC) {
				    state = TS_SE;
				}
				break;

			    case TS_SE:
				if (UCHAR(*p) == SE) {
				    /* end of subnegotiation */
				    state = TS_DATA;
				} else if (UCHAR(*p) == IAC) {
				    /* doubled IAC counts as data */
				    state = TS_SB;
				}
				break;
			    }
			    p++;
			    --size;
			}
			usr->flags = flags;
			usr->state = state;
			usr->newlines = nls;
			usr->inbufsz = q - usr->inbuf;
		    }
		    if (usr->newlines > 0) {
			p = (char *) memchr(usr->inbuf, LF, usr->inbufsz);
			--newlines;
			--(usr->newlines);
			lastuser = n;
			size = n = p - usr->inbuf;
			if (size != 0) {
			    memcpy(buf, usr->inbuf, size);
			}
			p++;   /* skip \n */
			n++;
			usr->inbufsz -= size + 1;
			if (usr->inbufsz != 0) {
			    /* can't rely on memcpy */
			    for (q = usr->inbuf, n = usr->inbufsz; n > 0; --n) {
				*q++ = *p++;
			    }
			}
			this_user = usr->u.obj;
			(--sp)->type = T_STRING;
			str_ref(sp->u.string = str_new(buf, (long) size));
			if (i_call(this_user, "receive_message", TRUE, 1)) {
			    i_del_value(sp++);
			}
			return;
		    } else if (usr->inbufsz == INBUF_SIZE) {
			/*
			 * input buffer full
			 */
			lastuser = n;
			(--sp)->type = T_STRING;
			str_ref(sp->u.string = 
				str_new(usr->inbuf, (long) INBUF_SIZE));
			usr->inbufsz = 0;
			this_user = usr->u.obj;
			if (i_call(this_user, "receive_message", TRUE, 1)) {
			    i_del_value(sp++);
			}
			return;
		    }
		} else {
		    /*
		     * binary mode
		     */
		    size = conn_read(usr->conn, buf, INBUF_SIZE);
		    if (size < 0) {
			comm_del(&users[n]);
		    } else if (size > 0) {
			lastuser = n;
			(--sp)->type = T_STRING;
			str_ref(sp->u.string = str_new(buf, (long) size));
			this_user = usr->u.obj;
			if (i_call(this_user, "receive_message", TRUE, 1)) {
			    i_del_value(sp++);
			}
			return;
		    }
		}
	    }
	    if (n == lastuser) {
		return;
	    }
	}
    }
}

/*
 * NAME:	comm->ip_number()
 * DESCRIPTION:	return the ip number of a user (as a string)
 */
string *comm_ip_number(obj)
object *obj;
{
    return conn_ipnum(users[UCHAR(obj->etabi)]->conn);
}

/*
 * NAME:	comm->close()
 * DESCRIPTION:	remove a user
 */
void comm_close(obj)
object *obj;
{
    register user **usr;

    usr = &users[UCHAR(obj->etabi)];
    if ((*usr)->outbufsz != 0) {
	/*
	 * flush last bit of output
	 */
	conn_write((*usr)->conn, (*usr)->outbuf, (*usr)->outbufsz);
    }
    comm_del(usr);
}

/*
 * NAME:	comm->user()
 * DESCRIPTION:	return the current user
 */
object *comm_user()
{
    return this_user;
}

/*
 * NAME:	comm->users()
 * DESCRIPTION:	return an array with all user objects
 */
array *comm_users()
{
    array *a;
    register int i;
    register user **usr;
    register value *v;

    a = arr_new((long) nusers);
    v = a->elts;
    for (i = nusers, usr = users; i > 0; usr++) {
	if (*usr != (user *) NULL) {
	    v->type = T_OBJECT;
	    v->oindex = (*usr)->u.obj->index;
	    v->u.objcnt = (*usr)->u.obj->count;
	    v++;
	    --i;
	}
    }
    return a;
}
dgd-net/src/comm.h   640    314      6        2666  5643553142  12344 0ustar  mudusers# define INBUF_SIZE	2048
# define OUTBUF_SIZE	1024

# define  PRC_TCP      1
# define  PRC_UDP      2
# define  PRC_TELNET   3

typedef struct _connection_ connection;

extern void	   conn_init	  P((int));
extern void	   conn_finish	  P((void));
extern connection *conn_listen    P((int, int));
extern connection *conn_accept    P((connection*));
extern connection *conn_connect   P((char*, int, int));
extern int         conn_connected P((connection*));
extern void	   conn_del	  P((connection*));
extern int	   conn_select	  P((int));
extern int         conn_recvfrom  P((connection*, char*, int));
extern int	   conn_read	  P((connection*, char*, int));
extern void        conn_sendto    P((connection*, char*, int, char*, int)); 
extern void	   conn_write	  P((connection*, char*, int));
extern string	  *conn_ipnum	  P((connection*));
extern int         conn_port      P((connection*));

extern void	comm_init	P((int));
extern void	comm_finish	P((void));
extern void     comm_listen     P((object*, int, int));
extern void     comm_connect    P((object*, char*, int, int));
extern void	comm_send	P((object*, string*));
extern void     comm_sendto     P((object*, string*, char*, int));
extern void	comm_echo	P((object*, int));
extern void	comm_flush	P((int));
extern void     comm_receive	P((void));
extern string  *comm_ip_number	P((object*));
extern void	comm_close	P((object*));
extern object  *comm_user	P((void));
extern array   *comm_users	P((void));
dgd-net/src/dgd.c   640    314      6        5135  5572236316  12136 0ustar  mudusers# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "ed.h"
# include "call_out.h"
# include "comm.h"
# include "node.h"
# include "compile.h"

/*
 * NAME:	call_driver_object()
 * DESCRIPTION:	call a function in the driver object
 */
bool call_driver_object(func, narg)
char *func;
int narg;
{
    static object *driver;
    static Uint dcount;
    static char *driver_name;

    if (driver == (object *) NULL || dcount != driver->count) {
	if (driver_name == (char *) NULL) {
	    driver_name = conf_driver();
	}
	driver = o_find(driver_name);
	if (driver == (object *) NULL) {
	    driver = c_compile(driver_name);
	}
	dcount = driver->count;
    }
    if (!i_call(driver, func, TRUE, narg)) {
	fatal("missing function in driver object: %s", func);
    }
    return TRUE;
}

static bool swap;	/* are objects to be swapped out? */
static bool dump;	/* is the program to dump? */
static bool intr;	/* received an interrupt? */
static bool stop;	/* is the program to terminate? */

/*
 * NAME:	swapout()
 * DESCRIPTION:	indicate that objects are to be swapped out
 */
void swapout()
{
    swap = TRUE;
}

/*
 * NAME:	dump_state()
 * DESCRIPTION:	indicate that the state must be dumped
 */
void dump_state()
{
    dump = TRUE;
}

/*
 * NAME:	interrupt()
 * DESCRIPTION:	register an interrupt
 */
void interrupt()
{
    intr = TRUE;
}

/*
 * NAME:	finish()
 * DESCRIPTION:	indicate that the program must finish
 */
void finish()
{
    stop = TRUE;
}

/*
 * NAME:	dgd_main()
 * DESCRIPTION:	the main loop of DGD
 */
int dgd_main(argc, argv)
int argc;
char **argv;
{
    if (argc < 2 || argc > 3) {
	P_message("Usage: dgd config_file [dump_file]\012");	/* LF */
	return 2;
    }

    if (ec_push()) {
	warning((char *) NULL);
	fatal("error during initialization");
    }
    if (argc == 2) {
	conf_init(argv[1], (char *) NULL);
    } else {
	conf_init(argv[1], argv[2]);
    }
    ec_pop();

    while (ec_push()) {
	i_log_error(FALSE);
	i_clear();
    }

    do {
	P_getevent();
	if (intr) {
	    intr = FALSE;
	    call_driver_object("interrupt", 0);
	    i_del_value(sp++);
	}

	co_call();
	comm_flush(FALSE);

	if (!stop) {
	    comm_receive();
	    comm_flush(TRUE);
	}

	o_clean();

	if (!mcheck()) {
	    d_swapout(1);
	    arr_freeall();
	    mpurge();
	    mexpand();
	} else if (swap) {
	    d_swapout(1);
	    arr_freeall();
	    mpurge();
	}
	swap = FALSE;

	if (dump) {
	    d_swapsync();
	    conf_dump();
	    dump = FALSE;
	}

	sw_copy();
    } while (!stop);

    ec_pop();
    comm_finish();
    ed_finish();
    sw_finish();
    return 0;
}
dgd-net/src/kfun/   755    314      6           0  5640047605  12114 5ustar  mudusersdgd-net/src/kfun/std.DGD.c   640    314      6       35636  5643554476  13574 0ustar  mudusers# ifndef FUNCDEF
# include "kfun.h"
# include "fcontrol.h"
# include "path.h"
# include "comm.h"
# include "call_out.h"
# include "ed.h"
# include "node.h"
# include "compile.h"
# endif


# ifdef FUNCDEF
FUNCDEF("call_other", kf_call_other, p_call_other)
# else
char p_call_other[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL, T_MIXED,
			3, T_MIXED, T_STRING, T_MIXED | T_ELLIPSIS };

/*
 * NAME:	kfun->call_other()
 * DESCRIPTION:	call a function in another object
 */
int kf_call_other(nargs)
int nargs;
{
    register object *obj;
    register value *val;
    char *file;

    if (nargs < 2) {
	return -1;
    }

    val = &sp[nargs - 1];
    switch (val->type) {
    case T_STRING:
	file = path_object(val->u.string->text);
	if (file == (char *) NULL) {
	    return 1;
	}
	obj = o_find(file);
	if (obj == (object *) NULL) {
	    /* object isn't loaded: compile it */
	    obj = c_compile(file);
	}
	str_del(val->u.string);
	break;

    case T_OBJECT:
	obj = o_object(val->oindex, val->u.objcnt);
	break;

    default:
	/* bad arg 1 */
	return 1;
    }

    /* default return value */
    val->type = T_INT;
    val->u.number = 0;
    --val;
    if (i_this_object()->count == 0) {
	/*
	 * cannot call_other from destructed object
	 */
	i_pop(nargs - 1);
	return 0;
    }

    if (i_call(obj, val->u.string->text, FALSE, nargs - 2)) {
	/* function exists */
	val = sp++;
	str_del((sp++)->u.string);
	*sp = *val;
    } else {
	/* function doesn't exist */
	str_del((sp++)->u.string);
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("this_object", kf_this_object, p_this_object)
# else
char p_this_object[] = { C_STATIC | C_LOCAL, T_OBJECT, 0 };

/*
 * NAME:	kfun->this_object()
 * DESCRIPTION:	return the current object
 */
int kf_this_object()
{
    register object *obj;

    --sp;
    obj = i_this_object();
    if (obj->count != 0) {
	sp->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("previous_object", kf_previous_object, p_previous_object)
# else
char p_previous_object[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL,
			     T_OBJECT, 1, T_INT };

/*
 * NAME:	kfun->previous_object()
 * DESCRIPTION:	return the previous object in the call_other chain
 */
int kf_previous_object(nargs)
int nargs;
{
    register object *obj;

    if (nargs == 0) {
	(--sp)->type = T_INT;
	sp->u.number = 0;
    }

    obj = i_prev_object((int) sp->u.number);
    if (obj != (object *) NULL) {
	sp->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("call_trace", kf_call_trace, p_call_trace)
# else
char p_call_trace[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
			T_MIXED | (2 << REFSHIFT), 0 };

/*
 * NAME:	kfun->call_trace()
 * DESCRIPTION:	return the entire call_other chain
 */
int kf_call_trace()
{
    (--sp)->type = T_ARRAY;
    arr_ref(sp->u.array = i_call_trace());
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("clone_object", kf_clone_object, p_clone_object)
# else
char p_clone_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_OBJECT, 1,
			  T_STRING };

/*
 * NAME:	kfun->clone_object()
 * DESCRIPTION:	clone a new object
 */
int kf_clone_object()
{
    register object *obj;
    char *file;

    file = path_object(sp->u.string->text);
    if (file == (char *) NULL) {
	return 1;
    }

    obj = o_find(file);
    if (obj == (object *) NULL) {
	obj = c_compile(file);
    }
    if (!(obj->flags & O_MASTER)) {
	error("Cloning from a clone");
    }
    str_del(sp->u.string);
    sp->type = T_OBJECT;
    obj = o_new((char *) NULL, obj, (control *) NULL);
    sp->oindex = obj->index;
    sp->u.objcnt = obj->count;
    i_call(obj, "", FALSE, 0);	/* cause creator to be called */
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("destruct_object", kf_destruct_object, p_destruct_object)
# else
char p_destruct_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID, 1,
			     T_OBJECT };

/*
 * NAME:	kfun->destruct_object()
 * DESCRIPTION:	destruct an object
 */
int kf_destruct_object()
{
    register object *obj;

    obj = o_object(sp->oindex, sp->u.objcnt);
    if (obj->flags & O_USER) {
	comm_close(obj);
    }
    if (obj->flags & O_EDITOR) {
	ed_del(obj);
    }
    i_odest(obj);	/* wipe out occurrances on the stack */
    o_del(obj);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("object_name", kf_object_name, p_object_name)
# else
char p_object_name[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_STRING, 1,
			 T_OBJECT };

/*
 * NAME:	kfun->object_name()
 * DESCRIPTION:	return the name of an object
 */
int kf_object_name()
{
    char *name;

    name = o_name(o_object(sp->oindex, sp->u.objcnt));
    sp->type = T_STRING;
    str_ref(sp->u.string = str_new((char *) NULL, strlen(name) + 1L));
    sp->u.string->text[0] = '/';
    strcpy(sp->u.string->text + 1, name);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("find_object", kf_find_object, p_find_object)
# else
char p_find_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_OBJECT, 1,
			 T_STRING };

/*
 * NAME:	kfun->find_object()
 * DESCRIPTION:	find the loaded object for a given object name
 */
int kf_find_object()
{
    char *name;
    object *obj;

    name = path_object(sp->u.string->text);
    if (name == (char *) NULL) {
	return 1;
    }

    str_del(sp->u.string);
    obj = o_find(name);
    if (obj != (object *) NULL) {
	sp->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("function_object", kf_function_object, p_function_object)
# else
char p_function_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_STRING, 2,
			     T_STRING, T_OBJECT };

/*
 * NAME:	kfun->function_object()
 * DESCRIPTION:	return the name of the program a function is in
 */
int kf_function_object()
{
    object *obj;
    dsymbol *symb;
    char *name;

    obj = o_object(sp->oindex, sp->u.objcnt);
    sp++;
    symb = ctrl_symb(o_control(obj), sp->u.string->text);
    str_del(sp->u.string);
    if (symb != (dsymbol *) NULL) {
	name = o_name(obj->ctrl->inherits[UCHAR(symb->inherit)].obj);
	str_ref(sp->u.string = str_new((char *) NULL, strlen(name) + 1L));
	sp->u.string->text[0] = '/';
	strcpy(sp->u.string->text + 1, name);
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("this_user", kf_this_user, p_this_user)
# else
char p_this_user[] = { C_STATIC | C_LOCAL, T_OBJECT, 0 };

/*
 * NAME:	kfun->this_user()
 * DESCRIPTION:	return the current user object (if any)
 */
int kf_this_user()
{
    object *obj;

    obj = comm_user();
    if (obj != (object *) NULL) {
	(--sp)->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	(--sp)->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("query_ip_number", kf_query_ip_number, p_query_ip_number)
# else
char p_query_ip_number[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_STRING, 1,
			     T_OBJECT };

/*
 * NAME:	kfun->query_ip_number()
 * DESCRIPTION:	return the ip number of a user
 */
int kf_query_ip_number()
{
    register object *obj;

    obj = o_object(sp->oindex, sp->u.objcnt);
    if (obj->flags & O_USER) {
	sp->type = T_STRING;
	str_ref(sp->u.string = comm_ip_number(obj));
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("users", kf_users, p_users)
# else
char p_users[] = { C_STATIC | C_LOCAL, T_OBJECT | (1 << REFSHIFT), 0 };

/*
 * NAME:	kfun->users()
 * DESCRIPTION:	return the array of users
 */
int kf_users()
{
    (--sp)->type = T_ARRAY;
    arr_ref(sp->u.array = comm_users());
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("strlen", kf_strlen, p_strlen)
# else
char p_strlen[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1, T_STRING };

/*
 * NAME:	kfun->strlen()
 * DESCRIPTION:	return the length of a string
 */
int kf_strlen()
{
    unsigned short len;

    len = sp->u.string->len;
    str_del(sp->u.string);
    sp->type = T_INT;
    sp->u.number = len;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("allocate", kf_allocate, p_allocate)
# else
char p_allocate[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
		      T_MIXED | (1 << REFSHIFT), 1, T_INT };

/*
 * NAME:	kfun->allocate()
 * DESCRIPTION:	allocate an array
 */
int kf_allocate()
{
    register int i;
    register value *v;

    arr_ref(sp->u.array = arr_new((long) sp->u.number));
    sp->type = T_ARRAY;
    for (i = sp->u.array->size, v = sp->u.array->elts; i > 0; --i, v++) {
	v->type = T_INT;
	v->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("sizeof", kf_sizeof, p_sizeof)
# else
char p_sizeof[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1,
		    T_MIXED | (1 << REFSHIFT) };

/*
 * NAME:	kfun->sizeof()
 * DESCRIPTION:	return the size of an array
 */
int kf_sizeof()
{
    unsigned short size;

    size = sp->u.array->size;
    arr_del(sp->u.array);
    sp->type = T_INT;
    sp->u.number = size;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("map_indices", kf_map_indices, p_map_indices)
# else
char p_map_indices[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
			 T_MIXED | (1 << REFSHIFT), 1, T_MAPPING };

/*
 * NAME:	kfun->map_indices()
 * DESCRIPTION:	return the array of mapping indices
 */
int kf_map_indices()
{
    array *a;

    a = map_indices(sp->u.array);
    arr_del(sp->u.array);
    sp->type = T_ARRAY;
    arr_ref(sp->u.array = a);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("map_values", kf_map_values, p_map_values)
# else
char p_map_values[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
			T_MIXED | (1 << REFSHIFT), 1, T_MAPPING };

/*
 * NAME:	kfun->map_values()
 * DESCRIPTION:	return the array of mapping values
 */
int kf_map_values()
{
    array *a;

    a = map_values(sp->u.array);
    arr_del(sp->u.array);
    sp->type = T_ARRAY;
    arr_ref(sp->u.array = a);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("map_sizeof", kf_map_sizeof, p_map_sizeof)
# else
char p_map_sizeof[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1,
			T_MAPPING };

/*
 * NAME:	kfun->map_sizeof()
 * DESCRIPTION:	return the number of index/value pairs in a mapping
 */
int kf_map_sizeof()
{
    unsigned short size;

    size = map_size(sp->u.array);
    arr_del(sp->u.array);
    sp->type = T_INT;
    sp->u.number = size;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("typeof", kf_typeof, p_typeof)
# else
char p_typeof[] = { C_STATIC | C_LOCAL, T_INT, 1, T_MIXED };

/*
 * NAME:	kfun->typeof()
 * DESCRIPTION:	return the type of a value
 */
int kf_typeof()
{
    unsigned short type;

    type = sp->type;
    i_del_value(sp);
    sp->type = T_INT;
    sp->u.number = type;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("error", kf_error, p_error)
# else
char p_error[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID, 1, T_STRING };

/*
 * NAME:	kfun->error()
 * DESCRIPTION:	cause an error
 */
int kf_error()
{
    if (strchr(sp->u.string->text, LF) != (char *) NULL) {
	error("'\\n' in error string");
    }
    error("%s", sp->u.string->text);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("send_message", kf_send_message, p_send_message)
# else
char p_send_message[] = { C_STATIC | C_LOCAL, T_VOID, 1, T_MIXED };

/*
 * NAME:	kfun->send_message()
 * DESCRIPTION:	send a message to a user
 */
int kf_send_message()
{
    object *obj;

    if (sp->type != T_INT && sp->type != T_STRING) {
	return 1;
    }

    obj = i_this_object();
    if (obj->count != 0) {
	if (obj->flags & O_USER) {
	    if (sp->type == T_INT) {
		comm_echo(obj, sp->u.number != 0);
	    } else {
		comm_send(obj, sp->u.string);
	    }
	} else if ((obj->flags & O_DRIVER) && sp->type == T_STRING) {
	    P_message(sp->u.string->text);
	}
    }
    if (sp->type == T_STRING) {
	str_del(sp->u.string);
    }
    sp->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("time", kf_time, p_time)
# else
char p_time[] = { C_STATIC | C_LOCAL, T_INT, 0 };

/*
 * NAME:	kfun->time()
 * DESCRIPTION:	return the current time
 */
int kf_time()
{
    (--sp)->type = T_INT;
    sp->u.number = P_time();
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("get_exec_cost", kf_get_exec_cost, p_get_exec_cost)
# else
char p_get_exec_cost[] = { C_STATIC | C_LOCAL, T_INT, 0 };

/*
 * NAME:	kfun->get_exec_cost()
 * DESCRIPTION:	return the allowed execution cost
 */
int kf_get_exec_cost()
{
    (--sp)->type = T_INT;
    sp->u.number = exec_cost;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("call_out", kf_call_out, p_call_out)
# else
char p_call_out[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL, T_INT, 3,
		      T_STRING, T_INT, T_MIXED | T_ELLIPSIS };

/*
 * NAME:	kfun->call_out()
 * DESCRIPTION:	start a call_out
 */
int kf_call_out(nargs)
int nargs;
{
    object *obj;
    uindex handle;

    if (nargs < 2) {
	return -1;
    }

    obj = i_this_object();
    if (obj->count != 0 &&
	(handle=co_new(obj, sp[nargs - 1].u.string,
		       (long) sp[nargs - 2].u.number, nargs - 2)) != 0) {
	/* pop duration */
	sp++;
    } else {
	/* no call_out was started: pop all arguments */
	i_pop(nargs - 1);
	handle = 0;
    }
    str_del(sp->u.string);
    sp->type = T_INT;
    sp->u.number = handle;

    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("remove_call_out", kf_remove_call_out, p_remove_call_out)
# else
char p_remove_call_out[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1,
			     T_INT };

/*
 * NAME:	kfun->remove_call_out()
 * DESCRIPTION:	remove a call_out
 */
int kf_remove_call_out()
{
    sp->u.number = co_del(i_this_object(), (uindex) sp->u.number);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("swapout", kf_swapout, p_swapout)
# else
char p_swapout[] = { C_STATIC | C_LOCAL, T_VOID, 0 };

/*
 * NAME:	kfun->swapout()
 * DESCRIPTION:	swap out all objects
 */
int kf_swapout()
{
    swapout();

    (--sp)->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("dump_state", kf_dump_state, p_dump_state)
# else
char p_dump_state[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID, 0 };

/*
 * NAME:	kfun->dump_state()
 * DESCRIPTION:	dump state
 */
int kf_dump_state()
{
    dump_state();
    (--sp)->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("shutdown", kf_shutdown, p_shutdown)
# else
char p_shutdown[] = { C_STATIC | C_LOCAL, T_VOID, 0 };

/*
 * NAME:	kfun->shutdown()
 * DESCRIPTION:	shut down the mud
 */
int kf_shutdown()
{
    finish();

    (--sp)->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("status", kf_status, p_status)
# else
char p_status[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL,
		    T_MIXED | (1 << REFSHIFT), 1, T_OBJECT };

/*
 * NAME:	kfun->status()
 * DESCRIPTION:	return an array with status information about the gamedriver
 *		or an object
 */
int kf_status(nargs)
int nargs;
{
    if (nargs == 0) {
	(--sp)->u.array = conf_status();
    } else {
	sp->u.array = conf_object(o_object(sp->oindex, sp->u.objcnt));
    }
    sp->type = T_ARRAY;
    arr_ref(sp->u.array);
    return 0;
}
# endif
dgd-net/src/kfun/std.c   640    314      6       43305  5643554157  13163 0ustar  mudusers# ifndef FUNCDEF
# include "kfun.h"
# include "fcontrol.h"
# include "path.h"
# include "comm.h"
# include "call_out.h"
# include "ed.h"
# include "node.h"
# include "compile.h"
# endif


# ifdef FUNCDEF
FUNCDEF("call_other", kf_call_other, p_call_other)
# else
char p_call_other[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL, T_MIXED,
			3, T_MIXED, T_STRING, T_MIXED | T_ELLIPSIS };

/*
 * NAME:	kfun->call_other()
 * DESCRIPTION:	call a function in another object
 */
int kf_call_other(nargs)
int nargs;
{
    register object *obj;
    register value *val;
    char *file;

    if (nargs < 2) {
	return -1;
    }

    val = &sp[nargs - 1];
    switch (val->type) {
    case T_STRING:
	file = path_object(val->u.string->text);
	if (file == (char *) NULL) {
	    return 1;
	}
	obj = o_find(file);
	if (obj == (object *) NULL) {
	    /* object isn't loaded: compile it */
	    obj = c_compile(file);
	}
	str_del(val->u.string);
	break;

    case T_OBJECT:
	obj = o_object(val->oindex, val->u.objcnt);
	break;

    default:
	/* bad arg 1 */
	return 1;
    }

    /* default return value */
    val->type = T_INT;
    val->u.number = 0;
    --val;
    if (i_this_object()->count == 0) {
	/*
	 * cannot call_other from destructed object
	 */
	i_pop(nargs - 1);
	return 0;
    }

    if (i_call(obj, val->u.string->text, FALSE, nargs - 2)) {
	/* function exists */
	val = sp++;
	str_del((sp++)->u.string);
	*sp = *val;
    } else {
	/* function doesn't exist */
	str_del((sp++)->u.string);
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("this_object", kf_this_object, p_this_object)
# else
char p_this_object[] = { C_STATIC | C_LOCAL, T_OBJECT, 0 };

/*
 * NAME:	kfun->this_object()
 * DESCRIPTION:	return the current object
 */
int kf_this_object()
{
    register object *obj;

    --sp;
    obj = i_this_object();
    if (obj->count != 0) {
	sp->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("previous_object", kf_previous_object, p_previous_object)
# else
char p_previous_object[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL,
			     T_OBJECT, 1, T_INT };

/*
 * NAME:	kfun->previous_object()
 * DESCRIPTION:	return the previous object in the call_other chain
 */
int kf_previous_object(nargs)
int nargs;
{
    register object *obj;

    if (nargs == 0) {
	(--sp)->type = T_INT;
	sp->u.number = 0;
    }

    obj = i_prev_object((int) sp->u.number);
    if (obj != (object *) NULL) {
	sp->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("call_trace", kf_call_trace, p_call_trace)
# else
char p_call_trace[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
			T_MIXED | (2 << REFSHIFT), 0 };

/*
 * NAME:	kfun->call_trace()
 * DESCRIPTION:	return the entire call_other chain
 */
int kf_call_trace()
{
    (--sp)->type = T_ARRAY;
    arr_ref(sp->u.array = i_call_trace());
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("clone_object", kf_clone_object, p_clone_object)
# else
char p_clone_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_OBJECT, 1,
			  T_STRING };

/*
 * NAME:	kfun->clone_object()
 * DESCRIPTION:	clone a new object
 */
int kf_clone_object()
{
    register object *obj;
    char *file;

    file = path_object(sp->u.string->text);
    if (file == (char *) NULL) {
	return 1;
    }

    obj = o_find(file);
    if (obj == (object *) NULL) {
	obj = c_compile(file);
    }
    if (!(obj->flags & O_MASTER)) {
	error("Cloning from a clone");
    }
    str_del(sp->u.string);
    sp->type = T_OBJECT;
    obj = o_new((char *) NULL, obj, (control *) NULL);
    sp->oindex = obj->index;
    sp->u.objcnt = obj->count;
    i_call(obj, "", FALSE, 0);	/* cause creator to be called */
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("destruct_object", kf_destruct_object, p_destruct_object)
# else
char p_destruct_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID, 1,
			     T_OBJECT };

/*
 * NAME:	kfun->destruct_object()
 * DESCRIPTION:	destruct an object
 */
int kf_destruct_object()
{
    register object *obj;

    obj = o_object(sp->oindex, sp->u.objcnt);
    if (obj->flags & O_USER) {
	comm_close(obj);
    }
    if (obj->flags & O_EDITOR) {
	ed_del(obj);
    }
    i_odest(obj);	/* wipe out occurrances on the stack */
    o_del(obj);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("object_name", kf_object_name, p_object_name)
# else
char p_object_name[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_STRING, 1,
			 T_OBJECT };

/*
 * NAME:	kfun->object_name()
 * DESCRIPTION:	return the name of an object
 */
int kf_object_name()
{
    char *name;

    name = o_name(o_object(sp->oindex, sp->u.objcnt));
    sp->type = T_STRING;
    str_ref(sp->u.string = str_new((char *) NULL, strlen(name) + 1L));
    sp->u.string->text[0] = '/';
    strcpy(sp->u.string->text + 1, name);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("find_object", kf_find_object, p_find_object)
# else
char p_find_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_OBJECT, 1,
			 T_STRING };

/*
 * NAME:	kfun->find_object()
 * DESCRIPTION:	find the loaded object for a given object name
 */
int kf_find_object()
{
    char *name;
    object *obj;

    name = path_object(sp->u.string->text);
    if (name == (char *) NULL) {
	return 1;
    }

    str_del(sp->u.string);
    obj = o_find(name);
    if (obj != (object *) NULL) {
	sp->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("function_object", kf_function_object, p_function_object)
# else
char p_function_object[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_STRING, 2,
			     T_STRING, T_OBJECT };

/*
 * NAME:	kfun->function_object()
 * DESCRIPTION:	return the name of the program a function is in
 */
int kf_function_object()
{
    object *obj;
    dsymbol *symb;
    char *name;

    obj = o_object(sp->oindex, sp->u.objcnt);
    sp++;
    symb = ctrl_symb(o_control(obj), sp->u.string->text);
    str_del(sp->u.string);
    if (symb != (dsymbol *) NULL) {
	name = o_name(obj->ctrl->inherits[UCHAR(symb->inherit)].obj);
	str_ref(sp->u.string = str_new((char *) NULL, strlen(name) + 1L));
	sp->u.string->text[0] = '/';
	strcpy(sp->u.string->text + 1, name);
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("this_user", kf_this_user, p_this_user)
# else
char p_this_user[] = { C_STATIC | C_LOCAL, T_OBJECT, 0 };

/*
 * NAME:	kfun->this_user()
 * DESCRIPTION:	return the current user object (if any)
 */
int kf_this_user()
{
    object *obj;

    obj = comm_user();
    if (obj != (object *) NULL) {
	(--sp)->type = T_OBJECT;
	sp->oindex = obj->index;
	sp->u.objcnt = obj->count;
    } else {
	(--sp)->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("query_ip_number", kf_query_ip_number, p_query_ip_number)
# else
char p_query_ip_number[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_STRING, 1,
			     T_OBJECT };

/*
 * NAME:	kfun->query_ip_number()
 * DESCRIPTION:	return the ip number of a user
 */
int kf_query_ip_number()
{
    register object *obj;

    obj = o_object(sp->oindex, sp->u.objcnt);
    if (obj->flags & O_USER) {
	sp->type = T_STRING;
	str_ref(sp->u.string = comm_ip_number(obj));
    } else {
	sp->type = T_INT;
	sp->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("users", kf_users, p_users)
# else
char p_users[] = { C_STATIC | C_LOCAL, T_OBJECT | (1 << REFSHIFT), 0 };

/*
 * NAME:	kfun->users()
 * DESCRIPTION:	return the array of users
 */
int kf_users()
{
    (--sp)->type = T_ARRAY;
    arr_ref(sp->u.array = comm_users());
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("strlen", kf_strlen, p_strlen)
# else
char p_strlen[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1, T_STRING };

/*
 * NAME:	kfun->strlen()
 * DESCRIPTION:	return the length of a string
 */
int kf_strlen()
{
    unsigned short len;

    len = sp->u.string->len;
    str_del(sp->u.string);
    sp->type = T_INT;
    sp->u.number = len;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("allocate", kf_allocate, p_allocate)
# else
char p_allocate[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
		      T_MIXED | (1 << REFSHIFT), 1, T_INT };

/*
 * NAME:	kfun->allocate()
 * DESCRIPTION:	allocate an array
 */
int kf_allocate()
{
    register int i;
    register value *v;

    arr_ref(sp->u.array = arr_new((long) sp->u.number));
    sp->type = T_ARRAY;
    for (i = sp->u.array->size, v = sp->u.array->elts; i > 0; --i, v++) {
	v->type = T_INT;
	v->u.number = 0;
    }
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("sizeof", kf_sizeof, p_sizeof)
# else
char p_sizeof[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1,
		    T_MIXED | (1 << REFSHIFT) };

/*
 * NAME:	kfun->sizeof()
 * DESCRIPTION:	return the size of an array
 */
int kf_sizeof()
{
    unsigned short size;

    size = sp->u.array->size;
    arr_del(sp->u.array);
    sp->type = T_INT;
    sp->u.number = size;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("map_indices", kf_map_indices, p_map_indices)
# else
char p_map_indices[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
			 T_MIXED | (1 << REFSHIFT), 1, T_MAPPING };

/*
 * NAME:	kfun->map_indices()
 * DESCRIPTION:	return the array of mapping indices
 */
int kf_map_indices()
{
    array *a;

    a = map_indices(sp->u.array);
    arr_del(sp->u.array);
    sp->type = T_ARRAY;
    arr_ref(sp->u.array = a);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("map_values", kf_map_values, p_map_values)
# else
char p_map_values[] = { C_TYPECHECKED | C_STATIC | C_LOCAL,
			T_MIXED | (1 << REFSHIFT), 1, T_MAPPING };

/*
 * NAME:	kfun->map_values()
 * DESCRIPTION:	return the array of mapping values
 */
int kf_map_values()
{
    array *a;

    a = map_values(sp->u.array);
    arr_del(sp->u.array);
    sp->type = T_ARRAY;
    arr_ref(sp->u.array = a);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("map_sizeof", kf_map_sizeof, p_map_sizeof)
# else
char p_map_sizeof[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1,
			T_MAPPING };

/*
 * NAME:	kfun->map_sizeof()
 * DESCRIPTION:	return the number of index/value pairs in a mapping
 */
int kf_map_sizeof()
{
    unsigned short size;

    size = map_size(sp->u.array);
    arr_del(sp->u.array);
    sp->type = T_INT;
    sp->u.number = size;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("typeof", kf_typeof, p_typeof)
# else
char p_typeof[] = { C_STATIC | C_LOCAL, T_INT, 1, T_MIXED };

/*
 * NAME:	kfun->typeof()
 * DESCRIPTION:	return the type of a value
 */
int kf_typeof()
{
    unsigned short type;

    type = sp->type;
    i_del_value(sp);
    sp->type = T_INT;
    sp->u.number = type;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("error", kf_error, p_error)
# else
char p_error[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID, 1, T_STRING };

/*
 * NAME:	kfun->error()
 * DESCRIPTION:	cause an error
 */
int kf_error()
{
    if (strchr(sp->u.string->text, LF) != (char *) NULL) {
	error("'\\n' in error string");
    }
    error("%s", sp->u.string->text);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("send_message", kf_send_message, p_send_message)
# else
char p_send_message[] = { C_STATIC | C_LOCAL, T_VOID, 1, T_MIXED };

/*
 * NAME:	kfun->send_message()
 * DESCRIPTION:	send a message to a user
 */
int kf_send_message()
{
    object *obj;

    if (sp->type != T_INT && sp->type != T_STRING) {
	return 1;
    }

    obj = i_this_object();
    if (obj->count != 0) {
	if ((obj->flags & O_DRIVER) && sp->type == T_STRING) {
	    P_message(sp->u.string->text);
	} else if (obj->flags & O_USER) {
	    if (sp->type == T_INT) {
		comm_echo(obj, sp->u.number != 0);
	    } else {
		comm_send(obj, sp->u.string);
	    }
	}
    }
    if (sp->type == T_STRING) {
	str_del(sp->u.string);
    }
    sp->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif

# ifdef FUNCDEF
FUNCDEF("open_port", kf_open_port, p_open_port)
# else
char p_open_port[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID,
		    3, T_OBJECT, T_INT, T_STRING };

/*
 * NAME:	kfun->open_port()
 * DESCRIPTION:	start listening on a port
 */
int kf_open_port()
{
    object *obj;
    char *str;
    int protocol;

    obj = i_this_object();
    if (obj->count == 0) {
	error("open_port() from destructed object");
    }
    if (!(obj->flags & O_DRIVER)) {
	error("open_port() only from driver object");
    }

    str = sp->u.string->text;
    if (strcmp(str, "tcp") == 0) {
        protocol = PRC_TCP;
    } else if (strcmp(str, "udp") == 0) {
        protocol = PRC_UDP;
    } else if (strcmp(str, "telnet") == 0) {
        protocol = PRC_TELNET;
    } else {
	return 3;
    }

    obj = o_object(sp[2].oindex, sp[2].u.objcnt);
    if (obj->flags & (O_USER | O_EDITOR)) {
        error("object already used for socket or editor");
    }
    comm_listen(o_object(sp[2].oindex, sp[2].u.objcnt),
		   sp[1].u.number, protocol);
    str_del(sp->u.string);
    sp += 2;
    sp->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif

# ifdef FUNCDEF
FUNCDEF("connect", kf_connect, p_connect)
# else
char p_connect[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID,
		    4, T_OBJECT, T_STRING, T_INT, T_STRING  };

/*
 * NAME:	kfun->connect()
 * DESCRIPTION:	initiate an ip connection
 */
int kf_connect()
{
    object *obj;
    char *str;
    int protocol;

    obj = i_this_object();
    if (obj->count == 0) {
	error("connect() from destructed object");
    }
    if (!(obj->flags & O_DRIVER)) {
        error("connect() only from driver object");
    }

    str = sp->u.string->text;
    if (strcmp(str, "tcp") == 0) {
	protocol = PRC_TCP;
    } else if (strcmp(str, "telnet") == 0) {
	protocol = PRC_TELNET;
    } else {
	return 4;
    }
    
    obj = o_object(sp[3].oindex, sp[3].u.objcnt);
    if (obj->flags & (O_USER | O_EDITOR)) {
        error("object already used for socket or editor");
    }
    comm_connect(obj, sp[2].u.string->text, sp[1].u.number, protocol);
    str_del(sp->u.string);
    str_del(sp[2].u.string);
    sp += 3;
    sp->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif

# ifdef FUNCDEF
FUNCDEF("send_datagram", kf_send_datagram, p_send_datagram)
# else
char p_send_datagram[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID,
			   3, T_STRING, T_STRING, T_INT };

/*
 * NAME:	kfun->send_datagram()
 * DESCRIPTION:	send a packet to a specific host and port (udp only)
 */
int kf_send_datagram()
{
    object *obj;

    obj = i_this_object();
    if (obj->count != 0 && obj->flags & O_USER) {
	comm_sendto(obj, sp[2].u.string, sp[1].u.string->text, sp->u.number);
    }
    str_del((++sp)->u.string);
    str_del((++sp)->u.string);
    sp->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif

# ifdef FUNCDEF
FUNCDEF("time", kf_time, p_time)
# else
char p_time[] = { C_STATIC | C_LOCAL, T_INT, 0 };

/*
 * NAME:	kfun->time()
 * DESCRIPTION:	return the current time
 */
int kf_time()
{
    (--sp)->type = T_INT;
    sp->u.number = P_time();
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("get_exec_cost", kf_get_exec_cost, p_get_exec_cost)
# else
char p_get_exec_cost[] = { C_STATIC | C_LOCAL, T_INT, 0 };

/*
 * NAME:	kfun->get_exec_cost()
 * DESCRIPTION:	return the allowed execution cost
 */
int kf_get_exec_cost()
{
    (--sp)->type = T_INT;
    sp->u.number = exec_cost;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("call_out", kf_call_out, p_call_out)
# else
char p_call_out[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL, T_INT, 3,
		      T_STRING, T_INT, T_MIXED | T_ELLIPSIS };

/*
 * NAME:	kfun->call_out()
 * DESCRIPTION:	start a call_out
 */
int kf_call_out(nargs)
int nargs;
{
    object *obj;
    uindex handle;

    if (nargs < 2) {
	return -1;
    }

    obj = i_this_object();
    if (obj->count != 0 &&
	(handle=co_new(obj, sp[nargs - 1].u.string,
		       (long) sp[nargs - 2].u.number, nargs - 2)) != 0) {
	/* pop duration */
	sp++;
    } else {
	/* no call_out was started: pop all arguments */
	i_pop(nargs - 1);
	handle = 0;
    }
    str_del(sp->u.string);
    sp->type = T_INT;
    sp->u.number = handle;

    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("remove_call_out", kf_remove_call_out, p_remove_call_out)
# else
char p_remove_call_out[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_INT, 1,
			     T_INT };

/*
 * NAME:	kfun->remove_call_out()
 * DESCRIPTION:	remove a call_out
 */
int kf_remove_call_out()
{
    sp->u.number = co_del(i_this_object(), (uindex) sp->u.number);
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("swapout", kf_swapout, p_swapout)
# else
char p_swapout[] = { C_STATIC | C_LOCAL, T_VOID, 0 };

/*
 * NAME:	kfun->swapout()
 * DESCRIPTION:	swap out all objects
 */
int kf_swapout()
{
    swapout();

    (--sp)->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("dump_state", kf_dump_state, p_dump_state)
# else
char p_dump_state[] = { C_TYPECHECKED | C_STATIC | C_LOCAL, T_VOID, 0 };

/*
 * NAME:	kfun->dump_state()
 * DESCRIPTION:	dump state
 */
int kf_dump_state()
{
    dump_state();
    (--sp)->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("shutdown", kf_shutdown, p_shutdown)
# else
char p_shutdown[] = { C_STATIC | C_LOCAL, T_VOID, 0 };

/*
 * NAME:	kfun->shutdown()
 * DESCRIPTION:	shut down the mud
 */
int kf_shutdown()
{
    finish();

    (--sp)->type = T_INT;
    sp->u.number = 0;
    return 0;
}
# endif


# ifdef FUNCDEF
FUNCDEF("status", kf_status, p_status)
# else
char p_status[] = { C_TYPECHECKED | C_STATIC | C_VARARGS | C_LOCAL,
		    T_MIXED | (1 << REFSHIFT), 1, T_OBJECT };

/*
 * NAME:	kfun->status()
 * DESCRIPTION:	return an array with status information about the gamedriver
 *		or an object
 */
int kf_status(nargs)
int nargs;
{
    if (nargs == 0) {
	(--sp)->u.array = conf_status();
    } else {
	sp->u.array = conf_object(o_object(sp->oindex, sp->u.objcnt));
    }
    sp->type = T_ARRAY;
    arr_ref(sp->u.array);
    return 0;
}
# endif
dgd-net/src/comm.DGD.c   640    314      6       32334  5643554266  12757 0ustar  mudusers# define INCLUDE_TELNET
# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "interpret.h"
# include "comm.h"

# ifndef TELOPT_LINEMODE
# define TELOPT_LINEMODE	34	/* linemode option */
# define LM_MODE		1
# define MODE_EDIT		0x01
# endif

typedef struct _user_ {
    union {
	object *obj;		/* associated object */
	struct _user_ *next;	/* next in free list */
    } u;
    int inbufsz;		/* bytes in input buffer */
    int outbufsz;		/* bytes in output buffer */
    char flags;			/* connection flags */
    char state;			/* telnet state */
    short newlines;		/* # of newlines in input buffer */
    connection *conn;		/* connection */
    char inbuf[INBUF_SIZE];	/* input buffer */
    char outbuf[OUTBUF_SIZE];	/* output buffer */
} user;

/* flags */
# define CF_ECHO	0x01	/* client echoes input */
# define CF_TELNET	0x02	/* telnet connection */
# define CF_GA		0x04	/* send GA after prompt */
# define CF_SEENCR	0x08	/* just seen a CR */

/* state */
# define TS_DATA	0
# define TS_IAC		1
# define TS_DO		2
# define TS_DONT	3
# define TS_WILL	4
# define TS_WONT	5
# define TS_SB		6
# define TS_SE		7

static user **users;		/* array of users */
static int maxusers;		/* max # of users */
static int nusers;		/* # of users */
static int newlines;		/* # of newlines in all input buffers */
static long binchars;		/* # characters in binary buffers */
static object *this_user;	/* current user */

/*
 * NAME:	comm->init()
 * DESCRIPTION:	initialize communications
 */
void comm_init(nusers, telnet_port, binary_port)
int nusers, telnet_port, binary_port;
{
    register int i;
    register user **usr;

    conn_init(nusers, telnet_port, binary_port);
    users = ALLOC(user*, maxusers = nusers);
    for (i = nusers, usr = users; i > 0; --i, usr++) {
	*usr = (user *) NULL;
    }
}

/*
 * NAME:	comm->finish()
 * DESCRIPTION:	terminate connections
 */
void comm_finish()
{
    comm_flush(FALSE);
    conn_finish();
}

/*
 * NAME:	comm->new()
 * DESCRIPTION:	accept a new connection
 */
static void comm_new(obj, conn, telnet)
object *obj;
connection *conn;
bool telnet;
{
    static char init[] = { IAC, WONT, TELOPT_ECHO, IAC, DO, TELOPT_LINEMODE };
    register user **usr;

    if (obj->flags & (O_USER | O_EDITOR)) {
	error("user object is already used for user or editor");
    }
    for (usr = users; *usr != (user *) NULL; usr++) ;
    mstatic();
    *usr = ALLOC(user, 1);
    mdynamic();
    (*usr)->u.obj = obj;
    obj->flags |= O_USER;
    obj->etabi = usr - users;
    (*usr)->inbufsz = 0;
    (*usr)->outbufsz = 0;
    (*usr)->conn = conn;
    if (telnet) {
	/* initialize connection */
	conn_write(conn, init, sizeof(init));
	(*usr)->flags = CF_TELNET | CF_ECHO;
	(*usr)->state = TS_DATA;
	(*usr)->newlines = 0;
    } else {
	(*usr)->flags = 0;
    }
    nusers++;
    this_user = obj;
}

/*
 * NAME:	comm->del()
 * DESCRIPTION:	delete a connection
 */
static void comm_del(usr)
register user **usr;
{
    object *obj, *olduser;

    conn_del((*usr)->conn);
    if ((*usr)->flags & CF_TELNET) {
	newlines -= (*usr)->newlines;
    } else {
	binchars -= (*usr)->inbufsz;
    }
    obj = (*usr)->u.obj;
    obj->flags &= ~O_USER;
    FREE(*usr);
    *usr = (user *) NULL;
    --nusers;

    olduser = this_user;
    this_user = obj;
    if (i_call(obj, "close", TRUE, 0)) {
	i_del_value(sp++);
    }
    if (obj == olduser) {
	this_user = (object *) NULL;
    } else {
	this_user = olduser;
    }
}

/*
 * NAME:	comm->send()
 * DESCRIPTION:	send a message to a user
 */
void comm_send(obj, str)
object *obj;
string *str;
{
    register user *usr;
    register char *p, *q;
    register unsigned short len, size;

    usr = users[UCHAR(obj->etabi)];
    p = str->text;
    len = str->len;
    size = usr->outbufsz;
    q = usr->outbuf + size;
    if (usr->flags & CF_TELNET) {
	/*
	 * telnet connection
	 */
	while (len != 0) {
	    if (UCHAR(*p) == IAC) {
		/*
		 * double the telnet IAC character
		 */
		if (size == OUTBUF_SIZE) {
		    conn_write(usr->conn, q = usr->outbuf, size);
		    size = 0;
		}
		*q++ = IAC;
		size++;
	    } else if (*p == LF) {
		/*
		 * insert CR before LF
		 */
		if (size == OUTBUF_SIZE) {
		    conn_write(usr->conn, q = usr->outbuf, size);
		    size = 0;
		}
		*q++ = CR;
		size++;
	    } else if ((*p & 0x7f) < ' ' && *p != HT && *p != BEL && *p != BS) {
		/*
		 * illegal character
		 */
		p++;
		--len;
		continue;
	    }
	    if (size == OUTBUF_SIZE) {
		conn_write(usr->conn, q = usr->outbuf, size);
		size = 0;
	    }
	    *q++ = *p++;
	    --len;
	    size++;
	}
    } else {
	/*
	 * binary connection
	 */
	while (size + len > OUTBUF_SIZE) {
	    memcpy(q, p, OUTBUF_SIZE - size);
	    p += OUTBUF_SIZE - size;
	    len -= OUTBUF_SIZE - size;
	    conn_write(usr->conn, q = usr->outbuf, OUTBUF_SIZE);
	    size = 0;
	}
	memcpy(q, p, len);
	size += len;
    }
    usr->outbufsz = size;
}

/*
 * NAME:	comm->echo()
 * DESCRIPTION:	turn on/off input echoing for a user
 */
void comm_echo(obj, echo)
object *obj;
int echo;
{
    register user *usr;
    char buf[3];

    usr = users[UCHAR(obj->etabi)];
    if ((usr->flags & CF_TELNET) && echo != (usr->flags & CF_ECHO)) {
	buf[0] = IAC;
	buf[1] = (echo) ? WONT : WILL;
	buf[2] = TELOPT_ECHO;
	conn_write(usr->conn, buf, 3);
	usr->flags ^= CF_ECHO;
    }
}

/*
 * NAME:	comm->flush()
 * DESCRIPTION:	flush output to all users
 */
void comm_flush(prompt)
int prompt;
{
    register user **usr;
    register int i, size;
    register char *p;

    for (usr = users, i = maxusers; i > 0; usr++, --i) {
	if (*usr != (user *) NULL && (size=(*usr)->outbufsz) > 0) {
	    if (prompt && (*usr)->u.obj == this_user &&
		((*usr)->flags & (CF_TELNET | CF_GA)) == (CF_TELNET | CF_GA)) {
		/*
		 * append "go ahead" to indicate that the prompt has been sent
		 */
		if (size >= OUTBUF_SIZE - 2) {
		    conn_write((*usr)->conn, (*usr)->outbuf, size);
		    size = 0;
		}
		p = (*usr)->outbuf + size;
		*p++ = IAC;
		*p++ = GA;
		size += 2;
	    }
	    conn_write((*usr)->conn, (*usr)->outbuf, size);
	    (*usr)->outbufsz = 0;
	}
    }
    this_user = (object *) NULL;
}

/*
 * NAME:	comm->receive()
 * DESCRIPTION:	receive a message from a user
 */
object *comm_receive(buf, size)
char *buf;
int *size;
{
    static int lastuser;
    connection *conn;
    object *o;
    register int n, i, state, flags, nls;
    register char *p, *q;

    if (nusers < maxusers) {
	/*
	 * accept new telnet connection
	 */
	conn = conn_tnew();
	if (conn != (connection *) NULL) {
	    if (ec_push()) {
		conn_del(conn);		/* delete connection */
		error((char *) NULL);	/* pass on error */
	    }
	    call_driver_object("telnet_connect", 0);
	    ec_pop();
	    if (sp->type != T_OBJECT) {
		fatal("driver->telnet_connect() did not return an object");
	    }
	    comm_new(o = o_object(sp->oindex, sp->u.objcnt), conn, TRUE);
	    sp++;
	    if (i_call(o, "open", TRUE, 0)) {
		i_del_value(sp++);
	    }
	    comm_flush(TRUE);
	}
    }

    if (nusers < maxusers) {
	/*
	 * accept new binary connection
	 */
	conn = conn_bnew();
	if (conn != (connection *) NULL) {
	    if (ec_push()) {
		conn_del(conn);		/* delete connection */
		error((char *) NULL);	/* pass on error */
	    }
	    call_driver_object("binary_connect", 0);
	    ec_pop();
	    if (sp->type != T_OBJECT) {
		fatal("driver->binary_connect() did not return an object");
	    }
	    comm_new(o = o_object(sp->oindex, sp->u.objcnt), conn, FALSE);
	    sp++;
	    if (i_call(o, "open", TRUE, 0)) {
		i_del_value(sp++);
	    }
	    comm_flush(TRUE);
	}
    }

    /*
     * read input from users
     */
    this_user = (object *) NULL;
    n = conn_select(newlines == 0 && binchars == 0);
    if (n <= 0) {
	/*
	 * call_out to do, or timeout
	 */
	if (newlines == 0 && binchars == 0) {
	    return (object *) NULL;
	}
    } else {
	static char intr[] =		{ '\177' };
	static char brk[] =		{ '\034' };
	static char tm[] =		{ IAC, WILL, TELOPT_TM };
	static char will_sga[] =	{ IAC, WILL, TELOPT_SGA };
	static char wont_sga[] =	{ IAC, WONT, TELOPT_SGA };
	static char mode_edit[] =	{ IAC, SB, TELOPT_LINEMODE, LM_MODE,
					  MODE_EDIT, IAC, SE };
	register user **usr;

	for (i = maxusers, usr = users; i > 0; --i, usr++) {
	    if (*usr != (user *) NULL && (*usr)->inbufsz != INBUF_SIZE) {
		p = (*usr)->inbuf + (*usr)->inbufsz;
		n = conn_read((*usr)->conn, p, INBUF_SIZE - (*usr)->inbufsz);
		if (n < 0) {
		    /*
		     * bad connection
		     */
		    comm_del(usr);
		} else if ((*usr)->flags & CF_TELNET) {
		    /*
		     * telnet mode
		     */
		    flags = (*usr)->flags;
		    state = (*usr)->state;
		    nls = (*usr)->newlines;
		    q = p;
		    while (n > 0) {
			switch (state) {
			case TS_DATA:
			    switch (UCHAR(*p)) {
			    case IAC:
				state = TS_IAC;
				break;

			    case BS:
			    case 0x7f:
				if (q != (*usr)->inbuf && q[-1] != LF) {
				    --q;
				}
				flags &= ~CF_SEENCR;
				break;

			    case CR:
				nls++;
				newlines++;
				*q++ = LF;
				flags |= CF_SEENCR;
				break;

			    case LF:
				if ((flags & CF_SEENCR) != 0) {
				    flags &= ~CF_SEENCR;
				    break;
				}
				nls++;
				newlines++;
				/* fall through */
			    default:
				*q++ = *p;
				flags &= ~CF_SEENCR;
				break;
			    }
			    break;

			case TS_IAC:
			    switch (UCHAR(*p)) {
			    case IAC:
				*q++ = *p;
				state = TS_DATA;
				break;

			    case DO:
				state = TS_DO;
				break;

			    case DONT:
				state = TS_DONT;
				break;

			    case WILL:
				state = TS_WILL;
				break;

			    case WONT:
				state = TS_WONT;
				break;

			    case SB:
				state = TS_SB;
				break;

			    case IP:
				conn_write((*usr)->conn, intr, 1);
				state = TS_DATA;
				break;

			    case BREAK:
				conn_write((*usr)->conn, brk, 1);
				state = TS_DATA;
				break;

			    default:
				/* let's hope it wasn't important */
				state = TS_DATA;
				break;
			    }
			    break;

			case TS_DO:
			    if (UCHAR(*p) == TELOPT_TM) {
				conn_write((*usr)->conn, tm, 3);
			    } else if (UCHAR(*p) == TELOPT_SGA) {
				flags &= ~CF_GA;
				conn_write((*usr)->conn, will_sga, 3);
			    }
			    state = TS_DATA;
			    break;

			case TS_DONT:
			    if (UCHAR(*p) == TELOPT_SGA) {
				flags |= CF_GA;
				conn_write((*usr)->conn, wont_sga, 3);
			    }
			    state = TS_DATA;
			    break;

			case TS_WILL:
			    if (UCHAR(*p) == TELOPT_LINEMODE) {
				/* linemode confirmed; now request editing */
				conn_write((*usr)->conn, mode_edit, 7);
			    }
			    /* fall through */
			case TS_WONT:
			    state = TS_DATA;
			    break;

			case TS_SB:
			    /* skip to the end */
			    if (UCHAR(*p) == IAC) {
				state = TS_SE;
			    }
			    break;

			case TS_SE:
			    if (UCHAR(*p) == SE) {
				/* end of subnegotiation */
				state = TS_DATA;
			    } else {
				state = TS_SB;
			    }
			    break;
			}
			p++;
			--n;
		    }
		    (*usr)->flags = flags;
		    (*usr)->state = state;
		    (*usr)->newlines = nls;
		    (*usr)->inbufsz = q - (*usr)->inbuf;
		} else {
		    /*
		     * binary mode
		     */
		    (*usr)->inbufsz += n;
		    binchars += n;
		}
	    }
	}
    }

    if (newlines != 0 || binchars != 0) {
	register user *usr;

	n = lastuser;
	for (;;) {
	    n = (n + 1) % maxusers;
	    usr = users[n];
	    if (usr != (user *) NULL && usr->inbufsz != 0) {
		if (usr->flags & CF_TELNET) {
		    /*
		     * telnet connection
		     */
		    if (usr->newlines != 0) {
			/*
			 * input terminated by \n
			 */
			p = (char *) memchr(usr->inbuf, LF, usr->inbufsz);
			usr->newlines--;
			--newlines;
			lastuser = n;
			*size = n = p - usr->inbuf;
			if (n != 0) {
			    memcpy(buf, usr->inbuf, n);
			}
			p++;	/* skip \n */
			n++;
			usr->inbufsz -= n;
			if (usr->inbufsz != 0) {
			    /* can't rely on memcpy */
			    for (q = usr->inbuf, n = usr->inbufsz; n > 0; --n) {
				*q++ = *p++;
			    }
			}
			return this_user = usr->u.obj;
		    } else if (usr->inbufsz == INBUF_SIZE) {
			/*
			 * input buffer full
			 */
			lastuser = n;
			memcpy(buf, usr->inbuf, *size = INBUF_SIZE);
			usr->inbufsz = 0;
			return this_user = usr->u.obj;
		    }
		} else {
		    /*
		     * binary connection
		     */
		    lastuser = n;
		    binchars -= usr->inbufsz;
		    memcpy(buf, usr->inbuf, *size = usr->inbufsz);
		    usr->inbufsz = 0;
		    return this_user = usr->u.obj;
		}
	    }
	}
    }

    return (object *) NULL;
}

/*
 * NAME:	comm->ip_number()
 * DESCRIPTION:	return the ip number of a user (as a string)
 */
string *comm_ip_number(obj)
object *obj;
{
    char *ipnum;

    ipnum = conn_ipnum(users[UCHAR(obj->etabi)]->conn);
    return str_new(ipnum, (long) strlen(ipnum));
}

/*
 * NAME:	comm->close()
 * DESCRIPTION:	remove a user
 */
void comm_close(obj)
object *obj;
{
    register user **usr;

    usr = &users[UCHAR(obj->etabi)];
    if ((*usr)->outbufsz != 0) {
	/*
	 * flush last bit of output
	 */
	conn_write((*usr)->conn, (*usr)->outbuf, (*usr)->outbufsz);
    }
    comm_del(usr);
}

/*
 * NAME:	comm->user()
 * DESCRIPTION:	return the current user
 */
object *comm_user()
{
    return this_user;
}

/*
 * NAME:	comm->users()
 * DESCRIPTION:	return an array with all user objects
 */
array *comm_users()
{
    array *a;
    register int i;
    register user **usr;
    register value *v;

    a = arr_new((long) nusers);
    v = a->elts;
    for (i = nusers, usr = users; i > 0; usr++) {
	if (*usr != (user *) NULL) {
	    v->type = T_OBJECT;
	    v->oindex = (*usr)->u.obj->index;
	    v->u.objcnt = (*usr)->u.obj->count;
	    v++;
	    --i;
	}
    }
    return a;
}
dgd-net/src/comm.DGD.h   640    314      6        1613  5643554307  12734 0ustar  mudusers# define INBUF_SIZE	2048
# define OUTBUF_SIZE	1024

typedef struct _connection_ connection;

extern void	   conn_init	P((int, unsigned int, unsigned int));
extern void	   conn_finish	P((void));
extern connection *conn_tnew	P((void));
extern connection *conn_bnew	P((void));
extern void	   conn_del	P((connection*));
extern int	   conn_select	P((int));
extern int	   conn_read	P((connection*, char*, int));
extern void	   conn_write	P((connection*, char*, int));
extern char	  *conn_ipnum	P((connection*));

extern void	comm_init	P((int, int, int));
extern void	comm_finish	P((void));
extern void	comm_send	P((object*, string*));
extern void	comm_echo	P((object*, int));
extern void	comm_flush	P((int));
extern object  *comm_receive	P((char*, int*));
extern string  *comm_ip_number	P((object*));
extern void	comm_close	P((object*));
extern object  *comm_user	P((void));
extern array   *comm_users	P((void));
dgd-net/src/dgd.DGD.c   640    314      6        5554  5572137626  12544 0ustar  mudusers# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "ed.h"
# include "call_out.h"
# include "comm.h"
# include "node.h"
# include "compile.h"

/*
 * NAME:	call_driver_object()
 * DESCRIPTION:	call a function in the driver object
 */
bool call_driver_object(func, narg)
char *func;
int narg;
{
    static object *driver;
    static Uint dcount;
    static char *driver_name;

    if (driver == (object *) NULL || dcount != driver->count) {
	if (driver_name == (char *) NULL) {
	    driver_name = conf_driver();
	}
	driver = o_find(driver_name);
	if (driver == (object *) NULL) {
	    driver = c_compile(driver_name);
	}
	dcount = driver->count;
    }
    if (!i_call(driver, func, TRUE, narg)) {
	fatal("missing function in driver object: %s", func);
    }
    return TRUE;
}

static bool swap;	/* are objects to be swapped out? */
static bool dump;	/* is the program to dump? */
static bool intr;	/* received an interrupt? */
static bool stop;	/* is the program to terminate? */

/*
 * NAME:	swapout()
 * DESCRIPTION:	indicate that objects are to be swapped out
 */
void swapout()
{
    swap = TRUE;
}

/*
 * NAME:	dump_state()
 * DESCRIPTION:	indicate that the state must be dumped
 */
void dump_state()
{
    dump = TRUE;
}

/*
 * NAME:	interrupt()
 * DESCRIPTION:	register an interrupt
 */
void interrupt()
{
    intr = TRUE;
}

/*
 * NAME:	finish()
 * DESCRIPTION:	indicate that the program must finish
 */
void finish()
{
    stop = TRUE;
}

/*
 * NAME:	dgd_main()
 * DESCRIPTION:	the main loop of DGD
 */
int dgd_main(argc, argv)
int argc;
char **argv;
{
    char buf[INBUF_SIZE];
    int size;
    object *usr;

    if (argc < 2 || argc > 3) {
	P_message("Usage: dgd config_file [dump_file]\012");	/* LF */
	return 2;
    }

    if (ec_push()) {
	warning((char *) NULL);
	fatal("error during initialization");
    }
    if (argc == 2) {
	conf_init(argv[1], (char *) NULL);
    } else {
	conf_init(argv[1], argv[2]);
    }
    ec_pop();

    while (ec_push()) {
	i_log_error(FALSE);
	i_clear();
    }

    do {
	P_getevent();
	if (intr) {
	    intr = FALSE;
	    call_driver_object("interrupt", 0);
	    i_del_value(sp++);
	}

	co_call();
	comm_flush(FALSE);

	if (!stop) {
	    usr = comm_receive(buf, &size);
	    if (usr != (object *) NULL) {
		(--sp)->type = T_STRING;
		str_ref(sp->u.string = str_new(buf, (long) size));
		if (i_call(usr, "receive_message", TRUE, 1)) {
		    i_del_value(sp++);
		}
		comm_flush(TRUE);
	    }
	}

	o_clean();

	if (!mcheck()) {
	    d_swapout(1);
	    arr_freeall();
	    mpurge();
	    mexpand();
	} else if (swap) {
	    d_swapout(1);
	    arr_freeall();
	    mpurge();
	}
	swap = FALSE;

	if (dump) {
	    d_swapsync();
	    conf_dump();
	    dump = FALSE;
	}

	sw_copy();
    } while (!stop);

    ec_pop();
    comm_finish();
    ed_finish();
    sw_finish();
    return 0;
}
dgd-net/src/host/   755    314      6           0  5640047605  12126 5ustar  mudusersdgd-net/src/host/unix/   755    314      6           0  5640047605  13111 5ustar  mudusersdgd-net/src/host/unix/connect.c   640    314      6       16051  5701631662  15005 0ustar  mudusers# define INCLUDE_FILE_IO
# include "dgd.h"
# include <sys/time.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
# include <errno.h>
# include "str.h"
# include "array.h"
# include "object.h"
# include "comm.h"

struct _connection_ {
    int fd;				/* file descriptor */
    struct sockaddr_in sin;             /* peer's address */
    struct _connection_ *next;		/* next in list */
    char host[16];                      /* ascii ip number of peer */
    char hostlen;                       /* length of host string */
};

static int nusers;			/* # of users */
static connection *connections;		/* connections array */
static connection *flist;		/* list of free connections */
static fd_set fds;			/* file descriptor bitmap */
static fd_set connectfds;               /* file descriptor bitmap */
static fd_set readfds;			/* file descriptor read bitmap */
static fd_set writefds;                 /* file descriptor write bitmap */
static fd_set failfds;                  /* file descriptor exception bitmap */
static int maxfd;			/* largest fd opened yet */

/*
 * NAME:	conn->init()
 * DESCRIPTION:	initialize connections
 */
void conn_init(maxusers)
int maxusers;
{
    register int n;
    register connection *conn;

    connections = ALLOC(connection, nusers = maxusers);
    for (n = nusers, conn = connections; n > 0; --n, conn++) {
	conn->fd = -1;
	conn->next = flist;
	flist = conn;
    }

    FD_ZERO(&fds);
    FD_ZERO(&connectfds);
}

/*
 * NAME:	conn->finish()
 * DESCRIPTION:	terminate connections
 */
void conn_finish()
{
}

/*
 * NAME:	conn->new()
 * DESCRIPTION:	initialize a new connection struct
 */
static connection *conn_new(fd, sin)
int fd;
struct sockaddr_in *sin;
{
    register connection *conn;
    conn = flist;
    flist = conn->next;
    conn->fd = fd;
    memcpy(&conn->sin, sin, sizeof(conn->sin));
    strcpy(conn->host, inet_ntoa(sin->sin_addr));
    conn->hostlen = strlen(conn->host);
    if (fd > maxfd) {
	maxfd = fd;
    }

    return conn;
}

/*
 * NAME:	conn->listen()
 * DESCRIPTION:	bind a connection to a local port
 */
connection *conn_listen(port, protocol)
int port, protocol;
{
    int fd;
    static struct sockaddr_in sin;
    int on = 1;

    fd = socket(PF_INET, (protocol == PRC_UDP) ? SOCK_DGRAM : SOCK_STREAM, 0);
    if (fd < 0) {
	return (connection *) NULL;
    }
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 
		   sizeof(on)) < 0) {
        close(fd);
        return (connection *) NULL;
    }

    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = INADDR_ANY;  /* htonl? */
    if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
	close(fd);
	return (connection *) NULL;
    }

    if (protocol != PRC_UDP && listen(fd, 5) < 0) {
	close(fd);
	return (connection *) NULL;
    }

    if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
	close(fd);
	return (connection *) NULL;
    }

    FD_SET(fd, &fds);
    return conn_new(fd, &sin);
}

/*
 * NAME:	conn->accept()
 * DESCRIPTION:	accept a connection
 */
connection *conn_accept(conn)
connection *conn;
{
    int fd;
    struct sockaddr_in sin;
    int len = sizeof(sin);

    fd = accept(conn->fd, (struct sockaddr *) &sin, &len);
    if (fd < 0) {
	return (connection *) NULL;
    }

    FD_SET(fd, &fds);
    return conn_new(fd, &sin);
}

/*
 * NAME:	conn->connect()
 * DESCRIPTION:	initiate a tcp connection
 */
connection *conn_connect(host, port, protocol)
char *host;
int port, protocol;
{
    int fd;
    static struct sockaddr_in sin;

    if (protocol != PRC_TCP) {
        return (connection *) NULL;
    }

    fd = socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
	return (connection *) NULL;
    }

    if (fcntl(fd, F_SETFL, FNDELAY) < 0) {
	close(fd);
	return (connection *) NULL;
    }

    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    sin.sin_addr.s_addr = inet_addr(host);
    if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0 &&
	errno != EINPROGRESS) {
	close(fd);
	return (connection *) NULL;
    }

    FD_SET(fd, &connectfds);
    return conn_new(fd, &sin);
}

/*
 * NAME:	conn->connected()
 * DESCRIPTION:	mark a connecting socket as active
 */
int conn_connected(conn)
register connection *conn;
{
    if (conn->fd == -1)
	return -1;
    if (FD_ISSET(conn->fd, &failfds)) {
	FD_CLR(conn->fd, &connectfds);
	return -1;
    } else if (FD_ISSET(conn->fd, &writefds)) {
	FD_CLR(conn->fd, &connectfds);
	FD_SET(conn->fd, &fds);
	return 1;
    }
    return 0;
}
    

/*
 * NAME:	conn->del()
 * DESCRIPTION:	delete a connection
 */
void conn_del(conn)
register connection *conn;
{
    if (conn->fd >= 0) {
	close(conn->fd);
	FD_CLR(conn->fd, &fds);
	FD_CLR(conn->fd, &connectfds);
	conn->fd = -1;
    }
    conn->next = flist;
    flist = conn;
}

/*
 * NAME:	conn->select()
 * DESCRIPTION:	wait for input from connections
 */
int conn_select(wait)
int wait;
{
    struct timeval timeout;

    memcpy(&readfds, &fds, sizeof(fd_set));
    memcpy(&writefds, &connectfds, sizeof(fd_set));
    memcpy(&failfds, &connectfds, sizeof(fd_set));
    timeout.tv_sec = (int) wait;
    timeout.tv_usec = 0;
    return select(maxfd + 1, &readfds, &writefds, &failfds, &timeout);
}

/*
 * NAME:	conn->recvfrom()
 * DESCRIPTION: read a datagram
 */
int conn_recvfrom(conn, buf, size)
connection *conn;
char *buf;
int size;
{
    struct sockaddr_in sin;
    int len = sizeof(sin);
    
    if (conn->fd < 0) {
	return -1;
    }
    if (!FD_ISSET(conn->fd, &readfds)) {
	return 0;
    }
    size = recvfrom(conn->fd, buf, size, 0, (struct sockaddr *)&sin, &len);
    memcpy(&(conn->sin), &sin, len);
    strcpy(conn->host, inet_ntoa(sin.sin_addr));
    conn->hostlen = strlen(conn->host);
    return size;  /* Size may legitimately be 0 */
}

/*
 * NAME:	conn->read()
 * DESCRIPTION:	read from a connection
 */
int conn_read(conn, buf, size)
connection *conn;
char *buf;
int size;
{
    if (conn->fd < 0) {
	return -1;
    }
    if (!FD_ISSET(conn->fd, &readfds) || size == 0) {
	return 0;
    }
    size = read(conn->fd, buf, size);
    return (size == 0) ? -1 : size;
}

/*
 * NAME:	conn->sendto()
 * DESCRIPTION: send a datagram
 */
void conn_sendto(conn, data, size, host, port)
connection *conn;
char *data, *host;
int   size,  port;
{
    static struct sockaddr_in sin;
    if (conn->fd >= 0) {
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = inet_addr(host);
	sin.sin_port = htons(port);
	sendto(conn->fd, data, size, 0, (struct sockaddr *)&sin, sizeof(sin));
    }
}

/*
 * NAME:	conn->write()
 * DESCRIPTION:	write to a connection
 */
void conn_write(conn, buf, size)
connection *conn;
char *buf;
register int size;
{
    if (conn->fd >= 0) {
	if (write(conn->fd, buf, size) < 0 && errno != EWOULDBLOCK) {
	    close(conn->fd);
	    FD_CLR(conn->fd, &fds);
	    FD_CLR(conn->fd, &connectfds);
	    conn->fd = -1;
	}
    }
}

/*
 * NAME:	conn->ipnum()
 * DESCRIPTION:	return the ip number of a connection
 */
string *conn_ipnum(conn)
connection *conn;
{
    return str_new(conn->host, conn->hostlen);
}

/*
 * NAME:	conn->port()
 * DESCRIPTION:	return the port number of a connection
 */
int conn_port(conn)
connection *conn;
{
    return ntohs(conn->sin.sin_port);
}

dgd-net/src/host/unix/connect.DGD.c   640    314      6       12122  5643554551  15403 0ustar  mudusers# define INCLUDE_FILE_IO
# include "dgd.h"
# include <sys/time.h>
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <netdb.h>
# include <errno.h>
# include "str.h"
# include "array.h"
# include "object.h"
# include "comm.h"

struct _connection_ {
    int fd;				/* file descriptor */
    struct sockaddr_in addr;		/* internet address of connection */
    struct _connection_ *next;		/* next in list */
};

static int nusers;			/* # of users */
static connection *connections;		/* connections array */
static connection *flist;		/* list of free connections */
static int telnet;			/* telnet port socket descriptor */
static int binary;			/* binary port socket descriptor */
static fd_set fds;			/* file descriptor bitmap */
static fd_set readfds;			/* file descriptor read bitmap */
static int maxfd;			/* largest fd opened yet */

/*
 * NAME:	conn->init()
 * DESCRIPTION:	initialize connections
 */
void conn_init(maxusers, telnet_port, binary_port)
int maxusers;
unsigned int telnet_port, binary_port;
{
    struct sockaddr_in sin;
    struct hostent *host;
    register int n;
    register connection *conn;
    char buffer[256];
    int on;

    gethostname(buffer, sizeof(buffer));
    host = gethostbyname(buffer);
    if (host == (struct hostent *) NULL) {
	perror("gethostbyname");
	exit(2);
    }

    telnet = socket(host->h_addrtype, SOCK_STREAM, 0);
    binary = socket(host->h_addrtype, SOCK_STREAM, 0);
    if (telnet < 0 || binary < 0) {
	perror("socket");
	exit(2);
    }
    on = 1;
    if (setsockopt(telnet, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
		   sizeof(on)) < 0) {
	perror("setsockopt");
	exit(2);
    }
    on = 1;
    if (setsockopt(binary, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
		   sizeof(on)) < 0) {
	perror("setsockopt");
	exit(2);
    }

    memset(&sin, '\0', sizeof(sin));
    memcpy(&sin.sin_addr, host->h_addr, host->h_length);
    sin.sin_port = htons(telnet_port);
    sin.sin_family = host->h_addrtype;
    sin.sin_addr.s_addr = INADDR_ANY;
    if (bind(telnet, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
	perror("bind");
	exit(2);
    }
    sin.sin_port = htons(binary_port);
    if (bind(binary, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
	perror("bind");
	exit(2);
    }

    if (listen(telnet, 5) < 0 || listen(binary, 5) < 0) {
	perror("listen");
	exit(2);
    }

    if (fcntl(telnet, F_SETFL, FNDELAY) < 0 ||
	fcntl(binary, F_SETFL, FNDELAY) < 0) {
	perror("fcntl");
	exit(2);
    }

    connections = ALLOC(connection, nusers = maxusers);
    for (n = nusers, conn = connections; n > 0; --n, conn++) {
	conn->fd = -1;
	conn->next = flist;
	flist = conn;
    }

    FD_ZERO(&fds);
}

/*
 * NAME:	conn->finish()
 * DESCRIPTION:	terminate connections
 */
void conn_finish()
{
    close(telnet);
    close(binary);
}

/*
 * NAME:	conn->tnew()
 * DESCRIPTION:	accept a new telnet connection
 */
connection *conn_tnew()
{
    int fd, len;
    struct sockaddr_in sin;
    register connection *conn;

    len = sizeof(sin);
    fd = accept(telnet, (struct sockaddr *) &sin, &len);
    if (fd < 0) {
	return (connection *) NULL;
    }

    conn = flist;
    flist = conn->next;
    conn->fd = fd;
    memcpy(&conn->addr, (char *) &sin, len);
    FD_SET(fd, &fds);
    if (fd > maxfd) {
	maxfd = fd;
    }

    return conn;
}

/*
 * NAME:	conn->bnew()
 * DESCRIPTION:	accept a new binary connection
 */
connection *conn_bnew()
{
    int fd, len;
    struct sockaddr_in sin;
    register connection *conn;

    len = sizeof(sin);
    fd = accept(binary, (struct sockaddr *) &sin, &len);
    if (fd < 0) {
	return (connection *) NULL;
    }

    conn = flist;
    flist = conn->next;
    conn->fd = fd;
    memcpy(&conn->addr, (char *) &sin, len);
    FD_SET(fd, &fds);
    if (fd > maxfd) {
	maxfd = fd;
    }

    return conn;
}

/*
 * NAME:	conn->del()
 * DESCRIPTION:	delete a connection
 */
void conn_del(conn)
register connection *conn;
{
    if (conn->fd >= 0) {
	close(conn->fd);
	FD_CLR(conn->fd, &fds);
	conn->fd = -1;
    }
    conn->next = flist;
    flist = conn;
}

/*
 * NAME:	conn->select()
 * DESCRIPTION:	wait for input from connections
 */
int conn_select(wait)
int wait;
{
    struct timeval timeout;

    memcpy(&readfds, &fds, sizeof(fd_set));
    timeout.tv_sec = (int) wait;
    timeout.tv_usec = 0;
    return select(maxfd + 1, &readfds, (fd_set *) NULL, (fd_set *) NULL,
		  &timeout);
}

/*
 * NAME:	conn->read()
 * DESCRIPTION:	read from a connection
 */
int conn_read(conn, buf, size)
connection *conn;
char *buf;
int size;
{
    if (conn->fd < 0) {
	return -1;
    }
    if (!FD_ISSET(conn->fd, &readfds)) {
	return 0;
    }
    size = read(conn->fd, buf, size);
    return (size == 0) ? -1 : size;
}

/*
 * NAME:	conn->write()
 * DESCRIPTION:	write to a connection
 */
void conn_write(conn, buf, size)
connection *conn;
char *buf;
register int size;
{
    if (conn->fd >= 0) {
	if (write(conn->fd, buf, size) < 0 && errno != EWOULDBLOCK) {
	    close(conn->fd);
	    FD_CLR(conn->fd, &fds);
	    conn->fd = -1;
	}
    }
}

/*
 * NAME:	conn->ipnum()
 * DESCRIPTION:	return the ip number of a connection
 */
char *conn_ipnum(conn)
connection *conn;
{
    return inet_ntoa(conn->addr.sin_addr);
}
dgd-net/src/config.DGD.c   640    314      6       47122  5701116425  13254 0ustar  mudusers# define INCLUDE_FILE_IO
# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "path.h"
# include "ed.h"
# include "call_out.h"
# include "comm.h"
# include "version.h"
# include "macro.h"
# include "token.h"
# include "ppcontrol.h"
# include "node.h"
# include "parser.h"
# include "compile.h"
# include "csupport.h"
# include "table.h"

typedef struct {
    char *name;		/* name of the option */
    short type;		/* option type */
    bool set;		/* TRUE if option is set */
    long low, high;	/* lower and higher bound, for numeric values */
    union {
	long num;	/* numeric value */
	char *str;	/* string value */
    } u;
} config;

static config conf[] = {
# define ARRAY_SIZE	0
				{ "array_size",		INT_CONST, FALSE,
							1000, 8192 },
# define AUTO_OBJECT	1
				{ "auto_object",	STRING_CONST, FALSE },
# define BINARY_PORT	2
				{ "binary_port",	INT_CONST, FALSE,
							1000 },
# define CACHE_SIZE	3
				{ "cache_size",		INT_CONST, FALSE,
							100, UINDEX_MAX },
# define CALL_OUTS	4
				{ "call_outs",		INT_CONST, FALSE,
							0, UINDEX_MAX },
# define CALL_STACK	5
				{ "call_stack",		INT_CONST, FALSE,
							10 },
# define CREATE		6
				{ "create",		STRING_CONST, FALSE },
# define DIRECTORY	7
				{ "directory",		STRING_CONST, FALSE },
# define DRIVER_OBJECT	8
				{ "driver_object",	STRING_CONST, FALSE },
# define DUMP_FILE	9
				{ "dump_file",		STRING_CONST, FALSE },
# define DYNAMIC_CHUNK	10
				{ "dynamic_chunk",	INT_CONST, FALSE },
# define ED_TMPFILE	11
				{ "ed_tmpfile",		STRING_CONST, FALSE },
# define EDITORS	12
				{ "editors",		INT_CONST, FALSE,
							1, 255 },
# define INCLUDE_DIRS	13
				{ "include_dirs",	'(', FALSE },
# define INCLUDE_FILE	14
				{ "include_file",	STRING_CONST, FALSE },
# define MAX_COST	15
				{ "max_cost",		INT_CONST, FALSE,
							100000L },
# define OBJECTS	16
				{ "objects",		INT_CONST, FALSE,
							100, UINDEX_MAX },
# define RESERVED_CSTACK 17
				{ "reserved_cstack",	INT_CONST, FALSE,
							5 },
# define RESERVED_VSTACK 18
				{ "reserved_vstack",	INT_CONST, FALSE,
							20 },
# define SECTOR_SIZE	19
				{ "sector_size",	INT_CONST, FALSE,
							512, 8192 },
# define STATIC_CHUNK	20
				{ "static_chunk",	INT_CONST, FALSE },
# define SWAP_FILE	21
				{ "swap_file",		STRING_CONST, FALSE },
# define SWAP_FRAGMENT	22
				{ "swap_fragment",	INT_CONST, FALSE },
# define SWAP_SIZE	23
				{ "swap_size",		INT_CONST, FALSE,
							1024, UINDEX_MAX },
# define TELNET_PORT	24
				{ "telnet_port",	INT_CONST, FALSE,
							1000 },
# define TYPECHECKING	25
				{ "typechecking",	INT_CONST, FALSE,
							0, 1 },
# define USERS		26
				{ "users",		INT_CONST, FALSE,
							1, 255 },
# define VALUE_STACK	27
				{ "value_stack",	INT_CONST, FALSE,
							100 },
# define NR_OPTIONS	28
};


typedef struct {
    char fill;		/* filler */
    char c;		/* char */
} calign;

typedef struct {
    char fill;		/* filler */
    short s;		/* short */
} salign;

typedef struct {
    char fill;		/* filler */
    Int i;		/* Int */
} ialign;

typedef struct {
    char fill;		/* filler */
    long l;		/* long */
} lalign;

typedef struct {
    char fill;		/* filler */
    char *p;		/* char* */
} palign;

typedef struct {	/* struct align */
    char c;
} align;


static char header[18];	/* dump file header */
static Uint starttime;	/* start time */
static Uint elapsed;	/* elapsed time */
static Uint boottime;	/* boot time */

/*
 * NAME:	conf->dump()
 * DESCRIPTION:	dump system state on file
 */
void conf_dump()
{
    Uint t[4];
    int fd;

    fd = sw_dump(conf[DUMP_FILE].u.str);
    if (!kf_dump(fd)) {
	fatal("failed to dump kfun table");
    }
    if (!o_dump(fd)) {
	fatal("failed to dump object table");
    }
    if (!co_dump(fd)) {
	fatal("failed to dump callout table");
    }
    if (!pc_dump(fd)) {
	fatal("failed to dump precompiled objects");
    }

    header[2] = conf[TYPECHECKING].u.num;
    t[0] = conf[SECTOR_SIZE].u.num;
    t[1] = P_time();
    t[2] = starttime;
    t[3] = elapsed + t[1] - boottime;

    lseek(fd, 0L, SEEK_SET);
    write(fd, header, sizeof(header));
    write(fd, (char *) t, sizeof(t));
}

/*
 * NAME:	conf->restore()
 * DESCRIPTION:	restore system stare from file
 */
static void conf_restore(fd)
int fd;
{
    char buffer[sizeof(header)];
    Uint t[4];

    if (read(fd, buffer, sizeof(header)) != sizeof(header) ||
	buffer[0] != 1 ||
	memcmp(buffer + 2, header + 2, sizeof(header) - 2) != 0 ||
	read(fd, (char *) t, sizeof(t)) != sizeof(t)) {
	fatal("bad or incompatible restore file header");
    }
    t[1] = P_time() - t[1];
    starttime = t[2];
    elapsed = t[3];
    sw_restore(fd, (int) t[0]);
    kf_restore(fd);
    o_restore(fd, t[1]);
    co_restore(fd, t[1]);
    pc_restore(fd);
}

/*
 * NAME:	conferr()
 * DESCRIPTION:	cause a fatal error during the configuration phase
 */
static void conferr(err)
char *err;
{
    fatal("config file, line %u: %s", tk_line(), err);
}

# define MAX_DIRS	32

/*
 * NAME:	config->init()
 * DESCRIPTION:	initialize the driver
 */
void conf_init(configfile, dumpfile)
char *configfile, *dumpfile;
{
    static char *nodir[1], *dirs[MAX_DIRS], buffer[STRINGSZ];
    register char *p;
    register int h, l, m, c;
    FILE *fp;
    short s;
    Int i;
    int fd;
    calign cdummy;
    salign sdummy;
    ialign idummy;
    lalign ldummy;
    palign pdummy;

    if (!pp_init(configfile, nodir, 0)) {
	fatal("cannot open config file");
    }
    while ((c=pp_gettok()) != EOF) {
	if (c != IDENTIFIER) {
	    conferr("option expected");
	}

	l = 0;
	h = NR_OPTIONS;
	for (;;) {
	    c = strcmp(yytext, conf[m = (l + h) >> 1].name);
	    if (c == 0) {
		break;	/* found */
	    } else if (c < 0) {
		h = m;	/* search in lower half */
	    } else {
		l = m + 1;	/* search in upper half */
	    }
	    if (l >= h) {
		conferr("unknown option");
	    }
	}

	if (pp_gettok() != '=') {
	    conferr("'=' expected");
	}

	if ((c=pp_gettok()) != conf[m].type) {
	    if (c != INT_CONST && c != STRING_CONST && c != '(') {
		conferr("syntax error");
	    } else {
		conferr("bad value type");
	    }
	}

	switch (c) {
	case INT_CONST:
	    if (yylval.number < conf[m].low ||
		(conf[m].high != 0 && yylval.number > conf[m].high)) {
		conferr("int value out of range");
	    }
	    conf[m].u.num = yylval.number;
	    break;

	case STRING_CONST:
	    p = (m == AUTO_OBJECT || m == DRIVER_OBJECT || m == INCLUDE_FILE) ?
		 path_resolve(yytext) : yytext;
	    if (conf[m].u.str != (char *) NULL) {
		FREE(conf[m].u.str);
	    }
	    l = strlen(p);
	    if (l >= STRINGSZ) {
		l = STRINGSZ - 1;
		p[l] = '\0';
	    }
	    mstatic();
	    conf[m].u.str = strcpy(ALLOC(char, l + 1), p);
	    mdynamic();
	    break;

	case '(':
	    if (pp_gettok() != '{') {
		conferr("'{' expected");
	    }
	    l = 0;
	    for (;;) {
		if (pp_gettok() != STRING_CONST) {
		    conferr("string expected");
		}
		if (l == MAX_DIRS - 1) {
		    conferr("too many include directories");
		}
		if (dirs[l] != (char *) NULL) {
		    FREE(dirs[l]);
		}
		mstatic();
		dirs[l++] = strcpy(ALLOC(char, strlen(yytext) + 1), yytext);
		mdynamic();
		if ((c=pp_gettok()) == '}') {
		    break;
		}
		if (c != ',') {
		    conferr("',' expected");
		}
	    }
	    if (pp_gettok() != ')') {
		conferr("')' expected");
	    }
	    dirs[l] = (char *) NULL;
	    break;
	}
	conf[m].set = TRUE;
	if (pp_gettok() != ';') {
	    conferr("';' expected");
	}
    }

    for (l = 0; l < NR_OPTIONS; l++) {
	char buf[128];

	if (!conf[l].set) {
	    sprintf(buf, "unspecified option %s", conf[l].name);
	    conferr(buf);
	}
    }
    pp_clear();

    if (dumpfile != (char *) NULL) {
	fd = open(dumpfile, O_RDONLY | O_BINARY);
	if (fd < 0) {
	    fatal("cannot open restore file");
	}
    }

    /* change directory */
    if (chdir(conf[DIRECTORY].u.str) < 0) {
	fatal("bad base directory \"%s\"", conf[DIRECTORY].u.str);
    }

    mstatic();

    /* initialize strings */
    str_init();

    /* initialize arrays */
    arr_init((int) conf[ARRAY_SIZE].u.num);

    /* initialize objects */
    o_init((int) conf[OBJECTS].u.num);

    /* initialize swap device */
    sw_init(conf[SWAP_FILE].u.str,
	    (int) conf[SWAP_SIZE].u.num,
	    (int) conf[CACHE_SIZE].u.num,
	    (int) conf[SECTOR_SIZE].u.num);

    /* initalize editor */
    ed_init(conf[ED_TMPFILE].u.str,
	    (int) conf[EDITORS].u.num);

    /* initialize call_outs */
    co_init((uindex) conf[CALL_OUTS].u.num,
	    (int) conf[SWAP_FRAGMENT].u.num);

    /* initialize kfuns */
    kf_init();

    /* initialize compiler */
    c_init(conf[AUTO_OBJECT].u.str,
	   conf[DRIVER_OBJECT].u.str,
	   conf[INCLUDE_FILE].u.str,
	   dirs,
	   (int) conf[TYPECHECKING].u.num);

    /* initialize interpreter */
    i_init((int) conf[VALUE_STACK].u.num,
	   (int) conf[RESERVED_VSTACK].u.num,
	   (int) conf[CALL_STACK].u.num,
	   (int) conf[RESERVED_CSTACK].u.num,
	   conf[CREATE].u.str);

    mdynamic();

    /* initialize memory manager */
    minit((unsigned int) conf[STATIC_CHUNK].u.num,
    	  (unsigned int) conf[DYNAMIC_CHUNK].u.num);

    /* create status.h file */
    sprintf(buffer, "%s/status.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file defines the fields of the array returned ");
    fprintf(fp, "by the\012 * status() kfun.  It is automatically generated ");
    fprintf(fp, "by DGD on startup.\012 */\012\012");
    fprintf(fp, "# define ST_VERSION\t0\t/* driver version */\012");

    fprintf(fp, "# define ST_STARTTIME\t1\t/* system start time */\012");
    fprintf(fp, "# define ST_BOOTTIME\t2\t/* system boot time */\012");
    fprintf(fp, "# define ST_UPTIME\t3\t/* system virtual uptime */\012");

    fprintf(fp, "# define ST_SWAPSIZE\t4\t/* # sectors on swap device */\012");
    fprintf(fp, "# define ST_SWAPUSED\t5\t/* # sectors allocated */\012");
    fprintf(fp, "# define ST_SECTORSIZE\t6\t/* size of swap sector */\012");
    fprintf(fp, "# define ST_SWAPRATE1\t7\t/* # objects swapped out per minute */\012");
    fprintf(fp, "# define ST_SWAPRATE5\t8\t/* # objects swapped out per five minutes */\012");

    fprintf(fp, "# define ST_SMEMSIZE\t9\t/* static memory allocated */\012");
    fprintf(fp, "# define ST_SMEMUSED\t10\t/* static memory in use */\012");
    fprintf(fp, "# define ST_DMEMSIZE\t11\t/* dynamic memory allocated */\012");
    fprintf(fp, "# define ST_DMEMUSED\t12\t/* dynamic memory in use */\012");

    fprintf(fp, "# define ST_OTABSIZE\t13\t/* object table size */\012");
    fprintf(fp, "# define ST_NOBJECTS\t14\t/* # objects in the system */\012");

    fprintf(fp, "# define ST_COTABSIZE\t15\t/* callouts table size */\012");
    fprintf(fp, "# define ST_NCOSHORT\t16\t/* # short-term callouts */\012");
    fprintf(fp, "# define ST_NCOLONG\t17\t/* # long-term callouts */\012");

    fprintf(fp, "# define ST_UTABSIZE\t18\t/* user table size */\012");
    fprintf(fp, "# define ST_ETABSIZE\t19\t/* editor table size */\012");

    fprintf(fp, "\012# define O_COMPILETIME\t0\t/* time of compilation */\012");
    fprintf(fp, "# define O_PROGSIZE\t1\t/* program size of object */\012");
    fprintf(fp, "# define O_DATASIZE\t2\t/* data size of object */\012");
    fprintf(fp, "# define O_NSECTORS\t3\t/* # sectors used by object */\012");
    fprintf(fp, "# define O_CALLOUTS\t4\t/* callouts in object */\012");
    fclose(fp);

    /* create type.h file */
    sprintf(buffer, "%s/type.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file gives definitions for the value returned ");
    fprintf(fp, "by the\012 * typeof() kfun.  It is automatically generated ");
    fprintf(fp, "by DGD on startup.\012 */\012\012");
    fprintf(fp, "# define T_INT\t\t%d\012", T_INT);
    fprintf(fp, "# define T_FLOAT\t%d\012", T_FLOAT);
    fprintf(fp, "# define T_STRING\t%d\012", T_STRING);
    fprintf(fp, "# define T_OBJECT\t%d\012", T_OBJECT);
    fprintf(fp, "# define T_ARRAY\t%d\012", T_ARRAY);
    fprintf(fp, "# define T_MAPPING\t%d\012", T_MAPPING);
    fclose(fp);

    /* create limits.h file */
    sprintf(buffer, "%s/limits.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file defines some basic sizes of datatypes and ");
    fprintf(fp, "resources.\012 * It is automatically generated by DGD on ");
    fprintf(fp, "startup.\012 */\012\012");
    fprintf(fp, "# define CHAR_BIT\t\t8\t\t/* # bits in character */\012");
    fprintf(fp, "# define CHAR_MIN\t\t0\t\t/* min character value */\012");
    fprintf(fp, "# define CHAR_MAX\t\t255\t\t/* max character value */\012\012");
    fprintf(fp, "# define INT_MIN\t\t0x80000000\t/* -2147483648 */\012");
    fprintf(fp, "# define INT_MAX\t\t2147483647\t/* max integer value */\012\012");
    fprintf(fp, "# define MAX_STRING_SIZE\t%u\t\t/* max string size */\012",
	    USHRT_MAX - sizeof(string));
    fprintf(fp, "# define MAX_ARRAY_SIZE\t\t%ld\t\t/* max array size */\012",
	    conf[ARRAY_SIZE].u.num);
    fprintf(fp, "# define MAX_MAPPING_SIZE\t%ld\t\t/* max mapping size */\012\012",
	    conf[ARRAY_SIZE].u.num);
    fprintf(fp, "# define MAX_EXEC_COST\t\t%ld\t\t/* max execution cost */\012",
	    conf[MAX_COST].u.num);
    fclose(fp);

    /* create float.h file */
    sprintf(buffer, "%s/float.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file describes the floating point type. It is ");
    fprintf(fp, "automatically\012 * generated by DGD on startup.\012 */\012\012");
    fprintf(fp, "# define FLT_RADIX\t2\t\t\t/* binary */\012");
    fprintf(fp, "# define FLT_ROUNDS\t1\t\t\t/* round to nearest */\012");
    fprintf(fp, "# define FLT_EPSILON\t7.2759576142E-12\t/* smallest x: 1.0 + x != 1.0 */\012");
    fprintf(fp, "# define FLT_DIG\t10\t\t\t/* decimal digits of precision*/\012");
    fprintf(fp, "# define FLT_MANT_DIG\t36\t\t\t/* binary digits of precision */\012");
    fprintf(fp, "# define FLT_MIN\t2.22507385851E-308\t/* positive minimum */\012");
    fprintf(fp, "# define FLT_MIN_EXP\t(-1021)\t\t\t/* minimum binary exponent */\012");
    fprintf(fp, "# define FLT_MIN_10_EXP\t(-307)\t\t\t/* minimum decimal exponent */\012");
    fprintf(fp, "# define FLT_MAX\t1.79769313485E+308\t/* positive maximum */\012");
    fprintf(fp, "# define FLT_MAX_EXP\t1024\t\t\t/* maximum binary exponent */\012");
    fprintf(fp, "# define FLT_MAX_10_EXP\t308\t\t\t/* maximum decimal exponent */\012");
    fclose(fp);

    /* preload compiled objects */
    pc_preload(conf[AUTO_OBJECT].u.str, conf[DRIVER_OBJECT].u.str);

    /* initialize dumpfile header */
    s = 0x1234;
    i = 0x12345678L;
    header[0] = 1;				/* valid dump flag */
    header[1] = 0;				/* dump file version number */
    header[2] = conf[TYPECHECKING].u.num;	/* global typechecking */
    header[3] = sizeof(uindex);			/* sizeof uindex */
    header[4] = sizeof(long);			/* sizeof long */
    header[5] = sizeof(char *);			/* sizeof char* */
    header[6] = ((char *) &s)[0];		/* 1 of 2 */
    header[7] = ((char *) &s)[1];		/* 2 of 2 */
    header[8] = ((char *) &i)[0];		/* 1 of 4 */
    header[9] = ((char *) &i)[1];		/* 2 of 4 */
    header[10] = ((char *) &i)[2];		/* 3 of 4 */
    header[11] = ((char *) &i)[3];		/* 4 of 4 */
    header[12] = (char *) &cdummy.c - (char *) &cdummy.fill; /* char align */
    header[13] = (char *) &sdummy.s - (char *) &sdummy.fill; /* short align */
    header[14] = (char *) &idummy.i - (char *) &idummy.fill; /* int align */
    header[15] = (char *) &ldummy.l - (char *) &ldummy.fill; /* long align */
    header[16] = (char *) &pdummy.p - (char *) &pdummy.fill; /* pointer align */
    header[17] = sizeof(align);				     /* struct align */

    starttime = boottime = P_time();
    i_set_cost((Int) conf[MAX_COST].u.num);
    if (dumpfile == (char *) NULL) {
	/*
	 * initialize mudlib
	 */
	call_driver_object("initialize", 0);
    } else {
	/*
	 * restore dump file
	 */
	conf_restore(fd);
	close(fd);
	call_driver_object("restored", 0);
    }
    i_del_value(sp++);

    /* initialize communications */
    mstatic();
    comm_init((int) conf[USERS].u.num,
	      (int) conf[TELNET_PORT].u.num,
	      (int) conf[BINARY_PORT].u.num);
    mdynamic();
}

/*
 * NAME:	config->basedir()
 * DESCRIPTION:	return the driver base directory
 */
char *conf_base_dir()
{
    return conf[DIRECTORY].u.str;
}

/*
 * NAME:	config->driver()
 * DESCRIPTION:	return the driver object name
 */
char *conf_driver()
{
    return conf[DRIVER_OBJECT].u.str;
}

/*
 * NAME:	config->exec_cost()
 * DESCRIPTION:	return the maximum execution cost
 */
Int conf_exec_cost()
{
    return conf[MAX_COST].u.num;
}

/*
 * NAME:	config->array_size()
 * DESCRIPTION:	return the maximum array size
 */
int conf_array_size()
{
    return conf[ARRAY_SIZE].u.num;
}

/*
 * NAME:	config->status()
 * DESCRIPTION:	return an array with information about resource usage
 */
array *conf_status()
{
    register value *v;
    array *a;
    char *version;
    allocinfo *mstat;
    uindex ncoshort, ncolong;

    a = arr_new(20L);
    v = a->elts;

    /* version */
    v->type = T_STRING;
    version = VERSION;
    str_ref((v++)->u.string = str_new(version, (long) strlen(version)));

    /* uptime */
    v->type = T_INT;
    (v++)->u.number = starttime;
    v->type = T_INT;
    (v++)->u.number = boottime;
    v->type = T_INT;
    (v++)->u.number = elapsed + P_time() - boottime;

    /* swap */
    v->type = T_INT;
    (v++)->u.number = conf[SWAP_SIZE].u.num;
    v->type = T_INT;
    (v++)->u.number = sw_count();
    v->type = T_INT;
    (v++)->u.number = conf[SECTOR_SIZE].u.num;
    v->type = T_INT;
    (v++)->u.number = co_swaprate1();
    v->type = T_INT;
    (v++)->u.number = co_swaprate5();

    /* memory */
    mstat = minfo();
    v->type = T_INT;
    (v++)->u.number = mstat->smemsize;
    v->type = T_INT;
    (v++)->u.number = mstat->smemused;
    v->type = T_INT;
    (v++)->u.number = mstat->dmemsize;
    v->type = T_INT;
    (v++)->u.number = mstat->dmemused;

    /* objects */
    v->type = T_INT;
    (v++)->u.number = conf[OBJECTS].u.num;
    v->type = T_INT;
    (v++)->u.number = o_count();

    /* callouts */
    co_info(&ncoshort, &ncolong);
    v->type = T_INT;
    (v++)->u.number = conf[CALL_OUTS].u.num;
    v->type = T_INT;
    (v++)->u.number = ncoshort;
    v->type = T_INT;
    (v++)->u.number = ncolong;

    /* users & editors */
    v->type = T_INT;
    (v++)->u.number = conf[USERS].u.num;
    v->type = T_INT;
    v->u.number = conf[EDITORS].u.num;

    return a;
}

/*
 * NAME:	config->object()
 * DESCRIPTION:	return resource usage of an object
 */
array *conf_object(obj)
object *obj;
{
    register control *ctrl;
    register value *v;
    array *clist, *a;
    dataspace *data;

    clist = co_list(obj);
    ctrl = o_control(obj);
    data = o_dataspace(obj);
    a = arr_new(5L);

    v = a->elts;
    v->type = T_INT;
    (v++)->u.number = ctrl->compiled;
    v->type = T_INT;
    (v++)->u.number = ctrl->ninherits * sizeof(dinherit) +
		      ctrl->progsize +
		      ctrl->nstrings * (long) sizeof(dstrconst) +
		      ctrl->strsize +
		      ctrl->nfuncdefs * sizeof(dfuncdef) +
		      ctrl->nvardefs * sizeof(dvardef) +
		      ctrl->nfuncalls * 2L +
		      ctrl->nsymbols * (long) sizeof(dsymbol);
    v->type = T_INT;
    (v++)->u.number = ctrl->nvariables * sizeof(value);
    v->type = T_INT;
    if (obj->flags & O_MASTER) {
	(v++)->u.number = ctrl->nsectors + data->nsectors;
    } else {
	(v++)->u.number = data->nsectors;
    }
    v->type = T_ARRAY;
    arr_ref(v->u.array = clist);

    return a;
}
dgd-net/src/config.c   640    314      6       47031  5701116401  12650 0ustar  mudusers# define INCLUDE_FILE_IO
# include "dgd.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "path.h"
# include "ed.h"
# include "call_out.h"
# include "comm.h"
# include "version.h"
# include "macro.h"
# include "token.h"
# include "ppcontrol.h"
# include "node.h"
# include "parser.h"
# include "compile.h"
# include "csupport.h"
# include "table.h"

typedef struct {
    char *name;		/* name of the option */
    short type;		/* option type */
    bool set;		/* TRUE if option is set */
    long low, high;	/* lower and higher bound, for numeric values */
    union {
	long num;	/* numeric value */
	char *str;	/* string value */
    } u;
} config;

static config conf[] = {
# define ARRAY_SIZE	0
				{ "array_size",		INT_CONST, FALSE,
							1000, 8192 },
# define AUTO_OBJECT	1
				{ "auto_object",	STRING_CONST, FALSE },
# define BINARY_PORT	2
				{ "binary_port",	INT_CONST, FALSE,
							1000 },
# define CACHE_SIZE	3
				{ "cache_size",		INT_CONST, FALSE,
							100, UINDEX_MAX },
# define CALL_OUTS	4
				{ "call_outs",		INT_CONST, FALSE,
							0, UINDEX_MAX },
# define CALL_STACK	5
				{ "call_stack",		INT_CONST, FALSE,
							10 },
# define CREATE		6
				{ "create",		STRING_CONST, FALSE },
# define DIRECTORY	7
				{ "directory",		STRING_CONST, FALSE },
# define DRIVER_OBJECT	8
				{ "driver_object",	STRING_CONST, FALSE },
# define DUMP_FILE	9
				{ "dump_file",		STRING_CONST, FALSE },
# define DYNAMIC_CHUNK	10
				{ "dynamic_chunk",	INT_CONST, FALSE },
# define ED_TMPFILE	11
				{ "ed_tmpfile",		STRING_CONST, FALSE },
# define EDITORS	12
				{ "editors",		INT_CONST, FALSE,
							1, 255 },
# define INCLUDE_DIRS	13
				{ "include_dirs",	'(', FALSE },
# define INCLUDE_FILE	14
				{ "include_file",	STRING_CONST, FALSE },
# define MAX_COST	15
				{ "max_cost",		INT_CONST, FALSE,
							100000L },
# define OBJECTS	16
				{ "objects",		INT_CONST, FALSE,
							100, UINDEX_MAX },
# define RESERVED_CSTACK 17
				{ "reserved_cstack",	INT_CONST, FALSE,
							5 },
# define RESERVED_VSTACK 18
				{ "reserved_vstack",	INT_CONST, FALSE,
							20 },
# define SECTOR_SIZE	19
				{ "sector_size",	INT_CONST, FALSE,
							512, 8192 },
# define STATIC_CHUNK	20
				{ "static_chunk",	INT_CONST, FALSE },
# define SWAP_FILE	21
				{ "swap_file",		STRING_CONST, FALSE },
# define SWAP_FRAGMENT	22
				{ "swap_fragment",	INT_CONST, FALSE },
# define SWAP_SIZE	23
				{ "swap_size",		INT_CONST, FALSE,
							1024, UINDEX_MAX },
# define TELNET_PORT	24
				{ "telnet_port",	INT_CONST, FALSE,
							1000 },
# define TYPECHECKING	25
				{ "typechecking",	INT_CONST, FALSE,
							0, 1 },
# define USERS		26
				{ "users",		INT_CONST, FALSE,
							1, 255 },
# define VALUE_STACK	27
				{ "value_stack",	INT_CONST, FALSE,
							100 },
# define NR_OPTIONS	28
};


typedef struct {
    char fill;		/* filler */
    char c;		/* char */
} calign;

typedef struct {
    char fill;		/* filler */
    short s;		/* short */
} salign;

typedef struct {
    char fill;		/* filler */
    Int i;		/* Int */
} ialign;

typedef struct {
    char fill;		/* filler */
    long l;		/* long */
} lalign;

typedef struct {
    char fill;		/* filler */
    char *p;		/* char* */
} palign;

typedef struct {	/* struct align */
    char c;
} align;


static char header[18];	/* dump file header */
static Uint starttime;	/* start time */
static Uint elapsed;	/* elapsed time */
static Uint boottime;	/* boot time */

/*
 * NAME:	conf->dump()
 * DESCRIPTION:	dump system state on file
 */
void conf_dump()
{
    Uint t[4];
    int fd;

    fd = sw_dump(conf[DUMP_FILE].u.str);
    if (!kf_dump(fd)) {
	fatal("failed to dump kfun table");
    }
    if (!o_dump(fd)) {
	fatal("failed to dump object table");
    }
    if (!co_dump(fd)) {
	fatal("failed to dump callout table");
    }
    if (!pc_dump(fd)) {
       fatal("failed to dump precompiled objects");
    }

    header[2] = conf[TYPECHECKING].u.num;
    t[0] = conf[SECTOR_SIZE].u.num;
    t[1] = P_time();
    t[2] = starttime;
    t[3] = elapsed + t[1] - boottime;

    lseek(fd, 0L, SEEK_SET);
    write(fd, header, sizeof(header));
    write(fd, (char *) t, sizeof(t));
}

/*
 * NAME:	conf->restore()
 * DESCRIPTION:	restore system stare from file
 */
static void conf_restore(fd)
int fd;
{
    char buffer[sizeof(header)];
    Uint t[4];

    if (read(fd, buffer, sizeof(header)) != sizeof(header) ||
	buffer[0] != 1 ||
	memcmp(buffer + 2, header + 2, sizeof(header) - 2) != 0 ||
	read(fd, (char *) t, sizeof(t)) != sizeof(t)) {
	fatal("bad or incompatible restore file header");
    }
    t[1] = P_time() - t[1];
    starttime = t[2];
    elapsed = t[3];
    sw_restore(fd, (int) t[0]);
    kf_restore(fd);
    o_restore(fd, t[1]);
    co_restore(fd, t[1]);
    pc_restore(fd);
}

/*
 * NAME:	conferr()
 * DESCRIPTION:	cause a fatal error during the configuration phase
 */
static void conferr(err)
char *err;
{
    fatal("config file, line %u: %s", tk_line(), err);
}

# define MAX_DIRS	32

/*
 * NAME:	config->init()
 * DESCRIPTION:	initialize the driver
 */
void conf_init(configfile, dumpfile)
char *configfile, *dumpfile;
{
    static char *nodir[1], *dirs[MAX_DIRS], buffer[STRINGSZ];
    register char *p;
    register int h, l, m, c;
    FILE *fp;
    short s;
    Int i;
    int fd;
    calign cdummy;
    salign sdummy;
    ialign idummy;
    lalign ldummy;
    palign pdummy;

    if (!pp_init(configfile, nodir, 0)) {
	fatal("cannot open config file");
    }
    while ((c=pp_gettok()) != EOF) {
	if (c != IDENTIFIER) {
	    conferr("option expected");
	}

	l = 0;
	h = NR_OPTIONS;
	for (;;) {
	    c = strcmp(yytext, conf[m = (l + h) >> 1].name);
	    if (c == 0) {
		break;	/* found */
	    } else if (c < 0) {
		h = m;	/* search in lower half */
	    } else {
		l = m + 1;	/* search in upper half */
	    }
	    if (l >= h) {
		conferr("unknown option");
	    }
	}

	if (pp_gettok() != '=') {
	    conferr("'=' expected");
	}

	if ((c=pp_gettok()) != conf[m].type) {
	    if (c != INT_CONST && c != STRING_CONST && c != '(') {
		conferr("syntax error");
	    } else {
		conferr("bad value type");
	    }
	}

	switch (c) {
	case INT_CONST:
	    if (yylval.number < conf[m].low ||
		(conf[m].high != 0 && yylval.number > conf[m].high)) {
		conferr("int value out of range");
	    }
	    conf[m].u.num = yylval.number;
	    break;

	case STRING_CONST:
	    p = (m == AUTO_OBJECT || m == DRIVER_OBJECT || m == INCLUDE_FILE) ?
		 path_resolve(yytext) : yytext;
	    if (conf[m].u.str != (char *) NULL) {
		FREE(conf[m].u.str);
	    }
	    l = strlen(p);
	    if (l >= STRINGSZ) {
		l = STRINGSZ - 1;
		p[l] = '\0';
	    }
	    mstatic();
	    conf[m].u.str = strcpy(ALLOC(char, l + 1), p);
	    mdynamic();
	    break;

	case '(':
	    if (pp_gettok() != '{') {
		conferr("'{' expected");
	    }
	    l = 0;
	    for (;;) {
		if (pp_gettok() != STRING_CONST) {
		    conferr("string expected");
		}
		if (l == MAX_DIRS - 1) {
		    conferr("too many include directories");
		}
		if (dirs[l] != (char *) NULL) {
		    FREE(dirs[l]);
		}
		mstatic();
		dirs[l++] = strcpy(ALLOC(char, strlen(yytext) + 1), yytext);
		mdynamic();
		if ((c=pp_gettok()) == '}') {
		    break;
		}
		if (c != ',') {
		    conferr("',' expected");
		}
	    }
	    if (pp_gettok() != ')') {
		conferr("')' expected");
	    }
	    dirs[l] = (char *) NULL;
	    break;
	}
	conf[m].set = TRUE;
	if (pp_gettok() != ';') {
	    conferr("';' expected");
	}
    }

    for (l = 0; l < NR_OPTIONS; l++) {
	char buf[128];

	if (!conf[l].set) {
	    sprintf(buf, "unspecified option %s", conf[l].name);
	    conferr(buf);
	}
    }
    pp_clear();

    if (dumpfile != (char *) NULL) {
	fd = open(dumpfile, O_RDONLY | O_BINARY);
	if (fd < 0) {
	    fatal("cannot open restore file");
	}
    }

    /* change directory */
    if (chdir(conf[DIRECTORY].u.str) < 0) {
	fatal("bad base directory \"%s\"", conf[DIRECTORY].u.str);
    }

    mstatic();

    /* initialize strings */
    str_init();

    /* initialize arrays */
    arr_init((int) conf[ARRAY_SIZE].u.num);

    /* initialize objects */
    o_init((int) conf[OBJECTS].u.num);

    /* initialize swap device */
    sw_init(conf[SWAP_FILE].u.str,
	    (int) conf[SWAP_SIZE].u.num,
	    (int) conf[CACHE_SIZE].u.num,
	    (int) conf[SECTOR_SIZE].u.num);

    /* initalize editor */
    ed_init(conf[ED_TMPFILE].u.str,
	    (int) conf[EDITORS].u.num);

    /* initialize call_outs */
    co_init((uindex) conf[CALL_OUTS].u.num,
	    (int) conf[SWAP_FRAGMENT].u.num);

    /* initialize kfuns */
    kf_init();

    /* initialize compiler */
    c_init(conf[AUTO_OBJECT].u.str,
	   conf[DRIVER_OBJECT].u.str,
	   conf[INCLUDE_FILE].u.str,
	   dirs,
	   (int) conf[TYPECHECKING].u.num);

    /* initialize interpreter */
    i_init((int) conf[VALUE_STACK].u.num,
	   (int) conf[RESERVED_VSTACK].u.num,
	   (int) conf[CALL_STACK].u.num,
	   (int) conf[RESERVED_CSTACK].u.num,
	   conf[CREATE].u.str);

    mdynamic();

    /* initialize memory manager */
    minit((unsigned int) conf[STATIC_CHUNK].u.num,
    	  (unsigned int) conf[DYNAMIC_CHUNK].u.num);

    /* create status.h file */
    sprintf(buffer, "%s/status.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file defines the fields of the array returned ");
    fprintf(fp, "by the\012 * status() kfun.  It is automatically generated ");
    fprintf(fp, "by DGD on startup.\012 */\012\012");
    fprintf(fp, "# define ST_VERSION\t0\t/* driver version */\012");

    fprintf(fp, "# define ST_STARTTIME\t1\t/* system start time */\012");
    fprintf(fp, "# define ST_BOOTTIME\t2\t/* system boot time */\012");
    fprintf(fp, "# define ST_UPTIME\t3\t/* system virtual uptime */\012");

    fprintf(fp, "# define ST_SWAPSIZE\t4\t/* # sectors on swap device */\012");
    fprintf(fp, "# define ST_SWAPUSED\t5\t/* # sectors allocated */\012");
    fprintf(fp, "# define ST_SECTORSIZE\t6\t/* size of swap sector */\012");
    fprintf(fp, "# define ST_SWAPRATE1\t7\t/* # objects swapped out per minute */\012");
    fprintf(fp, "# define ST_SWAPRATE5\t8\t/* # objects swapped out per five minutes */\012");

    fprintf(fp, "# define ST_SMEMSIZE\t9\t/* static memory allocated */\012");
    fprintf(fp, "# define ST_SMEMUSED\t10\t/* static memory in use */\012");
    fprintf(fp, "# define ST_DMEMSIZE\t11\t/* dynamic memory allocated */\012");
    fprintf(fp, "# define ST_DMEMUSED\t12\t/* dynamic memory in use */\012");

    fprintf(fp, "# define ST_OTABSIZE\t13\t/* object table size */\012");
    fprintf(fp, "# define ST_NOBJECTS\t14\t/* # objects in the system */\012");

    fprintf(fp, "# define ST_COTABSIZE\t15\t/* callouts table size */\012");
    fprintf(fp, "# define ST_NCOSHORT\t16\t/* # short-term callouts */\012");
    fprintf(fp, "# define ST_NCOLONG\t17\t/* # long-term callouts */\012");

    fprintf(fp, "# define ST_UTABSIZE\t18\t/* user table size */\012");
    fprintf(fp, "# define ST_ETABSIZE\t19\t/* editor table size */\012");

    fprintf(fp, "\012# define O_COMPILETIME\t0\t/* time of compilation */\012");
    fprintf(fp, "# define O_PROGSIZE\t1\t/* program size of object */\012");
    fprintf(fp, "# define O_DATASIZE\t2\t/* data size of object */\012");
    fprintf(fp, "# define O_NSECTORS\t3\t/* # sectors used by object */\012");
    fprintf(fp, "# define O_CALLOUTS\t4\t/* callouts in object */\012");
    fclose(fp);

    /* create type.h file */
    sprintf(buffer, "%s/type.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file gives definitions for the value returned ");
    fprintf(fp, "by the\012 * typeof() kfun.  It is automatically generated ");
    fprintf(fp, "by DGD on startup.\012 */\012\012");
    fprintf(fp, "# define T_INT\t\t%d\012", T_INT);
    fprintf(fp, "# define T_FLOAT\t%d\012", T_FLOAT);
    fprintf(fp, "# define T_STRING\t%d\012", T_STRING);
    fprintf(fp, "# define T_OBJECT\t%d\012", T_OBJECT);
    fprintf(fp, "# define T_ARRAY\t%d\012", T_ARRAY);
    fprintf(fp, "# define T_MAPPING\t%d\012", T_MAPPING);
    fclose(fp);

    /* create limits.h file */
    sprintf(buffer, "%s/limits.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file defines some basic sizes of datatypes and ");
    fprintf(fp, "resources.\012 * It is automatically generated by DGD on ");
    fprintf(fp, "startup.\012 */\012\012");
    fprintf(fp, "# define CHAR_BIT\t\t8\t\t/* # bits in character */\012");
    fprintf(fp, "# define CHAR_MIN\t\t0\t\t/* min character value */\012");
    fprintf(fp, "# define CHAR_MAX\t\t255\t\t/* max character value */\012\012");
    fprintf(fp, "# define INT_MIN\t\t0x80000000\t/* -2147483648 */\012");
    fprintf(fp, "# define INT_MAX\t\t2147483647\t/* max integer value */\012\012");
    fprintf(fp, "# define MAX_STRING_SIZE\t%u\t\t/* max string size */\012",
	    USHRT_MAX - sizeof(string));
    fprintf(fp, "# define MAX_ARRAY_SIZE\t\t%ld\t\t/* max array size */\012",
	    conf[ARRAY_SIZE].u.num);
    fprintf(fp, "# define MAX_MAPPING_SIZE\t%ld\t\t/* max mapping size */\012\012",
	    conf[ARRAY_SIZE].u.num);
    fprintf(fp, "# define MAX_EXEC_COST\t\t%ld\t\t/* max execution cost */\012",
	    conf[MAX_COST].u.num);
    fclose(fp);

    /* create float.h file */
    sprintf(buffer, "%s/float.h", dirs[0]);
    fp = fopen(path_file(path_resolve(buffer)), "w");
    if (fp == (FILE *) NULL) {
	fatal("cannot create \"%s\"", buffer);
    }
    P_fbinio(fp);

    fprintf(fp, "/*\012 * This file describes the floating point type. It is ");
    fprintf(fp, "automatically\012 * generated by DGD on startup.\012 */\012\012");
    fprintf(fp, "# define FLT_RADIX\t2\t\t\t/* binary */\012");
    fprintf(fp, "# define FLT_ROUNDS\t1\t\t\t/* round to nearest */\012");
    fprintf(fp, "# define FLT_EPSILON\t7.2759576142E-12\t/* smallest x: 1.0 + x != 1.0 */\012");
    fprintf(fp, "# define FLT_DIG\t10\t\t\t/* decimal digits of precision*/\012");
    fprintf(fp, "# define FLT_MANT_DIG\t36\t\t\t/* binary digits of precision */\012");
    fprintf(fp, "# define FLT_MIN\t2.22507385851E-308\t/* positive minimum */\012");
    fprintf(fp, "# define FLT_MIN_EXP\t(-1021)\t\t\t/* minimum binary exponent */\012");
    fprintf(fp, "# define FLT_MIN_10_EXP\t(-307)\t\t\t/* minimum decimal exponent */\012");
    fprintf(fp, "# define FLT_MAX\t1.79769313485E+308\t/* positive maximum */\012");
    fprintf(fp, "# define FLT_MAX_EXP\t1024\t\t\t/* maximum binary exponent */\012");
    fprintf(fp, "# define FLT_MAX_10_EXP\t308\t\t\t/* maximum decimal exponent */\012");
    fclose(fp);

    /* preload compiled objects */
    pc_preload(conf[AUTO_OBJECT].u.str, conf[DRIVER_OBJECT].u.str);

    /* initialize dumpfile header */
    s = 0x1234;
    i = 0x12345678L;
    header[0] = 1;				/* valid dump flag */
    header[1] = 0;				/* dump file version number */
    header[2] = conf[TYPECHECKING].u.num;	/* global typechecking */
    header[3] = sizeof(uindex);			/* sizeof uindex */
    header[4] = sizeof(long);			/* sizeof long */
    header[5] = sizeof(char *);			/* sizeof char* */
    header[6] = ((char *) &s)[0];		/* 1 of 2 */
    header[7] = ((char *) &s)[1];		/* 2 of 2 */
    header[8] = ((char *) &i)[0];		/* 1 of 4 */
    header[9] = ((char *) &i)[1];		/* 2 of 4 */
    header[10] = ((char *) &i)[2];		/* 3 of 4 */
    header[11] = ((char *) &i)[3];		/* 4 of 4 */
    header[12] = (char *) &cdummy.c - (char *) &cdummy.fill; /* char align */
    header[13] = (char *) &sdummy.s - (char *) &sdummy.fill; /* short align */
    header[14] = (char *) &idummy.i - (char *) &idummy.fill; /* int align */
    header[15] = (char *) &ldummy.l - (char *) &ldummy.fill; /* long align */
    header[16] = (char *) &pdummy.p - (char *) &pdummy.fill; /* pointer align */
    header[17] = sizeof(align);				     /* struct align */

    /* initialize communications */
    mstatic();
    comm_init((int) conf[USERS].u.num);
    mdynamic();

    starttime = boottime = P_time();
    i_set_cost((Int) conf[MAX_COST].u.num);
    if (dumpfile == (char *) NULL) {
	/*
	 * initialize mudlib
	 */
	call_driver_object("initialize", 0);
    } else {
	/*
	 * restore dump file
	 */
	conf_restore(fd);
	close(fd);
	call_driver_object("restored", 0);
    }
    i_del_value(sp++);
}

/*
 * NAME:	config->basedir()
 * DESCRIPTION:	return the driver base directory
 */
char *conf_base_dir()
{
    return conf[DIRECTORY].u.str;
}

/*
 * NAME:	config->driver()
 * DESCRIPTION:	return the driver object name
 */
char *conf_driver()
{
    return conf[DRIVER_OBJECT].u.str;
}

/*
 * NAME:	config->exec_cost()
 * DESCRIPTION:	return the maximum execution cost
 */
Int conf_exec_cost()
{
    return conf[MAX_COST].u.num;
}

/*
 * NAME:       config->array_size()
 * DESCRIPTION:        return the maximum array size
 */
int conf_array_size()
{
    return conf[ARRAY_SIZE].u.num;
}

/*
 * NAME:	config->status()
 * DESCRIPTION:	return an array with information about resource usage
 */
array *conf_status()
{
    register value *v;
    array *a;
    char *version;
    allocinfo *mstat;
    uindex ncoshort, ncolong;

    a = arr_new(20L);
    v = a->elts;

    /* version */
    v->type = T_STRING;
    version = VERSION;
    str_ref((v++)->u.string = str_new(version, (long) strlen(version)));

    /* uptime */
    v->type = T_INT;
    (v++)->u.number = starttime;
    v->type = T_INT;
    (v++)->u.number = boottime;
    v->type = T_INT;
    (v++)->u.number = elapsed + P_time() - boottime;

    /* swap */
    v->type = T_INT;
    (v++)->u.number = conf[SWAP_SIZE].u.num;
    v->type = T_INT;
    (v++)->u.number = sw_count();
    v->type = T_INT;
    (v++)->u.number = conf[SECTOR_SIZE].u.num;
    v->type = T_INT;
    (v++)->u.number = co_swaprate1();
    v->type = T_INT;
    (v++)->u.number = co_swaprate5();

    /* memory */
    mstat = minfo();
    v->type = T_INT;
    (v++)->u.number = mstat->smemsize;
    v->type = T_INT;
    (v++)->u.number = mstat->smemused;
    v->type = T_INT;
    (v++)->u.number = mstat->dmemsize;
    v->type = T_INT;
    (v++)->u.number = mstat->dmemused;

    /* objects */
    v->type = T_INT;
    (v++)->u.number = conf[OBJECTS].u.num;
    v->type = T_INT;
    (v++)->u.number = o_count();

    /* callouts */
    co_info(&ncoshort, &ncolong);
    v->type = T_INT;
    (v++)->u.number = conf[CALL_OUTS].u.num;
    v->type = T_INT;
    (v++)->u.number = ncoshort;
    v->type = T_INT;
    (v++)->u.number = ncolong;

    /* users & editors */
    v->type = T_INT;
    (v++)->u.number = conf[USERS].u.num;
    v->type = T_INT;
    v->u.number = conf[EDITORS].u.num;

    return a;
}

/*
 * NAME:	config->object()
 * DESCRIPTION:	return resource usage of an object
 */
array *conf_object(obj)
object *obj;
{
    register control *ctrl;
    register value *v;
    array *clist, *a;
    dataspace *data;

    clist = co_list(obj);
    ctrl = o_control(obj);
    data = o_dataspace(obj);
    a = arr_new(5L);

    v = a->elts;
    v->type = T_INT;
    (v++)->u.number = ctrl->compiled;
    v->type = T_INT;
    (v++)->u.number = ctrl->ninherits * sizeof(dinherit) +
		      ctrl->progsize +
		      ctrl->nstrings * (long) sizeof(dstrconst) +
		      ctrl->strsize +
		      ctrl->nfuncdefs * sizeof(dfuncdef) +
		      ctrl->nvardefs * sizeof(dvardef) +
		      ctrl->nfuncalls * 2L +
		      ctrl->nsymbols * (long) sizeof(dsymbol);
    v->type = T_INT;
    (v++)->u.number = ctrl->nvariables * sizeof(value);
    v->type = T_INT;
    if (obj->flags & O_MASTER) {
	(v++)->u.number = ctrl->nsectors + data->nsectors;
    } else {
	(v++)->u.number = data->nsectors;
    }
    v->type = T_ARRAY;
    arr_ref(v->u.array = clist);

    return a;
}
dgd-net/src/comp/   755    314      6           0  5640047605  12107 5ustar  mudusersdgd-net/src/comp/comp.DGD.c   640    314      6       30531  5701116740  13677 0ustar  mudusers# include "comp.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "path.h"
# include "hash.h"
# include "swap.h"
# include "comm.h"
# include "ed.h"
# include "call_out.h"
# include "node.h"
# include "codegen.h"
# include "compile.h"
# include "csupport.h"

static int size;		/* current size of the dumped line */

/*
 * NAME:	dump()
 * DESCRIPTION:	output a number
 */
static void dump(n)
int n;
{
    if (size == 16) {
	putchar('\n');
	size = 0;
    }
    printf("%d, ", n);
    size++;
}

/*
 * NAME:	dump_chars()
 * DESCRIPTION:	output a range of characters
 */
static void dump_chars(p, n)
register char *p;
register unsigned int n;
{
    while (n > 0) {
	dump(*p++);
	--n;
    }
}

/*
 * NAME:	dump_inherits()
 * DESCRIPTION:	output the inherited objects
 */
static void dump_inherits(ctrl)
register control *ctrl;
{
    register int i;

    printf("\nstatic pcinherit inherits[] = {\n");
    for (i = 0; i < ctrl->ninherits; i++) {
	printf("\"%s\", %u, %u,\n",
	       o_name(ctrl->inherits[i].obj),
	       ctrl->inherits[i].funcoffset,
	       ctrl->inherits[i].varoffset);
    }
    printf("};\n");
}

/*
 * NAME:	dump_program()
 * DESCRIPTION:	output the program
 */
static void dump_program(ctrl)
control *ctrl;
{
    if (ctrl->progsize != 0) {
	printf("\nstatic char program[] = {\n");
	size = 0;
	dump_chars(ctrl->prog, ctrl->progsize);
	printf("\n};\n");
    }
}

/*
 * NAME:	dump_strings()
 * DESCRIPTION:	output the strings
 */
static void dump_strings(ctrl)
register control *ctrl;
{
    register int i;
    register long len;

    if (ctrl->nstrings != 0) {
	printf("\nstatic dstrconst sstrings[] = {\n");
	len = 0;
	for (i = 0; i < ctrl->nstrings; i++) {
	    printf("{ %ld, %u },\n", len, ctrl->strings[i]->len);
	    len += ctrl->strings[i]->len;
	}
	printf("};\n\nstatic char stext[] = {\n");
	size = 0;
	for (i = 0; i < ctrl->nstrings; i++) {
	    dump_chars(ctrl->strings[i]->text, ctrl->strings[i]->len);
	}
	printf("\n};\n");
    }
}

/*
 * NAME:	dump_functions()
 * DESCRIPTION:	output the function table
 */
static void dump_functions(ctrl, nfuncs)
register control *ctrl;
register int nfuncs;
{
    register int i;

    if (nfuncs != 0) {
	printf("\nstatic pcfunc functions[] = {\n");
	for (i = 1; i <= nfuncs; i++) {
	    printf("func%d,\n", i);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dump_funcdefs()
 * DESCRIPTION:	output the function definitions
 */
static void dump_funcdefs(ctrl)
register control *ctrl;
{
    register int i;

    if (ctrl->nfuncdefs != 0) {
	printf("\nstatic dfuncdef funcdefs[] = {\n");
	for (i = 0; i < ctrl->nfuncdefs; i++) {
	    printf("{ %d, %d, %u, %u },\n",
		   ctrl->funcdefs[i].class,
		   ctrl->funcdefs[i].inherit,
		   ctrl->funcdefs[i].index,
		   ctrl->funcdefs[i].offset);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dump_vardefs()
 * DESCRIPTION:	output the variable definitions
 */
static void dump_vardefs(ctrl)
register control *ctrl;
{
    register int i;

    if (ctrl->nvardefs != 0) {
	printf("\nstatic dvardef vardefs[] = {\n");
	for (i = 0; i < ctrl->nvardefs; i++) {
	    printf("{ %d, %d, %u, %u },\n",
		   ctrl->vardefs[i].class,
		   ctrl->vardefs[i].inherit,
		   ctrl->vardefs[i].index,
		   ctrl->vardefs[i].type);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dump_funcalls()
 * DESCRIPTION:	output the function call table
 */
static void dump_funcalls(ctrl)
register control *ctrl;
{
    if (ctrl->nfuncalls > 0) {
	printf("\nstatic char funcalls[] = {\n");
	size = 0;
	dump_chars(ctrl->funcalls, ctrl->nfuncalls << 1);
	printf("\n};\n");
    }
}

/*
 * NAME:	dump_symbols()
 * DESCRIPTION:	output the symbol table
 */
static void dump_symbols(ctrl)
register control *ctrl;
{
    register uindex i;

    if (ctrl->nsymbols != 0) {
	printf("\nstatic dsymbol symbols[] = {\n");
	for (i = 0; i < ctrl->nsymbols; i++) {
	    printf("{ %d, %d, %u },\n",
		   ctrl->symbols[i].inherit,
		   ctrl->symbols[i].index,
		   ctrl->symbols[i].next);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dgd_main()
 * DESCRIPTION:	main routine of the precompiler
 */
int dgd_main(argc, argv)
int argc;
char *argv[];
{
    register int len;
    register control *ctrl;
    char *file, tag[9];
    int nfuncs;

    if (argc != 3) {
	P_message("usage: precomp config_file file\012");	/* LF */
	return 2;
    }

    if (ec_push()) {
	P_message("error in initialization\012");	/* LF */
	return 2;
    }
    conf_init(argv[1], (char *) NULL);
    ec_pop();

    len = strlen(file = path_resolve(argv[2]));
    if (len > 2 && file[len - 2] == '.' && file[len - 1] == 'c') {
	file[len -= 2] = '\0';
    }
    sprintf(tag, "T%03x%04x", hashstr(file, len) & 0xfff,
	    (unsigned short) P_random());

    printf("/*\n * This file was compiled from LPC with the DGD precompiler.");
    printf("\n * DGD is copyright by Felix A. Croes.");
    printf("  See the file \"Copyright\" for details.\n *\n");
    printf(" * File: \"/%s.c\"\n */\n", file);

    printf("\n# ifdef TAG\nTAG(%s)\n# else\n", tag);
    printf("# include \"dgd.h\"\n# include \"str.h\"\n");
    printf("# include \"array.h\"\n# include \"object.h\"\n");
    printf("# include \"interpret.h\"\n# include \"data.h\"\n");
    printf("# include \"xfloat.h\"\n# include \"csupport.h\"\n");

    if (ec_push()) {
	warning((char *) NULL);
	return 1;
    }
    ctrl = c_compile(file)->ctrl;
    ec_pop();

    dump_inherits(ctrl);
    dump_program(ctrl);
    dump_strings(ctrl);
    dump_functions(ctrl, nfuncs = cg_nfuncs());
    dump_funcdefs(ctrl);
    dump_vardefs(ctrl);
    dump_funcalls(ctrl);
    dump_symbols(ctrl);

    printf("\nprecomp %s = {\n%d, inherits,\n", tag, ctrl->ninherits);
    printf("%ldL,\n", ctrl->compiled);
    if (ctrl->progsize == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, program,\n", ctrl->progsize);
    }
    if (ctrl->nstrings == 0) {
	printf("0, 0, 0,\n");
    } else {
	printf("%u, sstrings, stext,\n", ctrl->nstrings);
    }
    if (nfuncs == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, functions,\n", nfuncs);
    }
    if (ctrl->nfuncdefs == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, funcdefs,\n", ctrl->nfuncdefs);
    }
    if (ctrl->nvardefs == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, vardefs,\n", ctrl->nvardefs);
    }
    if (ctrl->nfuncalls == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, funcalls,\n", ctrl->nfuncalls);
    }
    if (ctrl->nsymbols == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, symbols,\n", ctrl->nsymbols);
    }
    printf("%u, %u, %u\n", ctrl->nvariables, ctrl->nfloatdefs, ctrl->nfloats);
    printf("};\n# endif\n");

    return 0;
}


/*
 * "Dummy" routines.
 */

/*
 * NAME:	call_driver_object()
 * DESCRIPTION:	pretend to call a function in the driver object
 */
bool call_driver_object(func, narg)
char *func;
int narg;
{
    i_pop(narg);
    (--sp)->type = T_INT;
    sp->u.number = 0;
    return FALSE;
}

/*
 * NAME:	swapout()
 * DESCRIPTION:	pretend to indicate that objects are to be swapped out
 */
void swapout()
{
}

/*
 * NAME:	dump_state()
 * DESCRIPTION:	pretend to indicate that the program must finish
 */
void dump_state()
{
}

/*
 * NAME:	interrupt()
 * DESCRIPTION:	pretend to register an interrupt
 */
void interrupt()
{
}

/*
 * NAME:	finish()
 * DESCRIPTION:	pretend to indicate that the program must finish
 */
void finish()
{
}

pcfunc *pcfunctions;	/* dummy */

/*
 * NAME:	pc_preload()
 * DESCRIPTION:	pretend to preload compiled objects
 */
void pc_preload(auto_name, driver_name)
char *auto_name, *driver_name;
{
}

/*
 * NAME:	pc_control()
 * DESCRIPTION:	pretend to initialize the control block of a compiled object
 */
void pc_control(ctrl, obj)
control *ctrl;
object *obj;
{
}

bool pc_dump(fd)
int fd;
{
    return TRUE;
}

void pc_restore(fd)
int fd;
{
}

/*
 * NAME:	swap->init()
 * DESCRIPTION:	pretend to initialize the swap device
 */
void sw_init(file, total, cache, secsize)
char *file;
unsigned int total, cache, secsize;
{
}

/*
 * NAME:	swap->new()
 * DESCRIPTION:	pretend to return a newly created (empty) swap sector
 */
sector sw_new()
{
    return (sector) 0;
}

/*
 * NAME:	swap->del()
 * DESCRIPTION:	pretend to delete a swap sector
 */
void sw_del(sec)
unsigned int sec;
{
}

/*
 * NAME:	swap->readv()
 * DESCRIPTION:	pretend to read bytes from a vector of sectors
 */
void sw_readv(m, vec, size, idx)
char *m;
sector *vec;
long size, idx;
{
}

/*
 * NAME:	swap->writev()
 * DESCRIPTION:	pretend to write bytes to a vector of sectors
 */
void sw_writev(m, vec, size, idx)
char *m;
sector *vec;
long size, idx;
{
}

/*
 * NAME:	swap->mapsize()
 * DESCRIPTION:	pretend to count the number of sectors required for size bytes
 */
uindex sw_mapsize(size)
long size;
{
    return 0;
}

/*
 * NAME:	swap->count()
 * DESCRIPTION:	pretend to return the number of sectors presently in use
 */
uindex sw_count()
{
    return 0;
}

/*
 * NAME:	swap->copy()
 * DESCRIPTION:	pretend to copy a vector of sectors to a dump file
 */
void sw_copy()
{
}

/*
 * NAME:	swap->dump()
 * DESCRIPTION:	pretend to dump swap file
 */
int sw_dump(dumpfile)
char *dumpfile;
{
    return 0;
}

/*
 * NAME:	swap->restore()
 * DESCRIPTION:	pretend to restore swap file
 */
void sw_restore(fd, secsize)
int fd, secsize;
{
}

/*
 * NAME:	comm->init()
 * DESCRIPTION:	pretend to initialize communications
 */
void comm_init(nusers, telnet_port, binary_port)
int nusers, telnet_port, binary_port;
{
}

/*
 * NAME:	comm->finish()
 * DESCRIPTION:	pretend terminate connections
 */
void comm_finish()
{
}

/*
 * NAME:	comm->send()
 * DESCRIPTION:	pretend to send a message to a user
 */
void comm_send(obj, str)
object *obj;
string *str;
{
}

/*
 * NAME:	comm->echo()
 * DESCRIPTION:	pretend to turn on/off input echoing for a user
 */
void comm_echo(obj, echo)
object *obj;
bool echo;
{
}

/*
 * NAME:	comm->flush()
 * DESCRIPTION:	pretend to flush output to all users
 */
void comm_flush(flag)
bool flag;
{
}

/*
 * NAME:	comm->ip_number()
 * DESCRIPTION:	pretend to return the ip number of a user (as a string)
 */
string *comm_ip_number(obj)
object *obj;
{
    return (string *) NULL;
}

/*
 * NAME:	comm->close()
 * DESCRIPTION:	pretend to remove a user
 */
void comm_close(obj)
object *obj;
{
}

/*
 * NAME:	comm->user()
 * DESCRIPTION:	pretend to return the current user
 */
object *comm_user()
{
    return (object *) NULL;
}

/*
 * NAME:	comm->users()
 * DESCRIPTION:	pretend to return an array with all user objects
 */
array *comm_users()
{
    return (array *) NULL;
}

/*
 * NAME:	ed->init()
 * DESCRIPTION:	pretend to initialize editor handling
 */
void ed_init(tmp, num)
char *tmp;
int num;
{
}

/*
 * NAME:	ed->new()
 * DESCRIPTION:	pretend to start a new editor
 */
void ed_new(obj)
object *obj;
{
}

/*
 * NAME:	ed->del()
 * DESCRIPTION:	pretend to delete an editor instance
 */
void ed_del(obj)
object *obj;
{
}

/*
 * NAME:	ed->command()
 * DESCRIPTION:	pretend to handle an editor command
 */
string *ed_command(obj, cmd)
object *obj;
char *cmd;
{
    return (string *) NULL;
}

/*
 * NAME:	ed->status()
 * DESCRIPTION:	pretend to return the editor status of an object
 */
char *ed_status(obj)
object *obj;
{
    return (char *) NULL;
}

/*
 * NAME:	call_out->init()
 * DESCRIPTION:	pretend to initialize call_out handling
 */
void co_init(max, frag)
unsigned int max;
int frag;
{
}

/*
 * NAME:	call_out->new()
 * DESCRIPTION:	pretend to add a new call_out
 */
uindex co_new(obj, str, delay, nargs)
object *obj;
string *str;
Int delay;
int nargs;
{
    return 0;
}

/*
 * NAME:	call_out->del()
 * DESCRIPTION:	pretend to remove a call_out
 */
Int co_del(obj, handle)
object *obj;
unsigned int handle;
{
    return -1;
}

/*
 * NAME:	call_out->list()
 * DESCRIPTION:	pretend to return a list of callouts
 */
array *co_list(obj)
object *obj;
{
    return (array *) NULL;
}

/*
 * NAME:	call_out->call()
 * DESCRIPTION:	pretend to call expired call_outs
 */
void co_call()
{
}

/*
 * NAME:	call_out->info()
 * DESCRIPTION:	pretend to return information about callouts
 */
void co_info(n1, n2)
uindex *n1, *n2;
{
}

/*
 * NAME:	call_out->swaprate1()
 * DESCRIPTION:	pretend to return the number of objects swapped out per minute
 */
long co_swaprate1()
{
    return 0;
}

/*
 * NAME:	call_out->swaprate5()
 * DESCRIPTION:	pretend to return the number of objects swapped out per 5 mins
 */
long co_swaprate5()
{
    return 0;
}

/*
 * NAME:	call_out->dump()
 * DESCRIPTION:	pretend to dump call_out table
 */
bool co_dump(fd)
int fd;
{
    return FALSE;
}

/*
 * NAME:	call_out->restore()
 * DESCRIPTION:	pretend to restore call_out table
 */
void co_restore(fd, t)
int fd;
long t;
{
}
dgd-net/src/comp/comp.c   640    314      6       31500  5701116720  13275 0ustar  mudusers# include "comp.h"
# include "str.h"
# include "array.h"
# include "object.h"
# include "xfloat.h"
# include "interpret.h"
# include "data.h"
# include "path.h"
# include "hash.h"
# include "swap.h"
# include "comm.h"
# include "ed.h"
# include "call_out.h"
# include "node.h"
# include "codegen.h"
# include "compile.h"
# include "csupport.h"

static int size;		/* current size of the dumped line */

/*
 * NAME:	dump()
 * DESCRIPTION:	output a number
 */
static void dump(n)
int n;
{
    if (size == 16) {
	putchar('\n');
	size = 0;
    }
    printf("%d, ", n);
    size++;
}

/*
 * NAME:	dump_chars()
 * DESCRIPTION:	output a range of characters
 */
static void dump_chars(p, n)
register char *p;
register unsigned int n;
{
    while (n > 0) {
	dump(*p++);
	--n;
    }
}

/*
 * NAME:	dump_inherits()
 * DESCRIPTION:	output the inherited objects
 */
static void dump_inherits(ctrl)
register control *ctrl;
{
    register int i;

    printf("\nstatic pcinherit inherits[] = {\n");
    for (i = 0; i < ctrl->ninherits; i++) {
	printf("\"%s\", %u, %u,\n",
	       o_name(ctrl->inherits[i].obj),
	       ctrl->inherits[i].funcoffset,
	       ctrl->inherits[i].varoffset);
    }
    printf("};\n");
}

/*
 * NAME:	dump_program()
 * DESCRIPTION:	output the program
 */
static void dump_program(ctrl)
control *ctrl;
{
    if (ctrl->progsize != 0) {
	printf("\nstatic char program[] = {\n");
	size = 0;
	dump_chars(ctrl->prog, ctrl->progsize);
	printf("\n};\n");
    }
}

/*
 * NAME:	dump_strings()
 * DESCRIPTION:	output the strings
 */
static void dump_strings(ctrl)
register control *ctrl;
{
    register int i;
    register long len;

    if (ctrl->nstrings != 0) {
	printf("\nstatic dstrconst sstrings[] = {\n");
	len = 0;
	for (i = 0; i < ctrl->nstrings; i++) {
	    printf("{ %ld, %u },\n", len, ctrl->strings[i]->len);
	    len += ctrl->strings[i]->len;
	}
	printf("};\n\nstatic char stext[] = {\n");
	size = 0;
	for (i = 0; i < ctrl->nstrings; i++) {
	    dump_chars(ctrl->strings[i]->text, ctrl->strings[i]->len);
	}
	printf("\n};\n");
    }
}

/*
 * NAME:	dump_functions()
 * DESCRIPTION:	output the function table
 */
static void dump_functions(ctrl, nfuncs)
register control *ctrl;
register int nfuncs;
{
    register int i;

    if (nfuncs != 0) {
	printf("\nstatic pcfunc functions[] = {\n");
	for (i = 1; i <= nfuncs; i++) {
	    printf("func%d,\n", i);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dump_funcdefs()
 * DESCRIPTION:	output the function definitions
 */
static void dump_funcdefs(ctrl)
register control *ctrl;
{
    register int i;

    if (ctrl->nfuncdefs != 0) {
	printf("\nstatic dfuncdef funcdefs[] = {\n");
	for (i = 0; i < ctrl->nfuncdefs; i++) {
	    printf("{ %d, %d, %u, %u },\n",
		   ctrl->funcdefs[i].class,
		   ctrl->funcdefs[i].inherit,
		   ctrl->funcdefs[i].index,
		   ctrl->funcdefs[i].offset);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dump_vardefs()
 * DESCRIPTION:	output the variable definitions
 */
static void dump_vardefs(ctrl)
register control *ctrl;
{
    register int i;

    if (ctrl->nvardefs != 0) {
	printf("\nstatic dvardef vardefs[] = {\n");
	for (i = 0; i < ctrl->nvardefs; i++) {
	    printf("{ %d, %d, %u, %u },\n",
		   ctrl->vardefs[i].class,
		   ctrl->vardefs[i].inherit,
		   ctrl->vardefs[i].index,
		   ctrl->vardefs[i].type);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dump_funcalls()
 * DESCRIPTION:	output the function call table
 */
static void dump_funcalls(ctrl)
register control *ctrl;
{
    if (ctrl->nfuncalls > 0) {
	printf("\nstatic char funcalls[] = {\n");
	size = 0;
	dump_chars(ctrl->funcalls, ctrl->nfuncalls << 1);
	printf("\n};\n");
    }
}

/*
 * NAME:	dump_symbols()
 * DESCRIPTION:	output the symbol table
 */
static void dump_symbols(ctrl)
register control *ctrl;
{
    register uindex i;

    if (ctrl->nsymbols != 0) {
	printf("\nstatic dsymbol symbols[] = {\n");
	for (i = 0; i < ctrl->nsymbols; i++) {
	    printf("{ %d, %d, %u },\n",
		   ctrl->symbols[i].inherit,
		   ctrl->symbols[i].index,
		   ctrl->symbols[i].next);
	}
	printf("};\n");
    }
}

/*
 * NAME:	dgd_main()
 * DESCRIPTION:	main routine of the precompiler
 */
int dgd_main(argc, argv)
int argc;
char *argv[];
{
    register int len;
    register control *ctrl;
    char *file, tag[9];
    int nfuncs;

    if (argc != 3) {
	P_message("usage: precomp config_file file\012");	/* LF */
	return 2;
    }

    if (ec_push()) {
	P_message("error in initialization\012");	/* LF */
	return 2;
    }
    conf_init(argv[1], (char *) NULL);
    ec_pop();

    len = strlen(file = path_resolve(argv[2]));
    if (len > 2 && file[len - 2] == '.' && file[len - 1] == 'c') {
	file[len -= 2] = '\0';
    }
    sprintf(tag, "T%03x%04x", hashstr(file, len) & 0xfff,
	    (unsigned short) P_random());

    printf("/*\n * This file was compiled from LPC with the DGD precompiler.");
    printf("\n * DGD is copyright by Felix A. Croes.");
    printf("  See the file \"Copyright\" for details.\n *\n");
    printf(" * File: \"/%s.c\"\n */\n", file);

    printf("\n# ifdef TAG\nTAG(%s)\n# else\n", tag);
    printf("# include \"dgd.h\"\n# include \"str.h\"\n");
    printf("# include \"array.h\"\n# include \"object.h\"\n");
    printf("# include \"interpret.h\"\n# include \"data.h\"\n");
    printf("# include \"xfloat.h\"\n# include \"csupport.h\"\n");

    if (ec_push()) {
	warning((char *) NULL);
	return 1;
    }
    ctrl = c_compile(file)->ctrl;
    ec_pop();

    dump_inherits(ctrl);
    dump_program(ctrl);
    dump_strings(ctrl);
    dump_functions(ctrl, nfuncs = cg_nfuncs());
    dump_funcdefs(ctrl);
    dump_vardefs(ctrl);
    dump_funcalls(ctrl);
    dump_symbols(ctrl);

    printf("\nprecomp %s = {\n%d, inherits,\n", tag, ctrl->ninherits);
    printf("%ldL,\n", ctrl->compiled);
    if (ctrl->progsize == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, program,\n", ctrl->progsize);
    }
    if (ctrl->nstrings == 0) {
	printf("0, 0, 0,\n");
    } else {
	printf("%u, sstrings, stext,\n", ctrl->nstrings);
    }
    if (nfuncs == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, functions,\n", nfuncs);
    }
    if (ctrl->nfuncdefs == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, funcdefs,\n", ctrl->nfuncdefs);
    }
    if (ctrl->nvardefs == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, vardefs,\n", ctrl->nvardefs);
    }
    if (ctrl->nfuncalls == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, funcalls,\n", ctrl->nfuncalls);
    }
    if (ctrl->nsymbols == 0) {
	printf("0, 0,\n");
    } else {
	printf("%u, symbols,\n", ctrl->nsymbols);
    }
    printf("%u, %u, %u\n", ctrl->nvariables, ctrl->nfloatdefs, ctrl->nfloats);
    printf("};\n# endif\n");

    return 0;
}


/*
 * "Dummy" routines.
 */

/*
 * NAME:	call_driver_object()
 * DESCRIPTION:	pretend to call a function in the driver object
 */
bool call_driver_object(func, narg)
char *func;
int narg;
{
    i_pop(narg);
    (--sp)->type = T_INT;
    sp->u.number = 0;
    return FALSE;
}

/*
 * NAME:	swapout()
 * DESCRIPTION:	pretend to indicate that objects are to be swapped out
 */
void swapout()
{
}

/*
 * NAME:	dump_state()
 * DESCRIPTION:	pretend to indicate that the program must finish
 */
void dump_state()
{
}

/*
 * NAME:	interrupt()
 * DESCRIPTION:	pretend to register an interrupt
 */
void interrupt()
{
}

/*
 * NAME:	finish()
 * DESCRIPTION:	pretend to indicate that the program must finish
 */
void finish()
{
}

pcfunc *pcfunctions;	/* dummy */

/*
 * NAME:	pc_preload()
 * DESCRIPTION:	pretend to preload compiled objects
 */
void pc_preload(auto_name, driver_name)
char *auto_name, *driver_name;
{
}

/*
 * NAME:	pc_control()
 * DESCRIPTION:	pretend to initialize the control block of a compiled object
 */
void pc_control(ctrl, obj)
control *ctrl;
object *obj;
{
}

bool pc_dump(fd)
int fd;
{
    return TRUE;
}

void pc_restore(fd)
int fd;
{
}

/*
 * NAME:	swap->init()
 * DESCRIPTION:	pretend to initialize the swap device
 */
void sw_init(file, total, cache, secsize)
char *file;
unsigned int total, cache, secsize;
{
}

/*
 * NAME:	swap->new()
 * DESCRIPTION:	pretend to return a newly created (empty) swap sector
 */
sector sw_new()
{
    return (sector) 0;
}

/*
 * NAME:	swap->del()
 * DESCRIPTION:	pretend to delete a swap sector
 */
void sw_del(sec)
unsigned int sec;
{
}

/*
 * NAME:	swap->readv()
 * DESCRIPTION:	pretend to read bytes from a vector of sectors
 */
void sw_readv(m, vec, size, idx)
char *m;
sector *vec;
long size, idx;
{
}

/*
 * NAME:	swap->writev()
 * DESCRIPTION:	pretend to write bytes to a vector of sectors
 */
void sw_writev(m, vec, size, idx)
char *m;
sector *vec;
long size, idx;
{
}

/*
 * NAME:	swap->mapsize()
 * DESCRIPTION:	pretend to count the number of sectors required for size bytes
 */
uindex sw_mapsize(size)
long size;
{
    return 0;
}

/*
 * NAME:	swap->count()
 * DESCRIPTION:	pretend to return the number of sectors presently in use
 */
uindex sw_count()
{
    return 0;
}

/*
 * NAME:	swap->copy()
 * DESCRIPTION:	pretend to copy a vector of sectors to a dump file
 */
void sw_copy()
{
}

/*
 * NAME:	swap->dump()
 * DESCRIPTION:	pretend to dump swap file
 */
int sw_dump(dumpfile)
char *dumpfile;
{
    return 0;
}

/*
 * NAME:	swap->restore()
 * DESCRIPTION:	pretend to restore swap file
 */
void sw_restore(fd, secsize)
int fd, secsize;
{
}

/*
 * NAME:	comm->init()
 * DESCRIPTION:	pretend to initialize communications
 */
void comm_init(nusers)
int nusers;
{
}

/*
 * NAME:	comm->finish()
 * DESCRIPTION:	pretend terminate connections
 */
void comm_finish()
{
}

/*
 * NAME:	comm->send()
 * DESCRIPTION:	pretend to send a message to a user
 */
void comm_send(obj, str)
object *obj;
string *str;
{
}

/*
 * NAME:	comm->echo()
 * DESCRIPTION:	pretend to turn on/off input echoing for a user
 */
void comm_echo(obj, echo)
object *obj;
bool echo;
{
}

/*
 * NAME:	comm->flush()
 * DESCRIPTION:	pretend to flush output to all users
 */
void comm_flush(flag)
bool flag;
{
}

/*
 * NAME:        comm->listen()
 * DESCRIPTION: pretend to open a port for listening
 */
void comm_listen(obj, port, protocol)
object *obj;
int port, protocol;
{
}

/*
 * NAME:        comm->connect()
 * DESCRIPTION: pretend to initiate a telnet or tcp connection
 */
void comm_connect(obj, host, port, protocol)
object *obj;
char *host;
int port, protocol;
{
}

/*
 * NAME:        comm->sendto()
 * DESCRIPTION: pretend to send a datagram
 */
void comm_sendto(obj, data, host, port)
object *obj;
string *data;
char *host;
int port;
{
}

/*
 * NAME:	comm->ip_number()
 * DESCRIPTION:	pretend to return the ip number of a user (as a string)
 */
string *comm_ip_number(obj)
object *obj;
{
    return (string *) NULL;
}

/*
 * NAME:	comm->close()
 * DESCRIPTION:	pretend to remove a user
 */
void comm_close(obj)
object *obj;
{
}

/*
 * NAME:	comm->user()
 * DESCRIPTION:	pretend to return the current user
 */
object *comm_user()
{
    return (object *) NULL;
}

/*
 * NAME:	comm->users()
 * DESCRIPTION:	pretend to return an array with all user objects
 */
array *comm_users()
{
    return (array *) NULL;
}

/*
 * NAME:	ed->init()
 * DESCRIPTION:	pretend to initialize editor handling
 */
void ed_init(tmp, num)
char *tmp;
int num;
{
}

/*
 * NAME:	ed->new()
 * DESCRIPTION:	pretend to start a new editor
 */
void ed_new(obj)
object *obj;
{
}

/*
 * NAME:	ed->del()
 * DESCRIPTION:	pretend to delete an editor instance
 */
void ed_del(obj)
object *obj;
{
}

/*
 * NAME:	ed->command()
 * DESCRIPTION:	pretend to handle an editor command
 */
string *ed_command(obj, cmd)
object *obj;
char *cmd;
{
    return (string *) NULL;
}

/*
 * NAME:	ed->status()
 * DESCRIPTION:	pretend to return the editor status of an object
 */
char *ed_status(obj)
object *obj;
{
    return (char *) NULL;
}

/*
 * NAME:	call_out->init()
 * DESCRIPTION:	pretend to initialize call_out handling
 */
void co_init(max, frag)
unsigned int max;
int frag;
{
}

/*
 * NAME:	call_out->new()
 * DESCRIPTION:	pretend to add a new call_out
 */
uindex co_new(obj, str, delay, nargs)
object *obj;
string *str;
Int delay;
int nargs;
{
    return 0;
}

/*
 * NAME:	call_out->del()
 * DESCRIPTION:	pretend to remove a call_out
 */
Int co_del(obj, handle)
object *obj;
unsigned int handle;
{
    return -1;
}

/*
 * NAME:	call_out->list()
 * DESCRIPTION:	pretend to return a list of callouts
 */
array *co_list(obj)
object *obj;
{
    return (array *) NULL;
}

/*
 * NAME:	call_out->call()
 * DESCRIPTION:	pretend to call expired call_outs
 */
void co_call()
{
}

/*
 * NAME:	call_out->info()
 * DESCRIPTION:	pretend to return information about callouts
 */
void co_info(n1, n2)
uindex *n1, *n2;
{
}

/*
 * NAME:	call_out->swaprate1()
 * DESCRIPTION:	pretend to return the number of objects swapped out per minute
 */
long co_swaprate1()
{
    return 0;
}

/*
 * NAME:	call_out->swaprate5()
 * DESCRIPTION:	pretend to return the number of objects swapped out per 5 mins
 */
long co_swaprate5()
{
    return 0;
}

/*
 * NAME:	call_out->dump()
 * DESCRIPTION:	pretend to dump call_out table
 */
bool co_dump(fd)
int fd;
{
    return FALSE;
}

/*
 * NAME:	call_out->restore()
 * DESCRIPTION:	pretend to restore call_out table
 */
void co_restore(fd, t)
int fd;
long t;
{
}
dgd-net/doc/   755    314      6           0  5701313710  11116 5ustar  mudusersdgd-net/doc/kfun/   755    314      6           0  5640047605  12072 5ustar  mudusersdgd-net/doc/kfun/open_port   644    314      6        2126  5575122325  14103 0ustar  mudusersNAME
	open_port - associate an object with an internet port

SYNOPSIS
	void open_port(object obj, int port, string protocol)


DESCRIPTION
	Open a port on the host machine and connect it to obj.  This object
	is then known as a "port object".  The protocol may be any of "tcp",
	"udp", or "telnet".  What happens to the port object depends on the
	protocol.

	When a port is first opened, open() is called in its port object.
	When it is closed for any reason, close() is called in its port object.
	Destructing a port object will close its port first.

	In a telnet or tcp port, connection(string ipnumber, int port) will
	be called whenever a client connects to its port.  This function
	should return an object that will then be known as a "user object".

	In an udp port, 

	    receive_datagram(string data, string ipnumber, int port)

	will be called whenever a datagram arrives on its port.  The
	ipnumber and port will be those of the sender.  Udp port objects
	may also send datagrams.

	Only the driver object can use this function.

SEE ALSO
	kfun/send_datagram, kfun/send_message, kfun/connect



	dgd-net/doc/kfun/connect   644    314      6        1150  5574736015  13531 0ustar  mudusersNAME
	connect - initiate a tcp connection

SYNOPSIS
	void connect(object obj, string ipnumber, int port, string protocol)


DESCRIPTION
	Initiate a telnet or tcp connection to the specified host and port,
	and associate the connection with obj when it is established.
	The protocol may be "telnet" or "tcp".

	When the connection succeeds, open() will be called in obj.  If it
	fails or times out, close() will be called in obj.  After the
	connection is established, obj will be a normal user object.

	Only the driver object can use this function.


SEE ALSO
	kfun/open_port, kfun/send_message, kfun/send_datagram
dgd-net/doc/kfun/send_datagram   644    314      6         545  5571410517  14651 0ustar  mudusersNAME
	send_datagram - send a datagram

SYNOPSIS
	void send_datagram(string data, string destination, int port)


DESCRIPTION
	Send a UDP datagram to the specified host and udp port.  No hostname
	lookup is done so the destination must be an ip number.
	Only udp port objects can use this function.

SEE ALSO
	kfun/open_port, kfun/send_message, kfun/connect
dgd-net/doc/Networking   644    314      6        4441  5701313710  13253 0ustar  mudusers	General overview of the facilities of the DGD Networking package

This package extends the IP networking features of DGD, at the cost of some
security. (A driver that can initiate connections or send udp packets can,
if its internal security fails, be used as a platform for further attacks
by a cracker or other malicious user.)

To install it, just copy the files in this directory tree over your DGD
1.0.8.8 directory tree.  If you have a different DGD version, you should
check if all files changed by this package (the originals are inluded with
.DGD extensions) are still the same in your version.

The networking package introduces three special kinds of objects:
	- tcp and telnet port objects
	- tcp and telnet connection objects
	- udp port objects

Tcp and telnet port objects are associated with a tcp port.
Whenever a client seeks a connection with a port DGD has opened, 
	connection(string clienthost, int clientport)
is called in the port object associated with that port.  This function is
expected to return an object that will function as the connection object
for that client.

Udp port objects are associated with a udp port.  There are no udp
connection objects.  When a udp datagram arrives on a port DGD has opened,
	receive_datagram(string data, string fromhost, string fromport)
is called in the udp port object associated with it.

Tcp and telnet connection objects are associated with a client.  Whenever
data arrives on a tcp connection, receive_message(string data) is called in
the connection object.  When data arrives on a telnet connection, the
driver parses it according to the telnet protocol.  Whenever a full line is
parsed, receive_message(string text) is called in the connection object.

There are kfuns for opening ports, sending udp datagrams and tcp/telnet
data, and initiating tcp or telnet connections. See kfun/open_port,
kfun/send_datagram, kfun/send_message, and kfun/connect.

The config-file entries `telnet_port' and `binary_port' are still valid but
will be ignored.  The driver object should take care of opening the
appropriate ports during initialization.

The kfun query_ip_number() returns "0.0.0.0" for port objects.
The kfun users() returns port objects as well as connection objects.
The config-file entry `users' also counts port objects.

Richard Braakman <dark@xs4all.nl>
dgd-net/Copyright.DGD   640    314      6        1456  5643560124  12733 0ustar  mudusers   This program, Dworkin's Game Driver, is copyright 1993, 1994 by
Felix A. Croes, The Netherlands, email dworkin@cd.chalmers.se.  All rights
reserved.

   Permission is granted to copy and distribute the source and executables
made therefrom, but any commercial use whatsoever is not allowed, other than
by prior written permission from the author.

				- - - -

   Any modifications of this program without explicit copyright message are
automatically included in the copyright above.  Any explicit copyrights
should not contradict the terms stated above, but may put further restrictions
(for instance, prohibiting commercial use entirely); modifications should be
made in such a way that it is clear which copyright message applies where, and
in such a way that it is possible to regain the unmodified source.
dgd-net/Copyright.NET   644    314      6         705  5701314076  12741 0ustar  mudusersThe networking-DGD package is Copyright 1994, 1995 by Richard Braakman.

The package is also a derived work of Dworkin's Game Driver, which is
copyrighted by Felix Croes.  Therefore, his copyright applies to it
in addition to mine.  His copyright notice is included in the file
Copyright.DGD.

I grant permission for any use of this package which does not conflict
with the terms of the DGD copyright mentioned above.

Richard Braakman <dark@xs4all.nl>