/******************************************************************************
 * This file is part of a software distribution, which is furnished under the *
 * terms of a license.  Use of this software  by any means is subject to this *
 * license  and  signifies  the  acceptance of  the  licensing  terms  stated *
 * therein. Please see  the file LICENSE in the  top-level directory  of this *
 * software  distribution  for detailed copyright  disclaimers  and licensing *
 * terms.                                                                     *
 ******************************************************************************
 * Copryight (c) by Andreas S. Wetzel - All rights reserved.                  *
 ******************************************************************************/

/* $Id: vd_main.c,v 1.3 2001/04/09 21:00:17 mickey Exp $ */

#include <vchat.h>
#include <proto_vchatd.h>

#include <signal.h>
#include <arpa/inet.h>

/*** Globals ***/

VP	vp;
VD	vd;
VCONN	sconn;

char	*prog_name;

char 	hostname[32];
char	nlstr[] = "\r\n";

struct	in_addr our_ipaddr;
struct	sockaddr_in tel_sock_in;

/*** Externals ***/

extern int errno;

extern int sock;

extern ED	main_ed;
extern ED	*ed;
extern VTCAP	vtcap;

/*** Code ***/

int main(int argc, char *argv[])
{
	u_char	pwdbuf[VPPASSWDSIZE+1];
	u_char	*offmsg = NULL;
	char	tstring[256];
	u_int	len;
	int	ret;

#if HAVE_SIGACTION
	struct sigaction sa;
#else
	struct sigvec sv;
#endif

	BZERO(&vp, sizeof(VP));
	BZERO(&vd, sizeof(VD));

	/*
	 * Initialize certain variables at this point...
	 */

	if((prog_name = (char *)strrchr(argv[0], '/')) != NULL)
		prog_name++;
	else
		prog_name = argv[0];

	/*
	 * Set unbuffered output,
	 * so we wont have to mess
	 * up with lots of fflush'es.
	 */

	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stdin, NULL, _IONBF, 0);

	vd.my_pid = getpid();
	vp.sv_port = SERVER_PORT;
	vd.emu_ok = 0;

	/*
	 * Set some nice defaults
	 */

	vp.bs_mode		= 0;	/* Block backspace		*/
	vp.sc_mode		= 0;	/* Character scrolling		*/
	vp.word_wrap		= 1;	/* Word wrap on			*/
	vp.indent		= 1;	/* Indentation on		*/
	vp.hicolor		= 1;	/* High intens colors		*/
	vp.cursordelay		= 3;    /* 3 sec cursordelay		*/
	vp.videosnake		= 2;	/* Videosnake 2 mins		*/

	vp.history_lines = HISTORY_LINES; /* Command history lines	*/

	/*
	 * Initialize input context
	 */

	clear_ed(&main_ed);

	/*
	 * Set the environment TERMINFO if FORCE_LOCAL_TERMINFO is defined
	 */

#ifdef FORCE_LOCAL_TERMINFO

	sprintf(tstring, "TERMINFO=%s", FORCE_LOCAL_TERMINFO);

	if(putenv(tstring))
	{
		printf("%s: unable to set TERMINFO variable\r\n", prog_name);
		vsleep(VCHATD_WAITONEXIT, 0);
		return(-1);
	}
#endif

	/* Get parameters from commandline */
	/* and startup ...                 */

	init_tel_opts();

	if(get_param(argc, argv) || init_telnet_conn() || negotiate_telopts()
	|| request_termtype())
	{
		vsleep(VCHATD_WAITONEXIT, 0);
		return(-1);
	}

	sprintf(tstring, "TERM=%s", vp.emulation);

	if(putenv(tstring))
	{
		printf("%s: unable to set TERM variable.\r\n", prog_name);
		vsleep(VCHATD_WAITONEXIT, 0);
		return(-1);
	}

	log(VLOG_INFO, "Using terminal type %s", vp.emulation);

	if(init_vtcap())
	{
		vsleep(VCHATD_WAITONEXIT,0);
		return(-1);
	}

	show_banner();

	printf("%s", nlstr);

nickretry:

	if(query_nickname())
	{
		vsleep(VCHATD_WAITONEXIT, 0);
		return(-1);
	}

	/*
	 * Query password
	 */

	BZERO(pwdbuf, VPPASSWDSIZE+1);

	printf("%sEnter password for '%s' at server %s%s",
		nlstr, vp.nick, iptoname(vp.sv_ip), nlstr);
	printf("If you do not have a password, just press ENTER%s%s",
		nlstr, nlstr);

	printf("Password: ");
	fflush(stdout);

	if(get_user_input(pwdbuf, VPPASSWDSIZE, 0) == -1)
	{
		vsleep(VCHATD_WAITONEXIT, 0);
		return(-1);
	}

	printf("%s%s", nlstr, nlstr);

	/*
	 * Connect server
	 */

	printf("Trying %s:%d...", inet_ntoa(vp.sv_ip), vp.sv_port);
	fflush(stdout);

	ret = connect_server(&sconn, &vp.sv_ip, vp.sv_port, VSERVER_MAGIC, pwdbuf);

	BZERO(pwdbuf, VPPASSWDSIZE+1);

	switch(ret)
	{
		case -1:
		{
			printf("%sConnect failed (%s)%s%s",
				nlstr, strerror(errno),	nlstr, nlstr);
			vsleep(VCHATD_WAITONEXIT, 0);
			return(-1);
		}
		case CONN_OK:
		{
			break;
		}
		case CONN_ENDUP:
		case CONN_ENSIZE:
		case CONN_ENINVAL:
		{
			printf("%s%s%s%s", nlstr, v_error(ret), nlstr, nlstr);
			goto nickretry;
		}
		default:
		{
			printf("%s%s%s%s", nlstr, v_error(ret), nlstr, nlstr);
			vsleep(VCHATD_WAITONEXIT, 0);
			return(-1);
		}
	}

	/*
	 * Initialize command history buffer
	 */

	history_init();

	/*
	 * Switch terminal to META mode if possible
	 */

	if(vtcap.metamode_on)
		tputs(vtcap.metamode_on, 1, (void *)outc);

	/*
	 * Switch cursor keys to application mode
	 */

	keymode(1);

	/*
	 * Initilize status bar
	 */

	init_status();

	/*
	 * Initialize screen
	 */

	screen_init();

	vd.resize_ok = 0xff;

	/*
	 * We will silently ignore SIGINT as
	 * well as SIGQUIT for this session.
	 */

#if HAVE_SIGACTION
	sa.sa_handler = SIG_IGN;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTSTP, &sa, NULL);
#else
	sv.sv_handler = SIG_IGN;
	sigemptyset(&sv.sv_mask);
	sv.sv_flags = 0;

	sigvec(SIGINT, &sv, NULL);
	sigvec(SIGTSTP, &sv, NULL);
#endif
	/*
	 * Get any information already waiting on socket
	 */

	rcv_sv_msg();

	/*
	 * Initialize asynchronous I/O, timer event
	 * and window size change handlers.
	 */

	pbc_disable();

	v_io_init();
	v_timer_init();

	/*
	 * Add a 1 sec delay to catch a SUBMIT_TOPIC message
         * the server possibly sends before we are stuck in
         * the input_line() function. This is to avoid loosing
         * the first character after a topic has been entered.
	 */

	vsleep(1, 0);

	/*
	 * Main loop.
	 * Get user input and handle commands
	 */

	for(;;)
	{
		/*
		 * Get user input
		 */

		clear_ed(ed);
uinp:
		len = input_line(NULL, 0, (ED_HISTORY));

		if(!len)
		{
			continue;
		}
		else if(len == -2)	/*** History UP ***/
		{
			/*
			 * If we are at end of history then we will have
			 * to save the contents of the current input line 
			 * (if any) in order to have the ability to scroll 
			 * back down to this line. In any case the buffer
			 * indexed by vp.history_next must be freed if it
			 * has already been in use.
			 */

			if(vp.history_current == vp.history_next)
			{
				/*
				 * Free current buffer if already used
				 */

				if(vp.history[vp.history_next] != NULL)
				{
					free(vp.history[vp.history_next]);
					vp.history[vp.history_next] = NULL;
				}

				/*
				 * If the input line was not empty to the
				 * time when the user pressed the HISTORY
				 * UP key then save it into the current
				 * history position, so that we can scroll
				 * down back to it later.
				 */

				len = strlen(ed->buffer);

				if(len)
				{
					u_char	*newbuf;

					/*
					 * Allocate a new buffer
					 */

					if((newbuf = (u_char *)calloc(1, len+1)) != NULL)
					{
						strncpy(newbuf, ed->buffer, len);
						vp.history[vp.history_next] = newbuf;
					}
				}
			}

			/*
			 * Shift current position up one place
			 */

			if(vp.history_current == 0)
				vp.history_current = (vp.history_lines - 1);
			else
				--vp.history_current;

			/*
			 * Copy history buffer into current input
			 * buffer and re-edit this line
			 */

			clear_ed(ed);

			strcpy(ed->buffer, vp.history[vp.history_current]);
			ed->endpos += strlen(ed->buffer);
			ed->curpos = ed->endpos;

			if((ed->endpos - ed->margin) >= vtcap.cols)
				ed->margin = (ed->endpos - (vtcap.cols - 1));

			goto uinp;
		}
		else if(len == -4)	/*** History DOWN ***/
		{
			/*
			 * Shift current position one place down
			 */

			if(++vp.history_current >= vp.history_lines)
				vp.history_current = 0;

			/*
			 * Copy history buffer into current input buffer
			 */

			clear_ed(ed);

			if(vp.history[vp.history_current] != NULL)
			{
				strcpy(ed->buffer, vp.history[vp.history_current]);
				ed->endpos += strlen(ed->buffer);
				ed->curpos = ed->endpos;

				if((ed->endpos - ed->margin) >= vtcap.cols)
					ed->margin = (ed->endpos - (vtcap.cols - 1));
			}

			goto uinp;
		}

		/*
		 * Save commandline in history buffer
		 */

		history_save(ed->buffer);

		/*
		 * Process user input
		 */

		if(ed->buffer[0] == '.' && ed->buffer[1] != 'x')
		{
			handle_cmd(ed->buffer);
		}
		else if(ED_USED == 2 && ed->buffer[0] == '.' && ed->buffer[1] == 'x') 
		{
			break;
		}
		else if(ed->buffer[0] == '.' && ed->buffer[1] == 'x')
		{
			offmsg = &ed->buffer[3];
			break;
		}
		else
		{
			snd_serv(CMD_PUBMSG, ed->buffer, len);
		}
	}

	/*
	 * Diasble asynchronous I/O, send
	 * signoff command and exit program
	 */

	v_io_end();

	snd_serv(CMD_SIGNOFF, offmsg, (offmsg) ? strlen(offmsg) : 0);

	vquit("Have a nice day ...");

	/*** UNREACHED ***/

	return(0);
}


syntax highlighted by Code2HTML, v. 0.9.1