/****************************************************************************** * 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 #include #include #include /*** 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); }