package ssh;

import java.io.*;

/**
 * Use my ssh protocol to connect to an sshd server.<p>
 *
 * <b>Warning:</b> this class does no checking of the authenticity of
 * the remote host's public key.<p>
 *
 * It does allow the user to authenticate
 * to the host using a password, of course, since the host will not allow
 * the connection without some form of user authentication. <b>Warning:</b> the
 * password is <em>echoed to the console</em>.<p>
 *
 * The class spawns two threads that<ul>
 * <li>read data from System.in and write it to an OutputStream, and
 * <li>read data from some InputStream and write it to System.out.
 * </ul>
 * Another thread wakes up periodically to do
 * nothing, which works around a bug in System.in, to keep it from
 * blocking all the other threads.<p>
 * 
 * BUGS: System.in can't read in increments smaller than a line.
 * 
 * @license This code is Copyright 1999 Jon Howell. It is available for
 * use under the GNU Public License, available at:
 * http://www.gnu.org/copyleft/gpl.html
 * @author Jon Howell <jonh@cs.dartmouth.edu>
 * @rcs $Id: Terminal.java,v 1.2 2000/05/22 01:36:05 jonh Exp $ 
 */
public class Terminal {

	class StreamPumpThread extends Thread {
		InputStream streamIn;
		OutputStream streamOut;

		public StreamPumpThread(InputStream in, OutputStream out) {
			streamIn = in;
			streamOut = out;
		}

		public void run() {
			try {
				byte[] buf = new byte[1024];
				int rc;
				while (true) {
					rc = streamIn.read(buf, 0, buf.length);
					if (rc<=0) {
						throw new IOException("read()=="+rc);
					}
					streamOut.write(buf, 0, rc);
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	class WorkAroundThread extends Thread {
		public void run() {
			try {
				while (true) {
					sleep(20);	// wake up and jostle thread list every 20 ms
						// This works around a bug wherein a thread blocking
						// on stdin (System.in) blocks the entire process.
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	public Terminal(InputStream in, OutputStream out)
		throws IOException {
		WorkAroundThread wat = new WorkAroundThread();
		wat.setPriority(wat.getPriority()+5);
		wat.start();
		StreamPumpThread fromThread = new StreamPumpThread(System.in, out);
		fromThread.start();
		StreamPumpThread toThread = new StreamPumpThread(in, System.out);
		toThread.start();
	}
}
