	Linux for DOSBox
	Version 1.0
	Copyright (C) 2010 Joel Yliluoma -- http://iki.fi/bisqwit/
	License: zlib
        Portions of the code come straight from the Linux kernel.
  	---------------------------------------------------------
	
	LINUX.EXE is a stand-alone 16-bit realmode program for MS-DOS,
	which implements a FAST 4-tty Linux-compatible terminal emulator.
	It will emulate a 80x50 256-color terminal
	with xterm's 256-color extension.
	A status line is also displayed on the screen, which is accomplished
	by reprogramming the VGA text mode for 80x51 dimensions.

	Compile with Borland C++ 3.1. You need TASM, too.
	The packaged version of LINUX.EXE is compressed using UPX.
	Due to the compression, it will have a slight startup delay
	while it decompresses itself to RAM.

	To run, you need a version of MS-DOS (such as DOSBox) that has
	a special patch in it that implements the following callback
	routine:

        INT 21
         OPEN A NEW TERMINAL
             in:
              AX = 5300
              CX = rows
              DX = columns
             out:
              BX = fd
              CX = pid
         CLOSE TERMINAL
             in:
              AX = 5301
              BX = fd
              CX = pid
         WRITE STRING (NON-BLOCKING)
             in:
              AX = 5302
              BX = fd
              DS:DX = string address
              CX = string length
             out:
              CX = number of bytes written
         READ STRING (NON-BLOCKING)
             in:
              AX = 5303
              BX = fd
              DS:DX = target address
              CX = buffer capacity
             out:
              CX = number of bytes read
              DX = error code (or zero if CX != 0xFFFF)
         SEND A RESIZE EVENT
             in:
              AX = 5304
              BX = fd
              CX = rows
              DX = columns

An example of such an implementation is added to DOSBox 0.74 by
the following patch.

Do be careful when applying this patch. It opens a security hole to your
system, allowing any DOS program to issue arbitrary commands in your host
system with the privileges of the account that you use to run DOSBox.


diff -NaHudr dosbox-0.74/src/dos/dos.cpp dosbox-0.74-patched/src/dos/dos.cpp
--- dosbox-0.74/src/dos/dos.cpp	2010-05-10 20:43:54.000000000 +0300
+++ dosbox-0.74-patched/src/dos/dos.cpp	2010-09-30 02:32:59.437847584 +0300
@@ -32,6 +32,12 @@
 #include "support.h"
 #include "serialport.h"
 
+#include <pty.h>   /* FOR BISQWIT LINUX SHELL SUPPORT */
+#include <fcntl.h> /* FOR BISQWIT LINUX SHELL SUPPORT */
+#include <signal.h> /* FOR BISQWIT LINUX SHELL SUPPORT */
+#include <sys/errno.h> /* FOR BISQWIT LINUX SHELL SUPPORT */
+#include <sys/wait.h> /* FOR BISQWIT LINUX SHELL SUPPORT */
+
 DOS_Block dos;
 DOS_InfoBlock dos_infoblock;
 
@@ -778,6 +784,77 @@
 //TODO Think hard how shit this is gonna be
 //And will any game ever use this :)
 	case 0x53:					/* Translate BIOS parameter block to drive parameter block */
+		/* BISQWIT LINUX SHELL SUPPORT */
+		{
+		    switch(reg_al)
+		    {
+		        case 0: /* open */
+		        {
+		            int fd = -1, pid = -1;
+		            struct winsize ws;
+		            memset(&ws, 0, sizeof ws);
+		            ws.ws_row = reg_cx;
+		            ws.ws_col = reg_dx;
+		            
+		            pid = forkpty(&fd, NULL, NULL, &ws);
+		            if(!pid)
+		            {
+		                putenv("TERM=linux");
+		                execl(getenv("SHELL"), getenv("SHELL"), NULL);
+		                // not reached
+		            }
+		            fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+		            reg_bx = fd;
+		            reg_cx = pid;
+		            break;
+		        }
+		        case 1: /* close */
+		        {
+		            kill(reg_cx, SIGKILL);
+		            close(reg_bx);
+		            waitpid(reg_cx, NULL, 0);
+		            break;
+		        }
+		        case 2: /* send */
+		        {
+		            int fd = reg_bx; Bit16u towrite = reg_cx;
+		            unsigned char* bisqdata = new unsigned char[towrite];
+		            MEM_BlockRead(SegPhys(ds)+reg_dx, bisqdata, towrite);
+		            reg_cx = write(fd, bisqdata, towrite);
+		            //fprintf(stderr, "Sent <%.*s>\n", (int)reg_cx, bisqdata);
+		            delete[] bisqdata;
+		            break;
+		        }
+		        case 3: /* read */
+		        {
+		            int fd = reg_bx; Bit16u toread = reg_cx;
+		            if(toread > 0)
+		            {
+		                unsigned char* bisqdata = new unsigned char[toread];
+		                int r = read(fd, bisqdata, toread);
+		                if(r < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
+		                    r = 0;
+		                if(r > 0) MEM_BlockWrite(SegPhys(ds)+reg_dx, bisqdata, r);
+		                reg_cx = r;
+		                reg_dx = r < 0 ? errno : 0;
+		                //if(r > 0) fprintf(stderr, "Read <%.*s>\n", r, bisqdata);
+		                delete[] bisqdata;
+		            }
+		            break;
+		        }
+		        case 4: /* resize */
+		        {
+		            struct winsize ws;
+		            memset(&ws, 0, sizeof(ws));
+		            ws.ws_row = reg_cx;
+		            ws.ws_col = reg_dx;
+		            ioctl(reg_bx, TIOCSWINSZ, &ws);
+		            break;
+		        }
+		    }
+		    break;
+		}
+		/* END BISQWIT SSH SUPPORT */
 		E_Exit("Unhandled Dos 21 call %02X",reg_ah);
 		break;
 	case 0x54:					/* Get verify flag */
