示例#1
0
文件: mcp.c 项目: 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);
	*/
}
示例#2
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;
}
示例#3
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;
}
示例#4
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;
}
示例#5
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;
}
示例#6
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;
	}
}
示例#7
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;
}
示例#8
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;
}
示例#9
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;
}
示例#10
0
文件: mcp.c 项目: 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;
}
示例#11
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;
}
示例#12
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;
}
示例#13
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;
	}
}
示例#14
0
文件: mcp.c 项目: hyena/fuzzball
int
mcp_intern_is_mesg_start(McpFrame * mfr, const char *in)
{
	char mesgname[128];
	char authkey[128];
	char *subname = NULL;
	McpMesg *newmsg = NULL;
	McpPkg *pkg = NULL;
	int longlen = 0;

	if (!mcp_intern_is_ident(&in, mesgname, sizeof(mesgname)))
		return 0;
	if (strcmp_nocase(mesgname, MCP_INIT_PKG)) {
		if (!isspace(*in))
			return 0;
		while (isspace(*in))
			in++;
		if (!mcp_intern_is_unquoted(&in, authkey, sizeof(authkey)))
			return 0;
		if (strcmp(authkey, mfr->authkey))
			return 0;
	}

	if (strncmp_nocase(mesgname, MCP_INIT_PKG, 3)) {
		for (pkg = mfr->packages; pkg; pkg = pkg->next) {
			int pkgnamelen = strlen(pkg->pkgname);

			if (!strncmp_nocase(pkg->pkgname, mesgname, pkgnamelen)) {
				if (mesgname[pkgnamelen] == '\0' || mesgname[pkgnamelen] == '-') {
					if (pkgnamelen > longlen) {
						longlen = pkgnamelen;
					}
				}
			}
		}
	}
	if (!longlen) {
		int neglen = strlen(MCP_NEGOTIATE_PKG);

		if (!strncmp_nocase(mesgname, MCP_NEGOTIATE_PKG, neglen)) {
			longlen = neglen;
		} else if (!strcmp_nocase(mesgname, MCP_INIT_PKG)) {
			longlen = strlen(mesgname);
		} else {
			return 0;
		}
	}
	subname = mesgname + longlen;
	if (*subname) {
		*subname++ = '\0';
	}

	newmsg = (McpMesg *) malloc(sizeof(McpMesg));
	mcp_mesg_init(newmsg, mesgname, subname);
	while (*in) {
		if (!mcp_intern_is_keyval(newmsg, &in)) {
			mcp_mesg_clear(newmsg);
			free(newmsg);
			return 0;
		}
	}

	/* Okay, we've recieved a valid message. */
	if (newmsg->incomplete) {
		/* It's incomplete.  Remember it to finish later. */
		const char *msgdt = mcp_mesg_arg_getline(newmsg, MCP_DATATAG, 0);

		newmsg->datatag = string_dup(msgdt);
		mcp_mesg_arg_remove(newmsg, MCP_DATATAG);
		newmsg->next = mfr->messages;
		mfr->messages = newmsg;
	} else {
		/* It's complete.  Execute the callback function for this package. */
		mcp_frame_package_docallback(mfr, newmsg);
		mcp_mesg_clear(newmsg);
		free(newmsg);
	}
	return 1;
}
示例#15
0
文件: mcp.c 项目: 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);
		}
	}
}
示例#16
0
文件: help.c 项目: hyena/fuzzball
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);
		}
	}
}