コード例 #1
0
ファイル: sexpots.c プロジェクト: K6BSD/SBBSUnstable
char* iniGetExistingWord(str_list_t list, const char* section, const char* key
					,const char* deflt, char* value)
{
	char* p;

	if((p=iniGetExistingString(list, section, key, deflt, value)) !=NULL) {
		FIND_WHITESPACE(value);
		*value=0;
	}
	return p;
}
コード例 #2
0
ファイル: sdp_utils.c プロジェクト: Wafflespeanut/gecko-dev
/*
 * sdp_debug_msg_filter
 *
 * DESCRIPTION
 *     Check the passed message buffer for sensitive data that should
 *     not be output (such as SRTP Master Key/Salt). Sensitive data
 *     will be replaced with the '*' character(s).
 *
 * PARAMETERS
 *     buffer: pointer to the message buffer to filter.
 *
 *     length_bytes: size of message buffer in bytes.
 *
 * RETURN VALUE
 *     The buffer modified.
 */
char * sdp_debug_msg_filter (char *buffer, ulong length_bytes)
{
    char *current;
    char *last = buffer + length_bytes;
    int result;

    SDP_PRINT("\n%s:%d: Eliding sensitive data from debug output",
            __FILE__, __LINE__);
    /*
     * For SRTP Master Key/Salt has the form:
     * X-crypto:<crypto_suite_name> inline:<master_key_salt>||
     * Where <master_key_salt> is the data to elide (filter).
     */
    for (current=buffer;
         current<=last-MIN_CRYPTO_STRING_SIZE_BYTES;
         current++) {
        if ((*current == 'x') || (*current == 'X')) {
            result = cpr_strncasecmp(current, crypto_string, crypto_strlen);
            if (!result) {
                current += crypto_strlen;
                if (current > last) break;

                /* Skip over crypto suite name */
                FIND_WHITESPACE(current, last);

                /* Skip over whitespace */
                SKIP_WHITESPACE(current, last);

                /* identify inline keyword */
                result = cpr_strncasecmp(current, inline_string, inline_strlen);
                if (!result) {
                    current += inline_strlen;
                    if (current > last) break;

                    /* Hide sensitive key/salt data */
                    while (current<=last) {
                        if (*current == '|' || *current == '\n') {
                            /* Done */
                            break;
                        } else {
                            *current = '*';
                            current++;
                        }
                    }
                }
            }
        }
    }

    return buffer;
}
コード例 #3
0
ファイル: netwrap.c プロジェクト: K6BSD/SBBSUnstable
str_list_t DLLCALL getNameServerList(void)
{
#ifdef __unix__	/* Look up DNS server address */
	FILE*	fp;
	char*	p;
	char	str[128];
	str_list_t	list;

	if((list=strListInit())==NULL)
		return(NULL);
	if((fp=fopen("/etc/resolv.conf","r"))!=NULL) {
		while(!feof(fp)) {
			if(fgets(str,sizeof(str),fp)==NULL)
				break;
			truncsp(str);
			p=str;
			SKIP_WHITESPACE(p);
			if(strnicmp(p,"nameserver",10)!=0) /* no match */
				continue;
			FIND_WHITESPACE(p);	/* skip "nameserver" */
			SKIP_WHITESPACE(p);	/* skip more white-space */
			strListPush(&list,p);
		}
		fclose(fp);
	}
	return(list);

#elif defined(_WIN32)
	FIXED_INFO* FixedInfo=NULL;
	ULONG    	FixedInfoLen=0;
	IP_ADDR_STRING* ip;
	str_list_t	list;

	if((list=strListInit())==NULL)
		return(NULL);
	if(GetNetworkParams(FixedInfo,&FixedInfoLen) == ERROR_BUFFER_OVERFLOW) {
        FixedInfo=(FIXED_INFO*)malloc(FixedInfoLen);
		if(GetNetworkParams(FixedInfo,&FixedInfoLen) == ERROR_SUCCESS) {
			ip=&FixedInfo->DnsServerList;
			for(; ip!=NULL; ip=ip->Next)
				strListPush(&list,ip->IpAddress.String);
		}
        if(FixedInfo!=NULL)
            free(FixedInfo);
    }
	return(list);
#else
	#error "Need a get_nameserver() implementation for this platform"
#endif
}
コード例 #4
0
ファイル: sdp_utils.c プロジェクト: Wafflespeanut/gecko-dev
/* Function:    sdp_crypto_debug
 * Description: Check the passed buffer for sensitive data that should
 *		not be output (such as SRTP Master Key/Salt) and output
 *		the buffer as debug. Sensitive data will be replaced
 *		with the '*' character(s). This function may be used
 *		to display very large buffers so this function ensures
 *		that buginf is not overloaded.
 * Parameters:  buffer		pointer to the message buffer to filter.
 *              length_bytes	size of message buffer in bytes.
 * Returns:     Nothing.
 */
void sdp_crypto_debug (char *buffer, ulong length_bytes)
{
    char *current, *start;
    char *last = buffer + length_bytes;
    int result;

    /*
     * For SRTP Master Key/Salt has the form:
     * X-crypto:<crypto_suite_name> inline:<master_key_salt>||
     * Where <master_key_salt> is the data to elide (filter).
     */
    for (start=current=buffer;
         current<=last-MIN_CRYPTO_STRING_SIZE_BYTES;
         current++) {
        if ((*current == 'x') || (*current == 'X')) {
            result = cpr_strncasecmp(current, crypto_string, crypto_strlen);
            if (!result) {
                current += crypto_strlen;
                if (current > last) break;

                /* Skip over crypto suite name */
                FIND_WHITESPACE(current, last);

                /* Skip over whitespace */
                SKIP_WHITESPACE(current, last);

                /* identify inline keyword */
                result = cpr_strncasecmp(current, inline_string, inline_strlen);
                if (!result) {
                    int star_count = 0;

                    current += inline_strlen;
                    if (current > last) break;

                    sdp_dump_buffer(start, current - start);

                    /* Hide sensitive key/salt data */
                    while (current<=last) {
                        if (*current == '|' || *current == '\n') {
                            /* Done, print the stars */
                            while (star_count > star_strlen) {
                                /*
                                 * This code is only for the case where
                                 * too much base64 data was supplied
                                 */
                                sdp_dump_buffer((char*)star_string, star_strlen);
                                star_count -= star_strlen;
                            }
                            sdp_dump_buffer((char*)star_string, star_count);
                            break;
                        } else {
                            star_count++;
                            current++;
                        }
                    }
                    /* Update start pointer */
                    start=current;
                }
            }
        }
    }

    if (last > start) {
        /* Display remainder of buffer */
        sdp_dump_buffer(start, last - start);
    }
}
コード例 #5
0
ファイル: answer.cpp プロジェクト: K6BSD/SBBSUnstable
bool sbbs_t::answer()
{
	char	str[MAX_PATH+1],str2[MAX_PATH+1],c;
	char 	tmp[(MAX_PATH > CRYPT_MAX_TEXTSIZE ? MAX_PATH:CRYPT_MAX_TEXTSIZE)+1];
	char 	tmpname[CRYPT_MAX_TEXTSIZE+1];
	char 	path[MAX_PATH+1];
	int		i,l,in;
	struct tm tm;

	useron.number=0;
	answertime=logontime=starttime=now=time(NULL);
	/* Caller ID is IP address */
	SAFECOPY(cid,client_ipaddr);

	memset(&tm,0,sizeof(tm));
    localtime_r(&now,&tm); 

	safe_snprintf(str,sizeof(str),"%s  %s %s %02d %u            Node %3u"
		,hhmmtostr(&cfg,&tm,str2)
		,wday[tm.tm_wday]
        ,mon[tm.tm_mon],tm.tm_mday,tm.tm_year+1900,cfg.node_num);
	logline("@ ",str);

	safe_snprintf(str,sizeof(str),"%s  %s [%s]", connection, client_name, cid);
	logline("@+:",str);

	if(client_ident[0]) {
		safe_snprintf(str,sizeof(str),"Identity: %s",client_ident);
		logline("@*",str);
	}

	online=ON_REMOTE;

	if(sys_status&SS_RLOGIN) {
		if(incom(1000)==0) {
			for(i=0;i<(int)sizeof(str)-1;i++) {
				in=incom(1000);
				if(in==0 || in==NOINP)
					break;
				str[i]=in;
			}
			str[i]=0;
			for(i=0;i<(int)sizeof(str2)-1;i++) {
				in=incom(1000);
				if(in==0 || in==NOINP)
					break;
				str2[i]=in;
			}
			str2[i]=0;
			for(i=0;i<(int)sizeof(terminal)-1;i++) {
				in=incom(1000);
				if(in==0 || in==NOINP)
					break;
				terminal[i]=in;
			}
			terminal[i]=0;
			lprintf(LOG_DEBUG,"Node %d RLogin: '******' / '%.*s' / '%s'"
				,cfg.node_num
				,LEN_ALIAS*2,str
				,LEN_ALIAS*2,str2
				,terminal);
			SAFECOPY(rlogin_term, terminal);
			SAFECOPY(rlogin_name, str2);
			SAFECOPY(rlogin_pass, str);
			/* Truncate terminal speed (e.g. "/57600") from terminal-type string 
			   (but keep full terminal type/speed string in rlogin_term): */
			truncstr(terminal,"/");	
			useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, rlogin_name);
			if(useron.number) {
				getuserdat(&cfg,&useron);
				useron.misc&=~TERM_FLAGS;
				SAFEPRINTF(path,"%srlogin.cfg",cfg.ctrl_dir);
				if(!findstr(client.addr,path)) {
					SAFECOPY(tmp, rlogin_pass);
					for(i=0;i<3;i++) {
						if(stricmp(tmp,useron.pass)) {
							badlogin(useron.alias, tmp);
							rioctl(IOFI);       /* flush input buffer */
							bputs(text[InvalidLogon]);
							if(cfg.sys_misc&SM_ECHO_PW)
								safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt: '%s'"
									,0,useron.alias,tmp);
							else
								safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt"
									,0,useron.alias);
							logline(LOG_NOTICE,"+!",str);
							bputs(text[PasswordPrompt]);
							console|=CON_R_ECHOX;
							getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB);
							console&=~(CON_R_ECHOX|CON_L_ECHOX);
						}
						else {
							if(REALSYSOP) {
								rioctl(IOFI);       /* flush input buffer */
								if(!chksyspass())
									bputs(text[InvalidLogon]);
								else {
									i=0;
									break;
								}
							}
							else
								break;
						}
					}
					if(i) {
						if(stricmp(tmp,useron.pass)) {
							badlogin(useron.alias, tmp);
							bputs(text[InvalidLogon]);
							if(cfg.sys_misc&SM_ECHO_PW)
								safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt: '%s'"
									,0,useron.alias,tmp);
							else
								safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt"
									,0,useron.alias);
							logline(LOG_NOTICE,"+!",str);
						}
						lprintf(LOG_WARNING,"Node %d !CLIENT IP NOT LISTED in %s"
							,cfg.node_num,path);
						useron.number=0;
						hangup();
					}
				}
			}
			else
				lprintf(LOG_INFO,"Node %d RLogin: Unknown user: %s",cfg.node_num,rlogin_name);
		}
		if(rlogin_name[0]==0) {
			lprintf(LOG_NOTICE,"Node %d !RLogin: No user name received",cfg.node_num);
			sys_status&=~SS_RLOGIN;
		}
	}

	if(!(telnet_mode&TELNET_MODE_OFF)) {
		/* Disable Telnet Terminal Echo */
		request_telnet_opt(TELNET_WILL,TELNET_ECHO);
		/* Will suppress Go Ahead */
		request_telnet_opt(TELNET_WILL,TELNET_SUP_GA);
		/* Retrieve terminal type and speed from telnet client --RS */
		request_telnet_opt(TELNET_DO,TELNET_TERM_TYPE);
		request_telnet_opt(TELNET_DO,TELNET_TERM_SPEED);
		request_telnet_opt(TELNET_DO,TELNET_SEND_LOCATION);
		request_telnet_opt(TELNET_DO,TELNET_NEGOTIATE_WINDOW_SIZE);
		request_telnet_opt(TELNET_DO,TELNET_NEW_ENVIRON);
	}
#ifdef USE_CRYPTLIB
	if(sys_status&SS_SSH) {
		pthread_mutex_lock(&ssh_mutex);
		cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_USERNAME, tmpname, &i);
		tmpname[i]=0;
		SAFECOPY(rlogin_name, tmpname);
		cryptGetAttributeString(ssh_session, CRYPT_SESSINFO_PASSWORD, tmp, &i);
		tmp[i]=0;
		SAFECOPY(rlogin_pass, tmp);
		pthread_mutex_unlock(&ssh_mutex);
		lprintf(LOG_DEBUG,"Node %d SSH login: '******'"
			,cfg.node_num, tmpname);
		useron.number=userdatdupe(0, U_ALIAS, LEN_ALIAS, tmpname);
		if(useron.number) {
			getuserdat(&cfg,&useron);
			useron.misc&=~TERM_FLAGS;
			for(i=0;i<3;i++) {
				if(stricmp(tmp,useron.pass)) {
					badlogin(useron.alias, tmp);
					rioctl(IOFI);       /* flush input buffer */
					bputs(text[InvalidLogon]);
					if(cfg.sys_misc&SM_ECHO_PW)
						safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt: '%s'"
							,0,useron.alias,tmp);
					else
						safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt"
							,0,useron.alias);
					/* crash here Sept-12-2010
					   str	0x06b3fc4c "(0000)  Guest                      FAILED Password attempt: '*****@*****.**'"

					   and Oct-6-2010
					   str	0x070ffc4c "(0000)  Woot903                    FAILED Password attempt: 'p67890pppsdsjhsdfhhfhnhnfhfhfdhjksdjkfdskw3902391=`'"	char [261]
					*/
					logline(LOG_NOTICE,"+!",str);
					bputs(text[PasswordPrompt]);
					console|=CON_R_ECHOX;
					getstr(tmp,LEN_PASS*2,K_UPPER|K_LOWPRIO|K_TAB);
					console&=~(CON_R_ECHOX|CON_L_ECHOX);
				}
				else {
					if(REALSYSOP) {
						rioctl(IOFI);       /* flush input buffer */
						if(!chksyspass())
							bputs(text[InvalidLogon]);
						else {
							i=0;
							break;
						}
					}
					else
						break;
				}
			}
			if(i) {
				if(stricmp(tmp,useron.pass)) {
					badlogin(useron.alias, tmp);
					bputs(text[InvalidLogon]);
					if(cfg.sys_misc&SM_ECHO_PW)
						safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt: '%s'"
							,0,useron.alias,tmp);
					else
						safe_snprintf(str,sizeof(str),"(%04u)  %-25s  FAILED Password attempt"
							,0,useron.alias);
					logline(LOG_NOTICE,"+!",str);
				}
				useron.number=0;
				hangup();
			}
		}
		else
			lprintf(LOG_INFO,"Node %d SSH: Unknown user: %s",cfg.node_num,rlogin_name);
	}
#endif

	/* Detect terminal type */
    mswait(200);
	rioctl(IOFI);		/* flush input buffer */
	putcom( "\r\n"		/* locate cursor at column 1 */
			"\x1b[s"	/* save cursor position (necessary for HyperTerm auto-ANSI) */
    		"\x1b[255B"	/* locate cursor as far down as possible */
			"\x1b[255C"	/* locate cursor as far right as possible */
			"\b_"		/* need a printable at this location to actually move cursor */
			"\x1b[6n"	/* Get cursor position */
			"\x1b[u"	/* restore cursor position */
			"\x1b[!_"	/* RIP? */
			"\x1b[30;40m\xc2\x9f""Zuul.connection.write('\\x1b""Are you the gatekeeper?')\xc2\x9c"	/* ZuulTerm? */
			"\x1b[0m_"	/* "Normal" colors */
			"\x1b[2J"	/* clear screen */
			"\x1b[H"	/* home cursor */
			"\xC"		/* clear screen (in case not ANSI) */
			"\r"		/* Move cursor left (in case previous char printed) */
			);
	i=l=0;
	tos=1;
	lncntr=0;
	safe_snprintf(str, sizeof(str), "%s  %s", VERSION_NOTICE, COPYRIGHT_NOTICE);
	strip_ctrl(str, str);
	center(str);

	while(i++<50 && l<(int)sizeof(str)-1) { 	/* wait up to 5 seconds for response */
		c=incom(100)&0x7f;
		if(c==0)
			continue;
		i=0;
		if(l==0 && c!=ESC)	// response must begin with escape char
			continue;
		str[l++]=c;
		if(c=='R') {   /* break immediately if ANSI response */
			mswait(500);
			break; 
		}
	}

	while((c=(incom(100)&0x7f))!=0 && l<(int)sizeof(str)-1)
		str[l++]=c;
	str[l]=0;

    if(l) {
		c_escape_str(str,tmp,sizeof(tmp),TRUE);
		lprintf(LOG_DEBUG,"Node %d received terminal auto-detection response: '%s'"
			,cfg.node_num,tmp);
        if(str[0]==ESC && str[1]=='[' && str[l-1]=='R') {
			int	x,y;

			if(terminal[0]==0)
				SAFECOPY(terminal,"ANSI");
			autoterm|=(ANSI|COLOR);
			if(sscanf(str+2,"%u;%u",&y,&x)==2) {
				lprintf(LOG_DEBUG,"Node %d received ANSI cursor position report: %ux%u"
					,cfg.node_num, x, y);
				/* Sanity check the coordinates in the response: */
				if(x>=40 && x<=255) cols=x; 
				if(y>=10 && y<=255) rows=y;
			}
		}
		truncsp(str);
		if(strstr(str,"RIPSCRIP")) {
			if(terminal[0]==0)
				SAFECOPY(terminal,"RIP");
			logline("@R",strstr(str,"RIPSCRIP"));
			autoterm|=(RIP|COLOR|ANSI); }
		else if(strstr(str,"Are you the gatekeeper?"))  {
			if(terminal[0]==0)
				SAFECOPY(terminal,"HTML");
			logline("@H",strstr(str,"Are you the gatekeeper?"));
			autoterm|=HTML;
		} 
	}
	else if(terminal[0]==0)
		SAFECOPY(terminal,"DUMB");

	rioctl(IOFI); /* flush left-over or late response chars */

	if(!autoterm && str[0]) {
		c_escape_str(str,tmp,sizeof(tmp),TRUE);
		lprintf(LOG_NOTICE,"Node %d terminal auto-detection failed, response: '%s'"
			,cfg.node_num, tmp);
	}

	/* AutoLogon via IP or Caller ID here */
	if(!useron.number && !(sys_status&SS_RLOGIN)
		&& (startup->options&BBS_OPT_AUTO_LOGON) && cid[0]) {
		useron.number=userdatdupe(0, U_NOTE, LEN_NOTE, cid);
		if(useron.number) {
			getuserdat(&cfg, &useron);
			if(!(useron.misc&AUTOLOGON) || !(useron.exempt&FLAG('V')))
				useron.number=0;
		}
	}

	if(!online) 
		return(false); 

	if(stricmp(terminal,"sexpots")==0) {	/* dial-up connection (via SexPOTS) */
		SAFEPRINTF2(str,"%s connection detected at %lu bps", terminal, cur_rate);
		logline("@S",str);
		node_connection = (ushort)cur_rate;
		SAFEPRINTF(connection,"%lu",cur_rate);
		SAFECOPY(cid,"Unknown");
		SAFECOPY(client_name,"Unknown");
		if(telnet_location[0]) {			/* Caller-ID info provided */
			SAFEPRINTF(str, "CID: %s", telnet_location);
			logline("@*",str);
			SAFECOPY(cid,telnet_location);
			truncstr(cid," ");				/* Only include phone number in CID */
			char* p=telnet_location;
			FIND_WHITESPACE(p);
			SKIP_WHITESPACE(p);
			if(*p) {
				SAFECOPY(client_name,p);	/* CID name, if provided (maybe 'P' or 'O' if private or out-of-area) */
			}
		}
		SAFECOPY(client.addr,cid);
		SAFECOPY(client.host,client_name);
		client_on(client_socket,&client,TRUE /* update */);
	} else {
		if(telnet_location[0]) {			/* Telnet Location info provided */
			SAFEPRINTF(str, "Telnet Location: %s", telnet_location);
			logline("@*",str);
		}
	}


	useron.misc&=~TERM_FLAGS;
	useron.misc|=autoterm;
	SAFECOPY(useron.comp,client_name);

	if(!useron.number && rlogin_name[0]!=0 && !(cfg.sys_misc&SM_CLOSED) && !matchuser(&cfg, rlogin_name, /* Sysop alias: */FALSE)) {
		lprintf(LOG_INFO,"Node %d UNKNOWN %s-specified USERNAME: %s, starting new user signup",cfg.node_num,client.protocol,rlogin_name);
		bprintf("%s: %s\r\n", text[UNKNOWN_USER], rlogin_name);
		newuser();
	}

	if(!useron.number) {	/* manual/regular logon */

		/* Display ANSWER screen */
		rioctl(IOSM|PAUSE);
		sys_status|=SS_PAUSEON;
		SAFEPRINTF(str,"%sanswer",cfg.text_dir);
		SAFEPRINTF(path,"%s.rip",str);
		if((autoterm&RIP) && fexistcase(path))
			printfile(path,P_NOABORT);
		else {
			SAFEPRINTF(path,"%s.html",str);
			if((autoterm&HTML) && fexistcase(path))
				printfile(path,P_NOABORT);
			else {
				SAFEPRINTF(path,"%s.ans",str);
				if((autoterm&ANSI) && fexistcase(path))
					printfile(path,P_NOABORT);
				else {
					SAFEPRINTF(path,"%s.asc",str);
					if(fexistcase(path))
						printfile(path, P_NOABORT);
				}
			}
		}
		sys_status&=~SS_PAUSEON;
		exec_bin(cfg.login_mod,&main_csi);
	} else	/* auto logon here */
		if(logon()==false)
			return(false);


	if(!useron.number)
		hangup();

	/* Save the IP to the user's note */
	if(cid[0]) {
		SAFECOPY(useron.note,cid);
		putuserrec(&cfg,useron.number,U_NOTE,LEN_NOTE,useron.note);
	}

	/* Save host name to the user's computer description */
	if(client_name[0]) {
		SAFECOPY(useron.comp,client_name);
		putuserrec(&cfg,useron.number,U_COMP,LEN_COMP,useron.comp);
	}

	if(!online) 
		return(false); 

	if(!(sys_status&SS_USERON)) {
		errormsg(WHERE,ERR_CHK,"User not logged on",0);
		hangup();
		return(false); 
	}

	if(useron.pass[0])
		loginSuccess(startup->login_attempt_list, &client_addr);

	return(true);
}
コード例 #6
0
ファイル: scfgmsg.c プロジェクト: mattzorzin/synchronet
void msgs_cfg()
{
	static int dflt,msgs_dflt,bar;
	char	str[256],str2[256],done=0;
	char*	p;
	char*	tp;
    char	tmp[128];
	char	tmp_code[32];
	int		j,k,q,s;
	int		i,file,ptridx,n;
	unsigned total_subs;
	long	ported;
	sub_t	tmpsub;
	static grp_t savgrp;
	FILE*	stream;

while(1) {
	for(i=0;i<cfg.total_grps && i<MAX_OPTS;i++)
		sprintf(opt[i],"%-25s",cfg.grp[i]->lname);
	opt[i][0]=0;
	j=WIN_ORG|WIN_ACT|WIN_CHE;
	if(cfg.total_grps)
		j|=WIN_DEL|WIN_DELACT|WIN_GET;
	if(cfg.total_grps<MAX_OPTS)
		j|=WIN_INS|WIN_INSACT|WIN_XTR;
	if(savgrp.sname[0])
		j|=WIN_PUT;
	uifc.helpbuf=
		"`Message Groups:`\n"
		"\n"
		"This is a listing of message groups for your BBS. Message groups are\n"
		"used to logically separate your message `sub-boards` into groups. Every\n"
		"sub-board belongs to a message group. You must have at least one message\n"
		"group and one sub-board configured.\n"
		"\n"
		"One popular use for message groups is to separate local sub-boards and\n"
		"networked sub-boards. One might have a `Local` message group that contains\n"
		"non-networked sub-boards of various topics and also have a `FidoNet`\n"
		"message group that contains sub-boards that are echoed across FidoNet.\n"
		"Some sysops separate sub-boards into more specific areas such as `Main`,\n"
		"`Technical`, or `Adult`. If you have many sub-boards that have a common\n"
		"subject denominator, you may want to have a separate message group for\n"
		"those sub-boards for a more organized message structure.\n"
	;
	i=uifc.list(j,0,0,45,&msgs_dflt,&bar,"Message Groups",opt);
	if(i==-1) {
		j=save_changes(WIN_MID);
		if(j==-1)
		   continue;
		if(!j) {
			write_msgs_cfg(&cfg,backup_level);
            refresh_cfg(&cfg);
        }
		return;
    }
	if((i&MSK_ON)==MSK_INS) {
		i&=MSK_OFF;
		uifc.helpbuf=
			"`Group Long Name:`\n"
			"\n"
			"This is a description of the message group which is displayed when a\n"
			"user of the system uses the `/*` command from the main menu.\n"
		;
		strcpy(str,"Main");
		if(uifc.input(WIN_MID|WIN_SAV,0,0,"Group Long Name",str,LEN_GLNAME
			,K_EDIT)<1)
			continue;
		uifc.helpbuf=
			"`Group Short Name:`\n"
			"\n"
			"This is a short description of the message group which is used for the\n"
			"main menu and reading message prompts.\n"
		;
		sprintf(str2,"%.*s",LEN_GSNAME,str);
		if(uifc.input(WIN_MID,0,0,"Group Short Name",str2,LEN_GSNAME,K_EDIT)<1)
			continue;
		if((cfg.grp=(grp_t **)realloc(cfg.grp,sizeof(grp_t *)*(cfg.total_grps+1)))==NULL) {
            errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_grps+1);
			cfg.total_grps=0;
			bail(1);
            continue; 
		}

		if(cfg.total_grps) {	/* was cfg.total_subs (?) */
            for(j=cfg.total_grps;j>i;j--)   /* insert above */
                cfg.grp[j]=cfg.grp[j-1];
            for(j=0;j<cfg.total_subs;j++)   /* move sub group numbers */
                if(cfg.sub[j]->grp>=i)
                    cfg.sub[j]->grp++; 
		}

		if((cfg.grp[i]=(grp_t *)malloc(sizeof(grp_t)))==NULL) {
			errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(grp_t));
			continue; 
		}
		memset((grp_t *)cfg.grp[i],0,sizeof(grp_t));
		strcpy(cfg.grp[i]->lname,str);
		strcpy(cfg.grp[i]->sname,str2);
		cfg.total_grps++;
		uifc.changes=1;
		continue; 
	}
	if((i&MSK_ON)==MSK_DEL) {
		i&=MSK_OFF;
		uifc.helpbuf=
			"`Delete All Data in Group:`\n"
			"\n"
			"If you wish to delete the messages in all the sub-boards in this group,\n"
			"select `Yes`.\n"
		;
		j=1;
		strcpy(opt[0],"Yes");
		strcpy(opt[1],"No");
		opt[2][0]=0;
		j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0,"Delete All Data in Group",opt);
		if(j==-1)
			continue;
		if(j==0)
			for(j=0;j<cfg.total_subs;j++)
				if(cfg.sub[j]->grp==i) {
					sprintf(str,"%s%s.s*"
						,cfg.grp[cfg.sub[j]->grp]->code_prefix
						,cfg.sub[j]->code_suffix);
					strlwr(str);
					if(!cfg.sub[j]->data_dir[0])
						sprintf(tmp,"%ssubs/",cfg.data_dir);
					else
						strcpy(tmp,cfg.sub[j]->data_dir);
					delfiles(tmp,str);
					clearptrs(j); 
				}
		free(cfg.grp[i]);
		for(j=0;j<cfg.total_subs;) {
			if(cfg.sub[j]->grp==i) {	/* delete subs of this group */
				free(cfg.sub[j]);
				cfg.total_subs--;
				k=j;
				while(k<cfg.total_subs) {	/* move all subs down */
					cfg.sub[k]=cfg.sub[k+1];
					for(q=0;q<cfg.total_qhubs;q++)
						for(s=0;s<cfg.qhub[q]->subs;s++)
							if(cfg.qhub[q]->sub[s]==k)
								cfg.qhub[q]->sub[s]--;
					k++; 
				} 
			}
			else j++; 
		}
		for(j=0;j<cfg.total_subs;j++)	/* move sub group numbers down */
			if(cfg.sub[j]->grp>i)
				cfg.sub[j]->grp--;
		cfg.total_grps--;
		while(i<cfg.total_grps) {
			cfg.grp[i]=cfg.grp[i+1];
			i++; 
		}
		uifc.changes=1;
		continue; 
	}
	if((i&MSK_ON)==MSK_GET) {
		i&=MSK_OFF;
		savgrp=*cfg.grp[i];
		continue; 
	}
	if((i&MSK_ON)==MSK_PUT) {
		i&=MSK_OFF;
		*cfg.grp[i]=savgrp;
		uifc.changes=1;
		continue; 
	}
	done=0;
	while(!done) {
		j=0;
		sprintf(opt[j++],"%-27.27s%s","Long Name",cfg.grp[i]->lname);
		sprintf(opt[j++],"%-27.27s%s","Short Name",cfg.grp[i]->sname);
		sprintf(opt[j++],"%-27.27s%s","Internal Code Prefix",cfg.grp[i]->code_prefix);
		sprintf(opt[j++],"%-27.27s%.40s","Access Requirements"
			,cfg.grp[i]->arstr);
		strcpy(opt[j++],"Clone Options");
		strcpy(opt[j++],"Export Areas...");
		strcpy(opt[j++],"Import Areas...");
		strcpy(opt[j++],"Message Sub-boards...");
		opt[j][0]=0;
		sprintf(str,"%s Group",cfg.grp[i]->sname);
		uifc.helpbuf=
			"`Message Group Configuration:`\n"
			"\n"
			"This menu allows you to configure the security requirements for access\n"
			"to this message group. You can also add, delete, and configure the\n"
			"sub-boards of this group by selecting the `Messages Sub-boards...` option.\n"
		;
		switch(uifc.list(WIN_ACT,6,4,60,&dflt,0,str,opt)) {
			case -1:
				done=1;
				break;
			case 0:
				uifc.helpbuf=
					"`Group Long Name:`\n"
					"\n"
					"This is a description of the message group which is displayed when a\n"
					"user of the system uses the `/*` command from the main menu.\n"
				;
				strcpy(str,cfg.grp[i]->lname);	/* save incase setting to null */
				if(!uifc.input(WIN_MID|WIN_SAV,0,17,"Name to use for Listings"
					,cfg.grp[i]->lname,LEN_GLNAME,K_EDIT))
					strcpy(cfg.grp[i]->lname,str);
				break;
			case 1:
				uifc.helpbuf=
					"`Group Short Name:`\n"
					"\n"
					"This is a short description of the message group which is used for\n"
					"main menu and reading messages prompts.\n"
				;
				uifc.input(WIN_MID|WIN_SAV,0,17,"Name to use for Prompts"
					,cfg.grp[i]->sname,LEN_GSNAME,K_EDIT);
				break;
			case 2:
				uifc.helpbuf=
					"`Internal Code Prefix:`\n"
					"\n"
					"This is an `optional` code prefix used to help generate unique internal\n"
					"codes for the sub-boards in this message group. If this option\n"
					"is used, sub-board internal codes will be constructed from this prefix\n"
					"and the specified code suffix for each sub-board.\n"
				;
				uifc.input(WIN_MID|WIN_SAV,0,17,"Internal Code Prefix"
					,cfg.grp[i]->code_prefix,LEN_CODE,K_EDIT|K_UPPER);
				break;
			case 3:
				sprintf(str,"%s Group",cfg.grp[i]->sname);
				getar(str,cfg.grp[i]->arstr);
				break;
			case 4: 	/* Clone Options */
				j=0;
				strcpy(opt[0],"Yes");
				strcpy(opt[1],"No");
				opt[2][0]=0;
				uifc.helpbuf=
					"`Clone Sub-board Options:`\n"
					"\n"
					"If you want to clone the options of the first sub-board of this group\n"
					"into all sub-boards of this group, select `Yes`.\n"
					"\n"
					"The options cloned are posting requirements, reading requirements,\n"
					"operator requirments, moderated user requirments, toggle options,\n"
					"network options (including EchoMail origin line, EchoMail address,\n"
					"and QWK Network tagline), maximum number of messages, maximum number\n"
					"of CRCs, maximum age of messages, storage method, and data directory.\n"
				;
				j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0
					,"Clone Options of First Sub-board into All of Group",opt);
				if(j==0) {
					k=-1;
					for(j=0;j<cfg.total_subs;j++)
						if(cfg.sub[j]->grp==i) {
							if(k==-1)
								k=j;
							else {
								uifc.changes=1;
								cfg.sub[j]->misc=(cfg.sub[k]->misc|SUB_HDRMOD);
								strcpy(cfg.sub[j]->post_arstr,cfg.sub[k]->post_arstr);
								strcpy(cfg.sub[j]->read_arstr,cfg.sub[k]->read_arstr);
								strcpy(cfg.sub[j]->op_arstr,cfg.sub[k]->op_arstr);
								strcpy(cfg.sub[j]->mod_arstr,cfg.sub[k]->mod_arstr);
								strcpy(cfg.sub[j]->origline,cfg.sub[k]->origline);
								strcpy(cfg.sub[j]->tagline,cfg.sub[k]->tagline);
								strcpy(cfg.sub[j]->data_dir,cfg.sub[k]->data_dir);
								strcpy(cfg.sub[j]->post_sem,cfg.sub[k]->post_sem);
								cfg.sub[j]->maxmsgs=cfg.sub[k]->maxmsgs;
								cfg.sub[j]->maxcrcs=cfg.sub[k]->maxcrcs;
								cfg.sub[j]->maxage=cfg.sub[k]->maxage;

								cfg.sub[j]->faddr=cfg.sub[k]->faddr; 
							} 
						} 
				}
				break;
			case 5:
				k=0;
				ported=0;
				q=uifc.changes;
				strcpy(opt[k++],"SUBS.TXT    (Synchronet)");
				strcpy(opt[k++],"AREAS.BBS   (MSG)");
				strcpy(opt[k++],"AREAS.BBS   (SBBSecho)");
				strcpy(opt[k++],"FIDONET.NA  (Fido)");
				opt[k][0]=0;
				uifc.helpbuf=
					"`Export Area File Format:`\n"
					"\n"
					"This menu allows you to choose the format of the area file you wish to\n"
					"export the current message group into.\n"
				;
				k=0;
				k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
					,"Export Area File Format",opt);
				if(k==-1)
					break;
				if(k==0)
					sprintf(str,"%sSUBS.TXT",cfg.ctrl_dir);
				else if(k==1)
					sprintf(str,"AREAS.BBS");
				else if(k==2)
					sprintf(str,"%sAREAS.BBS",cfg.data_dir);
				else if(k==3)
					sprintf(str,"FIDONET.NA");
				if(k && k<3)
					if(uifc.input(WIN_MID|WIN_SAV,0,0,"Uplinks"
						,str2,sizeof(str2)-1,0)<=0) {
						uifc.changes=q;
						break; 
					}
				if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename"
					,str,sizeof(str)-1,K_EDIT)<=0) {
					uifc.changes=q;
					break; 
				}
				if(fexist(str)) {
					strcpy(opt[0],"Overwrite");
					strcpy(opt[1],"Append");
					opt[2][0]=0;
					j=0;
					j=uifc.list(WIN_MID|WIN_SAV,0,0,0,&j,0
						,"File Exists",opt);
					if(j==-1)
						break;
					if(j==0) j=O_WRONLY|O_TRUNC;
					else	 j=O_WRONLY|O_APPEND; 
				}
				else
					j=O_WRONLY|O_CREAT;
				if((stream=fnopen(&file,str,j))==NULL) {
					sprintf(str,"Open Failure: %d (%s)"
						,errno,strerror(errno));
					uifc.msg(str);
					uifc.changes=q;
					break; 
				}
				uifc.pop("Exporting Areas...");
				for(j=0;j<cfg.total_subs;j++) {
					if(cfg.sub[j]->grp!=i)
						continue;
					ported++;
					if(k==1) {		/* AREAS.BBS *.MSG */
						sprintf(str,"%s%s%s/"
							,cfg.echomail_dir
							,cfg.grp[cfg.sub[j]->grp]->code_prefix
							,cfg.sub[j]->code_suffix);
						fprintf(stream,"%-30s %-20s %s\r\n"
							,str,stou(cfg.sub[j]->sname),str2);
						continue; 
					}
					if(k==2) {		/* AREAS.BBS SBBSecho */
						fprintf(stream,"%s%-30s %-20s %s\r\n"
							,cfg.grp[cfg.sub[j]->grp]->code_prefix
							,cfg.sub[j]->code_suffix
							,stou(cfg.sub[j]->sname)
							,str2);
						continue; 
					}
					if(k==3) {		/* FIDONET.NA */
						fprintf(stream,"%-20s %s\r\n"
							,stou(cfg.sub[j]->sname),cfg.sub[j]->lname);
						continue; 
					}
					fprintf(stream,"%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
							"%s\r\n%s\r\n%s\r\n"
						,cfg.sub[j]->lname
						,cfg.sub[j]->sname
						,cfg.sub[j]->qwkname
						,cfg.sub[j]->code_suffix
						,cfg.sub[j]->data_dir
						,cfg.sub[j]->arstr
						,cfg.sub[j]->read_arstr
						,cfg.sub[j]->post_arstr
						,cfg.sub[j]->op_arstr
						);
					fprintf(stream,"%"PRIX32"\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n"
						,cfg.sub[j]->misc
						,cfg.sub[j]->tagline
						,cfg.sub[j]->origline
						,cfg.sub[j]->post_sem
						,cfg.sub[j]->newsgroup
						,smb_faddrtoa(&cfg.sub[j]->faddr,tmp)
						);
					fprintf(stream,"%"PRIu32"\r\n%"PRIu32"\r\n%u\r\n%u\r\n%s\r\n"
						,cfg.sub[j]->maxmsgs
						,cfg.sub[j]->maxcrcs
						,cfg.sub[j]->maxage
						,cfg.sub[j]->ptridx
						,cfg.sub[j]->mod_arstr
						);
					fprintf(stream,"***END-OF-SUB***\r\n\r\n"); 
				}
				fclose(stream);
				uifc.pop(0);
				sprintf(str,"%lu Message Areas Exported Successfully",ported);
				uifc.msg(str);
				uifc.changes=q;
				break;
			case 6:
				ported=0;
				k=0;
				strcpy(opt[k++],"SUBS.TXT    (Synchronet)");
				strcpy(opt[k++],"AREAS.BBS   (Generic)");
				strcpy(opt[k++],"AREAS.BBS   (SBBSecho)");
				strcpy(opt[k++],"FIDONET.NA  (Fido)");
				opt[k][0]=0;
				uifc.helpbuf=
					"`Import Area File Format:`\n"
					"\n"
					"This menu allows you to choose the format of the area file you wish to\n"
					"import into the current message group.\n"
				;
				k=0;
				k=uifc.list(WIN_MID|WIN_SAV,0,0,0,&k,0
					,"Import Area File Format",opt);
				if(k==-1)
					break;
				if(k==0)
					sprintf(str,"%sSUBS.TXT",cfg.ctrl_dir);
				else if(k==1)
					sprintf(str,"AREAS.BBS");
				else if(k==2)
					sprintf(str,"%sAREAS.BBS",cfg.data_dir);
				else if(k==3)
					sprintf(str,"FIDONET.NA");
				if(uifc.input(WIN_MID|WIN_SAV,0,0,"Filename"
					,str,sizeof(str)-1,K_EDIT)<=0)
                    break;
				if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
					uifc.msg("Open Failure");
                    break; 
				}
				uifc.pop("Importing Areas...");
				total_subs = cfg.total_subs;	 /* Save original number of subs */
				ptridx = 0;
				while(!feof(stream)) {
					if(!fgets(str,sizeof(str),stream)) break;
					truncsp(str);
					if(!str[0])
						continue;
					if(k) {
						p=str;
						while(*p && *p<=' ') p++;
						if(!*p || *p==';')
							continue;
						memset(&tmpsub,0,sizeof(sub_t));
						tmpsub.misc|=
							(SUB_FIDO|SUB_NAME|SUB_TOUSER|SUB_QUOTE|SUB_HYPER);
						if(k==1) {		/* AREAS.BBS Generic/*.MSG */
							p=str;
							SKIP_WHITESPACE(p);			/* Find path	*/
							FIND_WHITESPACE(p);			/* Skip path	*/
							SKIP_WHITESPACE(p);			/* Find tag		*/
							truncstr(p," \t");			/* Truncate tag */
							SAFECOPY(tmp_code,p);		/* Copy tag to internal code */
							SAFECOPY(tmpsub.lname,utos(p));
							SAFECOPY(tmpsub.sname,tmpsub.lname);
							SAFECOPY(tmpsub.qwkname,tmpsub.qwkname);
						}
						else if(k==2) { /* AREAS.BBS SBBSecho */
							p=str;
							SKIP_WHITESPACE(p);			/* Find internal code */
							tp=p;
							FIND_WHITESPACE(tp);
							*tp=0;						/* Truncate internal code */
							SAFECOPY(tmp_code,p);		/* Copy internal code suffix */
							p=tp+1;
							SKIP_WHITESPACE(p);			/* Find echo tag */
							truncstr(p," \t");			/* Truncate tag */
							SAFECOPY(tmpsub.lname,utos(p));
							SAFECOPY(tmpsub.sname,tmpsub.lname);
							SAFECOPY(tmpsub.qwkname,tmpsub.sname);
						}
						else if(k==3) { /* FIDONET.NA */
                            p=str;
							SKIP_WHITESPACE(p);			/* Find echo tag */
							tp=p;
							FIND_WHITESPACE(tp);		/* Find end of tag */
							*tp=0;						/* Truncate echo tag */
							SAFECOPY(tmp_code,p);		/* Copy tag to internal code suffix */
							SAFECOPY(tmpsub.sname,utos(p));	/* ... to short name, converting underscores to spaces */
							SAFECOPY(tmpsub.qwkname,tmpsub.sname);	/* ... to QWK name .... */
							p=tp+1;
							SKIP_WHITESPACE(p);			/* Find description */
							SAFECOPY(tmpsub.lname,p);	/* Copy description to long name */
						}
					}
					else {
						memset(&tmpsub,0,sizeof(sub_t));
						tmpsub.grp=i;
						sprintf(tmpsub.lname,"%.*s",LEN_SLNAME,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.sname,"%.*s",LEN_SSNAME,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.qwkname,"%.*s",10,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						SAFECOPY(tmp_code,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.data_dir,"%.*s",LEN_DIR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.read_arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.post_arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.op_arstr,"%.*s",LEN_ARSTR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.misc=ahtoul(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.tagline,"%.*s",80,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.origline,"%.*s",50,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.post_sem,"%.*s",LEN_DIR,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						SAFECOPY(tmpsub.newsgroup,str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.faddr=atofaddr(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.maxmsgs=atol(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.maxcrcs=atol(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.maxage=atoi(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						tmpsub.ptridx=atoi(str);
						if(!fgets(str,128,stream)) break;
						truncsp(str);
						sprintf(tmpsub.mod_arstr,"%.*s",LEN_ARSTR,str);

						while(!feof(stream)
							&& strcmp(str,"***END-OF-SUB***")) {
							if(!fgets(str,128,stream)) break;
							truncsp(str); 
						} 
					}

                    SAFECOPY(tmpsub.code_suffix, prep_code(tmp_code,cfg.grp[i]->code_prefix));
					truncsp(tmpsub.sname);
					truncsp(tmpsub.lname);
					truncsp(tmpsub.qwkname);

					if(tmpsub.code_suffix[0]==0
						|| tmpsub.sname[0]==0
						|| tmpsub.lname[0]==0
						|| tmpsub.qwkname[0]==0)
						continue;

					for(j=0;j<total_subs;j++) {
						if(cfg.sub[j]->grp!=i)
							continue;
						if(!stricmp(cfg.sub[j]->code_suffix,tmpsub.code_suffix))
							break; 
					}
					if(j==total_subs) {
						j=cfg.total_subs;
						if((cfg.sub=(sub_t **)realloc(cfg.sub
							,sizeof(sub_t *)*(cfg.total_subs+1)))==NULL) {
							errormsg(WHERE,ERR_ALLOC,nulstr,cfg.total_subs+1);
							cfg.total_subs=0;
							bail(1);
							break; 
						}

						if((cfg.sub[j]=(sub_t *)malloc(sizeof(sub_t)))
							==NULL) {
							errormsg(WHERE,ERR_ALLOC,nulstr,sizeof(sub_t));
							break; 
						}
						memset(cfg.sub[j],0,sizeof(sub_t)); 
					}
					if(!k) {
						n=cfg.sub[j]->ptridx;	/* save original ptridx */
						memcpy(cfg.sub[j],&tmpsub,sizeof(sub_t));
						cfg.sub[j]->ptridx=n;	/* restore original ptridx */
					} else {
                        cfg.sub[j]->grp=i;
						if(cfg.total_faddrs)
							cfg.sub[j]->faddr=cfg.faddr[0];
						strcpy(cfg.sub[j]->code_suffix,tmpsub.code_suffix);
						strcpy(cfg.sub[j]->sname,tmpsub.sname);
						strcpy(cfg.sub[j]->lname,tmpsub.lname);
						strcpy(cfg.sub[j]->qwkname,tmpsub.qwkname);
						strcpy(cfg.sub[j]->data_dir,tmpsub.data_dir);
						if(j==cfg.total_subs)
							cfg.sub[j]->maxmsgs=1000;
					}
					if(j==cfg.total_subs) {	/* adding new sub-board */
						for(;ptridx<USHRT_MAX;ptridx++) {
							for(n=0;n<total_subs;n++)
								if(cfg.sub[n]->ptridx==ptridx)
									break;
							if(n==total_subs)
								break; 
						}
						cfg.sub[j]->ptridx=ptridx;	/* use new ptridx */
						cfg.sub[j]->misc=tmpsub.misc;
						cfg.total_subs++; 
						ptridx++;	/* don't use the same ptridx for next sub */
					}
					uifc.changes=1; 
					ported++;
				}
				fclose(stream);
				uifc.pop(0);
				sprintf(str,"%lu Message Areas Imported Successfully",ported);
                uifc.msg(str);
				break;

			case 7:
                sub_cfg(i);
				break; 
			} 
		} 
	}
}