/* * IMC2 - an inter-mud communications protocol * * imc-config.c: configuration manipulation * * Copyright (C) 1996,1997 Oliver Jowett <oliver@jowett.manawatu.planet.co.nz> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING); if not, write to the * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /************************************************************** * Myth Mud improvements ALL by David Spink aka Morglum. * * This mud is NOT to be copied in whole or in part! No one * * has the permission to authorise the use of this code. * * In order to use this code you MUST comply with the terms * * and conditions in 'license.myth' (as shipped). * **************************************************************/ #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <unistd.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <fcntl.h> #include <errno.h> #include "imc.h" /* * I needed to split up imc.c (2600 lines and counting..) so this file now * contains: * * - config loading/saving (imc_readconfig, imc_saveconfig) * - ignores loading/saving (imc_readignores, imc_saveignores) * - config editing/displaying (imc_command) * - ignore editing/displaying (imc_ignore) */ /* USEIOCTL #defined if TIOCINQ or TIOCOUTQ are - we assume that the ioctls * work in that case. */ #if defined(TIOCINQ) && defined(TIOCOUTQ) #define USEIOCTL static int outqsize; #endif #define GETSTRING(key,var,len) \ else if (!strcasecmp(word,key)) { \ if (var[0]) imc_logstring("Warning: duplicate '" key "' lines"); \ imc_sncpy(var,value,len); \ } imc_siteinfo_struct imc_siteinfo; /* read config file */ int imc_readconfig(void) { FILE *cf; imc_info *i; char name[IMC_NAME_LENGTH], host[200]; char pw1[IMC_PW_LENGTH], pw2[IMC_PW_LENGTH]; unsigned short port; int count; char buf[1000]; char configfile[200]; int noforward, rcvstamp, flags; char word[1000]; short localport; char localname[IMC_NAME_LENGTH]; const char *value; int version=-1; unsigned long localip; char iname[200], ihost[200], iemail[200], iimail[200], iwww[200], idetails[1000], iflags[200]; localport=-1; localname[0]=iname[0]=ihost[0]=iemail[0]=iimail[0]=iwww[0]=idetails[0]= iflags[0]=0; localip=INADDR_ANY; imc_sncpy(configfile, imc_prefix, 193); strcat(configfile, "config"); imc_info_list=NULL; cf=fopen(configfile, "r"); if (!cf) { imc_logerror("imc_readconfig: couldn't open %s", configfile); return 0; } while(1) { if (fgets(buf, 1000, cf) == NULL) break; while (buf[0] && isspace(buf[strlen(buf)-1])) buf[strlen(buf)-1]=0; if (buf[0] == '#' || buf[0] == '\n' || !buf[0]) continue; value=imc_getarg(buf, word, 1000); if (!strcasecmp(word, "Version")) { imc_getarg(value, word, 1000); version=atoi(word); } else if (!strcasecmp(word, "Connection")) { imc_getarg(value, word, 1000); if (sscanf(value, "%[^:]:%[^:]:%hu:%[^:]:%[^:]:%d:%d:%n", name, host, &port, pw1, pw2, &rcvstamp, &noforward, &count)<7) { imc_logerror("Bad 'Connection' line: %s", buf); continue; } flags=imc_flagvalue(word + count, imc_connection_flags); i=imc_new_info(); i->name = imc_strdup(name); i->host = imc_strdup(host); i->clientpw = imc_strdup(pw1); i->serverpw = imc_strdup(pw2); i->port = port; i->rcvstamp = rcvstamp; i->noforward = noforward; i->flags = flags; } else if (!strcasecmp(word, "LocalPort")) { if (localport!=-1) imc_logstring("Warning: duplicate 'LocalPort' lines"); localport=atoi(value); } else if (!strcasecmp(word, "Bind")) { if (localip!=INADDR_ANY) imc_logstring("Warning: duplicate 'Bind' lines"); localip=inet_addr(value); } GETSTRING("LocalName", localname, 1000) GETSTRING("InfoName", iname, 200) GETSTRING("InfoHost", ihost, 200) GETSTRING("InfoEmail", iemail, 200) GETSTRING("InfoImail", iimail, 200) GETSTRING("InfoWWW", iwww, 200) GETSTRING("InfoFlags", iflags, 200) GETSTRING("InfoDetails", idetails, 1000) else if (imc_readconfighook(word, value)) ; else if (version==-1) { if (sscanf(buf, "%[^:]:%[^:]:%hu:%[^:]:%[^:]:%d:%d:%n", name, host, &port, pw1, pw2, &rcvstamp, &noforward, &count)<7) { imc_logerror("Bad config line: %s", buf); continue; } flags=imc_flagvalue(buf + count, imc_connection_flags); i=imc_new_info(); i->name = imc_strdup(name); i->host = imc_strdup(host); i->clientpw = imc_strdup(pw1); i->serverpw = imc_strdup(pw2); i->port = port; i->rcvstamp = rcvstamp; i->noforward = noforward; i->flags = flags; } else imc_logerror("Bad config line: %s", buf); } if (ferror(cf)) { imc_lerror("imc_readconfig"); fclose(cf); return 0; } fclose(cf); imc_siteinfo.name=imc_strdup(iname); imc_siteinfo.host=imc_strdup(ihost); imc_siteinfo.email=imc_strdup(iemail); imc_siteinfo.imail=imc_strdup(iimail); imc_siteinfo.www=imc_strdup(iwww); imc_siteinfo.details=imc_strdup(idetails); imc_siteinfo.flags=imc_strdup(iflags); if (!localname[0]) { imc_logstring("warning: missing 'LocalName' line in config"); imc_name=NULL; } else imc_name=imc_strdup(localname); if (localport==-1) { imc_logerror("warning: missing 'LocalPort' line in config"); imc_port=0; } else imc_port=localport; imc_bind=localip; if (!iname[0] || !iemail[0]) imc_logerror("InfoName and InfoEmail MUST be set to start IMC. See the IMC README"); return 1; } /* save the IMC config file */ int imc_saveconfig(void) { FILE *out; imc_info *i; char configfile[200]; if (imc_active == IA_NONE) return 0; imc_sncpy(configfile, imc_prefix, 193); strcat(configfile, "config"); out = fopen(configfile, "w"); if (!out) { imc_lerror("imc_saveconfig: error opening %s", configfile); return 0; } fprintf(out, "# Version <config_file_version>\n" "# LocalName <local_imc_name>\n" "# LocalPort <local_imc_port>\n" "# Connection Name:Host:Port:ClientPW:ServerPW:RcvStamp:NoForward:" "Flags\n"); fprintf(out, "Version 1\n"); if (imc_active >= IA_CONFIG2) { fprintf(out, "LocalName %s\n", imc_name); fprintf(out, "LocalPort %hu\n", imc_port); if (imc_bind!=htonl(INADDR_ANY)) { struct in_addr a; a.s_addr=imc_bind; fprintf(out, "Bind %s\n", inet_ntoa(a)); } } if (imc_siteinfo.name[0]) fprintf(out, "InfoName %s\n", imc_siteinfo.name); if (imc_siteinfo.host[0]) fprintf(out, "InfoHost %s\n", imc_siteinfo.host); if (imc_siteinfo.email[0]) fprintf(out, "InfoEmail %s\n", imc_siteinfo.email); if (imc_siteinfo.imail[0]) fprintf(out, "InfoImail %s\n", imc_siteinfo.imail); if (imc_siteinfo.www[0]) fprintf(out, "InfoWWW %s\n", imc_siteinfo.www); if (imc_siteinfo.details[0]) fprintf(out, "InfoDetails %s\n", imc_siteinfo.details); if (imc_siteinfo.flags[0]) fprintf(out, "InfoFlags %s\n", imc_siteinfo.flags); for (i=imc_info_list; i; i=i->next) fprintf(out, "Connection %s:%s:%hu:%s:%s:%d:%d:%s\n", i->name, i->host, i->port, i->clientpw, i->serverpw, i->rcvstamp, i->noforward, imc_flagname(i->flags, imc_connection_flags)); imc_saveconfighook(out); if (ferror(out)) { imc_lerror("imc_saveconfig: error saving %s", configfile); fclose(out); return 0; } fclose(out); return 1; } /* runtime changing of IMC config * returns >0 success * <0 error * ==0 unknown command * * commands: * reload * add <mudname> * delete <mudname> * rename <oldname> <newname> * set <mudname> <host|port|clientpw|serverpw|flags|noforward| * rcvstamp> <newvalue> * set <mudname> all <host> <port> <clientpw> <serverpw> <noforward> * <rcvstamp> <flags> * localname <name> * localport <port> */ int imc_command(const char *argument) { char arg1[IMC_DATA_LENGTH]; char arg2[IMC_DATA_LENGTH]; char arg3[IMC_DATA_LENGTH]; imc_info *i; argument=imc_getarg(argument, arg1, IMC_DATA_LENGTH); argument=imc_getarg(argument, arg2, IMC_DATA_LENGTH); if (imc_active==IA_NONE) { imc_qerror("IMC is not initialized"); return -1; } if (!strcasecmp(arg1, "reload")) { /* reload config file - shut down and restart */ char *temp; if (imc_lock) { imc_qerror("Reloading the config from within IMC is a Bad Thing <tm>"); return -1; } temp=imc_strdup(imc_prefix); /* imc_prefix gets freed, so keep a copy */ imc_shutdown(); imc_startup(temp); imc_strfree(temp); return 1; } if (!arg1[0] || !arg2[0]) return 0; if (!strcasecmp(arg1, "add")) { if (imc_name && !strcasecmp(arg2, imc_name)) { imc_qerror("%s has been specified as the local mud name. Use 'imc add'" "to add connections to _other_ muds", imc_name); return -1; } if (imc_getinfo(arg2)!=NULL) { imc_qerror("A mud by that name is already configured"); return -1; } i=imc_new_info(); i->name = imc_strdup(arg2); i->host = imc_strdup(""); i->clientpw = imc_strdup(""); i->serverpw = imc_strdup(""); return 1; } else if (!strcasecmp(arg1, "delete")) { i=imc_getinfo(arg2); if (!i) { imc_qerror("Entry not found"); return -1; } imc_delete_info(i); imc_saveconfig(); return 1; } else if (!strcasecmp(arg1, "rename")) { i=imc_getinfo(arg2); if (!i) { imc_qerror("Entry not found"); return -1; } if (i->connection) imc_disconnect(i->name); argument=imc_getarg(argument, arg3, IMC_DATA_LENGTH); if (!arg3[0]) return 0; imc_strfree(i->name); i->name = imc_strdup(arg3); imc_saveconfig(); return 1; } else if (!strcasecmp(arg1, "set")) { i=imc_getinfo(arg2); if (!i) { imc_qerror("Entry not found"); return -1; } argument=imc_getarg(argument, arg3, IMC_DATA_LENGTH); if (!arg3[0] || !argument[0]) return 0; else if (!strcasecmp(arg3, "all")) { if (i->host) imc_strfree(i->host); if (i->clientpw) imc_strfree(i->clientpw); if (i->serverpw) imc_strfree(i->serverpw); argument=imc_getarg(argument, arg3, IMC_DATA_LENGTH); i->host=imc_strdup(arg3); argument=imc_getarg(argument, arg3, IMC_DATA_LENGTH); i->port=strtoul(arg3, NULL, 10); argument=imc_getarg(argument, arg3, IMC_PW_LENGTH); i->clientpw=imc_strdup(arg3); argument=imc_getarg(argument, arg3, IMC_PW_LENGTH); i->serverpw=imc_strdup(arg3); argument=imc_getarg(argument, arg3, IMC_DATA_LENGTH); i->rcvstamp=strtoul(arg3, NULL, 10); argument=imc_getarg(argument, arg3, IMC_DATA_LENGTH); i->noforward=strtoul(arg3, NULL, 10); argument=imc_getarg(argument, arg3, IMC_DATA_LENGTH); i->flags=imc_flagvalue(arg3, imc_connection_flags); imc_saveconfig(); return 1; } else if (!strcasecmp(arg3, "host")) { if (i->host) imc_strfree(i->host); i->host=imc_strdup(argument); imc_saveconfig(); return 1; } else if (!strcasecmp(arg3, "port")) { i->port=strtoul(argument, NULL, 10); imc_saveconfig(); return 1; } else if (!strcasecmp(arg3, "clientpw")) { if (i->clientpw) imc_strfree(i->clientpw); i->clientpw=imc_strdup(argument); imc_saveconfig(); return 1; } else if (!strcasecmp(arg3, "serverpw")) { if (i->serverpw) imc_strfree(i->serverpw); i->serverpw=imc_strdup(argument); imc_saveconfig(); return 1; } else if (!strcasecmp(arg3, "rcvstamp")) { i->rcvstamp=strtoul(argument, NULL, 10); imc_saveconfig(); return 1; } else if (!strcasecmp(arg3, "noforward")) { i->noforward=strtoul(argument, NULL, 10); imc_saveconfig(); return 1; } else if (!strcasecmp(arg3, "flags")) { i->flags=imc_flagvalue(argument, imc_connection_flags); imc_saveconfig(); return 1; } return 0; } else if (!strcasecmp(arg1, "localname")) { if (imc_lock) { imc_qerror("Changing localname from within IMC is a Bad Thing <tm>"); return -1; } /* shut down IMC, change name, and restart */ if (imc_active >= IA_UP) imc_shutdown_network(); if (imc_name) imc_strfree(imc_name); imc_name=imc_strdup(arg2); imc_active=IA_CONFIG2; imc_startup_network(); imc_saveconfig(); return 1; } else if (!strcasecmp(arg1, "localport")) { int p=atoi(arg2); if ((p<1024 || p>65535) && p!=0) { imc_qerror("Port number must be 0 or 1024..65535"); return -1; } if (imc_active >= IA_LISTENING) imc_shutdown_port(); imc_port=p; if (imc_active == IA_UP && imc_port) imc_startup_port(); imc_saveconfig(); return 1; } else if (!strcasecmp(arg1, "info")) { if (!strcasecmp(arg2, "name")) { imc_strfree(imc_siteinfo.name); imc_siteinfo.name=imc_strdup(argument); if (imc_active == IA_CONFIG2) imc_startup_network(); } else if (!strcasecmp(arg2, "host")) { imc_strfree(imc_siteinfo.host); imc_siteinfo.host=imc_strdup(argument); } else if (!strcasecmp(arg2, "email")) { imc_strfree(imc_siteinfo.email); imc_siteinfo.email=imc_strdup(argument); if (imc_active == IA_CONFIG2) imc_startup_network(); } else if (!strcasecmp(arg2, "imail")) { imc_strfree(imc_siteinfo.imail); imc_siteinfo.imail=imc_strdup(argument); } else if (!strcasecmp(arg2, "www")) { imc_strfree(imc_siteinfo.www); imc_siteinfo.www=imc_strdup(argument); } else if (!strcasecmp(arg2, "details")) { imc_strfree(imc_siteinfo.details); imc_siteinfo.details=imc_strdup(argument); } else if (!strcasecmp(arg2, "flags")) { imc_strfree(imc_siteinfo.flags); imc_siteinfo.flags=imc_strdup(argument); } else return 0; imc_saveconfig(); return 1; } return 0; } /* read an IMC rignores file */ int imc_readignores(void) { FILE *inf; char buf[1000]; char name[200]; char arg[IMC_NAME_LENGTH]; int type; int count; imc_sncpy(name, imc_prefix, 191); strcat(name, "rignores"); inf=fopen(name, "r"); if (!inf) { imc_logerror("imc_readignores: couldn't open %s", name); return 0; } while (!ferror(inf) && !feof(inf)) { if (fgets(buf, 1000, inf) == NULL) break; if (buf[0] == '#' || buf[0] == '\n') continue; sscanf(buf, "%[^ \n]%n", arg, &count); type=imc_statevalue(buf+count, imc_ignore_types); imc_addignore(arg, type); /* add the entry */ } if (ferror(inf)) { imc_lerror("imc_readignores"); fclose(inf); return 0; } fclose(inf); return 1; } /* save the current rignore list */ int imc_saveignores(void) { FILE *out; char name[200]; imc_ignore_data *ign; imc_sncpy(name, imc_prefix, 191); strcat(name, "rignores"); out = fopen(name, "w"); if (!out) { imc_lerror("imc_saveignores: error opening %s", name); return 0; } fprintf(out, "# IMC rignores file, one name per line, no leading spaces\n" "# types: ignore, notrust, trust\n" "# lines starting with '#' are discarded\n"); for (ign=imc_ignore_list; ign; ign=ign->next) fprintf(out, "%s%s%s %s\n", (ign->match & IMC_IGNORE_PREFIX) ? "*" : "", ign->name, (ign->match & IMC_IGNORE_SUFFIX) ? "*" : "", imc_statename(ign->type, imc_ignore_types)); if (ferror(out)) { imc_lerror("imc_saveignores: error saving %s", name); fclose(out); return 0; } fclose(out); return 1; } imc_ignore_data *imc_newignore(void) { imc_ignore_data *ign; ign=imc_malloc(sizeof(*ign)); ign->name=NULL; ign->match=IMC_IGNORE_EXACT; ign->type=-1; ign->next=imc_ignore_list; imc_ignore_list=ign; return ign; } void imc_freeignore(imc_ignore_data *ign) { if (ign->name) imc_strfree(ign->name); imc_free(ign, sizeof(*ign)); } int imc_delignore(const char *what) { imc_ignore_data *ign, *last; char *who; char buf[IMC_DATA_LENGTH]; int match=0; strcpy(buf, what); who=buf; if (who[0]=='*') { who++; match|=IMC_IGNORE_PREFIX; } if (who[0] && who[strlen(who)-1]=='*') { who[strlen(who)-1]=0; match|=IMC_IGNORE_SUFFIX; } for (last=NULL, ign=imc_ignore_list; ign; last=ign, ign=ign->next) if (match==ign->match && !strcasecmp(who, ign->name)) { if (!last) imc_ignore_list=ign->next; else last->next=ign->next; imc_freeignore(ign); return 1; } return 0; } void imc_addignore(const char *what, int type) { imc_ignore_data *ign; char buf[IMC_DATA_LENGTH]; char *who; int match=0; ign=imc_newignore(); ign->type=type; strcpy(buf, what); who=buf; if (who[0]=='*') { match |= IMC_IGNORE_PREFIX; who++; } if (who[0] && who[strlen(who)-1]=='*') { who[strlen(who)-1]=0; match |= IMC_IGNORE_SUFFIX; } ign->match=match; ign->name=imc_strdup(who); } /* add/remove/list rignores */ const char *imc_ignore(const char *what) { int count; imc_ignore_data *ign; char arg[IMC_NAME_LENGTH]; int type; what=imc_getarg(what, arg, IMC_NAME_LENGTH); if (!arg[0]) { char *buf=imc_getsbuf(IMC_DATA_LENGTH); strcpy(buf, "Current entries:\n\r"); for (count=0, ign=imc_ignore_list; ign; ign=ign->next, count++) sprintf(buf + strlen(buf), " %10s %s%s%s\n\r", imc_statename(ign->type, imc_ignore_types), (ign->match & IMC_IGNORE_PREFIX) ? "*" : "", ign->name, (ign->match & IMC_IGNORE_SUFFIX) ? "*" : ""); if (!count) strcat(buf, " none"); else sprintf(buf + strlen(buf), "[total %d]", count); imc_shrinksbuf(buf); return buf; } if (!what[0]) return "Must specify both action and name."; if (!strcasecmp(arg, "delete")) { if (imc_delignore(what)) { imc_saveignores(); return "Entry deleted."; } return "Entry not found."; } type=imc_statevalue(arg, imc_ignore_types); if (type<0) return "Unknown ignore type"; imc_addignore(what, type); imc_saveignores(); return "Entry added."; } /* check if needle is in haystack (case-insensitive) */ static int substr(const char *needle, const char *haystack) { int len=strlen(needle); if (!len) return 1; while ((haystack=strchr(haystack, *needle))!=NULL) if (!strncasecmp(haystack, needle, len)) return 1; return 0; } /* find ignore data on someone */ imc_ignore_data *imc_findignore(const char *who, int type) { imc_ignore_data *ign; int len; int wlen=strlen(who); for (ign=imc_ignore_list; ign; ign=ign->next) { if (type>=0 && type!=ign->type) continue; len=strlen(ign->name); switch (ign->match) { case 0: /* exact match */ if (!strcasecmp(ign->name, who)) return ign; break; case IMC_IGNORE_SUFFIX: /* abcd* */ if (!strncasecmp(ign->name, who, len)) return ign; break; case IMC_IGNORE_PREFIX: /* *abcd */ wlen=strlen(who); if (wlen>=len && !strncasecmp(ign->name, who+wlen-len, len)) return ign; break; case IMC_IGNORE_PREFIX|IMC_IGNORE_SUFFIX: /* *abcd* */ if (substr(ign->name, who)) return ign; break; } } return NULL; } /* check if a packet from a given source should be ignored */ int imc_isignored(const char *who) { return (imc_findignore(who, IMC_IGNORE)!=NULL); } /* show current IMC socket states */ const char *imc_sockets(void) { imc_connect *c; char *buf=imc_getsbuf(IMC_DATA_LENGTH); char *state; int r, s; if (imc_active<IA_UP) return "IMC is not active.\n\r"; sprintf(buf, "%4s %-9s %-15s %-11s %-11s %-3s %-3s\n\r", "Desc", "Mud", "State", "Inbuf", "Outbuf", "Sp1", "Sp2"); for (c=imc_connect_list; c; c=c->next) { switch (c->state) { case IMC_CLOSED: state = "closed"; break; case IMC_CONNECTING: state = "connecting"; break; case IMC_WAIT1: state = "wait1"; break; case IMC_WAIT2: state = "wait2"; break; case IMC_CONNECTED: state = "connected"; break; default: state = "unknown"; break; } #ifdef USEIOCTL /* try to work out the system buffer sizes */ r=0; ioctl(c->desc, TIOCINQ, &r); r += strlen(c->inbuf); s=outqsize; if (s) { ioctl(c->desc, TIOCOUTQ, &s); s=outqsize-s; } s += strlen(c->outbuf); #else r=strlen(c->inbuf); s=strlen(c->outbuf); #endif sprintf(buf+strlen(buf), "%4d %-9s %-15s %5d/%-5d %5d/%-5d %3d %3d\n\r", c->desc, c->info ? c->info->name : "unknown", state, r, c->insize, s, c->outsize, c->spamcounter1, c->spamcounter2); } imc_shrinksbuf(buf); return buf; } /* list current connections/known muds * level=0 is mortal-level access (mudnames and connection states) * level=1 is imm-level access (names, hosts, ports, states) * level=2 is full access (names, hosts, ports, passwords, flags, states) * level=3 is all known muds on IMC, and no direct connection status * level=4 is IMC local config info (mortal-safe) * level=5 is IMC local config info */ const char *imc_list(int level) { imc_info *i; char *buf=imc_getsbuf(IMC_DATA_LENGTH); char *state; imc_reminfo *p; if (level<=2) { strcpy(buf, "Direct connections:\n\r"); switch (level) { case 0: sprintf(buf + strlen(buf), "%-10s %-15s %-8s", "Name", "State", "LastConn"); break; case 1: sprintf(buf + strlen(buf), "%-10s %-30s %5s %-13s %-8s", "Name", "Host", "Port", "State", "LastConn"); break; case 2: sprintf(buf + strlen(buf), "%-8s %-25s %5s %-13s %-10s %-10s\n" " %-8s %-9s %-5s %-5s %-8s %s", "Name", "Host", "Port", "State", "ClientPW", "ServerPW", "RcvStamp", "NoForward", "Timer", "TimeD", "LastConn", "Flags"); break; } for (i=imc_info_list; i; i=i->next) { char lastconn[20]; state = i->connection ? "connected" : "not connected"; if (i->connection) lastconn[0]=0; else if (!i->last_connected) strcpy(lastconn, "never"); else { long diff=(long)imc_now - (long)i->last_connected; sprintf(lastconn, "%5ld:%02ld", diff/3600, (diff/60) % 60); } switch (level) { case 0: sprintf(buf + strlen(buf), "\n\r%-10s %-15s %8s", i->name, state, lastconn); break; case 1: sprintf(buf + strlen(buf), "\n\r%-10s %-30s %5hu %-13s %8s", i->name, i->host, i->port, state, lastconn); break; case 2: sprintf(buf + strlen(buf), "\n\r%-8s %-25s %5hu %-13s %-10s %-10s" "\n\r %-8d %-9d %-5d %-5ld %8s %s", i->name, i->host, i->port, state, i->clientpw, i->serverpw, i->rcvstamp, i->noforward, imc_next_event(ev_reconnect, i), i->timer_duration, lastconn, imc_flagname(i->flags, imc_connection_flags)); break; } } imc_shrinksbuf(buf); return buf; } if (level==3 || level==6) { strcpy(buf, "Active muds on IMC:\n\r"); if (imc_is_router) sprintf(buf + strlen(buf), "%-10s %-10s %-9s %-20s %-10s", "Name", "Last alive", "Ping time", "IMC Version", "Route"); else sprintf(buf + strlen(buf), "%-10s %-10s %-20s %-10s", "Name", "Last alive", "IMC Version", "Route"); for (p=imc_reminfo_list; p; p=p->next) { if (p->hide && level==3) continue; if (imc_is_router) if (p->ping) sprintf(buf + strlen(buf), "\n\r%-10s %9ds %7dms %-20s %-10s %s", p->name, (int) (imc_now - p->alive), p->ping, p->version, p->route ? p->route : "broadcast", p->type ? "expired" : ""); else sprintf(buf + strlen(buf), "\n\r%-10s %9ds %9s %-20s %-10s %s", p->name, (int) (imc_now - p->alive), "unknown", p->version, p->route ? p->route : "broadcast", p->type ? "expired" : ""); else sprintf(buf + strlen(buf), "\n\r%-10s %9ds %-20s %-10s %s", p->name, (int) (imc_now - p->alive), p->version, p->route ? p->route : "broadcast", p->type ? "expired" : ""); } imc_shrinksbuf(buf); return buf; } if (level==4) { sprintf(buf, "Local IMC configuration:\n\r" " IMC name: %s\n\r" " IMC version: %s\n\r" " IMC state: %s", imc_name ? imc_name : "not set", IMC_VERSIONID, (imc_active>=IA_UP) ? "active" : "not active"); imc_shrinksbuf(buf); return buf; } if (level==5) { sprintf(buf, "Local IMC configuration:\n\r" " IMC name: %s\n\r" " IMC port: %hu\n\r" " IMC version: %s\n\r" " IMC state: %s\n\r" "Site information:\n\r" " Full name: %s\n\r" " Host/port: %s\n\r" " Email: %s\n\r" " IMC mail: %s\n\r" " Webpage: %s\n\r" " Details: %s\n\r" " Flags: %s\n\r", (imc_active>=IA_CONFIG2) ? imc_name : "not set", imc_port, IMC_VERSIONID, imc_statename(imc_active, imc_active_names), imc_siteinfo.name, imc_siteinfo.host, imc_siteinfo.email, imc_siteinfo.imail, imc_siteinfo.www, imc_siteinfo.details, imc_siteinfo.flags); imc_shrinksbuf(buf); return buf; } imc_shrinksbuf(buf); return "Bad invocaton of imc_list."; } /* get some IMC stats, return a string describing them */ const char *imc_getstats(void) { char *buf=imc_getsbuf(300); int evcount; imc_event *ev; for (evcount=0, ev=imc_event_list; ev; ev=ev->next, evcount++) ; sprintf(buf, "IMC statistics\n\r" "\n\r" "Received packets: %ld\n\r" "Received bytes: %ld (%ld/second)\n\r" "Transmitted packets: %ld\n\r" "Transmitted bytes: %ld (%ld/second)\n\r" "Maximum packet size: %d\n\r" "Pending events: %d\n\r" "Sequence drops: %d\n\r", imc_stats.rx_pkts, imc_stats.rx_bytes, imc_stats.rx_bytes / ((imc_now - imc_stats.start) ? (imc_now - imc_stats.start) : 1), imc_stats.tx_pkts, imc_stats.tx_bytes, imc_stats.tx_bytes / ((imc_now - imc_stats.start) ? (imc_now - imc_stats.start) : 1), imc_stats.max_pkt, evcount, imc_stats.sequence_drops); imc_shrinksbuf(buf); return buf; }