/*
 * ircII: a new irc client.  I like it.  I hope you will too!
 *
 * Written By Michael Sandrof
 * 
 * Copyright (c) 1990 Michael Sandrof.
 * Copyright (c) 1991, 1992 Troy Rollo.
 * Copyright (c) 1992-2003 Matthew R. Green.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Id: irc.c,v 1.114 2004/05/11 18:13:54 f Exp $
 */

#define IRCII_VERSION	"20040511"	/* YYYYMMDD */
/**************************** PATCHED by Flier ******************************/
#define SCROLLZ_VERSION "1.9.3"
/****************************************************************************/

#include "irc.h"

#include <sys/stat.h>
#ifndef __MSDOS__
#include <pwd.h>
#endif /* __MSDOS__ */

#ifdef ISC22
# include <sys/bsdtypes.h>
#endif /* ISC22 */

#ifdef ESIX
# include <lan/net_types.h>
#endif /* ESIX */

/**************************** PATCHED by Flier ******************************
#ifdef DO_USER2
# include <setjmp.h>
#endif
****************************************************************************/

#include "status.h"
#include "dcc.h"
#include "names.h"
#include "vars.h"
#include "input.h"
#include "alias.h"
#include "output.h"
#include "ircterm.h"
#include "exec.h"
#include "screen.h"
#include "log.h"
#include "server.h"
#include "hook.h"
#include "keys.h"
#include "ircaux.h"
#include "edit.h"
#include "window.h"
#include "history.h"
#include "exec.h"
#include "notify.h"
#include "mail.h"
#include "debug.h"
#include "newio.h"
#include "ctcp.h"
#include "parse.h"

/************************ PATCHED by Flier **************************/
#include "myvars.h"
#include "cdcc.h"
/****************************************************************************/

int	irc_port = IRC_PORT,			/* port of ircd */
	send_text_flag = -1,			/* used in the send_text()
						 * routine */
	use_flow_control = USE_FLOW_CONTROL,	/* true: ^Q/^S used for flow
						 * cntl */
	irc_io_loop = 1,			/* see irc_io below */
	break_io_processing = 0,		/* more forceful than
						 * irc_io_loop */
	current_numeric,			/* this is negative of the
						 * current numeric! */
	dumb = 0,				/* if true, IRCII is put in
						 * "dumb" mode */
	no_fork = 0,				/* if true, IRCII won't with
						 * -b or -e */
	use_input = 1,				/* if 0, stdin is never
						 * checked */
	waiting = 0,				/* used by /WAIT command */
	who_mask = 0;				/* keeps track of which /who
						 * switchs are set */

char	*zero	= "0";
char	*one	= "1";

char	oper_command = 0;	/* true just after an oper() command is
				 * given.  Used to tell the difference
				 * between an incorrect password generated by
				 * an oper() command and one generated when
				 * connecting to a new server */

char	FAR MyHostName[80];	       	/* The local machine name. Used by
					 * DCC TALK */
	struct	in_addr	MyHostAddr;	/* The local machine address */
	struct	in_addr forced_ip_addr;	/* The local machine address */
extern	char	*last_away_nick;

char	*invite_channel = (char *) 0,	/* last channel of an INVITE */
	*ircrc_file = (char *) 0,	/* full path .ircrc file */
	*ircquick_file = (char *)0,	/* full path .ircquick file */
	*my_path = (char *) 0,		/* path to users home dir */
	*irc_path = (char *) 0,		/* paths used by /load */
	*irc_lib = (char *) 0,		/* path to the ircII library */
 	*nickname = (char *) 0,		/* users nickname */
	FAR hostname[NAME_LEN + 1],    	/* name of current host */
	FAR realname[REALNAME_LEN + 1],	/* real name of user */
	FAR username[NAME_LEN + 1],    	/* usernameof user */
	*source_host = NULL,		/* specify a specific source host
					 * for multi-homed machines */
	*send_umode = NULL,		/* sent umode */
	*args_str = (char *) 0,		/* list of command line args */
	empty_string[] = "",		/* just an empty string */
	*who_name = (char *) 0,		/* extra /who switch info */
	*who_file = (char *) 0,		/* extra /who switch info */
	*who_server = (char *) 0,	/* extra /who switch info */
	*who_host = (char *) 0,		/* extra /who switch info */
	*who_nick = (char *) 0,		/* extra /who switch info */
	*who_real = (char *) 0,		/* extra /who switch info */
	*cannot_open = (char *) 0,	/* extra /who switch info */
	*cut_buffer = (char *) 0;	/* global cut_buffer */
u_char	*last_notify_nick = (u_char *) 0; /* last detected nickname */

	int away_set = 0;		/* set if there is an away
					 * message anywhere */
	int	qflag;			/* set if we ignore .ircrc */
	int	bflag;			/* set if we load .ircrc before connecting */
	int	tflag;			/* don't use termcap ti/te sequences */
	time_t	idle_time = 0;
	time_t  start_time;

static	RETSIGTYPE	cntl_c _((void));
static	RETSIGTYPE	sig_user1 _((void));
static	RETSIGTYPE	sig_refresh_screen _((void));
static	void		real_sig_user1 _((void));
static	int		do_sig_user1;
/**************************** PATCHED by Flier ******************************/
/*#ifdef	DO_USER2
static	RETSIGTYPE	sig_user2 _((void)) ;
#endif*/
static	RETSIGTYPE	sig_user2 _((void)) ;
/****************************************************************************/
#ifdef	MUNIX
static	RETSIGTYPE	cntl_y _((void));
#endif
#ifdef CORECATCH
/*static	RETSIGTYPE	coredump _((void)) ;*/
static	RETSIGTYPE	coredump _((int)) ;
/****************************************************************************/
#endif /* CORECATCH */
static	void	process_hostname _((void));
static	void	TimerTimeout _((struct timeval *tv));
static	void	quit_response _((char *, char *));
static	void	show_version _((void));
static	char	*get_arg _((char *, char *, int *));
static	char	*parse_args _((char **, int));

static	int	cntl_c_hit = 0;

/**************************** PATCHED by Flier ******************************
#ifdef DO_USER2
	jmp_buf	outta_here;
#endif
****************************************************************************/

	char	irc_version[] = IRCII_VERSION;

static	char	FAR switch_help[] =
/**************************** Patched by Flier ******************************/
/*"Usage: irc [switches] [nickname] [server list] \n\*/
/****************************************************************************/
"Usage: scrollz [switches] [nickname] [server list] \n\
  The [nickname] can be at most 9 characters long on some server\n\
  The [server list] is a whitespace separated list of server names\n\
  The [switches] may be any or all of the following:\n\
   -c <channel>\tjoins <channel> on startup\n\
   -p <port>\tdefault server connection port (usually 6667)\n\
   -f\t\tyour terminal uses flow control (^S/^Q), so IRCII shouldn't\n\
   -F\t\tyour terminal doesn't use flow control (default)\n\
   -h <host>\tuse the following host for virtual hosting\n\
   -H <host>\toriginating address for dcc requests (to work behind NATs etc)\n\
   -C <name>\tused to cloak process as name\n\
   -s\t\tdon't use separate server processes (ircio)\n\
   -S\t\tuse separate server processes (ircio)\n\
   -d\t\truns IRCII in \"dumb\" terminal mode\n\
   -q\t\tdoes not load .scrollzrc nor .scrollzquick\n\
   -a\t\tadds default servers and command line servers to server list\n\
   -b\t\tload .scrollzrc before connecting to a server\n\
   -t\t\tdo not use termcap ti and te sequences at startup\n\
   -T\t\tuse termcap ti and te sequences at startup (default)\n\
   -l <file>\tloads <file> in place of your .scrollzrc\n\
   -I <file>\tloads <file> in place of your .scrollzquick\n\
   -L <file>\tloads <file> in place of your .scrollzrc and expands $ expandos\n";
/**************************** PATCHED by Flier ******************************/
static int DoOrigNick=0;

extern void Logo _((char *, char *, char *));
extern void CheckTimeMinute _((void));
extern void CheckCdccTimers _((void));
extern void InitVars _((void));
extern void Reset _((char *, char *, char *));
extern void SwitchNick _((void));
extern void CleanUp _((void));
extern int  CheckChannel2 _((char *, char *));
extern void SetStampFormat _((char *));

#ifdef WANTANSI
char *Colors[SZNUMCOLORS]={
 /*  off  */
 "\033[0m" ,
 /*  bold       underline  flash      reverse */
 "\033[1m" , "\033[4m"  , "\033[5m"  , "\033[7m"  ,
 /*  black      red        green      yellow     blue          */
 "\033[30m", "\033[31m" , "\033[32m" , "\033[33m" , "\033[34m" ,
 /*  purple     cyan       white      blackbg    redbg         */
 "\033[35m", "\033[36m" , "\033[37m" , "\033[40m" , "\033[41m" ,
 /*  greenbg    yellowbg   bluebg     purplebg   cyanbg        */
 "\033[42m", "\033[43m" , "\033[44m" , "\033[45m" , "\033[46m" ,
 /*  whitebg    nobold                                         */
 "\033[47m", "\033[22m"
};
#endif

struct friends *frlist;
struct autobankicks *abklist;
struct words *wordlist;
struct wholeftstr *wholist;
struct splitstr *splitlist,*splitlist1;
#ifdef ACID
struct list *nickwatchlist,*tmpnickwatch;
#endif
struct spingstr *spinglist;
struct encrstr *encrlist;
char  defban;
char  bold=2;
char  *DefaultServer=(char *) 0;
char  *ScrollZstr=(char *) 0;
char  *ScrollZver="ircII " IRCII_VERSION "+ScrollZ " SCROLLZ_VERSION " (11.5.2004)+Cdcc v" CDCC_VERSION;
char  *ScrollZver1=(char *) 0;
#ifdef EXTRA_STUFF
char  *EString=(char *) 0;
#endif
char  *DefaultSignOff=(char *) 0;
char  *DefaultSetAway=(char *) 0;
char  *DefaultSetBack=(char *) 0;
char  *DefaultUserinfo=(char *) 0;
char  *DefaultFinger=(char *) 0;
char  *AutoJoinChannels=(char *) 0;
char  *CdccUlDir=(char *) 0;
char  *CdccDlDir=(char *) 0;
char  *WhoKilled=(char *) 0;
char  *CdccChannels=(char *) 0;
char  *AutoRejoinChannels=(char *) 0;
char  *MDopWatchChannels=(char *) 0;
char  *ShowFakesChannels=(char *) 0;
char  *KickOnFloodChannels=(char *) 0;
char  *KickWatchChannels=(char *) 0;
char  *NHProtChannels=(char *) 0;
char  *NickWatchChannels=(char *) 0;
char  *ShowAwayChannels=(char *) 0;
char  *KickOpsChannels=(char *) 0;
char  *KickOnBanChannels=(char *) 0;
char  *BitchChannels=(char *) 0;
char  *FriendListChannels=(char *) 0;
#ifdef EXTRAS
char  *IdleKickChannels=(char *) 0;
char  *SignoffChannels=(char *) 0;
#endif
char  *CompressModesChannels=(char *) 0;
char  *BKChannels=(char *) 0;
#if defined(EXTRAS) || defined(FLIER)
char  *AutoInvChannels;
#endif
char  *EncryptPassword=(char *) 0;
#ifdef OPER
char  *StatskFilter=(char *) 0;
char  *StatsiFilter=(char *) 0;
char  *StatscFilter=(char *) 0;
char  *StatslFilter=(char *) 0;
char  *StatsdFilter=(char *) 0;
#endif
char  *AutoReplyBuffer=(char *) 0;
char  *OrigNick=(char *) 0;
/* patched by acidflash */
#ifdef OPER
char *AcidVersion="OperMods v1.0 by acidflash";
#endif
/****** Coded by Zakath ******/
char  *HelpPathVar=(char *) 0;
char  *CelerityNtfy=(char *) 0;
struct urlstr *urllist;
int   AwayMsgNum=0;
int   CdccPackNum=0;
int   CdccSendNum=0;
int   CdccRecvNum=0;
#if defined(EXTRAS) || defined(FLIER)
int   AutoInv;
#endif
#ifdef CELE
int   SentAway=0;
#endif
char  *URLBuffer=(char *) 0;
/*******************************/
char  *LastChat=(char *) 0;
char  *CurrentDCC=(char *) 0;
char  *DefaultK=(char *) 0;
char  *DefaultBK=(char *) 0;
char  *DefaultBKI=(char *) 0;
char  *DefaultBKT=(char *) 0;
char  *DefaultFK=(char *) 0;
char  *DefaultLK=(char *) 0;
char  *DefaultABK=(char *) 0;
char  *DefaultSK=(char *) 0;
#ifdef OPER
char  *DefaultKill=(char *) 0;
#endif
char  *PermUserMode=(char *) 0;
char  *AutoReplyString=(char *) 0;
#ifdef ACID
char  *ForceJoinChannels=(char *) 0;
#endif
char  *TimeStampString=(char *) 0;
char  *ChanLogChannels=(char *) 0;
char  *ChanLogDir=(char *) 0;
char  *ChanLogPrefix=(char *) 0;
char  *ChanLogPostfix=(char *) 0;
int   DeopPrinted;
int   KickPrinted;
int   NickPrinted;
int   usersloaded;
int   inSZNotify;
int   inSZLinks;
int   inSZFKill;
int   inSZTrace;
int   ExtMes;
int   NHProt;
int   NHDisp;
int   AutoGet;
int   DeopSensor;
int   KickSensor;
int   NickSensor;
int   AutoAwayTime;
int   NickWatch;
int   MDopWatch;
int   KickWatch;
int   MDopTimer;
int   KickTimer;
int   NickTimer;
int   IgnoreTime;
int   ShitIgnoreTime;
int   AutoRejoin;
int   AutoJoinOnInv;
int   FloodProt;
int   FloodMessages;
int   FloodSeconds;
int   CdccIdle;
int   CdccLimit;
int   CdccQueueLimit;
#ifdef EXTRA_STUFF
int   RenameFiles;
#endif
int   Security;
int   ServerNotice;
int   CTCPCloaking;
int   ShowFakes;
int   ShowAway;
int   AutoOpDelay;
#if defined(CELE)
struct timeval LagTimer;
#else
int   LagTimer;
#endif
int   KickOps;
int   KickOnFlood;
int   KickOnBan;
#ifdef SCKICKS
int   NumberOfScatterKicks;
#endif
#ifndef CELE
int   NumberOfSignOffMsgs;
#endif
int   ShowNick;
int   PlistTime;
int   NlistTime;
int   LinksNumber;
int   AwaySaveSet;
int   ShowWallop;
int   LongStatus;
double BytesReceived;
double BytesSent;
int   FriendList;
int   OrigNickChange;
int   IRCQuit;
int   NotifyMode;
int   URLCatch;
int   Ego;
int   LogOn;
int   ShowDCCStatus;
int   DCCDone;
int   AutoNickCompl;
int   CdccStats;
#if defined(OPERVISION) && defined(WANTANSI)
int   OperV;
#endif
int   Bitch;
#ifdef EXTRAS
int   IdleKick;
int   IdleTime;
int   ShowSignoffChan;
#endif
int   CompressModes;
#ifdef WANTANSI
int   DisplaymIRC;
#endif
int   DCCWarning;
int   CdccOverWrite;
int   OrigNickDelay;
int   Stamp;
int   CdccVerbose;
int   ARinWindow;
int   BKList;
int   OrigNickQuiet;
int   OrigNickSent;
int   OrigNickNumber;
#ifdef EXTRAS
int   ShowSignAllChan;
int   ShowNickAllChan;
#endif
int   ExtPub;
int   ChanLog;
int   AwayEncrypt;
#ifdef ACID
int   ForceJoin;
#endif
time_t LastCheck;
time_t LastPlist;
time_t LastNlist;
time_t LastServer;
time_t LastNick;
time_t LastLinks;
#if defined(CELE)
struct timeval PingSent;
#else
time_t PingSent=0;
#endif
time_t LastTS=0;
/****** Coded by Zakath ******/
char VersionInfo[] = {
#ifdef WANTANSI
    'A',
#else
    'a',
#endif
#ifdef EXTRAS
    'E',
#else
    'e',
#endif
#ifdef NEWCSCAN
    'C',
#else
    'c',
#endif
#ifdef SCKICKS
    'S',
#else
    's',
#endif
#ifdef CTCPPAGE
    'P',
#else
    'p',
#endif
#ifdef COUNTRY
    'Y',
#else
    'y',
#endif
#ifdef LITE
    'L',
#else
    'l',
#endif
#ifdef SORTED_NICKS
    'N',
#else
    'n',
#endif
#ifdef ALTERNATIVE_PUBLICS
    'U',
#else
    'u',
#endif
#ifdef BROKEN_MIRC_RESUME
    'M',
#else
    'm',
#endif
#if defined(OPERVISION) && defined(WANTANSI)
    ' ',
    'O',
    'V',
#endif
#ifdef CELE
    ' ',
    'c',
    'y',
#endif
    ' ',
#ifdef GENX
    'G',
#else
    'g',
#endif
#ifdef ACID
    'I',
#else
    'i',
#endif
#ifdef VILAS
    'V',
#else
    'v',
#endif
#ifdef JIMMIE
    'J',
#else
    'j',
#endif
#ifdef TDF
    'X',
#else
    'x',
#endif
#ifdef OGRE
    'Z',
#else
    'z',
#endif
#ifdef OPER
    ' ',
    'O',
    'P',
    'E',
    'R',
#endif
#ifdef HAVE_SSL
    ' ',
    'S',
    'S',
    'L',
#endif
    '\0'};
/*****************************/
struct NickList *tabnickcompl=NULL;
#ifdef WANTANSI
struct colorstr CmdsColors[NUMCMDCOLORS];
#endif
/****************************************************************************/

/* irc_exit: cleans up and leaves */
RETSIGTYPE
/**************************** PATCHED by Flier ******************************/
irc_exit(quit)
/****************************************************************************/
{
	do_hook(EXIT_LIST, "Exiting");
	close_server(-1, empty_string);
	logger(0);
	set_history_file((char *) 0);
#ifndef _Windows
	clean_up_processes();
#endif /* _Windows */
	if (!dumb)
	{
		cursor_to_input();	/* Needed so that ircII doesn't gobble
					 * the last line of the kill. */
		term_cr();
		if (term_clear_to_eol())
			term_space_erase(0);
		term_reset();
#ifdef ESIX
		endwin();		/* Added for curses */
		system("tput reset");
		new_stty("sane");
#endif /* ESIX */
/**************************** PATCHED by Flier ******************************/
#ifdef SZNCURSES
                endwin();
#endif /* SZNCURSES */
/****************************************************************************/
	}
/**************************** PATCHED by Flier ******************************/
        /*exit(0);*/
        CleanUp();
#ifdef _Windows
   DestroyWindow(hwndMain);
#else
        exit(quit);
#endif /* _Windows */
/****************************************************************************/
}

#ifdef CORECATCH
/* sigsegv: something to handle segfaults in a nice way */
/* this needs to be changed to *NOT* use printf(). */
RETSIGTYPE
coredump(sig)
	int	sig;
{
	printf("IRCII has been terminated by a SIG%s\n\r", signals[sig]);
	printf("Please inform the ircii bugs list (ircii-bugs@eterna.com.au) of this\n\r");
	printf("with as much detail as possible about what you were doing when it happened.\n\r");
	printf("Please include the version of IRCII (%s) and type of system in the report.\n\r", irc_version);
	fflush(stdout);
/**************************** PATCHED by Flier ******************************/
        /*irc_exit();*/
        irc_exit(0);
/****************************************************************************/
}
#endif

/*
 * quit_response: Used by irc_io when called from irc_quit to see if we got
 * the right response to our question.  If the response was affirmative, the
 * user gets booted from irc.  Otherwise, life goes on. 
 */
static	void
quit_response(dummy, ptr)
	char	*dummy;
	char	*ptr;
{
 	size_t	len;
 	int	old_irc_io_loop;

	old_irc_io_loop = irc_io_loop;
	irc_io_loop = 0;
	if ((len = strlen(ptr)) != 0)
	{
		if (!my_strnicmp(ptr, "yes", len))
		{
			send_to_server("QUIT");
/**************************** PATCHED by Flier ******************************/
                        /*irc_exit();*/
                        irc_exit(0);
/****************************************************************************/
		}
	}
	irc_io_loop = old_irc_io_loop;
}

/* irc_quit: prompts the user if they wish to exit, then does the right thing */
void
irc_quit(key, ptr)
	u_int	key;
	char *	ptr;
{
	static	int in_it = 0;

	if (in_it)
		return;
	in_it = 1;
	add_wait_prompt("Do you really want to quit? ", quit_response,
		empty_string, WAIT_PROMPT_LINE);
	in_it = 0;
}

/*
 * cntl_c: emergency exit.... if somehow everything else freezes up, hitting
 * ^C five times should kill the program. 
 */
static	RETSIGTYPE
cntl_c()
{
#ifdef SYSVSIGNALS
	(void) MY_SIGNAL(SIGINT, (sigfunc *) cntl_c, 0);
#endif /* SYSVSIGNALS */
	if (cntl_c_hit++ >= 4)
/**************************** PATCHED by Flier ******************************/
		/*irc_exit();*/
		irc_exit(152);
/****************************************************************************/
}

static RETSIGTYPE
sig_user1()
{
#ifdef SYSVSIGNALS
	(void) sigfunc *(SIGUSR1, (sigfunc *) sig_user1, 0);
#endif /* SYSVSIGNALS */
	do_sig_user1++;
}

static void
real_sig_user1()
{
	say("Got SIGUSR1, closing DCC connections and EXECed processes");
	close_all_dcc();
#ifndef _Windows
	close_all_exec();
#endif /* _Windows */
}

/**************************** PATCHED by Flier ******************************
#ifdef DO_USER2
****************************************************************************/
static RETSIGTYPE
sig_user2()
{
#ifdef SYSVSIGNALS
	(void) MY_SIGNAL(SIGUSR2, (sigfunc *) sig_user2, 0);
#endif /* SYSVSIGNALS */
/**************************** PATCHED by Flier ******************************/
	/*say("Got SIGUSR2, jumping to normal loop");	 unsafe
	longjmp(outta_here);*/
 	say("Got SIGUSR2, reloading ScrollZ.save");
 	Reset(NULL,NULL,NULL);
/****************************************************************************/
}
/**************************** PATCHED by Flier ******************************
#endif 
****************************************************************************/

#ifdef MUNIX
/* A characteristic of PCS MUNIX - Ctrl-Y produces a SIGQUIT */
static RETSIGTYPE
cntl_y()
{
	(void) MY_SIGNAL(SIGQUIT, (sigfunc *) cntl_y, 0);
	edit_char(25); /* Ctrl-Y */	/* unsafe */
}
#endif

static RETSIGTYPE
sig_refresh_screen()
{
	do_refresh_screen++;
}

/* shows the version of irc */
static	void
show_version()
{
	printf("ircII version %s\n\r", irc_version);
	exit (0);
}

/*
 * process_hostname: Called at startup and to deal with /SET IRCHOST changes.
 */
static void
process_hostname()
{
#ifndef INET6
	struct hostent *hp;
#endif

	if (source_host)
		strncpy(MyHostName, source_host, sizeof(MyHostName)-1);
	else
		gethostname(MyHostName, sizeof(MyHostName));
#ifndef INET6
	if ((hp = gethostbyname(MyHostName)) != NULL)
/**************************** Patched by Flier ******************************/
        {
                int s;

/****************************************************************************/
		bcopy(hp->h_addr, (char *) &MyHostAddr, sizeof(MyHostAddr));
/**************************** Patched by Flier ******************************/
                if ((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0) {
                    struct sockaddr_in localaddr;

                    memset(&localaddr, 0, sizeof(struct sockaddr_in));
                    localaddr.sin_family = AF_INET;
                    localaddr.sin_addr = MyHostAddr;
                    localaddr.sin_port = 0;
                    if ((bind(s, (struct sockaddr *) &localaddr, sizeof(localaddr))) != 0) {
                        memset(&MyHostAddr, 0, sizeof(MyHostAddr));
                        say("Invalid virtual host %s", MyHostName);
                    }
                    close(s);
                }
        }
/****************************************************************************/
#endif
}

/* get_arg: used by parse_args() to get an argument after a switch */
static	char	*
get_arg(arg, next, ac)
	char	*arg;
	char	*next;
	int	*ac;
{
	(*ac)++;
	if (*arg)
		return (arg);
	else
	{
		if (next)
			return (next);
		fprintf(stderr, "irc: missing parameter\n");
                exit(1);
 		return (0); /* cleans up a warning */
	}
}

/*
 * parse_args: parse command line arguments for irc, and sets all initial
 * flags, etc. 
 */
static	char	*
parse_args(argv, argc)
	char	**argv;
	int	argc;
{
	char	*arg,
		*ptr;
	int	ac;
	int	add_servers = 0;
	char	*channel = (char *) NULL;
	struct	passwd	*entry;
#ifdef _Windows
	u_char	buffer[BIG_BUFFER_SIZE];
#endif
/**************************** PATCHED by Flier ******************************/
	/*int	minus_minus = 0;*/
        char    *CloakCommand = NULL;
/****************************************************************************/

	*realname = '\0';
	ac = 1;
	malloc_strcpy(&args_str, argv[0]);
	malloc_strcat(&args_str, " ");
	while ((arg = argv[ac++]) != (char *) NULL)
	{
		malloc_strcat(&args_str, argv[ac-1]);
		malloc_strcat(&args_str, " ");
		if ((*arg == '-') != '\0')
		{
/**************************** PATCHED by Flier ******************************/
			/*++arg;*/
			while (*arg && *arg == '-')
                            arg++;
/****************************************************************************/
			while (*arg)
			{
				switch (*(arg++))
				{
/**************************** PATCHED by Flier ******************************/
				case 'C':
                                        malloc_strcpy(&CloakCommand, get_arg(arg, argv[ac], &ac));
					break;
/****************************************************************************/
				case 'v':
					show_version();
					break;
				case 'b':
					if (qflag)
					{
						fprintf(stderr, "Can not use -b with -q\n");
						exit(1);
					}
					bflag = 1;
					break;
				case 'c':
					malloc_strcpy(&channel, get_arg(arg,
							argv[ac], &ac));
					break;
				case 'p':
					irc_port = atoi(get_arg(arg, argv[ac],
							&ac));
					break;
				case 'f':
					use_flow_control = 1;
					break;
				case 'F':
					use_flow_control = 0;
					break;
				case 'd':
					dumb = 1;
					break;
				case 'H':
				{
					char *buf = (char *) 0;

					struct hostent *hp;
					malloc_strcpy(&buf, get_arg(arg, argv[ac], &ac));
					if ((hp = gethostbyname(buf)) != NULL)
						bcopy(hp->h_addr, (char *) &forced_ip_addr, sizeof(forced_ip_addr));
					free(buf);
					break;
				}
				case 'h':
					malloc_strcpy(&source_host, get_arg(arg,
							argv[ac], &ac));
					break;
#ifdef DEBUG
				case 'D':
					setdlevel(atoi(get_arg(arg, argv[ac],
						&ac)));
					break;
				case 'o':
					{
						FILE	*fp;
						char	*file = get_arg(arg, argv[ac], &ac);

						if (!file)
						{
							printf("irc: need filename for -o\n");
							exit(-1);
						}
						fp = freopen(file, "w", stderr);
						if (!fp)
						{
							printf("irc: can not open %s: %s\n", file, errno ? "" : strerror(errno));
							exit(-1);
						}
					}
					break;
#endif /* DEBUG */
				case 'l':
					malloc_strcpy(&ircrc_file, get_arg(arg,
							argv[ac], &ac));
					break;
				case 'L':
					malloc_strcpy(&ircrc_file, get_arg(arg,
							argv[ac], &ac));
					malloc_strcat(&ircrc_file," -");
					break;
				case 'I':
					malloc_strcpy(&ircquick_file,get_arg(arg, argv[ac], &ac));
					break;
				case 'a':
					add_servers = 1;
					break;
				case 's':
					using_server_process = 0;
					break;
				case 'S':
					using_server_process = 1;
					break;
				case 't':
					tflag = 1;
					break;
				case 'T':
					tflag = 0;
					break;
				case 'q':
					if (bflag)
					{
						fprintf(stderr, "Can not use -q with -b\n");
						exit(1);
					}
					qflag = 1;
					break;
/**************************** PATCHED by Flier ******************************/
                                /* what the hell is this */
				/*case '-':
					if (argv[ac])
					{
						while ((arg = argv[ac++]) != NULL)
						{
							malloc_strcat(&command_line, arg);
							malloc_strcat(&command_line, " ");*/	/* a bit wasteful; only at startup */
						/*}
						command_line[strlen(command_line)-1] = '\0';
					}
					minus_minus = 1;
					break;*/
/****************************************************************************/
				default:
					fprintf(stderr, "%s", switch_help);
					exit(1);
				}
			}
		}
		else
		{
 			if (strchr(arg, '.') || (nickname && *nickname))
				build_server_list(arg);
			else
 				malloc_strcpy(&nickname, arg);
		}
/**************************** PATCHED by Flier ******************************/
		/*if (minus_minus)
			break;*/
/****************************************************************************/
	}
/**************************** PATCHED by Flier ******************************/
/* Patched by Zakath */
	if ((ptr = getenv("IRCHELP"))) malloc_strcpy(&HelpPathVar, ptr);
/* ***************** */
/****************************************************************************/
	if ((char *) 0 != (ptr = (char *) getenv("IRCLIB")))
	{
		malloc_strcpy(&irc_lib, ptr);
		malloc_strcat(&irc_lib, "/");
	}
	else
		malloc_strcpy(&irc_lib, IRCLIB);

	/* -h overrides environment variable */
	if ((char *) 0 == source_host && (char *) 0 != (ptr = getenv("IRCHOST")))
		malloc_strcpy(&source_host, ptr);

	if ((char *) 0 == ircrc_file && (char *) 0 != (ptr = getenv("IRCRC")))
		malloc_strcpy(&ircrc_file, ptr);

	if ((char *) 0 == ircquick_file && (char *) 0 != (ptr = getenv("IRCQUICK")))
		malloc_strcpy(&ircrc_file, ptr);

 	if ((nickname == 0 || *nickname == '\0') && (char *) 0 != (ptr = getenv("IRCNICK")))
 		malloc_strcpy(&nickname, ptr);

	if ((char *) 0 != (ptr = getenv("IRCUMODE")))
		malloc_strcpy(&send_umode, ptr);

	if ((char *) 0 != (ptr = getenv("IRCNAME")))
		strmcpy(realname, ptr, REALNAME_LEN);

	if ((char *) 0 != (ptr = getenv("IRCPATH")))
		malloc_strcpy(&irc_path, ptr);
	else
	{
#ifdef IRCPATH
		malloc_strcpy(&irc_path, IRCPATH);
#else
#ifdef __MSDOS__
		malloc_strcpy(&irc_path, ".:~/irc:");
#else
		malloc_strcpy(&irc_path, ".:~/.irc:");
#endif /* __MSDOS__ */
		malloc_strcat(&irc_path, irc_lib);
		malloc_strcat(&irc_path, "script");
#endif
	}

	set_string_var(LOAD_PATH_VAR, irc_path);
	new_free(&irc_path);
	if ((char *) 0 != (ptr = getenv("IRCSERVER")))
		build_server_list(ptr);
	if (0 == number_of_servers || add_servers)
	{
#ifdef SERVERS_FILE
		if (read_server_file() || (number_of_servers == 0))
#endif
		{
 			char *s = (char *) 0;

#ifdef _Windows
			GetProfileString("IRC", "Server",
						"Choose.File->Setup.From.Menu",
						buffer, sizeof(buffer));
 			malloc_strcpy(&s, buffer);
#else
 			malloc_strcpy(&s, DEFAULT_SERVER);
#endif /* _Windows */
 			build_server_list(s);
 			new_free(&s);
		}
	}
#ifdef _Windows
 	if (nickname == 0 || !*nickname)
 	{
 		GetProfileString("IRC", "Nick", "ircuser", buffer, BIG_BUFFER_SIZE);
 		malloc_strcpy(&nickname, buffer);
 	}
	GetProfileString("IRC", "UserName", "ircuser", username, NAME_LEN + 1);
	GetProfileString("IRC", "RealName", "ircuser", realname, REALNAME_LEN + 1);
	GetProfileString("IRC", "StartDir", get_path(4), buffer, BIG_BUFFER_SIZE);
	malloc_strcpy(&my_path, buffer);
#else /* _Windows */
	if ((struct passwd *) 0 != (entry = getpwuid(getuid())))
	{
		if ((*realname == '\0') && entry->pw_gecos && *(entry->pw_gecos))
		{
#ifdef GECOS_DELIMITER
			if ((ptr = index(entry->pw_gecos, GECOS_DELIMITER)) 
					!= NULL)
				*ptr = '\0';
#endif /* GECOS_DELIMITER */
			if ((ptr = index(entry->pw_gecos, '&')) == NULL)
				strmcpy(realname, entry->pw_gecos, REALNAME_LEN);
			else {
 				size_t len = ptr - entry->pw_gecos;

				if (len < REALNAME_LEN && *(entry->pw_name)) {
					char *q = realname + len;

					strmcpy(realname, entry->pw_gecos, len);
					strmcat(realname, entry->pw_name, REALNAME_LEN);
					strmcat(realname, ptr + 1, REALNAME_LEN);
					if (islower(*q) && (q == realname || isspace(*(q - 1))))
						*q = toupper(*q);
				} else
					strmcpy(realname, entry->pw_gecos, REALNAME_LEN);
			}
		}
		if (entry->pw_name && *(entry->pw_name))
			strmcpy(username, entry->pw_name, NAME_LEN);

		if (entry->pw_dir && *(entry->pw_dir))
			malloc_strcpy(&my_path, entry->pw_dir);
	}
#endif /* _Windows */
	if ((char *) 0 != (ptr = getenv("HOME")))
		malloc_strcpy(&my_path, ptr);
	else if (*my_path == '\0')
		malloc_strcpy(&my_path, "/");

	if ('\0' == *realname)
		strmcpy(realname, "*Unknown*", REALNAME_LEN);

	if ('\0' == *username)
	{
		if ((ptr = getenv("USER")) != NULL)
			strmcpy(username, ptr, NAME_LEN);
		else
			strmcpy(username, "Unknown", NAME_LEN);
	}
	if ((char *) 0 != (ptr = getenv("IRCUSER")))
		strmcpy(username, ptr, REALNAME_LEN);

/**************************** PATCHED by Flier ******************************/
        if ((ptr = getenv("DCCHOST"))) {
            char *buf = (char *) 0;
            struct hostent *hp;

            malloc_strcpy(&buf, ptr);
            if ((hp = gethostbyname(buf)) != NULL)
                bcopy(hp->h_addr, (char *) &forced_ip_addr, sizeof(forced_ip_addr));
            new_free(&buf);
        }
        /* for Da_P */
        if ((ptr = getenv("VIRTIP"))) malloc_strcpy(&source_host, ptr);
/****************************************************************************/

        process_hostname();
 	if (nickname == 0 || *nickname == '\0')
 		malloc_strcpy(&nickname, username);
/**************************** PATCHED by Flier ******************************/
/*#if 0*/ /* blundernet changed this */
/****************************************************************************/
	if (0 == check_nickname(nickname))
	{
		fprintf(stderr, "Illegal nickname %s\n", nickname);
		exit(1);
	}
/**************************** PATCHED by Flier ******************************/
/*#endif*/
/****************************************************************************/
	if ((char *) 0 == ircrc_file)
	{
		ircrc_file = (char *) new_malloc(strlen(my_path) +
			strlen(IRCRC_NAME) + 1);
		strcpy(ircrc_file, my_path);
		strcat(ircrc_file, IRCRC_NAME);
	}
	if ((char *) 0 == ircquick_file)
	{
		ircquick_file = (char *) new_malloc(strlen(my_path) +
			strlen(IRCQUICK_NAME) + 1);
		strcpy(ircquick_file, my_path);
		strcat(ircquick_file, IRCQUICK_NAME);
	}
/**************************** PATCHED by Flier ******************************/
        if (CloakCommand) {
            for (ac = argc - 1; ac >= 0; ac--) memset(argv[ac], 0, strlen(argv[ac]));
            strcpy(argv[0], CloakCommand);
            new_free(&CloakCommand);
        }
/****************************************************************************/
        return (channel);
}

/*
 * TimerTimeout:  Called from irc_io to help create the timeout
 * part of the call to select.
 */
static void
TimerTimeout(struct timeval *tv)
{
	struct timeval current;
/**************************** PATCHED by Flier ******************************/
        time_t nickt = LastNick + OrigNickDelay;
	struct timeval largest;
/****************************************************************************/

	tv->tv_usec = 0;
	tv->tv_sec  = 0;

/**************************** PATCHED by Flier ******************************/
        DoOrigNick = 0;
	/* If ORIGNICK is off set nickt to current + 75 to prevent excessive
	   CPU usage (meaning we actually ignore this event, see below) */
	gettimeofday(&current, NULL);
        if (!OrigNickChange) nickt = current.tv_sec + 75;
/****************************************************************************/

	if (!PendingTimers)
	{
/**************************** PATCHED by Flier ******************************/
		/*tv->tv_sec = 70;*/ /* Just larger than the maximum of 60 */
                if (nickt - current.tv_sec < 70) DoOrigNick = 1;
                tv->tv_sec = nickt - current.tv_sec > 70 ? 70 : nickt - current.tv_sec;
                if (DoOrigNick && tv->tv_sec <= 0) tv->tv_sec = 70;
/****************************************************************************/
		return;
	}
/**************************** PATCHED by Flier ******************************/
	/*gettimeofday(&current, NULL);*/
        if (PendingTimers->time > nickt) {
            largest.tv_sec = nickt;
            largest.tv_usec = 0;
            DoOrigNick = 1;
        }
        else {
            largest.tv_sec = PendingTimers->time;
            largest.tv_usec = PendingTimers->microseconds;
        }
/****************************************************************************/

/**************************** PATCHED by Flier ******************************/
	/*if (PendingTimers->time < current.tv_sec ||
	    (PendingTimers->time == current.tv_sec &&
	    PendingTimers->microseconds < current.tv_usec))
	{*/
		/* No time to lose, the event is now or was */
		/*return;
	}

	tv->tv_sec = PendingTimers->time - current.tv_sec;
	if (PendingTimers->microseconds >= current.tv_usec)
		tv->tv_usec = PendingTimers->microseconds - current.tv_usec;
	else
	{
		tv->tv_usec = current.tv_usec - PendingTimers->microseconds;
		tv->tv_sec -= 1;
	}*/
	if (largest.tv_sec < current.tv_sec ||
	    (largest.tv_sec == current.tv_sec && largest.tv_usec < current.tv_usec))
	{
		/* No time to lose, the event is now or was */
		return;
	}
	tv->tv_sec = largest.tv_sec - current.tv_sec;
	if (largest.tv_usec >= current.tv_usec)
		tv->tv_usec = largest.tv_usec - current.tv_usec;
	else
	{
		tv->tv_usec = current.tv_usec - largest.tv_usec;
		tv->tv_sec -= 1;
	}
/****************************************************************************/
}

/*
 * irc_io: the main irc input/output loop.   Handles all io from keyboard,
 * server, exec'd processes, etc.  If a prompt is specified, it is displayed
 * in the input line and cannot be backspaced over, etc. The func is a
 * function which will take the place of the SEND_LINE function (which is
 * what happens when you hit return at the end of a line). This function must
 * decide if it's ok to exit based on anything you really want.  It can then
 * set the global irc_io_loop to false to cause irc_io to exit. 
 */
int
irc_io(prompt, func, my_use_input, loop)
	char	*prompt;
 	void	(*func) _((u_int, char *));
	int	my_use_input;
	int	loop;
{
	static	int	level = 0;
	fd_set	rd,
		wd;
 	char	lbuf[BIG_BUFFER_SIZE + 1];	/* buffer much bigger than
						 * IRCD_BUFFER_SIZE */
	struct	timeval cursor_timeout,
		clock_timeout,
		right_away,
		timer,
		*timeptr;
	int	hold_over;
	int	old_loop;
	char	*last_input = NULL;
	char	*last_prompt = NULL;
 	void	(*last_func) _((u_int, char *));
	int	one_key = 0;
	Screen	*screen,
		*old_current_screen;

	last_func = get_send_line();
 	if (my_use_input == -1)
		one_key = 1, prompt = NULL;
#ifdef	PRIV_PORT_ULC
	seteuid(getuid());
#endif
	/* time before cursor jumps from display area to input line */
	cursor_timeout.tv_usec = 0L;
	cursor_timeout.tv_sec = 1L;

	/* time delay for updating of internal clock */
	clock_timeout.tv_usec = 0L;
	clock_timeout.tv_sec = 30L;

	right_away.tv_usec = 0L;
	right_away.tv_sec = 0L;

	old_loop = irc_io_loop;
	irc_io_loop = loop;

			/*
			 * irc_io has been recursive to date.
			 * with multiple xterms and screen
			 * windows, this has to change
			 */
	if (level++ > 5)
	{
		level--;
		irc_io_loop = old_loop;
		return (1);
	}
	if (!dumb)
	{
		if (my_use_input)
		{
			malloc_strcpy(&last_input, get_input());
			set_input(empty_string);
			last_func = get_send_line();
			change_send_line(func);
		}
		if (prompt)
		{
			malloc_strcpy(&last_prompt, get_input_prompt());
			set_input_prompt(prompt);
		}
	}
	/*
	 * Here we work out if this has been called recursively or
	 * not..  and if not so.. -phone
	 */

/**************************** PATCHED by Flier ******************************/
/*#if defined(DEBUG) || defined(DO_USER2)
	if (level != 1)
	{
#ifdef DEBUG
		yell("--- Recursive call to irc_io() - careful");
#endif
	}
	else
	{
#ifdef DO_USER2
		if (setjmp(outta_here))
			yell("*** Got SIGUSR2, Aborting");
#endif
	}
#endif*/
#if defined(DEBUG)
	if (level != 1)
            yell("--- Recursive call to irc_io() - careful");
#endif
/****************************************************************************/

	timeptr = &clock_timeout;
	do
	{
		break_io_processing = 0;
 		sed = 0;
                FD_ZERO(&rd);
		FD_ZERO(&wd);
		set_process_bits(&rd);
		set_server_bits(&rd, &wd);
#ifndef _Windows
		if (my_use_input)
			for (screen = screen_list;screen; screen = screen->next)
				if (screen->alive)
				{
					FD_SET(screen->fdin, &rd);
					if (!is_main_screen(screen))
						FD_SET(screen->wservin, &rd);
				}
		set_dcc_bits(&rd, &wd);
		if (term_reset_flag)
		{
			refresh_screen(0, (char *) 0);
			term_reset_flag = 0;
		}
#endif /* _Windows */
		TimerTimeout(&timer);
		if (timer.tv_sec <= timeptr->tv_sec)
			timeptr = &timer;
		if ((hold_over = unhold_windows()) != 0)
			timeptr = &right_away;
		Debug((7, "irc_io: selecting with %ld:%ld timeout", timeptr->tv_sec,
			timeptr->tv_usec));
/**************************** Patched by Flier ******************************/
                if (!hold_over)
                    cursor_to_input();
/****************************************************************************/
		switch (new_select(&rd, &wd, timeptr))
		{
		case 0:
		case -1:
	/*
	 * yay for the QNX socket manager... drift here, drift there, oops,
	 * i fell down a hole..
	 */
#ifdef __QNX__
			if (errno == EBADF || errno == ESRCH)
				irc_io_loop = 0;
#endif
			if (cntl_c_hit)
			{
				if (one_key)
				{
					irc_io_loop = 0;
					break;
				}
 				edit_char((u_int)'\003');
				cntl_c_hit = 0;
			}
			if (do_status_alarmed)
			{
				real_status_alarmed();
				do_status_alarmed = 0;
			}
			if (do_refresh_screen)
			{
				refresh_screen(0, (char *) 0);
				do_refresh_screen = 0;
			}
			if (do_sig_user1)
			{
				real_sig_user1();
				do_sig_user1 = 0;
			}
/**************************** Patched by Flier ******************************/
                        /* moved above */
			/*if (!hold_over)
				cursor_to_input();*/
/****************************************************************************/
			break;
		default:
#ifndef _Windows
			if (term_reset_flag)
			{
				refresh_screen(0, (char *) 0);
				term_reset_flag = 0;
			}
#endif /* _Windows */
			old_current_screen = current_screen;
			set_current_screen(last_input_screen);
			if (!break_io_processing)
				dcc_check(&rd, &wd);
			if (!break_io_processing)
				do_server(&rd, &wd);
			set_current_screen(old_current_screen);
			for (screen = screen_list; screen &&
				!break_io_processing; screen = screen->next)
			{
				if (!screen->alive)
					continue;
				set_current_screen(screen);
#ifdef WINDOW_CREATE
				if (!is_main_screen(screen) &&
				    FD_ISSET(screen->wservin, &rd))
					screen_wserv_message(screen);
#endif /* WINDOW_CREATE */
				if (FD_ISSET(screen->fdin, &rd))
				{

	/*
	 * This section of code handles all in put from the terminal(s).
	 * connected to ircII.  Perhaps the idle time *shouldn't* be 
	 * reset unless its not a screen-fd that was closed..
	 *
	 * This section indented - phone, jan 1993
	 */

			idle_time = time(0);
			if (dumb)
			{
				int     old_timeout;

				old_timeout = dgets_timeout(1);
 				if (dgets(lbuf, INPUT_BUFFER_SIZE,
						screen->fdin, (char *) 0))
				{
					(void) dgets_timeout(old_timeout);
					if (one_key)
					{
						irc_io_loop = 0;
						break;
					}
 					*(lbuf + strlen(lbuf) - 1) = '\0';
					if (get_int_var(INPUT_ALIASES_VAR))	
 						parse_line(NULL, lbuf,
						    empty_string, 1, 0, 0);
					else
 						parse_line(NULL, lbuf,
						    NULL, 1, 0, 0);
				}
				else
				{
					say("IRCII exiting on EOF from stdin");
/**************************** PATCHED by Flier ******************************/
                                        /*irc_exit();*/
                                        irc_exit(0);
/****************************************************************************/
				}
			}
			else
			{
				int server;
				char	loc_buffer[BIG_BUFFER_SIZE + 1];
				int	n, i;

				server = from_server;
				from_server = get_window_server(0);
				last_input_screen = screen;
				if (one_key)
				{
/**************************** PATCHED by Flier ******************************/
					/*if (read(screen->fdin, lbuf, 1))*/
#ifdef SZNCURSES
 					if (term_read(lbuf,1))
#else
 					if (read(screen->fdin, lbuf, 1))
#endif /* SZNCURSES */
/****************************************************************************/
					{
						irc_io_loop = 0;
						break;
					}
				/*
				 * Following Fizzy's remark below, if we 
				 * don't use window create, we can't kill
				 * then, can we?  --FlashMan, October 1994
				 */
#ifdef WINDOW_CREATE
					else
					{
#ifndef _Windows
						if (!is_main_screen(screen))
							kill_screen(screen);
						else
#endif /* _Windows */
/**************************** PATCHED by Flier ******************************/
							/*irc_exit();*/
							irc_exit(0);
/****************************************************************************/
					}
#endif /* WINDOW_CREATE */
				}
/**************************** PATCHED by Flier ******************************/
				/*else if ((n = read(screen->fdin, loc_buffer,
						BIG_BUFFER_SIZE)) != 0)*/
#ifdef SZNCURSES
 				else if ((n=term_read(loc_buffer,BIG_BUFFER_SIZE))!=0)
#else
				else if ((n = read(screen->fdin, loc_buffer,
					      BIG_BUFFER_SIZE)) != 0)
#endif /* SZNCURSES */
/****************************************************************************/
					for (i = 0; i < n; i++)
 						edit_char((u_int)loc_buffer[i]);
		/*
		 * if the current screen isn't the main  screen,
		 * then the socket to the current screen must have
		 * closed, so we call kill_screen() to handle 
		 * this - phone, jan 1993.
		 * but not when we arent running windows - Fizzy, may 1993
		 * if it is the main screen we got an EOF on, we exit..
		 * closed tty -> chew cpu -> bad .. -phone, july 1993.
		 */
#ifdef WINDOW_CREATE
				else
				{
					if (!is_main_screen(screen))
						kill_screen(screen);
					else
/**************************** PATCHED by Flier ******************************/
						/*irc_exit();*/
						irc_exit(0);
/****************************************************************************/
				}
#endif /* WINDOW_CREATE */
				cntl_c_hit = 0;
				from_server = server;
			}

		/* End of intendation */

				}
			}
			set_current_screen(old_current_screen);
#ifndef _Windows
			if (!break_io_processing)
				do_processes(&rd);
#endif /* _Windows */
			break;
		}
		execute_timer();
#ifndef _Windows
		check_process_limits();
		while (check_wait_status(-1) >= 0)
			;
#endif /* _Windows */
		if ((primary_server == -1) && !never_connected)
			do_hook(DISCONNECT_LIST, "%s", nickname);
		timeptr = &clock_timeout;

		old_current_screen = current_screen;
		for (screen = screen_list; screen; screen = screen->next)
		{
			set_current_screen(screen);
			if (screen->alive && is_cursor_in_display())
				timeptr = &cursor_timeout;
		}
		set_current_screen(old_current_screen);

		if (update_clock(0, 0, 0))
		{
			if (get_int_var(CLOCK_VAR) || check_mail_status())
			{
				status_update(1);
				cursor_to_input();
			}
			if (primary_server != -1)
				do_notify();
/**************************** PATCHED by Flier ******************************/
                        CheckTimeMinute();
                        CheckCdccTimers();
                        SetStampFormat(NULL);
                        if (from_server>=0 && from_server<number_of_servers) {
#if defined(CELE)
                            gettimeofday(&PingSent,NULL);
                            if (PingSent.tv_sec-start_time>30)
#else
                                PingSent=time((time_t *) 0);
                            if (PingSent-start_time>30)
#endif
                                send_to_server("PING szlagmeter");
                        }
/****************************************************************************/
		}
/**************************** PATCHED by Flier ******************************/
                /* update time stamp if necessary */
                if (Stamp) SetStampFormat(NULL);
                if (DoOrigNick) {
                    if (OrigNickChange && OrigNick && DoOrigNick) {
                        char *curnick=get_server_nickname(from_server);

                        if (curnick && !CheckChannel2(OrigNick,curnick)) SwitchNick();
                        LastNick=time(NULL);
                    }
                }
/****************************************************************************/
	}
	while (irc_io_loop);
	level--;
	irc_io_loop = old_loop;
	if (! dumb)
	{
		if (my_use_input)
		{
			set_input(last_input);
			new_free(&last_input);
			change_send_line(last_func);
		}
		if (prompt)
		{
			if (level == 0)
			    set_input_prompt(get_string_var(INPUT_PROMPT_VAR));
			else
			    set_input_prompt(last_prompt);
			new_free(&last_prompt);
		}
	}
	update_input(UPDATE_ALL);
	return (0);
}

int
#ifdef _Windows
old_main(int argc, char **argv)
#else
/*ARGSUSED*/
main _((int, char *[], char *[]));

int
main(argc, argv, envp)
	int	argc;
	char	*argv[];
	char	*envp[];
#endif /* _Windows */
{
	char	*channel;

	srandom(time(NULL) ^ getpid());	/* something */

/**************************** Patched by Flier ******************************/
        memset(&forced_ip_addr, 0, sizeof(struct in_addr));
        memset(&MyHostAddr, 0, sizeof(struct in_addr));
/****************************************************************************/
#ifdef _Windows
	reset_pointers();
#endif /* _Windows */
	start_time = time((time_t *)0);
#ifdef	SOCKS
	SOCKSinit(argv[0]);
#endif /* SOCKS */
	channel = parse_args(argv, argc);
#if defined(ESIX)
	/* Curses code added for ESIX use */
	if (!dumb)
	{
		initscr();
		noecho();
		cbreak();
	}
#endif /* ESIX */
#ifndef _Windows
	if ((use_input == 0) && !no_fork)
	{
		if (fork())
			_exit(0);
	}
#endif /* _Windows */
#if defined(ESIX) || defined(_Windows)
	if (gethostname(hostname, NAME_LEN) == NULL)
#else
	if (gethostname(hostname, NAME_LEN))
#endif /* ESIX */
	{
#ifdef _Windows
		switch(WSAGetLastError())
	{
	case WSAEFAULT:
      		MessageBox(0, "Couldn't get host name", 0, MB_OK);
		break;
	case WSANOTINITIALISED:
		MessageBox(0, "Couldn't get host name", 0, MB_OK);
		break;
	case WSAENETDOWN:
		MessageBox(0, "Couldn't get host name", 0, MB_OK);
		break;
	case WSAEINPROGRESS:
		MessageBox(0, "Couldn't get host name", 0, MB_OK);
		break;
	default:
		break;
	}

#else
		fprintf(stderr, "irc: couldn't figure out the name of your machine!\n");
		exit(1);
#endif /* _Windows */
	}
/**************************** PATCHED by Flier ******************************/
        printf("Process [%d] connected to tty [%s]\n",getpid(),ttyname(0));
/****************************************************************************/
	term_set_fp(stdout);
	if (dumb)
		new_window();
	else
	{
		init_screen();
#ifndef _Windows
/**************************** PATCHED by Flier ******************************/
/* Patch for OS/2 EMX */
/*#if !defined(MUNIX) && !defined(_RT) && !defined(ESIX)*/
#if !defined(MUNIX) && !defined(_RT) && !defined(ESIX) && !defined(__EMX__)
/****************************************************************************/
		(void) MY_SIGNAL(SIGCONT, (sigfunc *) term_cont, 0);
#endif /* !defined(MUNIX) && !defined(_RT) && !defined(ESIX) */
#if !defined(_RT) && defined(SIGWINCH)
		(void) MY_SIGNAL(SIGWINCH, (sigfunc *) sig_refresh_screen, 0);
#endif /* _RT */
#ifndef ALLOC_DEBUG
# ifdef CORECATCH
		(void) MY_SIGNAL(SIGSEGV, (sigfunc *) coredump, 0);
#  ifdef SIGBUS
		(void) MY_SIGNAL(SIGBUS, (sigfunc *) coredump, 0);
#  endif
# else
		(void) MY_SIGNAL(SIGSEGV, (sigfunc *) SIG_DFL, 0);
		/* Linux doesn't have SIGBUS */
#  ifdef SIGBUS
		(void) MY_SIGNAL(SIGBUS, (sigfunc *) SIG_DFL, 0);
#  endif /* SIGBUS */
# endif /* CORECATCH */
#endif /* ALLOC_DEBUG */
#ifdef MUNIX
		(void) MY_SIGNAL(SIGQUIT, (sigfunc *) cntl_y, 0);
#endif
		(void) MY_SIGNAL(SIGHUP, (sigfunc *) irc_exit, 0);
		(void) MY_SIGNAL(SIGTERM, (sigfunc *) irc_exit, 0);
		(void) MY_SIGNAL(SIGPIPE, (sigfunc *) SIG_IGN, 0);
		(void) MY_SIGNAL(SIGINT, (sigfunc *) cntl_c, 0);
#ifdef SIGSTOP
		(void) MY_SIGNAL(SIGSTOP, (sigfunc *) SIG_IGN, 0);
#endif
		(void) MY_SIGNAL(SIGUSR1, (sigfunc *) sig_user1, 0);
/**************************** PATCHED by Flier ******************************/
/*#ifdef DO_USER2*/
/****************************************************************************/
		(void) MY_SIGNAL(SIGUSR2, (sigfunc *) sig_user2, 0);
/**************************** PATCHED by Flier ******************************/
/*#endif*/
/****************************************************************************/
#endif /* _Windows */
	}

/**************************** Patched by Flier ******************************/
        InitVars();
/****************************************************************************/
	init_variables();
/**************************** Patched by Flier ******************************/
        SetStampFormat(NULL);
/****************************************************************************/

	if (!dumb)
	{
		build_status((char *) 0);
		update_input(UPDATE_ALL);
	}

#ifdef MOTD_FILE
	{
		struct	stat	motd_stat,
				my_stat;
		char	*motd = NULL;
		int	des;

		malloc_strcpy(&motd, irc_lib);
		malloc_strcat(&motd, MOTD_FILE);
		if (stat(motd, &motd_stat) == 0)
		{
			u_char	*s = (u_char *) 0;

			malloc_strcpy(&s, my_path);
#ifdef __MSDOS__
			malloc_strcat(&s, "/ircmotd.red");
#else
			malloc_strcat(&s, "/.ircmotd");
#endif /* __MSDOS__ */
			if (stat(s, &my_stat))
			{
				my_stat.st_atime = 0L;
				my_stat.st_mtime = 0L;
			}
			unlink(s);
			if ((des = open(s, O_CREAT, S_IREAD | S_IWRITE))
					!= -1)
				new_close(des);
			new_free(&s);
			if (motd_stat.st_mtime > my_stat.st_mtime)
			{
				put_file(motd);
		/* Thanks to Mark Dame <mdame@uceng.ec.edu> for this one */

#if defined(PAUSE_AFTER_MOTD) && PAUSE_AFTER_MOTD
		input_pause("********  Press any key to continue  ********");
#endif
				clear_window_by_refnum(0);
			}
		}
		new_free(&motd);
	}
#endif /* MOTD_FILE */

/**************************** Patched by Flier ******************************/
        Logo(NULL,NULL,NULL);
/****************************************************************************/
	if (bflag)
	{
		loading_global = 1;
/**************************** Patched by Flier ******************************/
		/*load(empty_string, "global", empty_string);*/
		load(empty_string, "szglobal", empty_string);
/****************************************************************************/
		loading_global = 0;
		load_ircrc();
	}

	get_connected(0, 0);
        if (channel)
	{
		char    *ptr;
 
		ptr = strtok(channel, ",");
		if (is_channel(ptr))
/**************************** Patched by Flier ******************************/
			/*add_channel(ptr, 0, CHAN_LIMBO, (ChannelList *) 0);*/
			add_channel(ptr, 0, CHAN_LIMBO, NULL, NULL, 0);
/****************************************************************************/
		while ((ptr = strtok(NULL,",")) != NULL)
			if (is_channel(ptr))
/**************************** Patched by Flier ******************************/
				/*add_channel(ptr, 0, CHAN_LIMBO, (ChannelList *) 0);*/
				add_channel(ptr, 0, CHAN_LIMBO, NULL, NULL, 0);
/****************************************************************************/
		new_free(&channel);
	}
	idle_time = time(0);
	set_input(empty_string);
#ifndef _Windows
	irc_io(get_string_var(INPUT_PROMPT_VAR), NULL, use_input, irc_io_loop);
/**************************** PATCHED by Flier ******************************/
        /*irc_exit();*/
        irc_exit(0);
/****************************************************************************/
#endif /* _Windows */
 	return 0;
}

/* 
 * set_irchost: This sets the source host for subsequent connections.
 */
void
set_irchost ()
{
	char *irchost;

	irchost = get_string_var(IRCHOST_VAR);

	if (!irchost || !*irchost)
		source_host = NULL;
	else
		malloc_strcpy(&source_host, irchost);

	process_hostname();
}
