Esempio n. 1
0
const char *
GuiHelper(int descr,
		  const char *title,
		  int pagecount, const char **pagenames, const char **pageids,
		  Gui_CB callback, GuiErr_CB error_cb, void *context)
{
	McpMesg msg;
	McpFrame *mfr = descr_mcpframe(descr);
	const char *id;
	int i;

	if (!mfr) {
		return NULL;
	}
	if (GuiSupported(descr)) {
		id = gui_dlog_alloc(descr, callback, error_cb, context);
		mcp_mesg_init(&msg, GUI_PACKAGE, "dlog-create");
		mcp_mesg_arg_append(&msg, "dlogid", id);
		mcp_mesg_arg_append(&msg, "type", "helper");
		mcp_mesg_arg_append(&msg, "title", title);
		for (i = 0; i < pagecount; i++) {
			mcp_mesg_arg_append(&msg, "panes", pageids[i]);
			mcp_mesg_arg_append(&msg, "names", pagenames[i]);
		}
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		return id;
	} else {
		return NULL;
	}
}
Esempio n. 2
0
void
mcpedit_program(int descr, dbref player, dbref prog, const char *name,
                McpFrame *mfr)
{
    char namestr[BUFFER_LEN];
    char refstr[BUFFER_LEN];
    struct line *curr;
    McpMesg msg;
    McpVer supp;

    supp = mcp_frame_package_supported(mfr, "dns-org-mud-moo-simpleedit");
    if (supp.verminor == 0 && supp.vermajor == 0) {
        do_prog(descr, player, name);
        return;
    }

    FLAGS(prog) |= INTERNAL;

    snprintf(refstr, sizeof(refstr), "%d.prog.", prog);
    snprintf(namestr, sizeof(namestr), "a program named %s(%d)", NAME(prog),
             prog);
    mcp_mesg_init(&msg, "dns-org-mud-moo-simpleedit", "content");
    mcp_mesg_arg_append(&msg, "reference", refstr);
    mcp_mesg_arg_append(&msg, "type", "muf-code");
    mcp_mesg_arg_append(&msg, "name", namestr);
    for (curr = DBFETCH(prog)->sp.program.first; curr; curr = curr->next)
        mcp_mesg_arg_append(&msg, "content", DoNull(curr->this_line));

    mcp_frame_output_mesg(mfr, &msg);
    mcp_mesg_clear(&msg);

    free_prog_text(DBFETCH(prog)->sp.program.first);
    DBFETCH(prog)->sp.program.first = NULL;
}
Esempio n. 3
0
int
GuiSetVal(const char *dlogid, const char *id, int lines, const char **value)
{
	McpMesg msg;
	McpFrame *mfr;
	int i;
	int descr = gui_dlog_get_descr(dlogid);

	mfr = descr_mcpframe(descr);
	if (!mfr) {
		return EGUINODLOG;
	}
	if (GuiSupported(descr)) {
		mcp_mesg_init(&msg, GUI_PACKAGE, "ctrl-value");
		mcp_mesg_arg_append(&msg, "dlogid", dlogid);
		mcp_mesg_arg_append(&msg, "id", id);
		for (i = 0; i < lines; i++) {
			mcp_mesg_arg_append(&msg, "value", value[i]);
		}
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		gui_value_set_local(dlogid, id, lines, value);
		return 0;
	}
	return EGUINOSUPPORT;
}
Esempio n. 4
0
int
GuiMenuItem(const char *dlogid, const char *id, const char *type, const char *name, const char **args)
{
	McpMesg msg;
	McpFrame *mfr;
	int i;
	int descr = gui_dlog_get_descr(dlogid);

	mfr = descr_mcpframe(descr);
	if (!mfr) {
		return EGUINODLOG;
	}
	if (GuiSupported(descr)) {
		mcp_mesg_init(&msg, GUI_PACKAGE, "menu-item");
		mcp_mesg_arg_append(&msg, "dlogid", dlogid);
		mcp_mesg_arg_append(&msg, "id", id);
		mcp_mesg_arg_append(&msg, "name", name);
		mcp_mesg_arg_append(&msg, "type", name);
		i = 0;
		while (args && args[i]) {
			const char *arg = args[i];
			const char *val = args[i + 1];

			mcp_mesg_arg_append(&msg, arg, val);
			i += 2;
		}
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		return 0;
	}
	return EGUINOSUPPORT;
}
Esempio n. 5
0
int
GuiListInsert(const char *dlogid, const char *id, int after, int lines, const char **value)
{
	McpMesg msg;
	McpFrame *mfr;
	char numbuf[32];
	int i;
	int descr = gui_dlog_get_descr(dlogid);

	mfr = descr_mcpframe(descr);
	if (!mfr) {
		return EGUINODLOG;
	}
	if (GuiSupported(descr)) {
		mcp_mesg_init(&msg, GUI_PACKAGE, "list-insert");
		mcp_mesg_arg_append(&msg, "dlogid", dlogid);
		mcp_mesg_arg_append(&msg, "id", id);
		if (after > 0) {
			snprintf(numbuf, sizeof(numbuf), "%d", after);
			mcp_mesg_arg_append(&msg, "after", numbuf);
		}
		for (i = 0; i < lines; i++) {
			mcp_mesg_arg_append(&msg, "values", value[i]);
		}
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		return 0;
	}
	return EGUINOSUPPORT;
}
Esempio n. 6
0
int
gui_dlog_closeall_descr(int descr)
{
	DlogData *ptr;
	McpMesg msg;

	ptr = dialog_list;
	while (ptr) {
		while (ptr) {
			if (ptr->descr == descr) {
				break;
			}
			ptr = ptr->next;
		}
		if (!ptr) {
			return 0;
		}
		if (ptr->callback) {
			mcp_mesg_init(&msg, GUI_PACKAGE, "ctrl-event");
			mcp_mesg_arg_append(&msg, "dlogid", ptr->id);
			mcp_mesg_arg_append(&msg, "id", "_closed");
			mcp_mesg_arg_append(&msg, "dismissed", "1");
			mcp_mesg_arg_append(&msg, "event", "buttonpress");
			ptr->callback(ptr->descr, ptr->id, "_closed", "buttonpress", &msg, 1, ptr->context);
			mcp_mesg_clear(&msg);
		}
		ptr = ptr->next;
	}
	return 0;
}
Esempio n. 7
0
File: mcp.c Progetto: hyena/fuzzball
void
mcp_negotiation_start(McpFrame * mfr)
{
	McpMesg reply;

	mfr->enabled = 1;
	mcp_mesg_init(&reply, MCP_INIT_PKG, "");
	mcp_mesg_arg_append(&reply, "version", "2.1");
	mcp_mesg_arg_append(&reply, "to", "2.1");
	mcp_frame_output_mesg(mfr, &reply);
	mcp_mesg_clear(&reply);
	mfr->enabled = 0;
}
Esempio n. 8
0
File: mcp.c Progetto: hyena/fuzzball
int
mcp_intern_is_keyval(McpMesg * msg, const char **in)
{
	char keyname[128];
	char value[BUFFER_LEN];
	const char *old = *in;
	int deferred = 0;

	if (!isspace(**in))
		return 0;
	while (isspace(**in))
		(*in)++;
	if (!mcp_intern_is_ident(in, keyname, sizeof(keyname))) {
		*in = old;
		return 0;
	}
	if (**in == '*') {
		msg->incomplete = 1;
		deferred = 1;
		(*in)++;
	}
	if (**in != ':') {
		*in = old;
		return 0;
	}
	(*in)++;
	if (!isspace(**in)) {
		*in = old;
		return 0;
	}
	while (isspace(**in))
		(*in)++;
	if (!mcp_intern_is_unquoted(in, value, sizeof(value)) &&
		!mcp_intern_is_quoted(in, value, sizeof(value))
			) {
		*in = old;
		return 0;
	}

	if (deferred) {
		mcp_mesg_arg_append(msg, keyname, NULL);
	} else {
		mcp_mesg_arg_append(msg, keyname, value);
	}
	return 1;
}
Esempio n. 9
0
int
GuiListDel(const char *dlogid, const char *id, int from, int to)
{
	McpMesg msg;
	McpFrame *mfr;
	char numbuf[32];
	int descr = gui_dlog_get_descr(dlogid);

	mfr = descr_mcpframe(descr);
	if (!mfr) {
		return EGUINODLOG;
	}
	if (GuiSupported(descr)) {
		mcp_mesg_init(&msg, GUI_PACKAGE, "list-delete");
		mcp_mesg_arg_append(&msg, "dlogid", dlogid);
		mcp_mesg_arg_append(&msg, "id", id);
		if (from == GUI_LIST_END) {
			mcp_mesg_arg_append(&msg, "from", "end");
		} else {
			snprintf(numbuf, sizeof(numbuf), "%d", from);
			mcp_mesg_arg_append(&msg, "from", numbuf);
		}
		if (to == GUI_LIST_END) {
			mcp_mesg_arg_append(&msg, "to", "end");
		} else {
			snprintf(numbuf, sizeof(numbuf), "%d", to);
			mcp_mesg_arg_append(&msg, "to", numbuf);
		}
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		return 0;
	}
	return EGUINOSUPPORT;
}
Esempio n. 10
0
const char *
GuiSimple(int descr, const char *title, Gui_CB callback, GuiErr_CB error_cb, void *context)
{
	McpMesg msg;
	McpFrame *mfr = descr_mcpframe(descr);
	const char *id;

	if (!mfr) {
		return NULL;
	}
	if (GuiSupported(descr)) {
		id = gui_dlog_alloc(descr, callback, error_cb, context);
		mcp_mesg_init(&msg, GUI_PACKAGE, "dlog-create");
		mcp_mesg_arg_append(&msg, "dlogid", id);
		mcp_mesg_arg_append(&msg, "type", "simple");
		mcp_mesg_arg_append(&msg, "title", title);
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		return id;
	} else {
		return NULL;
	}
}
Esempio n. 11
0
int
gui_ctrl_make_l(const char *dlogid, const char *type, const char *pane, const char *id, const char *text, const char *value,
				int layout, ...)
{
	va_list ap;
	McpMesg msg;
	McpFrame *mfr;
	int descr;

	va_start(ap, layout);

	descr = gui_dlog_get_descr(dlogid);
	mfr = descr_mcpframe(descr);
	if (!mfr) {
		va_end(ap);
		return EGUINODLOG;
	}
	if (GuiSupported(descr)) {
		char cmdname[64];

		snprintf(cmdname, sizeof(cmdname), "ctrl-%.55s", type);
		mcp_mesg_init(&msg, GUI_PACKAGE, cmdname);
		gui_ctrl_process_layout(&msg, layout);
		mcp_mesg_arg_append(&msg, "dlogid", dlogid);
		mcp_mesg_arg_append(&msg, "id", id);
		if (text)
			mcp_mesg_arg_append(&msg, "text", text);
		if (value) {
			mcp_mesg_arg_append(&msg, "value", value);
			if (id) {
				gui_value_set_local(dlogid, id, 1, &value);
			}
		}
		if (pane)
			mcp_mesg_arg_append(&msg, "pane", pane);
		while (1) {
			const char *val;
			const char *arg;

			arg = va_arg(ap, const char *);

			if (!arg)
				break;
			val = va_arg(ap, const char *);

			mcp_mesg_arg_append(&msg, arg, val);
		}
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		va_end(ap);
		return 0;
	}
	va_end(ap);
	return EGUINOSUPPORT;
}
Esempio n. 12
0
int
gui_ctrl_make_v(const char *dlogid, const char *type, const char *pane,
		        const char *id, const char *text, const char *value,
				int layout, const char **args)
{
	McpMesg msg;
	McpFrame *mfr;
	int descr;
	int i;

	descr = gui_dlog_get_descr(dlogid);
	mfr = descr_mcpframe(descr);
	if (!mfr) {
		return EGUINODLOG;
	}
	if (GuiSupported(descr)) {
		char cmdname[64];

		snprintf(cmdname, sizeof(cmdname), "ctrl-%.55s", type);
		mcp_mesg_init(&msg, GUI_PACKAGE, cmdname);
		gui_ctrl_process_layout(&msg, layout);
		mcp_mesg_arg_append(&msg, "dlogid", dlogid);
		mcp_mesg_arg_append(&msg, "id", id);
		if (text)
			mcp_mesg_arg_append(&msg, "text", text);
		if (value) {
			mcp_mesg_arg_append(&msg, "value", value);
			if (id) {
				gui_value_set_local(dlogid, id, 1, &value);
			}
		}
		if (pane)
			mcp_mesg_arg_append(&msg, "pane", pane);
		i = 0;
		while (args && args[i]) {
			const char *arg = args[i];
			const char *val = args[i + 1];

			if (id && !string_compare(arg, "value")) {
				gui_value_set_local(dlogid, id, 1, &val);
			}
			mcp_mesg_arg_append(&msg, arg, val);
			i += 2;
		}
		mcp_frame_output_mesg(mfr, &msg);
		mcp_mesg_clear(&msg);
		return 0;
	}
	return EGUINOSUPPORT;
}
Esempio n. 13
0
File: mcp.c Progetto: hyena/fuzzball
void
mcp_frame_package_renegotiate(const char* package)
{
	McpVer nullver = { 0, 0 };
	McpFrameList* mfrl = mcp_frame_list;
	McpFrame* mfr;
	McpMesg cando;
	char verbuf[32];
	McpPkg *p;

	p = mcp_PackageList;
	while (p) {
		if (!strcmp_nocase(p->pkgname, package)) {
			break;
		}
		p = p->next;
	}

	if (!p) {
		mcp_mesg_init(&cando, MCP_NEGOTIATE_PKG, "can");
		mcp_mesg_arg_append(&cando, "package", package);
		mcp_mesg_arg_append(&cando, "min-version", "0.0");
		mcp_mesg_arg_append(&cando, "max-version", "0.0");
	} else {
		mcp_mesg_init(&cando, MCP_NEGOTIATE_PKG, "can");
		mcp_mesg_arg_append(&cando, "package", p->pkgname);
		snprintf(verbuf, sizeof(verbuf), "%d.%d", p->minver.vermajor, p->minver.verminor);
		mcp_mesg_arg_append(&cando, "min-version", verbuf);
		snprintf(verbuf, sizeof(verbuf), "%d.%d", p->maxver.vermajor, p->maxver.verminor);
		mcp_mesg_arg_append(&cando, "max-version", verbuf);
	}

	while (mfrl) {
		mfr = mfrl->mfr;
		if (mfr->enabled) {
			if (mcp_version_compare(mfr->version, nullver) > 0) {
				mcp_frame_package_remove(mfr, package);
				mcp_frame_output_mesg(mfr, &cando);
			}
		}
		mfrl = mfrl->next;
	}
	mcp_mesg_clear(&cando);

	/*
	mcp_mesg_init(&cando, MCP_NEGOTIATE_PKG, "end");
	mcp_frame_output_mesg(mfr, &cando);
	mcp_mesg_clear(&cando);
	*/
}
Esempio n. 14
0
File: mcp.c Progetto: hyena/fuzzball
int
mcp_intern_is_mesg_cont(McpFrame * mfr, const char *in)
{
	char datatag[128];
	char keyname[128];
	McpMesg *ptr;

	if (*in != '*') {
		return 0;
	}
	in++;
	if (!isspace(*in))
		return 0;
	while (isspace(*in))
		in++;
	if (!mcp_intern_is_unquoted(&in, datatag, sizeof(datatag)))
		return 0;
	if (!isspace(*in))
		return 0;
	while (isspace(*in))
		in++;
	if (!mcp_intern_is_ident(&in, keyname, sizeof(keyname)))
		return 0;
	if (*in != ':')
		return 0;
	in++;
	if (!isspace(*in))
		return 0;
	in++;

	for (ptr = mfr->messages; ptr; ptr = ptr->next) {
		if (!strcmp(datatag, ptr->datatag)) {
			mcp_mesg_arg_append(ptr, keyname, in);
			break;
		}
	}
	if (!ptr) {
		return 0;
	}
	return 1;
}
Esempio n. 15
0
int
GuiClose(const char *id)
{
	McpMesg msg;
	McpFrame *mfr;
	int descr = gui_dlog_get_descr(id);

	mfr = descr_mcpframe(descr);
	if (!mfr) {
		return EGUINODLOG;
	}
	if (GuiSupported(descr)) {
		if (!GuiClosed(id)) {
			mcp_mesg_init(&msg, GUI_PACKAGE, "dlog-close");
			mcp_mesg_arg_append(&msg, "dlogid", id);
			mcp_frame_output_mesg(mfr, &msg);
			mcp_mesg_clear(&msg);
		}
		return 0;
	}
	return EGUINOSUPPORT;
}
Esempio n. 16
0
void
gui_ctrl_process_layout(McpMesg * msg, int layout)
{
	char buf[32];

	buf[0] = '\0';
	if ((layout & GUI_N))
		strcatn(buf, sizeof(buf), "n");

	if ((layout & GUI_S))
		strcatn(buf, sizeof(buf), "s");

	if ((layout & GUI_E))
		strcatn(buf, sizeof(buf), "e");

	if ((layout & GUI_W))
		strcatn(buf, sizeof(buf), "w");

	if (strcmp(buf, ""))
		mcp_mesg_arg_append(msg, "sticky", buf);


	snprintf(buf, sizeof(buf), "%d", GET_COLSKIP(layout));
	if (strcmp(buf, "0"))
		mcp_mesg_arg_append(msg, "colskip", buf);


	snprintf(buf, sizeof(buf), "%d", GET_COLSPAN(layout));
	if (strcmp(buf, "1"))
		mcp_mesg_arg_append(msg, "colspan", buf);


	snprintf(buf, sizeof(buf), "%d", GET_ROWSPAN(layout));
	if (strcmp(buf, "1"))
		mcp_mesg_arg_append(msg, "rowspan", buf);


	snprintf(buf, sizeof(buf), "%d", GET_LEFTPAD(layout));
	if (strcmp(buf, "0"))
		mcp_mesg_arg_append(msg, "leftpad", buf);


	snprintf(buf, sizeof(buf), "%d", GET_TOPPAD(layout));
	if (strcmp(buf, "0"))
		mcp_mesg_arg_append(msg, "toppad", buf);


	if ((layout & GUI_NONL))
		mcp_mesg_arg_append(msg, "newline", "0");

	if ((layout & GUI_HEXP))
		mcp_mesg_arg_append(msg, "hweight", "1");

	if ((layout & GUI_VEXP))
		mcp_mesg_arg_append(msg, "vweight", "1");

	if ((layout & GUI_REPORT))
		mcp_mesg_arg_append(msg, "report", "1");

	if ((layout & GUI_REQUIRED))
		mcp_mesg_arg_append(msg, "required", "1");
}
Esempio n. 17
0
void
mcppkg_help_request(McpFrame * mfr, McpMesg * msg, McpVer ver, void *context)
{
	FILE *f;
	const char* file;
	char buf[BUFFER_LEN];
	char topic[BUFFER_LEN];
	char *p;
	int arglen, found;
	McpVer supp = mcp_frame_package_supported(mfr, "org-fuzzball-help");
	McpMesg omsg;

	if (supp.verminor == 0 && supp.vermajor == 0) {
		notify(mcpframe_to_user(mfr), "MCP: org-fuzzball-help not supported.");
		return;
	}

	if (!string_compare(msg->mesgname, "request")) {
		char *onwhat;
		char *valtype;

		onwhat = mcp_mesg_arg_getline(msg, "topic", 0);
		valtype = mcp_mesg_arg_getline(msg, "type", 0);

		*topic = '\0';
		strcpyn(topic, sizeof(topic), onwhat);
		if (*onwhat) {
			strcatn(topic, sizeof(topic), "|");
		}

		if (!string_compare(valtype, "man")) {
			file = MAN_FILE;
		} else if (!string_compare(valtype, "mpi")) {
			file = MPI_FILE;
		} else if (!string_compare(valtype, "help")) {
			file = HELP_FILE;
		} else if (!string_compare(valtype, "news")) {
			file = NEWS_FILE;
		} else {
			snprintf(buf, sizeof(buf), "Sorry, %s is not a valid help type.", valtype);
			mcp_mesg_init(&omsg, "org-fuzzball-help", "error");
			mcp_mesg_arg_append(&omsg, "text", buf);
			mcp_mesg_arg_append(&omsg, "topic", onwhat);
			mcp_frame_output_mesg(mfr, &omsg);
			mcp_mesg_clear(&omsg);
			return;
		}

		if ((f = fopen(file, "rb")) == NULL) {
			snprintf(buf, sizeof(buf), "Sorry, %s is missing.  Management has been notified.", file);
			fprintf(stderr, "help: No file %s!\n", file);
			mcp_mesg_init(&omsg, "org-fuzzball-help", "error");
			mcp_mesg_arg_append(&omsg, "text", buf);
			mcp_mesg_arg_append(&omsg, "topic", onwhat);
			mcp_frame_output_mesg(mfr, &omsg);
			mcp_mesg_clear(&omsg);
		} else {
			if (*topic) {
				arglen = strlen(topic);
				do {
					do {
						if (!(fgets(buf, sizeof buf, f))) {
							snprintf(buf, sizeof(buf), "Sorry, no help available on topic \"%s\"", onwhat);
							fclose(f);
							mcp_mesg_init(&omsg, "org-fuzzball-help", "error");
							mcp_mesg_arg_append(&omsg, "text", buf);
							mcp_mesg_arg_append(&omsg, "topic", onwhat);
							mcp_frame_output_mesg(mfr, &omsg);
							mcp_mesg_clear(&omsg);
							return;
						}
					} while (*buf != '~');
					do {
						if (!(fgets(buf, sizeof buf, f))) {
							snprintf(buf, sizeof(buf), "Sorry, no help available on topic \"%s\"", onwhat);
							fclose(f);
							mcp_mesg_init(&omsg, "org-fuzzball-help", "error");
							mcp_mesg_arg_append(&omsg, "text", buf);
							mcp_mesg_arg_append(&omsg, "topic", onwhat);
							mcp_frame_output_mesg(mfr, &omsg);
							mcp_mesg_clear(&omsg);
							return;
						}
					} while (*buf == '~');
					p = buf;
					found = 0;
					buf[strlen(buf) - 1] = '|';
					while (*p && !found) {
						if (strncasecmp(p, topic, arglen)) {
							while (*p && (*p != '|'))
								p++;
							if (*p)
								p++;
						} else {
							found = 1;
						}
					}
				} while (!found);
			}
			mcp_mesg_init(&omsg, "org-fuzzball-help", "entry");
			mcp_mesg_arg_append(&omsg, "topic", onwhat);
			while (fgets(buf, sizeof buf, f)) {
				if (*buf == '~')
					break;
				for (p = buf; *p; p++) {
					if (*p == '\n' || *p == '\r') {
						*p = '\0';
						break;
					}
				}
				if (!*buf) {
					strcpyn(buf, sizeof(buf), "  ");
				}
				mcp_mesg_arg_append(&omsg, "text", buf);
			}
			fclose(f);
			mcp_frame_output_mesg(mfr, &omsg);
			mcp_mesg_clear(&omsg);
		}
	}
}
Esempio n. 18
0
File: mcp.c Progetto: hyena/fuzzball
void
mcp_basic_handler(McpFrame * mfr, McpMesg * mesg, void *dummy)
{
	McpVer myminver = { 2, 1 };
	McpVer mymaxver = { 2, 1 };
	McpVer minver = { 0, 0 };
	McpVer maxver = { 0, 0 };
	McpVer nullver = { 0, 0 };
	const char *ptr;
	const char *auth;

	if (!*mesg->mesgname) {
		auth = mcp_mesg_arg_getline(mesg, "authentication-key", 0);
		if (auth) {
			mfr->authkey = string_dup(auth);
		} else {
			McpMesg reply;
			char authval[128];

			mcp_mesg_init(&reply, MCP_INIT_PKG, "");
			mcp_mesg_arg_append(&reply, "version", "2.1");
			mcp_mesg_arg_append(&reply, "to", "2.1");
			snprintf(authval, sizeof(authval), "%.8lX", (unsigned long)(RANDOM() ^ RANDOM()));
			mcp_mesg_arg_append(&reply, "authentication-key", authval);
			mfr->authkey = string_dup(authval);
			mcp_frame_output_mesg(mfr, &reply);
			mcp_mesg_clear(&reply);
		}

		ptr = mcp_mesg_arg_getline(mesg, "version", 0);
		if (!ptr)
			return;
		while (isdigit(*ptr))
			minver.vermajor = (minver.vermajor * 10) + (*ptr++ - '0');
		if (*ptr++ != '.')
			return;
		while (isdigit(*ptr))
			minver.verminor = (minver.verminor * 10) + (*ptr++ - '0');

		ptr = mcp_mesg_arg_getline(mesg, "to", 0);
		if (!ptr) {
			maxver = minver;
		} else {
			while (isdigit(*ptr))
				maxver.vermajor = (maxver.vermajor * 10) + (*ptr++ - '0');
			if (*ptr++ != '.')
				return;
			while (isdigit(*ptr))
				maxver.verminor = (maxver.verminor * 10) + (*ptr++ - '0');
		}

		mfr->version = mcp_version_select(myminver, mymaxver, minver, maxver);
		if (mcp_version_compare(mfr->version, nullver)) {
			McpMesg cando;
			char verbuf[32];
			McpPkg *p = mcp_PackageList;

			mfr->enabled = 1;
			while (p) {
				if (strcmp_nocase(p->pkgname, MCP_INIT_PKG)) {
					mcp_mesg_init(&cando, MCP_NEGOTIATE_PKG, "can");
					mcp_mesg_arg_append(&cando, "package", p->pkgname);
					snprintf(verbuf, sizeof(verbuf), "%d.%d", p->minver.vermajor, p->minver.verminor);
					mcp_mesg_arg_append(&cando, "min-version", verbuf);
					snprintf(verbuf, sizeof(verbuf), "%d.%d", p->maxver.vermajor, p->maxver.verminor);
					mcp_mesg_arg_append(&cando, "max-version", verbuf);
					mcp_frame_output_mesg(mfr, &cando);
					mcp_mesg_clear(&cando);
				}
				p = p->next;
			}
			mcp_mesg_init(&cando, MCP_NEGOTIATE_PKG, "end");
			mcp_frame_output_mesg(mfr, &cando);
			mcp_mesg_clear(&cando);
		}
	}
}