int main()
{
  char s[] = "";
  int x;

  x = string_printable(s);
  printf("%d\n", x);

  return 0;
}
Exemplo n.º 2
0
/* SM3 */
static int sm_rx_getdat(s_rx_emsidat *d)
{
	int rc = 0;
	int pos = 0;
	int emsi_len = 0;
	short unsigned ourcrc;
	short unsigned remcrc;
	char *emsi_dat = NULL;
	
	if( d->tries_recv++ )
		log("emsi data receive - retry %d", d->tries_recv);
	
	/*
	 * At this point, there is a EMSI_DATXXXX packet in
	 * the buffer, there XXXX is the hex length of emsi
	 * data packet
	 */
	if( strspn(d->buf+8, "0123456789abcdefABCDEF") != 4 )
		return SM1;
	
	if( sscanf(d->buf+8, "%04x", &emsi_len) != 1 )
		return SM1;
	
	/*
	 * Don't receive emsi packet's longer our "limit"
	 */
	if( emsi_len > EMSI_MAXDAT )
	{
		CLEARIN();
		log("emsi data packet too long %db (maximum %db allowed)",
				emsi_len, EMSI_MAXDAT);
		return SM1;
	}
	
	/* Increase packet's length on CRC length */
	emsi_len += 16;
	
	emsi_dat = (char*)xmalloc(emsi_len + 1);
	strncpy(emsi_dat, d->buf, 12);
	pos = 12;
	
	while( pos < emsi_len )
	{
		if( timer_expired(d->mast_timer) )
			break;
		
		if( (rc = GETCHAR(1)) < 0 )
		{
			if( rc != TTY_TIMEOUT )
				break;
		}
		else
		{
			emsi_dat[pos++] = (unsigned char)rc;
			emsi_dat[pos  ] = '\0';
		}
	}
	
	if( pos != emsi_len )
	{
		/* Fatal error occured */
		DEB((D_HSHAKE, "sm_rx_getdat: can't get emsi_dat packet"));
		DEB((D_HSHAKE, "sm_rx_getdat: buffer: \"%s\"",
				string_printable(emsi_dat)));
		free(emsi_dat);
		return SME;
	}

	DEB((D_HSHAKE, "sm_rx_getdat: got \"%s\"",
			string_printable(emsi_dat)));

	/*
	 * Get CRC given by remote
	 */
	if( sscanf(emsi_dat + emsi_len - 4 , "%04hX", &remcrc) != 1 )
	{
		log("bad emsi data packet (can't get CRC16)");
		free(emsi_dat);
		
		return(SM1);
	}
	
	/*
	 * Calculate our own crc of the data packet
	 */
	ourcrc = getcrc16xmodem(emsi_dat, emsi_len-4);
	
	/*
	 * Compare our and remote CRCs
	 */
	if( ourcrc != remcrc )
	{
		DEB((D_HSHAKE, "sm_rx_getdat: our = %hX, remote = %hX",	ourcrc, remcrc));
		log("got emsi data packet with bad CRC");
		free(emsi_dat);
		
		return SM1;
	}
	
	/*
	 * Parse received emsi data packet. All obtained
	 * information will be stored in d->remote_emsi
	 */
	rc = emsi_parsedat(emsi_dat+12, d->remote_emsi);
	
	free(emsi_dat);
		
	if( rc )
	{
		log("received invalid emsi data packet");
		return SM1;
	}
	
	/* Send acknowlegment */
	if( PUTSTR("**EMSI_ACKA490\r**EMSI_ACKA490\r") < 0 )
		return SME;
	if( FLUSHOUT() < 0 )
		return SME;
	
	return SM0;
}
Exemplo n.º 3
0
int exec_command(s_exec_options *eopt)
{
	pid_t pid = 0;
	int status = 0;
	time_t starttime = 0;
	time_t timer = 0;
	char *tempfile = NULL;
	struct sigaction new_chld;
	struct sigaction old_chld;
	sigset_t new_mask;
	sigset_t old_mask;
	
	if( eopt->command == NULL )
		return -1;
	
	if( eopt->options & EXEC_OPT_LOGOUT )
	{
		tempfile = file_gettmp();
		if( !tempfile )
			log("cannot generate temporary file name");
	}

	/* Block SIGCHLD */
	sigemptyset(&new_mask);
	sigaddset(&new_mask, SIGCHLD);
	sigprocmask(SIG_BLOCK, &new_mask, NULL);
	
	/* Set the default SIGCHLD handler */
	new_chld.sa_handler = SIG_DFL;
	sigaction(SIGCHLD, &new_chld, &old_chld);

	if( (pid = fork()) == -1 )
	{
		logerr("exec error: cannot fork()");
		return -1;
	}

	if( !pid )
	{
		if( exec_redirect_descriptor(0, "/dev/null", O_RDONLY) == -1 )
			exit(128);
		
		if( tempfile )
		{
			if( exec_redirect_descriptor(1, tempfile, O_WRONLY|O_CREAT|O_TRUNC) == -1
			 || exec_redirect_descriptor(2, tempfile, O_WRONLY) == -1 )
				exit(128);
		}
		else
		{
			if( exec_redirect_descriptor(1, "/dev/null", O_WRONLY) == -1
			 || exec_redirect_descriptor(2, "/dev/null", O_WRONLY) == -1 )
				exit(128);
		}

		if( eopt->options & EXEC_OPT_SETSID )
			setsid();
		
		if( eopt->options & EXEC_OPT_USESHELL )
			execle("/bin/sh", "sh", "-c", eopt->command, NULL, eopt->envp);
		else
		{
			char *argv[EXEC_MAX_NUM_ARGS+1];
			int argc = string_parse_regular(argv, EXEC_MAX_NUM_ARGS,
			                                eopt->command);
			if( argc > 0 )
			{
				argv[argc] = NULL;
				execve(argv[0], argv, eopt->envp);
			}
			/* eopt->command is corrupted now */
		}
		
		/* We get here only in case of errors */
		logerr("cannot execute \"%s\"", eopt->command);
		
		exit(128);
	}
	
	/*
	 * We are inside parent process, do:
	 * 
	 * 1) if OUTMODE_LOGPIPE is used than log child process ouput
	 * 2) wait for child process to exit
	 */

	log("running \"%s\", PID %d",
		string_printable(eopt->command), (int)pid);

	if( !(eopt->options & EXEC_OPT_NOWAIT) )
	{
		starttime = time(NULL); /* Set process start time */
		
		if( waitpid(pid, &status, 0) > 0 )
		{
			eopt->runtime = time(NULL) - starttime;
	
			if( eopt->runtime < 0 )
				eopt->runtime = 0;

			/*
			 * Write process's output to the log file
			 */
			if( tempfile )
			{
				char buf[256];
				FILE *fp = file_open(tempfile, "r");

				if( !fp )
					logerr("cannot open temporary file \"%s\"", tempfile);
				else
				{
					while( fgets(buf, sizeof(buf), fp) )
					{
						string_chomp(buf);
						log("[%d] %s", pid, string_printable(buf));
					}
					file_close(fp);
				}
			}

			if( WIFEXITED(status) )
			{
				eopt->retc = WEXITSTATUS(status);
				log("process %d exit with code %d (%d seconds)",
					(int)pid, eopt->retc, eopt->runtime);
			}
			else if( WIFSIGNALED(status) )
			{
				eopt->retc = -1;
				log("process %d terminated on signal %d (%d seconds)",
					(int)pid, WTERMSIG(status), eopt->runtime);
			}
			else
			{
				eopt->retc = -1;
				log("process %d return with unknown status (%d seconds)",
					(int)pid, eopt->runtime);
			}
		}
		else
		{
			eopt->retc = -1;
			logerr("waitpid return error for PID %d", (int)pid);
		}
	}

	if( tempfile )
	{
		if( unlink(tempfile) == -1 && errno != ENOENT )
			logerr("cannot unlink temporary file \"%s\"", tempfile);
		free(tempfile);
	}

	/* Restore the original SIGCHLD handler */
	sigaction(SIGCHLD, &old_chld, NULL);

	/* Unblock SIGCHLD */
	sigprocmask(SIG_UNBLOCK, &new_mask, NULL);
	
	return eopt->retc;
}
Exemplo n.º 4
0
/* SM2 */
static int sm_rx_waitseq(s_rx_emsidat *d)
{
	int rc, pos = 0;
	
	timer_set(&d->sync_timer, 20);

	while(1)
	{
		if( timer_expired(d->mast_timer) )
		{
			DEB((D_HSHAKE, "sm_rx_waitseq: master timer expired"));
			log("master timer expired");
			return SME;
		}
		
		if( timer_expired(d->sync_timer) )
		{
			DEB((D_HSHAKE, "sm_rx_waitseq: sync timer expired"));
			return SM1;
		}
		
		if( (rc = GETCHAR(1)) < 0 )
		{
			if( rc != TTY_TIMEOUT )
			{
				DEB((D_HSHAKE, "sm_rx_waitseq: got ERROR/HANGUP"));
				return SME;
			}
		}
		else if( rc == XON || rc == XOFF )
		{
			/* Do nothing. Drop them down */
		}
		else if( rc == '*' )
		{
			memset(d->buf, '\0', sizeof(d->buf));
			pos = 0;
			d->emsi_seq = 1;
		}
		else if( d->emsi_seq && rc > ' ' && rc < '~' )
		{
			if( pos < sizeof(d->buf)-1 )
			{
				d->buf[pos++] = rc;
				d->buf[pos  ] = '\0';
			}
			
			if( pos == sizeof(d->buf)-1 )
			{
				DEB((D_HSHAKE, "sm_rx_waitseq: emsi buffer full \"%s\"", d->buf));
				
				d->emsi_seq = 0;
				
				if( d->caller && !strncasecmp(d->buf, "EMSI_ACKA490", 12) )
				{
					/* Do nothing. Drop it down. */
				}
				else if( !strncasecmp(d->buf, "EMSI_HBTEAEE", 12) )
				{
					/*
					 * Remote wants some time to think
					 */
					return SM2;
				}
				else if( !strncasecmp(d->buf, "EMSI_DAT", 8) )
				{
					/*
					 * Start receiving emsi data packet
					 */
					return SM3;
				}
#ifndef BUGGY_EMSI			      
				else if( !strncasecmp(d->buf, "EMSI_INQC816", 12) )
				{
				        return SM1;
				}
#endif /*BUGGY_EMSI*/				
				else
				{
					DEB((D_HSHAKE, "got unexpected emsi sequence: \"%s\"",
							string_printable(d->buf)));
					log("got unexpected emsi sequence \"%s\"",
							string_printable(d->buf));
				}
			}
		}
		else if( d->emsi_seq )
		{
			d->emsi_seq = 0;
			DEB((D_HSHAKE, "sm_rx_waitseq: bad character 0x%02x in \"%s\"",
					rc, string_printable(d->buf)));
		}
	}

	return SME;
}
Exemplo n.º 5
0
/* SM2 */
static int sm_tx_waitseq(s_tx_emsidat *d)
{
	int rc, pos = 0;
	
	timer_set(&d->sync_timer, (d->tries > 1) ? 20 : 10);
	
	while(1)
	{
		if( timer_expired(d->mast_timer) )
		{
			DEB((D_HSHAKE, "sm_tx_waitseq: master timer expired"));
			log("master timer expired");
			return(SME);
		}
		
		if( timer_expired(d->sync_timer) )
		{
			DEB((D_HSHAKE, "sm_tx_waitseq: sync timer expired"));
			return(SM1);
		}
		
		if( (rc = GETCHAR(1)) < 0 )
		{
			if( rc != TTY_TIMEOUT )
			{
				DEB((D_HSHAKE, "sm_rx_waitseq: got ERROR/HANGUP"));
				return SME;
			}
		}
		else if( rc == XON || rc == XOFF )
		{
			/* Do nothing. Drop them down */
		}
		else if( rc == '*' )
		{
			memset(d->buf, '\0', sizeof(d->buf));
			pos = 0;
			d->emsi_seq = 1;
		}
		else if( d->emsi_seq && rc > ' ' && rc < '~' )
		{
			if( pos < sizeof(d->buf)-1 )
			{
				d->buf[pos++] = rc;
				d->buf[pos  ] = '\0';
			}
			
			if( pos == (sizeof(d->buf) - 1) )
			{
				DEB((D_HSHAKE, "sm_tx_waitseq: emsi buffer full \"%s\"", d->buf));
				
				d->emsi_seq = 0;
				
				if( !strncasecmp(d->buf, "EMSI_REQA77E", 12) )
				{
					/* Do nothing. Drop it down */
				}
				else if( !strncasecmp(d->buf, "EMSI_ACKA490", 12) )
				{
					/*
					 * Remote acknowleged our
					 * emsi data packet. exit.
					 */
					return SM0;
				}
				else if( !strncasecmp(d->buf, "EMSI_NAKEEC3", 12) )
				{
					/*
					 * Remote failed on our emsi data
					 * packet. Resend EMSI_DAT only after
					 * first EMSI_NAK
					 */
					DEB((D_HSHAKE, "sm_tx_waitseq: got NAK"));
					if( !d->nakcount++ )
						return SM1;
				}
				else if( !strncasecmp(d->buf, "EMSI_INQC816", 12) )
				{
					/*
					 * Do nothing. Just update sync timer
					 */
					return SM2;
				}
				else if( !strncasecmp(d->buf, "EMSI_DAT", 8) )
				{
					/*
					 * 1) We are calling system
					 * We got an echo of our sequence,
					 * possible they don't know about
					 * FIDO. yet :) Resend EMSI_INQ
					 * again.
					 * 2) We are asnwering system
					 * Think where is a stupid mailer
					 * that didn't seen our EMSI_ACK,
					 * so send it again in hope to the
					 * best
					 */
					DEB((D_HSHAKE, "sm_tx_waitseq: got echo \"%s\"",
							string_printable(d->buf)));

					if( d->caller )
					{
						/* Wait for a login prompt */
						sleep(2);
						
						if( PUTSTR("**EMSI_INQC816\r") < 0
						 || FLUSHOUT() < 0 )
							return SME;

						/* Wait for a password prompt */
						sleep(2);
						
						if( PUTSTR("**EMSI_INQC816\r") < 0
						 || FLUSHOUT() < 0 )
							return SME;
						
						return SM1;
					}
					else
					{
						/* Send acknowlegment */
						if( PUTSTR("**EMSI_ACKA490\r**EMSI_ACKA490\r") < 0 )
							return SME;
						if( FLUSHOUT() < 0 )
							return SME;
					}
				}
				else
				{
					DEB((D_HSHAKE, "got unexpected emsi sequence: \"%s\"",
							string_printable(d->buf)));
					log("got unexpected emsi sequence \"%s\"",
							string_printable(d->buf));
				}
			}
		}
		else if( d->emsi_seq )
		{
			d->emsi_seq = 0;
			DEB((D_HSHAKE, "sm_tx_waitseq: bad character 0x%02x in \"%s\"",
					rc, string_printable(d->buf)));
		}
	}

	return SME;
}
Exemplo n.º 6
0
void binkp_log_sysinfo(s_binkp_sysinfo *binkp)
{
	int i;
	char abuf[BF_MAXADDRSTR+1];
	
	for( i = 0; i < state.n_remoteaddr; i++ ) {
		log("   Address : %s", ftn_addrstr(abuf, state.remoteaddrs[i].addr));
	}
	
	if( *binkp->systname && *binkp->phone )
		log("    System : %s (%s)",
			string_printable(binkp->systname),
			string_printable(binkp->phone));
	else if( *binkp->systname )
		log("    System : %s",
			string_printable(binkp->systname));
	else if( *binkp->phone )
		log("     Phone : %s",
			string_printable(binkp->phone));

#ifdef BFORCE_LOG_PASSWD
	if( *binkp->passwd )
		log("  Password : %s", string_printable(binkp->passwd));
#endif

	if( *binkp->opt )
		log("   Options : %s", string_printable(binkp->opt));

	if( *binkp->sysop && *binkp->location )
		log("     SysOp : %s from %s",
			string_printable(binkp->sysop),
			string_printable(binkp->location));
	else if( *binkp->sysop )
		log("     SysOp : %s",
			string_printable(binkp->sysop));
	else if( *binkp->location )
		log("  Location : %s",
			string_printable(binkp->location));

	if( *binkp->progname )
	{
		log("    Mailer : %s (%s/%d.%d)",
			*binkp->progname ? string_printable(binkp->progname) : "?",
			*binkp->protname ? string_printable(binkp->protname) : "?",
			binkp->majorver, binkp->minorver);
	}
	if( *binkp->flags )
		log("     Flags : %s", string_printable(binkp->flags));
	if( *binkp->timestr )
		log("      Time : %s", string_printable(binkp->timestr));
}
Exemplo n.º 7
0
/* ------------------------------------------------------------------------- */
int session_init_incoming()
{
	int    c = 0;
	int    pos = 0;
	bool   canemsi = FALSE;
	bool   canyoohoo = FALSE;
	bool   canftsc = FALSE;
	char   buf[13];
	int    emsi_seq = 0;      /* start reading emsi sequence     */
	int    yoohoo_count = 0;  /* number of ENQ received          */
	int    tsync_count  = 0;  /* number of NAK or 'C' received   */
	int    yoohoo_need = 1;
	int    tsync_need = 1;
	time_t mast_timer = 0;    /* master timer, seems to be 60sec */
	time_t sync_timer = 0;
	long   options = conf_options(cf_options);
	int    unexp_count = 0;

	state.session = SESSION_UNKNOWN;
	
	//log("init");
	
	if( (options & OPTIONS_NO_EMSI) != OPTIONS_NO_EMSI ) {
		//log("can emsi");
		canemsi = TRUE;
	}
	if( (options & OPTIONS_NO_YOOHOO) != OPTIONS_NO_YOOHOO ) {
		//log("can yahoo");
		canyoohoo = TRUE;
	}
	if( (options & OPTIONS_NO_FTS1) != OPTIONS_NO_FTS1 ) {
		//log("can ftsc");
		canftsc = TRUE;
	}
	
	yoohoo_need = canemsi ? 2 : 1;
	tsync_need = (canemsi || canyoohoo) ? 2 : 1;

	if( PUTCHAR('\r') < 0 ) {
		log("error: cannot put char");
		return 1;
	}
	
	/*
	 * Output banner
	 */
	if( canemsi && PUTSTR("**EMSI_REQA77E\r") < 0 ) {
		log("error: cannot put banner");
		return 1;
	}

	if( state.connstr )
	{
		/* Show connect string */
		if( PUTCHAR('[') < 0 ) {
			log("error: cannot put ']'");
			return 1;
		}
		if( PUTSTR(state.connstr) < 0 ) {
			log("error: cannot put connstr");
			return 1;
		}
		if( PUTSTR("]\n") < 0 ) {
			log("error: cannot put ']'");
			return 1;
		}
	}
	
	if( PUTSTR(BF_BANNERVER) < 0 || PUTCHAR(' ') < 0
	 || PUTSTR(BF_COPYRIGHT) < 0 || PUTCHAR('\n') < 0 ) {
		log("session_init_incoming error: output");
		return 1;
	}

	if( FLUSHOUT() < 0 ) {
		log("session_init_incoming error: flush");
		return 1;
	}
	
	/* Start timers */
	timer_set(&mast_timer, INCOMING_MAST_TIMER);
	timer_set(&sync_timer, INCOMING_SYNC_TIMER/2);
	
	/*
	 * Determine supported handshakes on called system
	 * (support for FTS-1, YooHoo, EMSI)
	 */
	 
	//log("begin loop");
	while(1)
	{
		if( timer_expired(mast_timer) )
		{
			log("session initialisation timed out");
			DEB((D_HSHAKE, "handshake initialisation timed out"));
			
			return 1;
		}
		
		if( timer_expired(sync_timer) )
		{
			DEB((D_HSHAKE, "rx_init: resyncing"));
			
			if( canemsi && PUTSTR("**EMSI_REQA77E\r") < 0 ) {
				log("session_init_incoming error: output");
				return 1;
			}

			if( FLUSHOUT() < 0 ) {
				log("session_init_incoming error: flush");
				return 1;
			}
			
			timer_set(&sync_timer, INCOMING_SYNC_TIMER);
		}
		
		/*
		 * Pickup next char
		 */
		if( (c = GETCHAR(1)) < 0 )
		{
			if( c != TTY_TIMEOUT )
			{
				DEB((D_HSHAKE, "rx_init: got TTY_ERROR/TTY_HANGUP"));
				return 1;
			}				
		}
		else if( c == XON || c == XOFF )
		{
			/* Do nothing. Drop them down */
		}
		else if( c == YOOHOO )
		{
			if( ++yoohoo_count >= yoohoo_need && canyoohoo )
			{
				DEB((D_HSHAKE, "rx_init: exit with YooHoo"));
				state.session = SESSION_YOOHOO;
				
				return 0;
			}
		}
		else if( c == TSYNC )
		{
			if( ++tsync_count > tsync_need && canftsc )
			{
				DEB((D_HSHAKE, "rx_init: exit with FTS-1"));
				state.session = SESSION_FTSC;
				
				return 0;
			}
		}
		else if( canemsi && c > ' ' && c < '~' )
		{
			tsync_count = 0;
			yoohoo_count = 0;
			
			if( c == '*' )
			{
				memset(buf, '\0', sizeof(buf));
				pos = 0;
				emsi_seq = 1;
			}
			else if( emsi_seq )
			{
				if( pos < sizeof(buf)-1 )
				{
					buf[pos++] = (char)(c & 0xff);
					buf[pos  ] = '\0';
				}
			
				if( pos >= sizeof(buf)-1 )
				{
					emsi_seq = 0;
					
					DEB((D_HSHAKE, "rx_init: emsi buffer full \"%s\"",
							string_printable(buf)));
					
					if( !strncasecmp(buf, "EMSI_INQC816", 12) )
					{
						DEB((D_HSHAKE, "rx_init: exit with EMSI"));
						state.session = SESSION_EMSI;
						
						return 0;
					}
					else if( !strncasecmp(buf, "EMSI", 4) )
					{
						log("unexpected emsi sequence \"%s\"",
								string_printable(buf));
						
						if( ++unexp_count > 10 )
						{
							log("too many unexpected emsi sequences");
							return 1;
						}
					}
				}
			}
		}
		else if( emsi_seq )
		{
			emsi_seq = 0;
			DEB((D_HSHAKE, "rx_init: bad character 0x%02x in \"%s\"",
					c, string_printable(buf)));
		}
	}
	
	return 1;
}
Exemplo n.º 8
0
/* ------------------------------------------------------------------------- */
int session_init_outgoing()
{
	int    c = 0;
	int    tries = 0;
	int    pos_emsi = 0;
	int    pos_intro = 0;
	bool   canemsi = FALSE;
	bool   canyoohoo = FALSE;
	bool   canftsc = FALSE;
	bool   canintro = FALSE;
	char   buf_emsi[13];
	char   buf_intro[256];
	int    emsi_seq = 0;    /* start reading emsi sequence     */
	int    enqcount = 0;    /* number of ENQ received          */
	int    nakcount = 0;    /* number of NAK or 'C' received   */
	int    enq_need = 1;
	int    nak_need = 1;
	time_t mast_timer = 0;  /* master timer, seems to be 60sec */
	time_t sync_timer = 0;  /* resync every .. seconds         */
	long   options = conf_options(cf_options);
	int    intro_lines = 0;
	int    intro_count = 0;
	int    unexp_count = 0;

	state.session = SESSION_UNKNOWN;
	
	if( (options & OPTIONS_NO_EMSI) != OPTIONS_NO_EMSI )
		canemsi = TRUE;
	if( (options & OPTIONS_NO_YOOHOO) != OPTIONS_NO_YOOHOO )
		canyoohoo = TRUE;
	if( (options & OPTIONS_NO_FTS1) != OPTIONS_NO_FTS1 )
		canftsc = TRUE;
	if( (options & OPTIONS_NO_INTRO) != OPTIONS_NO_INTRO )
		canintro = TRUE;
	
	enq_need = canemsi ? 2 : 1;
	nak_need = (canemsi || canyoohoo) ? 2 : 1;
	
	/*
	 * Put CR until any character received
	 */
	if( PUTCHAR('\r') < 0 || FLUSHOUT() < 0 ) {
		log("error: output");
		return 1;
	}
	
	while( !CHARWAIT(1) )
	{
		if( ++tries > 15 )
		{
			log("too much tries waking remote");
			return 1;
		}
		
		if( PUTCHAR('\r') < 0 || FLUSHOUT() < 0 ) {
			log("error: output");
			return 1;
		}
	}
	
#ifdef DEBUG
	if( tries > 0 )
		DEB((D_HSHAKE, "tx_init: remote waked on %d try", tries));
#endif
	
	/*
	 * Safety is the 1st law
	 */
	*buf_emsi = '\0';
	*buf_intro = '\0';
	
	/*
	 * Start timers
	 */
	timer_set(&mast_timer, OUTGOING_MAST_TIMER);
	timer_set(&sync_timer, OUTGOING_SYNC_TIMER*2);

	/*
	 * Determine supported handshakes on called system
	 * (support for FTS-1, YooHoo, EMSI)
	 */
	while(1)
	{
		if( timer_expired(mast_timer) )
		{
			log("session initialisation timed out");
			DEB((D_HSHAKE, "handshake initialisation timed out"));
			
			return 1;
		}
		
		if( timer_expired(sync_timer) )
		{
			DEB((D_HSHAKE, "tx_sendsync: resyncing"));
			
			if( canemsi && PUTSTR("**EMSI_INQC816**EMSI_INQC816") < 0 ) {
				log("error: output");
				return 1;
			}
			if( canyoohoo && PUTCHAR(YOOHOO) < 0 ) {
				log("error: output");
				return 1;
			}
			if( canftsc && PUTCHAR(TSYNC) < 0 ) {
				log("error: output");
				return 1;
			}
			if( canemsi && PUTCHAR('\r') < 0 ) {
				log("error: output");
				return 1;
			}

			if( FLUSHOUT() < 0 ) {
				log("error: flush");
				return 1;
			}
			
			timer_set(&sync_timer, OUTGOING_SYNC_TIMER);
		}
		
		/*
		 * Pickup next char
		 */
		c = GETCHAR(1);
		
		if( canintro && c > 0 )
		{
			if( c == XON || c == XOFF )
			{
				/* Do nothing. Drop them down */
			}
			else if( c == '\r' || c == '\n' )
			{
				if( pos_intro > 0 )
				{
					intro_lines += 1;
					intro_count += pos_intro;
					
					recode_intro_in(buf_intro);
					log("intro: \"%s\"",
						string_printable(buf_intro));
					
					pos_intro = 0;
					buf_intro[0] = '\0';
				}
			}
			else if( pos_intro < sizeof(buf_intro) - 1 )
			{
				buf_intro[pos_intro++] = (char)c;
				buf_intro[pos_intro  ] = '\0';
			}
			
			if( pos_intro >= sizeof(buf_intro) - 1 )
			{
				intro_lines += 1;
				intro_count += pos_intro;
				
				recode_intro_in(buf_intro);
				log("intro buffer is full");
				log("intro: \"%s\"",
					string_printable(buf_intro));
				
				pos_intro = 0;
				buf_intro[0] = '\0';
			}

			if( intro_lines >= INTRO_MAX_LINES )
			{
				log("stop logging intro: %d lines limit", intro_lines);
				canintro = FALSE;
			}
			else if( intro_count >= INTRO_MAX_SIZE )
			{
				log("stop logging intro: %d bytes limit", intro_count);
				canintro = FALSE;
			}
		}
		
		if( c < 0 )
		{
			if( c != TTY_TIMEOUT )
			{
				DEB((D_HSHAKE, "tx_init: got TTY_ERROR/TTY_HANGUP"));
				return 1;
			}				
		}
		else if( c == XON || c == XOFF )
		{
			/* Do nothing. Drop them down */
		}
		else if( c == ENQ )
		{
			if( enq_need && ++enqcount >= enq_need && canyoohoo )
			{
				DEB((D_HSHAKE, "tx_init: exit with YooHoo"));
				state.session = SESSION_YOOHOO;
				return 0;
			}
		}
		else if( c == TSYNC )
		{
			if( nak_need && ++nakcount > nak_need && canftsc )
			{
				DEB((D_HSHAKE, "tx_init: exit with FTS-1"));
				state.session = SESSION_FTSC;
				return 0;
			}
		}
		else if( canemsi && c > ' ' && c < '~' )
		{
			if( c != 'C' )
				nakcount = 0;
			
			enqcount = 0;
			
			if( c == '*' )
			{
				memset(buf_emsi, '\0', sizeof(buf_emsi));
				pos_emsi = 0;
				emsi_seq = 1;
			}
			else if( emsi_seq )
			{
				if( pos_emsi < sizeof(buf_emsi)-1 )
				{
					buf_emsi[pos_emsi++] = (char)c;
					buf_emsi[pos_emsi  ] = '\0';
				}
			
				if( pos_emsi >= sizeof(buf_emsi)-1 )
				{
					emsi_seq = 0;
					
					DEB((D_HSHAKE, "tx_init: emsi buffer full \"%s\"",
							string_printable(buf_emsi)));
					
					if( !strncasecmp(buf_emsi, "EMSI_REQA77E", 12)
					 || !strncasecmp(buf_emsi, "EMSI_NAKEEC3", 12) )
					{
						DEB((D_HSHAKE, "tx_init: exit with EMSI"));
						state.session = SESSION_EMSI;
						
						if( PUTSTR("**EMSI_INQC816\r") < 0
						 || PUTSTR("**EMSI_INQC816\r") < 0 ) {
							log("error: output");
							return 1;
						}
						if( FLUSHOUT() < 0 ) {
							log("error: output");
							return 1;
						}
						
						return 0;
					}
					else if( !strncasecmp(buf_emsi, "EMSI_INQC816", 12) )
					{
						/*
						 * Most probable it is echo of
						 * our own EMSI_INQ, try to send
						 * separated EMSI_INQ as user
						 * name and password to be sure
						 * that they understand us.
						 */

						/* Wait for a login prompt */
						sleep(3);
						
						if( PUTSTR("**EMSI_INQC816\r") < 0
						 || FLUSHOUT() < 0 ) {
							log("error: flush");
							return 1;
						}

						/* Wait for a password prompt */
						sleep(2);
						
						if( PUTSTR("**EMSI_INQC816\r") < 0
						 || FLUSHOUT() < 0 ) {
							log("error: output");
							return 1;
						}
						
						timer_set(&sync_timer, OUTGOING_SYNC_TIMER);
					}
					else if( !strncasecmp(buf_emsi, "EMSI", 4) )
					{
						log("unexpected emsi sequence \"%s\"",
								string_printable(buf_emsi));
						
						if( ++unexp_count > 10 )
						{
							log("too many unexpected emsi sequences");
							return 1;
						}
					}
				}
			}
		}
		else if( emsi_seq )
		{
			emsi_seq = 0;
			DEB((D_HSHAKE, "sm_rx_waitseq: bad character 0x%02x in \"%s\"",
					c, string_printable(buf_emsi)));
		}
	}
	//log("session_init_outgoing: end loop");

	return 1;
}