void mcp_negotiate_handler(McpFrame * mfr, McpMesg * mesg, McpVer version, void *dummy) { McpVer minver = { 0, 0 }; McpVer maxver = { 0, 0 }; const char *ptr; const char *pkg; if (!strcmp(mesg->mesgname, "can")) { pkg = mcp_mesg_arg_getline(mesg, "package", 0); if (!pkg) return; ptr = mcp_mesg_arg_getline(mesg, "min-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, "max-version", 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'); } mcp_frame_package_add(mfr, pkg, minver, maxver); } else if (!strcmp(mesg->mesgname, "end")) { /* nothing to do for end of package negotiations. */ } }
void gui_pkg_callback(McpFrame * mfr, McpMesg * msg, McpVer ver, void *context) { DlogData *dat; const char *dlogid = mcp_mesg_arg_getline(msg, "dlogid", 0); const char *id = mcp_mesg_arg_getline(msg, "id", 0); if (!dlogid || !*dlogid) { show_mcp_error(mfr, msg->mesgname, "Missing dialog ID."); return; } dat = gui_dlog_find(dlogid); if (!dat) { show_mcp_error(mfr, msg->mesgname, "Invalid dialog ID."); return; } if (!string_compare(msg->mesgname, "ctrl-value")) { int valcount = mcp_mesg_arg_linecount(msg, "value"); int i; const char **value = (const char **) malloc(sizeof(const char *) * valcount); if (!id || !*id) { show_mcp_error(mfr, msg->mesgname, "Missing control ID."); return; } for (i = 0; i < valcount; i++) { value[i] = mcp_mesg_arg_getline(msg, "value", i); } gui_value_set_local(dlogid, id, valcount, value); free((char **)value); } else if (!string_compare(msg->mesgname, "ctrl-event")) { const char *evt = mcp_mesg_arg_getline(msg, "event", 0); const char *dismissed = mcp_mesg_arg_getline(msg, "dismissed", 0); int did_dismiss = 1; if (!id || !*id) { show_mcp_error(mfr, msg->mesgname, "Missing control ID."); return; } if (!evt || !*evt) { evt = "buttonpress"; } if (NULL != dismissed) { if (!string_compare(dismissed, "false")) { did_dismiss = 0; } else if (!string_compare(dismissed, "0")) { did_dismiss = 0; } } if (did_dismiss) { dat->dismissed = 1; } if (dat->callback) { dat->callback(dat->descr, dlogid, id, evt, msg, did_dismiss, dat->context); } } else if (!string_compare(msg->mesgname, "error")) { const char *err = mcp_mesg_arg_getline(msg, "errcode", 0); const char *text = mcp_mesg_arg_getline(msg, "errtext", 0); const char *id = mcp_mesg_arg_getline(msg, "id", 0); if (!err) { err = ""; } if (!text) { text = ""; } if (dat->error_cb) { dat->error_cb(dat->descr, dlogid, id, err, text, dat->context); } } }
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; }
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); } } }
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); } } }