/******************************************************************************
* 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