static void handlenetoutput(int len)
{
	/*	here we could do smart tricks how to handle 0xFF:s in output
	 *	stream  like writing twice every sequence of FF:s (thus doing
	 *	many write()s. But I think interactive telnet application does
	 *	not need to be 100% 8-bit clean, so changing every 0xff:s to
	 *	0x7f:s
	 *
	 *	2002-mar-21, Przemyslaw Czerpak ([email protected])
	 *	I don't agree.
	 *	first - I cannot use programs like sz/rz
	 *	second - the 0x0D is sent as one character and if the next
	 *	         char is 0x0A then it's eaten by a server side.
	 *	third - whay doy you have to make 'many write()s'?
	 *	        I don't understand.
	 *	So I implemented it. It's realy useful for me. I hope that
	 *	others people will find it interesting to.
	 */

	int i, j;
	byte * p = G.buf;
	byte outbuf[4*DATABUFSIZE];

	for (i = len, j = 0; i > 0; i--, p++)
	{
		if (*p == 0x1d)
		{
			conescape();
			return;
		}
		outbuf[j++] = *p;
		if (*p == 0xff)
		    outbuf[j++] = 0xff;
		else if (*p == 0x0d)
		    outbuf[j++] = 0x00;
	}
	if (j > 0 )
	    write(G.netfd, outbuf, j);
}
extern int telnet_main(int argc, char** argv)
{
	int len;
	struct sockaddr_in s_in;
#ifdef USE_POLL
	struct pollfd ufds[2];
#else
	fd_set readfds;
	int maxfd;
#endif

#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
	int opt;
#endif

#ifdef CONFIG_FEATURE_AUTOWIDTH
	get_terminal_width_height(0, &win_width, &win_height);
#endif

#ifdef CONFIG_FEATURE_TELNET_TTYPE
    ttype = getenv("TERM");
#endif

	memset(&G, 0, sizeof G);

	if (tcgetattr(0, &G.termios_def) < 0)
		exit(1);

	G.termios_raw = G.termios_def;
	cfmakeraw(&G.termios_raw);

	if (argc < 2)
		bb_show_usage();

#ifdef CONFIG_FEATURE_TELNET_AUTOLOGIN
	autologin = NULL;
	while ((opt = getopt(argc, argv, "al:")) != EOF) {
		switch (opt) {
			case 'l':
				autologin = optarg;
				break;
			case 'a':
				autologin = getenv("USER");
				break;
			case '?':
				bb_show_usage();
				break;
		}
	}
	if (optind < argc) {
		bb_lookup_host(&s_in, argv[optind++]);
		s_in.sin_port = bb_lookup_port((optind < argc) ? argv[optind++] :
				"telnet", "tcp", 23);
		if (optind < argc)
			bb_show_usage();
	} else
		bb_show_usage();
#else
	bb_lookup_host(&s_in, argv[1]);
	s_in.sin_port = bb_lookup_port((argc == 3) ? argv[2] : "telnet", "tcp", 23);
#endif

	G.netfd = xconnect(&s_in);

	setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof one);

	signal(SIGINT, fgotsig);

#ifdef USE_POLL
	ufds[0].fd = 0; ufds[1].fd = G.netfd;
	ufds[0].events = ufds[1].events = POLLIN;
#else
	FD_ZERO(&readfds);
	FD_SET(0, &readfds);
	FD_SET(G.netfd, &readfds);
	maxfd = G.netfd + 1;
#endif

	while (1)
	{
#ifndef USE_POLL
		fd_set rfds = readfds;

		switch (select(maxfd, &rfds, NULL, NULL, NULL))
#else
		switch (poll(ufds, 2, -1))
#endif
		{
		case 0:
			/* timeout */
		case -1:
			/* error, ignore and/or log something, bay go to loop */
			if (G.gotsig)
				conescape();
			else
				sleep(1);
			break;
		default:

#ifdef USE_POLL
			if (ufds[0].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(0, &rfds))
#endif
			{
				len = read(0, G.buf, DATABUFSIZE);

				if (len <= 0)
					doexit(0);

				TRACE(0, ("Read con: %d\n", len));

				handlenetoutput(len);
			}

#ifdef USE_POLL
			if (ufds[1].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(G.netfd, &rfds))
#endif
			{
				len = read(G.netfd, G.buf, DATABUFSIZE);

				if (len <= 0)
				{
					WriteCS(1, "Connection closed by foreign host.\r\n");
					doexit(1);
				}
				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));

				handlenetinput(len);
			}
		}
	}
}
int telnet_main(int argc, char **argv)
{
	char *host;
	int port;
	int len;
#ifdef USE_POLL
	struct pollfd ufds[2];
#else
	fd_set readfds;
	int maxfd;
#endif

	INIT_G();

#if ENABLE_FEATURE_AUTOWIDTH
	get_terminal_width_height(0, &G.win_width, &G.win_height);
#endif

#if ENABLE_FEATURE_TELNET_TTYPE
	G.ttype = getenv("TERM");
#endif

	if (tcgetattr(0, &G.termios_def) >= 0) {
		G.do_termios = 1;
		G.termios_raw = G.termios_def;
		cfmakeraw(&G.termios_raw);
	}

	if (argc < 2)
		bb_show_usage();

#if ENABLE_FEATURE_TELNET_AUTOLOGIN
	if (1 & getopt32(argv, "al:", &G.autologin))
		G.autologin = getenv("USER");
	argv += optind;
#else
	argv++;
#endif
	if (!*argv)
		bb_show_usage();
	host = *argv++;
	port = bb_lookup_port(*argv ? *argv++ : "telnet", "tcp", 23);
	if (*argv) /* extra params?? */
		bb_show_usage();

	G.netfd = create_and_connect_stream_or_die(host, port);

	setsockopt(G.netfd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1));

	signal(SIGINT, fgotsig);

#ifdef USE_POLL
	ufds[0].fd = 0; ufds[1].fd = G.netfd;
	ufds[0].events = ufds[1].events = POLLIN;
#else
	FD_ZERO(&readfds);
	FD_SET(STDIN_FILENO, &readfds);
	FD_SET(G.netfd, &readfds);
	maxfd = G.netfd + 1;
#endif

	while (1) {
#ifndef USE_POLL
		fd_set rfds = readfds;

		switch (select(maxfd, &rfds, NULL, NULL, NULL))
#else
		switch (poll(ufds, 2, -1))
#endif
		{
		case 0:
			/* timeout */
		case -1:
			/* error, ignore and/or log something, bay go to loop */
			if (G.gotsig)
				conescape();
			else
				sleep(1);
			break;
		default:

#ifdef USE_POLL
			if (ufds[0].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(STDIN_FILENO, &rfds))
#endif
			{
				len = read(STDIN_FILENO, G.buf, DATABUFSIZE);
				if (len <= 0)
					doexit(EXIT_SUCCESS);
				TRACE(0, ("Read con: %d\n", len));
				handlenetoutput(len);
			}

#ifdef USE_POLL
			if (ufds[1].revents) /* well, should check POLLIN, but ... */
#else
			if (FD_ISSET(G.netfd, &rfds))
#endif
			{
				len = read(G.netfd, G.buf, DATABUFSIZE);
				if (len <= 0) {
					write_str(1, "Connection closed by foreign host\r\n");
					doexit(EXIT_FAILURE);
				}
				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));
				handlenetinput(len);
			}
		}
	}
}
Beispiel #4
0
extern int telnet_main(int argc, char** argv)
{
	struct in_addr host;
	int port;
	int len;
#ifdef USE_POLL
	struct pollfd ufds[2];
#else	
	fd_set readfds;
	int maxfd;
#endif	

#ifdef BB_FEATURE_AUTOWIDTH
    struct winsize winp;
    if( ioctl(0, TIOCGWINSZ, &winp) == 0 ) {
	win_width  = winp.ws_col;
	win_height = winp.ws_row;
    }
#endif

#ifdef BB_FEATURE_TELNET_TTYPE
    ttype = getenv("TERM");
#endif

	memset(&G, 0, sizeof G);

	if (tcgetattr(0, &G.termios_def) < 0)
		exit(1);
	
	G.termios_raw = G.termios_def;
	cfmakeraw(&G.termios_raw);
	
	if (argc < 2)	show_usage();
	port = (argc > 2)? getport(argv[2]): 23;
	
	host = getserver(argv[1]);

	G.netfd = remote_connect(host, port);

	signal(SIGINT, fgotsig);

#ifdef USE_POLL
	ufds[0].fd = 0; ufds[1].fd = G.netfd;
	ufds[0].events = ufds[1].events = POLLIN;
#else	
	FD_ZERO(&readfds);
	FD_SET(0, &readfds);
	FD_SET(G.netfd, &readfds);
	maxfd = G.netfd + 1;
#endif
	
	while (1)
	{
#ifndef USE_POLL
		fd_set rfds = readfds;
		
		switch (select(maxfd, &rfds, NULL, NULL, NULL))
#else
		switch (poll(ufds, 2, -1))
#endif			
		{
		case 0:
			/* timeout */
		case -1:
			/* error, ignore and/or log something, bay go to loop */
			if (G.gotsig)
				conescape();
			else
				sleep(1);
			break;
		default:

#ifdef USE_POLL
			if (ufds[0].revents) /* well, should check POLLIN, but ... */
#else				
			if (FD_ISSET(0, &rfds))
#endif				
			{
				len = read(0, G.buf, DATABUFSIZE);

				if (len <= 0)
					doexit(0);

				TRACE(0, ("Read con: %d\n", len));
				
				handlenetoutput(len);
			}

#ifdef USE_POLL
			if (ufds[1].revents) /* well, should check POLLIN, but ... */
#else				
			if (FD_ISSET(G.netfd, &rfds))
#endif				
			{
				len = read(G.netfd, G.buf, DATABUFSIZE);

				if (len <= 0)
				{
					WriteCS(1, "Connection closed by foreign host.\r\n");
					doexit(1);
				}
				TRACE(0, ("Read netfd (%d): %d\n", G.netfd, len));

				handlenetinput(len);
			}
		}
	}
}