2021-02-06 09:39:32 +01:00
/*
2021-02-06 16:06:31 +01:00
* Copyright ( C ) 2002 - 2019 The DOSBox Team
2021-02-06 09:39:32 +01:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
2021-02-06 16:06:31 +01:00
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2021-02-06 09:39:32 +01:00
*/
# include <stdlib.h>
# include <stdarg.h>
# include <string.h>
# ifdef HW_RVL
# include <wiihardware.h>
# endif
# include "dosbox.h"
# include "regs.h"
# include "control.h"
# include "shell.h"
# include "callback.h"
# include "support.h"
Bitu call_shellstop ;
/* Larger scope so shell_del autoexec can use it to
* remove things from the environment */
2021-02-06 16:06:31 +01:00
DOS_Shell * first_shell = 0 ;
2021-02-06 09:39:32 +01:00
static Bitu shellstop_handler ( void ) {
return CBRET_STOP ;
}
static void SHELL_ProgramStart ( Program * * make ) {
* make = new DOS_Shell ;
}
2021-02-06 16:06:31 +01:00
//Repeat it with the correct type, could do it in the function below, but this way it should be
//clear that if the above function is changed, this function might need a change as well.
static void SHELL_ProgramStart_First_shell ( DOS_Shell * * make ) {
* make = new DOS_Shell ;
}
2021-02-06 09:39:32 +01:00
# define AUTOEXEC_SIZE 4096
static char autoexec_data [ AUTOEXEC_SIZE ] = { 0 } ;
static std : : list < std : : string > autoexec_strings ;
typedef std : : list < std : : string > : : iterator auto_it ;
void VFILE_Remove ( const char * name ) ;
void AutoexecObject : : Install ( const std : : string & in ) {
if ( GCC_UNLIKELY ( installed ) ) E_Exit ( " autoexec: already created %s " , buf . c_str ( ) ) ;
installed = true ;
buf = in ;
autoexec_strings . push_back ( buf ) ;
this - > CreateAutoexec ( ) ;
//autoexec.bat is normally created AUTOEXEC_Init.
//But if we are already running (first_shell)
//we have to update the envirionment to display changes
if ( first_shell ) {
//create a copy as the string will be modified
std : : string : : size_type n = buf . size ( ) ;
char * buf2 = new char [ n + 1 ] ;
safe_strncpy ( buf2 , buf . c_str ( ) , n + 1 ) ;
if ( ( strncasecmp ( buf2 , " set " , 4 ) = = 0 ) & & ( strlen ( buf2 ) > 4 ) ) {
char * after_set = buf2 + 4 ; //move to variable that is being set
char * test = strpbrk ( after_set , " = " ) ;
if ( ! test ) { first_shell - > SetEnv ( after_set , " " ) ; return ; }
* test + + = 0 ;
//If the shell is running/exists update the environment
first_shell - > SetEnv ( after_set , test ) ;
}
delete [ ] buf2 ;
}
}
void AutoexecObject : : InstallBefore ( const std : : string & in ) {
if ( GCC_UNLIKELY ( installed ) ) E_Exit ( " autoexec: already created %s " , buf . c_str ( ) ) ;
installed = true ;
buf = in ;
autoexec_strings . push_front ( buf ) ;
this - > CreateAutoexec ( ) ;
}
void AutoexecObject : : CreateAutoexec ( void ) {
/* Remove old autoexec.bat if the shell exists */
if ( first_shell ) VFILE_Remove ( " AUTOEXEC.BAT " ) ;
//Create a new autoexec.bat
autoexec_data [ 0 ] = 0 ;
size_t auto_len ;
2021-02-06 16:06:31 +01:00
for ( auto_it it = autoexec_strings . begin ( ) ; it ! = autoexec_strings . end ( ) ; it + + ) {
std : : string linecopy = ( * it ) ;
std : : string : : size_type offset = 0 ;
//Lets have \r\n as line ends in autoexec.bat.
while ( offset < linecopy . length ( ) ) {
std : : string : : size_type n = linecopy . find ( " \n " , offset ) ;
if ( n = = std : : string : : npos ) break ;
std : : string : : size_type rn = linecopy . find ( " \r \n " , offset ) ;
if ( rn ! = std : : string : : npos & & rn + 1 = = n ) { offset = n + 1 ; continue ; }
// \n found without matching \r
linecopy . replace ( n , 1 , " \r \n " ) ;
offset = n + 2 ;
}
2021-02-06 09:39:32 +01:00
auto_len = strlen ( autoexec_data ) ;
2021-02-06 16:06:31 +01:00
if ( ( auto_len + linecopy . length ( ) + 3 ) > AUTOEXEC_SIZE ) {
2021-02-06 09:39:32 +01:00
E_Exit ( " SYSTEM:Autoexec.bat file overflow " ) ;
}
2021-02-06 16:06:31 +01:00
sprintf ( ( autoexec_data + auto_len ) , " %s \r \n " , linecopy . c_str ( ) ) ;
2021-02-06 09:39:32 +01:00
}
2021-02-06 16:06:31 +01:00
if ( first_shell ) VFILE_Register ( " AUTOEXEC.BAT " , ( Bit8u * ) autoexec_data , ( Bit32u ) strlen ( autoexec_data ) ) ;
2021-02-06 09:39:32 +01:00
}
AutoexecObject : : ~ AutoexecObject ( ) {
if ( ! installed ) return ;
// Remove the line from the autoexecbuffer and update environment
for ( auto_it it = autoexec_strings . begin ( ) ; it ! = autoexec_strings . end ( ) ; ) {
2021-02-06 16:06:31 +01:00
if ( ( * it ) = = buf ) {
2021-02-06 09:39:32 +01:00
std : : string : : size_type n = buf . size ( ) ;
char * buf2 = new char [ n + 1 ] ;
safe_strncpy ( buf2 , buf . c_str ( ) , n + 1 ) ;
2021-02-06 16:06:31 +01:00
bool stringset = false ;
2021-02-06 09:39:32 +01:00
// If it's a environment variable remove it from there as well
2021-02-06 16:06:31 +01:00
if ( ( strncasecmp ( buf2 , " set " , 4 ) = = 0 ) & & ( strlen ( buf2 ) > 4 ) ) {
2021-02-06 09:39:32 +01:00
char * after_set = buf2 + 4 ; //move to variable that is being set
char * test = strpbrk ( after_set , " = " ) ;
2021-02-06 16:06:31 +01:00
if ( ! test ) {
delete [ ] buf2 ;
continue ;
}
2021-02-06 09:39:32 +01:00
* test = 0 ;
2021-02-06 16:06:31 +01:00
stringset = true ;
2021-02-06 09:39:32 +01:00
//If the shell is running/exists update the environment
2021-02-06 16:06:31 +01:00
if ( first_shell ) first_shell - > SetEnv ( after_set , " " ) ;
2021-02-06 09:39:32 +01:00
}
delete [ ] buf2 ;
2021-02-06 16:06:31 +01:00
if ( stringset & & first_shell & & first_shell - > bf & & first_shell - > bf - > filename . find ( " AUTOEXEC.BAT " ) ! = std : : string : : npos ) {
//Replace entry with spaces if it is a set and from autoexec.bat, as else the location counter will be off.
* it = buf . assign ( buf . size ( ) , ' ' ) ;
it + + ;
} else {
it = autoexec_strings . erase ( it ) ;
}
2021-02-06 09:39:32 +01:00
} else it + + ;
}
this - > CreateAutoexec ( ) ;
}
DOS_Shell : : DOS_Shell ( ) : Program ( ) {
input_handle = STDIN ;
echo = true ;
exit = false ;
bf = 0 ;
call = false ;
completion_start = NULL ;
}
Bitu DOS_Shell : : GetRedirection ( char * s , char * * ifn , char * * ofn , bool * append ) {
char * lr = s ;
char * lw = s ;
char ch ;
Bitu num = 0 ;
bool quote = false ;
char * t ;
while ( ( ch = * lr + + ) ) {
if ( quote & & ch ! = ' " ' ) { /* don't parse redirection within quotes. Not perfect yet. Escaped quotes will mess the count up */
* lw + + = ch ;
continue ;
}
switch ( ch ) {
case ' " ' :
quote = ! quote ;
break ;
case ' > ' :
* append = ( ( * lr ) = = ' > ' ) ;
if ( * append ) lr + + ;
lr = ltrim ( lr ) ;
if ( * ofn ) free ( * ofn ) ;
* ofn = lr ;
while ( * lr & & * lr ! = ' ' & & * lr ! = ' < ' & & * lr ! = ' | ' ) lr + + ;
//if it ends on a : => remove it.
if ( ( * ofn ! = lr ) & & ( lr [ - 1 ] = = ' : ' ) ) lr [ - 1 ] = 0 ;
2021-02-06 16:06:31 +01:00
// if(*lr && *(lr+1))
// *lr++=0;
// else
2021-02-06 09:39:32 +01:00
// *lr=0;
t = ( char * ) malloc ( lr - * ofn + 1 ) ;
safe_strncpy ( t , * ofn , lr - * ofn + 1 ) ;
* ofn = t ;
continue ;
case ' < ' :
if ( * ifn ) free ( * ifn ) ;
lr = ltrim ( lr ) ;
* ifn = lr ;
while ( * lr & & * lr ! = ' ' & & * lr ! = ' > ' & & * lr ! = ' | ' ) lr + + ;
if ( ( * ifn ! = lr ) & & ( lr [ - 1 ] = = ' : ' ) ) lr [ - 1 ] = 0 ;
2021-02-06 16:06:31 +01:00
// if(*lr && *(lr+1))
// *lr++=0;
// else
2021-02-06 09:39:32 +01:00
// *lr=0;
t = ( char * ) malloc ( lr - * ifn + 1 ) ;
safe_strncpy ( t , * ifn , lr - * ifn + 1 ) ;
* ifn = t ;
continue ;
case ' | ' :
ch = 0 ;
num + + ;
}
* lw + + = ch ;
}
* lw = 0 ;
return num ;
2021-02-06 16:06:31 +01:00
}
2021-02-06 09:39:32 +01:00
void DOS_Shell : : ParseLine ( char * line ) {
LOG ( LOG_EXEC , LOG_ERROR ) ( " Parsing command line: %s " , line ) ;
/* Check for a leading @ */
if ( line [ 0 ] = = ' @ ' ) line [ 0 ] = ' ' ;
line = trim ( line ) ;
/* Do redirection and pipe checks */
2021-02-06 16:06:31 +01:00
2021-02-06 09:39:32 +01:00
char * in = 0 ;
char * out = 0 ;
Bit16u dummy , dummy2 ;
Bit32u bigdummy = 0 ;
Bitu num = 0 ; /* Number of commands in this line */
bool append ;
bool normalstdin = false ; /* wether stdin/out are open on start. */
bool normalstdout = false ; /* Bug: Assumed is they are "con" */
2021-02-06 16:06:31 +01:00
2021-02-06 09:39:32 +01:00
num = GetRedirection ( line , & in , & out , & append ) ;
2021-02-06 16:06:31 +01:00
if ( num > 1 ) LOG_MSG ( " SHELL: Multiple command on 1 line not supported " ) ;
2021-02-06 09:39:32 +01:00
if ( in | | out ) {
2021-02-06 16:06:31 +01:00
normalstdin = ( psp - > GetFileHandle ( 0 ) ! = 0xff ) ;
normalstdout = ( psp - > GetFileHandle ( 1 ) ! = 0xff ) ;
2021-02-06 09:39:32 +01:00
}
if ( in ) {
if ( DOS_OpenFile ( in , OPEN_READ , & dummy ) ) { //Test if file exists
DOS_CloseFile ( dummy ) ;
2021-02-06 16:06:31 +01:00
LOG_MSG ( " SHELL: Redirect input from %s " , in ) ;
2021-02-06 09:39:32 +01:00
if ( normalstdin ) DOS_CloseFile ( 0 ) ; //Close stdin
DOS_OpenFile ( in , OPEN_READ , & dummy ) ; //Open new stdin
}
}
if ( out ) {
2021-02-06 16:06:31 +01:00
LOG_MSG ( " SHELL: Redirect output to %s " , out ) ;
2021-02-06 09:39:32 +01:00
if ( normalstdout ) DOS_CloseFile ( 1 ) ;
if ( ! normalstdin & & ! in ) DOS_OpenFile ( " con " , OPEN_READWRITE , & dummy ) ;
bool status = true ;
/* Create if not exist. Open if exist. Both in read/write mode */
if ( append ) {
if ( ( status = DOS_OpenFile ( out , OPEN_READWRITE , & dummy ) ) ) {
DOS_SeekFile ( 1 , & bigdummy , DOS_SEEK_END ) ;
} else {
status = DOS_CreateFile ( out , DOS_ATTR_ARCHIVE , & dummy ) ; //Create if not exists.
}
} else {
status = DOS_OpenFileExtended ( out , OPEN_READWRITE , DOS_ATTR_ARCHIVE , 0x12 , & dummy , & dummy2 ) ;
}
2021-02-06 16:06:31 +01:00
2021-02-06 09:39:32 +01:00
if ( ! status & & normalstdout ) DOS_OpenFile ( " con " , OPEN_READWRITE , & dummy ) ; //Read only file, open con again
if ( ! normalstdin & & ! in ) DOS_CloseFile ( 0 ) ;
}
/* Run the actual command */
DoCommand ( line ) ;
/* Restore handles */
if ( in ) {
DOS_CloseFile ( 0 ) ;
if ( normalstdin ) DOS_OpenFile ( " con " , OPEN_READWRITE , & dummy ) ;
free ( in ) ;
}
if ( out ) {
DOS_CloseFile ( 1 ) ;
if ( ! normalstdin ) DOS_OpenFile ( " con " , OPEN_READWRITE , & dummy ) ;
if ( normalstdout ) DOS_OpenFile ( " con " , OPEN_READWRITE , & dummy ) ;
if ( ! normalstdin ) DOS_CloseFile ( 0 ) ;
free ( out ) ;
}
}
2021-02-06 16:06:31 +01:00
void DOS_Shell : : RunInternal ( void ) {
2021-02-06 09:39:32 +01:00
char input_line [ CMD_MAXLINE ] = { 0 } ;
2021-02-06 16:06:31 +01:00
while ( bf ) {
if ( bf - > ReadLine ( input_line ) ) {
if ( echo ) {
2021-02-06 09:39:32 +01:00
if ( input_line [ 0 ] ! = ' @ ' ) {
ShowPrompt ( ) ;
WriteOut_NoParsing ( input_line ) ;
WriteOut_NoParsing ( " \n " ) ;
2021-02-06 16:06:31 +01:00
}
}
ParseLine ( input_line ) ;
if ( echo ) WriteOut_NoParsing ( " \n " ) ;
}
2021-02-06 09:39:32 +01:00
}
}
void DOS_Shell : : Run ( void ) {
char input_line [ CMD_MAXLINE ] = { 0 } ;
std : : string line ;
if ( cmd - > FindStringRemainBegin ( " /C " , line ) ) {
strcpy ( input_line , line . c_str ( ) ) ;
char * sep = strpbrk ( input_line , " \r \n " ) ; //GTA installer
if ( sep ) * sep = 0 ;
DOS_Shell temp ;
temp . echo = echo ;
temp . ParseLine ( input_line ) ; //for *.exe *.com |*.bat creates the bf needed by runinternal;
temp . RunInternal ( ) ; // exits when no bf is found.
return ;
}
/* Start a normal shell and check for a first command init */
2021-02-06 16:06:31 +01:00
if ( cmd - > FindString ( " /INIT " , line , true ) ) {
WriteOut ( MSG_Get ( " SHELL_STARTUP_BEGIN " ) , VERSION ) ;
2021-02-06 09:39:32 +01:00
# if C_DEBUG
2021-02-06 16:06:31 +01:00
WriteOut ( MSG_Get ( " SHELL_STARTUP_DEBUG " ) ) ;
2021-02-06 09:39:32 +01:00
# endif
2021-02-06 16:06:31 +01:00
if ( machine = = MCH_CGA ) WriteOut ( MSG_Get ( " SHELL_STARTUP_CGA " ) ) ;
if ( machine = = MCH_HERC ) WriteOut ( MSG_Get ( " SHELL_STARTUP_HERC " ) ) ;
WriteOut ( MSG_Get ( " SHELL_STARTUP_END " ) ) ;
2021-02-06 09:39:32 +01:00
strcpy ( input_line , line . c_str ( ) ) ;
line . erase ( ) ;
ParseLine ( input_line ) ;
2021-02-06 16:06:31 +01:00
} else {
WriteOut ( MSG_Get ( " SHELL_STARTUP_SUB " ) , VERSION ) ;
2021-02-06 09:39:32 +01:00
}
do {
if ( bf ) {
if ( bf - > ReadLine ( input_line ) ) {
if ( echo ) {
if ( input_line [ 0 ] ! = ' @ ' ) {
ShowPrompt ( ) ;
WriteOut_NoParsing ( input_line ) ;
WriteOut_NoParsing ( " \n " ) ;
} ;
} ;
ParseLine ( input_line ) ;
if ( echo ) WriteOut ( " \n " ) ;
}
} else {
if ( echo ) ShowPrompt ( ) ;
InputCommand ( input_line ) ;
ParseLine ( input_line ) ;
if ( echo & & ! bf ) WriteOut_NoParsing ( " \n " ) ;
}
} while ( ! exit ) ;
}
void DOS_Shell : : SyntaxError ( void ) {
WriteOut ( MSG_Get ( " SHELL_SYNTAXERROR " ) ) ;
}
class AUTOEXEC : public Module_base {
private :
AutoexecObject autoexec [ 17 ] ;
AutoexecObject autoexec_echo ;
public :
AUTOEXEC ( Section * configuration ) : Module_base ( configuration ) {
/* Register a virtual AUOEXEC.BAT file */
std : : string line ;
Section_line * section = static_cast < Section_line * > ( configuration ) ;
/* Check -securemode switch to disable mount/imgmount/boot after running autoexec.bat */
bool secure = control - > cmdline - > FindExist ( " -securemode " , true ) ;
/* add stuff from the configfile unless -noautexec or -securemode is specified. */
char * extra = const_cast < char * > ( section - > data . c_str ( ) ) ;
if ( extra & & ! secure & & ! control - > cmdline - > FindExist ( " -noautoexec " , true ) ) {
/* detect if "echo off" is the first line */
2021-02-06 16:06:31 +01:00
size_t firstline_length = strcspn ( extra , " \r \n " ) ;
2021-02-06 09:39:32 +01:00
bool echo_off = ! strncasecmp ( extra , " echo off " , 8 ) ;
2021-02-06 16:06:31 +01:00
if ( echo_off & & firstline_length = = 8 ) extra + = 8 ;
else {
echo_off = ! strncasecmp ( extra , " @echo off " , 9 ) ;
if ( echo_off & & firstline_length = = 9 ) extra + = 9 ;
else echo_off = false ;
}
/* if "echo off" move it to the front of autoexec.bat */
if ( echo_off ) {
autoexec_echo . InstallBefore ( " @echo off " ) ;
if ( * extra = = ' \r ' ) extra + + ; //It can point to \0
if ( * extra = = ' \n ' ) extra + + ; //same
}
2021-02-06 09:39:32 +01:00
2021-02-06 16:06:31 +01:00
/* Install the stuff from the configfile if anything left after moving echo off */
2021-02-06 09:39:32 +01:00
2021-02-06 16:06:31 +01:00
if ( * extra ) autoexec [ 0 ] . Install ( std : : string ( extra ) ) ;
2021-02-06 09:39:32 +01:00
}
/* Check to see for extra command line options to be added (before the command specified on commandline) */
/* Maximum of extra commands: 10 */
Bitu i = 1 ;
while ( control - > cmdline - > FindString ( " -c " , line , true ) & & ( i < = 11 ) ) {
# if defined (WIN32) || defined (OS2)
//replace single with double quotes so that mount commands can contain spaces
for ( Bitu temp = 0 ; temp < line . size ( ) ; + + temp ) if ( line [ temp ] = = ' \' ' ) line [ temp ] = ' \" ' ;
# endif //Linux users can simply use \" in their shell
autoexec [ i + + ] . Install ( line ) ;
}
/* Check for the -exit switch which causes dosbox to when the command on the commandline has finished */
bool addexit = control - > cmdline - > FindExist ( " -exit " , true ) ;
/* Check for first command being a directory or file */
2021-02-06 16:06:31 +01:00
char buffer [ CROSS_LEN + 1 ] ;
char orig [ CROSS_LEN + 1 ] ;
2021-02-06 09:39:32 +01:00
char cross_filesplit [ 2 ] = { CROSS_FILESPLIT , 0 } ;
2021-02-06 16:06:31 +01:00
Bitu dummy = 1 ;
bool command_found = false ;
while ( control - > cmdline - > FindCommand ( dummy + + , line ) & & ! command_found ) {
2021-02-06 09:39:32 +01:00
struct stat test ;
2021-02-06 16:06:31 +01:00
if ( line . length ( ) > CROSS_LEN ) continue ;
2021-02-06 09:39:32 +01:00
strcpy ( buffer , line . c_str ( ) ) ;
2021-02-06 16:06:31 +01:00
if ( stat ( buffer , & test ) ) {
if ( getcwd ( buffer , CROSS_LEN ) = = NULL ) continue ;
if ( strlen ( buffer ) + line . length ( ) + 1 > CROSS_LEN ) continue ;
2021-02-06 09:39:32 +01:00
strcat ( buffer , cross_filesplit ) ;
strcat ( buffer , line . c_str ( ) ) ;
2021-02-06 16:06:31 +01:00
if ( stat ( buffer , & test ) ) continue ;
2021-02-06 09:39:32 +01:00
}
2021-02-06 16:06:31 +01:00
if ( test . st_mode & S_IFDIR ) {
2021-02-06 09:39:32 +01:00
autoexec [ 12 ] . Install ( std : : string ( " MOUNT C \" " ) + buffer + " \" " ) ;
autoexec [ 13 ] . Install ( " C: " ) ;
if ( secure ) autoexec [ 14 ] . Install ( " z: \\ config.com -securemode " ) ;
2021-02-06 16:06:31 +01:00
command_found = true ;
2021-02-06 09:39:32 +01:00
} else {
char * name = strrchr ( buffer , CROSS_FILESPLIT ) ;
2021-02-06 16:06:31 +01:00
if ( ! name ) { //Only a filename
2021-02-06 09:39:32 +01:00
line = buffer ;
2021-02-06 16:06:31 +01:00
if ( getcwd ( buffer , CROSS_LEN ) = = NULL ) continue ;
if ( strlen ( buffer ) + line . length ( ) + 1 > CROSS_LEN ) continue ;
2021-02-06 09:39:32 +01:00
strcat ( buffer , cross_filesplit ) ;
strcat ( buffer , line . c_str ( ) ) ;
2021-02-06 16:06:31 +01:00
if ( stat ( buffer , & test ) ) continue ;
2021-02-06 09:39:32 +01:00
name = strrchr ( buffer , CROSS_FILESPLIT ) ;
2021-02-06 16:06:31 +01:00
if ( ! name ) continue ;
2021-02-06 09:39:32 +01:00
}
* name + + = 0 ;
2021-02-06 16:06:31 +01:00
if ( access ( buffer , F_OK ) ) continue ;
2021-02-06 09:39:32 +01:00
autoexec [ 12 ] . Install ( std : : string ( " MOUNT C \" " ) + buffer + " \" " ) ;
autoexec [ 13 ] . Install ( " C: " ) ;
/* Save the non-modified filename (so boot and imgmount can use it (long filenames, case sensivitive)) */
strcpy ( orig , name ) ;
upcase ( name ) ;
if ( strstr ( name , " .BAT " ) ! = 0 ) {
if ( secure ) autoexec [ 14 ] . Install ( " z: \\ config.com -securemode " ) ;
/* BATch files are called else exit will not work */
autoexec [ 15 ] . Install ( std : : string ( " CALL " ) + name ) ;
if ( addexit ) autoexec [ 16 ] . Install ( " exit " ) ;
} else if ( ( strstr ( name , " .IMG " ) ! = 0 ) | | ( strstr ( name , " .IMA " ) ! = 0 ) ) {
//No secure mode here as boot is destructive and enabling securemode disables boot
/* Boot image files */
autoexec [ 15 ] . Install ( std : : string ( " BOOT " ) + orig ) ;
} else if ( ( strstr ( name , " .ISO " ) ! = 0 ) | | ( strstr ( name , " .CUE " ) ! = 0 ) ) {
/* imgmount CD image files */
/* securemode gets a different number from the previous branches! */
autoexec [ 14 ] . Install ( std : : string ( " IMGMOUNT D \" " ) + orig + std : : string ( " \" -t iso " ) ) ;
//autoexec[16].Install("D:");
if ( secure ) autoexec [ 15 ] . Install ( " z: \\ config.com -securemode " ) ;
/* Makes no sense to exit here */
} else {
if ( secure ) autoexec [ 14 ] . Install ( " z: \\ config.com -securemode " ) ;
autoexec [ 15 ] . Install ( name ) ;
if ( addexit ) autoexec [ 16 ] . Install ( " exit " ) ;
}
2021-02-06 16:06:31 +01:00
command_found = true ;
2021-02-06 09:39:32 +01:00
}
}
2021-02-06 16:06:31 +01:00
/* Combining -securemode, noautoexec and no parameters leaves you with a lovely Z:\. */
if ( ! command_found ) {
if ( secure ) autoexec [ 12 ] . Install ( " z: \\ config.com -securemode " ) ;
}
2021-02-06 09:39:32 +01:00
VFILE_Register ( " AUTOEXEC.BAT " , ( Bit8u * ) autoexec_data , ( Bit32u ) strlen ( autoexec_data ) ) ;
}
} ;
static AUTOEXEC * test ;
void AUTOEXEC_Init ( Section * sec ) {
test = new AUTOEXEC ( sec ) ;
}
2021-02-06 16:06:31 +01:00
static Bitu INT2E_Handler ( void ) {
/* Save return address and current process */
RealPt save_ret = real_readd ( SegValue ( ss ) , reg_sp ) ;
Bit16u save_psp = dos . psp ( ) ;
/* Set first shell as process and copy command */
dos . psp ( DOS_FIRST_SHELL ) ;
DOS_PSP psp ( DOS_FIRST_SHELL ) ;
psp . SetCommandTail ( RealMakeSeg ( ds , reg_si ) ) ;
SegSet16 ( ss , RealSeg ( psp . GetStack ( ) ) ) ;
reg_sp = 2046 ;
/* Read and fix up command string */
CommandTail tail ;
MEM_BlockRead ( PhysMake ( dos . psp ( ) , 128 ) , & tail , 128 ) ;
if ( tail . count < 127 ) tail . buffer [ tail . count ] = 0 ;
else tail . buffer [ 126 ] = 0 ;
char * crlf = strpbrk ( tail . buffer , " \r \n " ) ;
if ( crlf ) * crlf = 0 ;
/* Execute command */
if ( strlen ( tail . buffer ) ) {
DOS_Shell temp ;
temp . ParseLine ( tail . buffer ) ;
temp . RunInternal ( ) ;
}
/* Restore process and "return" to caller */
dos . psp ( save_psp ) ;
SegSet16 ( cs , RealSeg ( save_ret ) ) ;
reg_ip = RealOff ( save_ret ) ;
reg_ax = 0 ;
return CBRET_NONE ;
}
2021-02-06 09:39:32 +01:00
static char const * const path_string = " PATH=Z: \\ " ;
static char const * const comspec_string = " COMSPEC=Z: \\ COMMAND.COM " ;
static char const * const full_name = " Z: \\ COMMAND.COM " ;
static char const * const init_line = " /INIT AUTOEXEC.BAT " ;
void SHELL_Init ( ) {
/* Add messages */
MSG_Add ( " SHELL_ILLEGAL_PATH " , " Illegal Path. \n " ) ;
MSG_Add ( " SHELL_CMD_HELP " , " If you want a list of all supported commands type \033 [33;1mhelp /all \033 [0m . \n A short list of the most often used commands: \n " ) ;
MSG_Add ( " SHELL_CMD_ECHO_ON " , " ECHO is on. \n " ) ;
MSG_Add ( " SHELL_CMD_ECHO_OFF " , " ECHO is off. \n " ) ;
MSG_Add ( " SHELL_ILLEGAL_SWITCH " , " Illegal switch: %s. \n " ) ;
MSG_Add ( " SHELL_MISSING_PARAMETER " , " Required parameter missing. \n " ) ;
MSG_Add ( " SHELL_CMD_CHDIR_ERROR " , " Unable to change to: %s. \n " ) ;
2021-02-06 16:06:31 +01:00
MSG_Add ( " SHELL_CMD_CHDIR_HINT " , " Hint: To change to different drive type \033 [31m%c: \033 [0m \n " ) ;
2021-02-06 09:39:32 +01:00
MSG_Add ( " SHELL_CMD_CHDIR_HINT_2 " , " directoryname is longer than 8 characters and/or contains spaces. \n Try \033 [31mcd %s \033 [0m \n " ) ;
MSG_Add ( " SHELL_CMD_CHDIR_HINT_3 " , " You are still on drive Z:, change to a mounted drive with \033 [31mC: \033 [0m. \n " ) ;
MSG_Add ( " SHELL_CMD_DATE_HELP " , " Displays or changes the internal date. \n " ) ;
MSG_Add ( " SHELL_CMD_DATE_ERROR " , " The specified date is not correct. \n " ) ;
MSG_Add ( " SHELL_CMD_DATE_DAYS " , " 3SunMonTueWedThuFriSat " ) ; // "2SoMoDiMiDoFrSa"
MSG_Add ( " SHELL_CMD_DATE_NOW " , " Current date: " ) ;
MSG_Add ( " SHELL_CMD_DATE_SETHLP " , " Type 'date MM-DD-YYYY' to change. \n " ) ;
MSG_Add ( " SHELL_CMD_DATE_FORMAT " , " M/D/Y " ) ;
MSG_Add ( " SHELL_CMD_DATE_HELP_LONG " , " DATE [[/T] [/H] [/S] | MM-DD-YYYY] \n " \
" MM-DD-YYYY: new date to set \n " \
" /S: Permanently use host time and date as DOS time \n " \
" /F: Switch back to DOSBox internal time (opposite of /S) \n " \
" /T: Only display date \n " \
" /H: Synchronize with host \n " ) ;
MSG_Add ( " SHELL_CMD_TIME_HELP " , " Displays the internal time. \n " ) ;
MSG_Add ( " SHELL_CMD_TIME_NOW " , " Current time: " ) ;
MSG_Add ( " SHELL_CMD_TIME_HELP_LONG " , " TIME [/T] [/H] \n " \
" /T: Display simple time \n " \
" /H: Synchronize with host \n " ) ;
MSG_Add ( " SHELL_CMD_MKDIR_ERROR " , " Unable to make: %s. \n " ) ;
MSG_Add ( " SHELL_CMD_RMDIR_ERROR " , " Unable to remove: %s. \n " ) ;
MSG_Add ( " SHELL_CMD_DEL_ERROR " , " Unable to delete: %s. \n " ) ;
MSG_Add ( " SHELL_SYNTAXERROR " , " The syntax of the command is incorrect. \n " ) ;
MSG_Add ( " SHELL_CMD_SET_NOT_SET " , " Environment variable %s not defined. \n " ) ;
MSG_Add ( " SHELL_CMD_SET_OUT_OF_SPACE " , " Not enough environment space left. \n " ) ;
MSG_Add ( " SHELL_CMD_IF_EXIST_MISSING_FILENAME " , " IF EXIST: Missing filename. \n " ) ;
MSG_Add ( " SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER " , " IF ERRORLEVEL: Missing number. \n " ) ;
MSG_Add ( " SHELL_CMD_IF_ERRORLEVEL_INVALID_NUMBER " , " IF ERRORLEVEL: Invalid number. \n " ) ;
MSG_Add ( " SHELL_CMD_GOTO_MISSING_LABEL " , " No label supplied to GOTO command. \n " ) ;
MSG_Add ( " SHELL_CMD_GOTO_LABEL_NOT_FOUND " , " GOTO: Label %s not found. \n " ) ;
MSG_Add ( " SHELL_CMD_FILE_NOT_FOUND " , " File %s not found. \n " ) ;
MSG_Add ( " SHELL_CMD_FILE_EXISTS " , " File %s already exists. \n " ) ;
MSG_Add ( " SHELL_CMD_DIR_INTRO " , " Directory of %s. \n " ) ;
MSG_Add ( " SHELL_CMD_DIR_BYTES_USED " , " %5d File(s) %17s Bytes. \n " ) ;
MSG_Add ( " SHELL_CMD_DIR_BYTES_FREE " , " %5d Dir(s) %17s Bytes free. \n " ) ;
MSG_Add ( " SHELL_EXECUTE_DRIVE_NOT_FOUND " , " Drive %c does not exist! \n You must \033 [31mmount \033 [0m it first. Type \033 [1;33mintro \033 [0m or \033 [1;33mintro mount \033 [0m for more information. \n " ) ;
MSG_Add ( " SHELL_EXECUTE_ILLEGAL_COMMAND " , " Illegal command: %s. \n " ) ;
MSG_Add ( " SHELL_CMD_PAUSE " , " Press any key to continue. \n " ) ;
MSG_Add ( " SHELL_CMD_PAUSE_HELP " , " Waits for 1 keystroke to continue. \n " ) ;
MSG_Add ( " SHELL_CMD_COPY_FAILURE " , " Copy failure : %s. \n " ) ;
MSG_Add ( " SHELL_CMD_COPY_SUCCESS " , " %d File(s) copied. \n " ) ;
MSG_Add ( " SHELL_CMD_SUBST_NO_REMOVE " , " Unable to remove, drive not in use. \n " ) ;
MSG_Add ( " SHELL_CMD_SUBST_FAILURE " , " SUBST failed. You either made an error in your commandline or the target drive is already used. \n It's only possible to use SUBST on Local drives " ) ;
# ifdef HW_RVL
MSG_Add ( " SHELL_STARTUP_BEGIN " ,
" \033 [44;1m======================== "
" ======================== "
" ====================== \n "
" | \033 [32mWelcome to DOSBox %-8s \033 [37m | \n "
" | | \n "
// "| DOSBox runs real and protected mode games. |\n"
" | For a short introduction for new users type: \033 [33mINTRO \033 [37m | \n "
" | For supported shell commands type: \033 [33mHELP \033 [37m | \n "
" | | \n "
" | To adjust the emulated CPU speed, use \033 [31mctrl-F11 \033 [37m and \033 [31mctrl-F12 \033 [37m. | \n "
" | To activate the keymapper \033 [31mctrl-F1 \033 [37m. | \n "
" | For more information read the \033 [36mREADME \033 [37m file in the DOSBox directory. | \n "
" | | \n "
) ;
MSG_Add ( " SHELL_STARTUP_CGA " , " | DOSBox supports Composite CGA mode. | \n "
" | Use \033 [31m(alt-)F11 \033 [37m to change the colours when in this mode. | \n "
" | | \n "
) ;
MSG_Add ( " SHELL_STARTUP_HERC " , " \xBA Use \033 [31mF11 \033 [37m to cycle through white, amber, and green monochrome color. \xBA \n "
" \xBA \xBA \n "
) ;
MSG_Add ( " SHELL_STARTUP_DEBUG " ,
" | Press \033 [31malt-Pause \033 [37m to enter the debugger or start the exe with \033 [33mDEBUG \033 [37m. | \n "
" | | \n "
) ;
MSG_Add ( " SHELL_STARTUP_END " ,
" | \033 [32mHAVE FUN! \033 [37m | \n "
" | \033 [32mThe DOSBox Team \033 [37m | \n "
" ======================== "
" ======================== "
" ====================== \033 [0m \n "
//"\n" //Breaks the startup message if you type a mount and a drive change.
) ;
# else
MSG_Add ( " SHELL_STARTUP_BEGIN " ,
" \033 [44;1m \xC9 \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD "
" \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD "
" \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xBB \n "
" \xBA \033 [32mWelcome to DOSBox %-8s \033 [37m \xBA \n "
" \xBA \xBA \n "
// "\xBA DOSBox runs real and protected mode games. \xBA\n"
" \xBA For a short introduction for new users type: \033 [33mINTRO \033 [37m \xBA \n "
" \xBA For supported shell commands type: \033 [33mHELP \033 [37m \xBA \n "
" \xBA \xBA \n "
" \xBA To adjust the emulated CPU speed, use \033 [31mctrl-F11 \033 [37m and \033 [31mctrl-F12 \033 [37m. \xBA \n "
" \xBA To activate the keymapper \033 [31mctrl-F1 \033 [37m. \xBA \n "
" \xBA For more information read the \033 [36mREADME \033 [37m file in the DOSBox directory. \xBA \n "
" \xBA \xBA \n "
) ;
MSG_Add ( " SHELL_STARTUP_CGA " , " \xBA DOSBox supports Composite CGA mode. \xBA \n "
2021-02-06 16:06:31 +01:00
" \xBA Use \033 [31mF12 \033 [37m to set composite output ON, OFF, or AUTO (default). \xBA \n "
" \xBA \033 [31m(Alt-)F11 \033 [37m changes hue; \033 [31mctrl-alt-F11 \033 [37m selects early/late CGA model. \xBA \n "
2021-02-06 09:39:32 +01:00
" \xBA \xBA \n "
) ;
MSG_Add ( " SHELL_STARTUP_HERC " , " \xBA Use \033 [31mF11 \033 [37m to cycle through white, amber, and green monochrome color. \xBA \n "
" \xBA \xBA \n "
) ;
MSG_Add ( " SHELL_STARTUP_DEBUG " ,
" \xBA Press \033 [31malt-Pause \033 [37m to enter the debugger or start the exe with \033 [33mDEBUG \033 [37m. \xBA \n "
" \xBA \xBA \n "
) ;
MSG_Add ( " SHELL_STARTUP_END " ,
" \xBA \033 [32mHAVE FUN! \033 [37m \xBA \n "
" \xBA \033 [32mThe DOSBox Team \033 [33mhttp://www.dosbox.com \033 [37m \xBA \n "
" \xC8 \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD "
" \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD "
" \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xCD \xBC \033 [0m \n "
//"\n" //Breaks the startup message if you type a mount and a drive change.
) ;
# endif
2021-02-06 16:06:31 +01:00
MSG_Add ( " SHELL_STARTUP_SUB " , " \n \n \033 [32;1mDOSBox %s Command Shell \033 [0m \n \n " ) ;
2021-02-06 09:39:32 +01:00
MSG_Add ( " SHELL_CMD_CHDIR_HELP " , " Displays/changes the current directory. \n " ) ;
MSG_Add ( " SHELL_CMD_CHDIR_HELP_LONG " , " CHDIR [drive:][path] \n "
" CHDIR [..] \n "
" CD [drive:][path] \n "
" CD [..] \n \n "
" .. Specifies that you want to change to the parent directory. \n \n "
" Type CD drive: to display the current directory in the specified drive. \n "
" Type CD without parameters to display the current drive and directory. \n " ) ;
MSG_Add ( " SHELL_CMD_CLS_HELP " , " Clear screen. \n " ) ;
MSG_Add ( " SHELL_CMD_DIR_HELP " , " Directory View. \n " ) ;
MSG_Add ( " SHELL_CMD_ECHO_HELP " , " Display messages and enable/disable command echoing. \n " ) ;
MSG_Add ( " SHELL_CMD_EXIT_HELP " , " Exit from the shell. \n " ) ;
MSG_Add ( " SHELL_CMD_HELP_HELP " , " Show help. \n " ) ;
MSG_Add ( " SHELL_CMD_MKDIR_HELP " , " Make Directory. \n " ) ;
MSG_Add ( " SHELL_CMD_MKDIR_HELP_LONG " , " MKDIR [drive:][path] \n "
" MD [drive:][path] \n " ) ;
MSG_Add ( " SHELL_CMD_RMDIR_HELP " , " Remove Directory. \n " ) ;
MSG_Add ( " SHELL_CMD_RMDIR_HELP_LONG " , " RMDIR [drive:][path] \n "
" RD [drive:][path] \n " ) ;
MSG_Add ( " SHELL_CMD_SET_HELP " , " Change environment variables. \n " ) ;
MSG_Add ( " SHELL_CMD_IF_HELP " , " Performs conditional processing in batch programs. \n " ) ;
MSG_Add ( " SHELL_CMD_GOTO_HELP " , " Jump to a labeled line in a batch script. \n " ) ;
MSG_Add ( " SHELL_CMD_SHIFT_HELP " , " Leftshift commandline parameters in a batch script. \n " ) ;
MSG_Add ( " SHELL_CMD_TYPE_HELP " , " Display the contents of a text-file. \n " ) ;
MSG_Add ( " SHELL_CMD_TYPE_HELP_LONG " , " TYPE [drive:][path][filename] \n " ) ;
MSG_Add ( " SHELL_CMD_REM_HELP " , " Add comments in a batch file. \n " ) ;
MSG_Add ( " SHELL_CMD_REM_HELP_LONG " , " REM [comment] \n " ) ;
MSG_Add ( " SHELL_CMD_NO_WILD " , " This is a simple version of the command, no wildcards allowed! \n " ) ;
MSG_Add ( " SHELL_CMD_RENAME_HELP " , " Renames one or more files. \n " ) ;
MSG_Add ( " SHELL_CMD_RENAME_HELP_LONG " , " RENAME [drive:][path]filename1 filename2. \n "
" REN [drive:][path]filename1 filename2. \n \n "
" Note that you can not specify a new drive or path for your destination file. \n " ) ;
MSG_Add ( " SHELL_CMD_DELETE_HELP " , " Removes one or more files. \n " ) ;
MSG_Add ( " SHELL_CMD_COPY_HELP " , " Copy files. \n " ) ;
MSG_Add ( " SHELL_CMD_CALL_HELP " , " Start a batch file from within another batch file. \n " ) ;
MSG_Add ( " SHELL_CMD_SUBST_HELP " , " Assign an internal directory to a drive. \n " ) ;
MSG_Add ( " SHELL_CMD_LOADHIGH_HELP " , " Loads a program into upper memory (requires xms=true,umb=true). \n " ) ;
MSG_Add ( " SHELL_CMD_CHOICE_HELP " , " Waits for a keypress and sets ERRORLEVEL. \n " ) ;
MSG_Add ( " SHELL_CMD_CHOICE_HELP_LONG " , " CHOICE [/C:choices] [/N] [/S] text \n "
" /C[:]choices - Specifies allowable keys. Default is: yn. \n "
" /N - Do not display the choices at end of prompt. \n "
" /S - Enables case-sensitive choices to be selected. \n "
" text - The text to display as a prompt. \n " ) ;
MSG_Add ( " SHELL_CMD_ATTRIB_HELP " , " Does nothing. Provided for compatibility. \n " ) ;
MSG_Add ( " SHELL_CMD_PATH_HELP " , " Provided for compatibility. \n " ) ;
MSG_Add ( " SHELL_CMD_VER_HELP " , " View and set the reported DOS version. \n " ) ;
MSG_Add ( " SHELL_CMD_VER_VER " , " DOSBox version %s. Reported DOS version %d.%02d. \n " ) ;
/* Regular startup */
call_shellstop = CALLBACK_Allocate ( ) ;
/* Setup the startup CS:IP to kill the last running machine when exitted */
RealPt newcsip = CALLBACK_RealPointer ( call_shellstop ) ;
SegSet16 ( cs , RealSeg ( newcsip ) ) ;
reg_ip = RealOff ( newcsip ) ;
CALLBACK_Setup ( call_shellstop , shellstop_handler , CB_IRET , " shell stop " ) ;
PROGRAMS_MakeFile ( " COMMAND.COM " , SHELL_ProgramStart ) ;
/* Now call up the shell for the first time */
Bit16u psp_seg = DOS_FIRST_SHELL ;
Bit16u env_seg = DOS_FIRST_SHELL + 19 ; //DOS_GetMemory(1+(4096/16))+1;
Bit16u stack_seg = DOS_GetMemory ( 2048 / 16 ) ;
SegSet16 ( ss , stack_seg ) ;
reg_sp = 2046 ;
/* Set up int 24 and psp (Telarium games) */
real_writeb ( psp_seg + 16 + 1 , 0 , 0xea ) ; /* far jmp */
real_writed ( psp_seg + 16 + 1 , 1 , real_readd ( 0 , 0x24 * 4 ) ) ;
real_writed ( 0 , 0x24 * 4 , ( ( Bit32u ) psp_seg < < 16 ) | ( ( 16 + 1 ) < < 4 ) ) ;
/* Set up int 23 to "int 20" in the psp. Fixes what.exe */
real_writed ( 0 , 0x23 * 4 , ( ( Bit32u ) psp_seg < < 16 ) ) ;
2021-02-06 16:06:31 +01:00
/* Set up int 2e handler */
Bitu call_int2e = CALLBACK_Allocate ( ) ;
RealPt addr_int2e = RealMake ( psp_seg + 16 + 1 , 8 ) ;
CALLBACK_Setup ( call_int2e , & INT2E_Handler , CB_IRET_STI , Real2Phys ( addr_int2e ) , " Shell Int 2e " ) ;
RealSetVec ( 0x2e , addr_int2e ) ;
2021-02-06 09:39:32 +01:00
/* Setup MCBs */
DOS_MCB pspmcb ( ( Bit16u ) ( psp_seg - 1 ) ) ;
pspmcb . SetPSPSeg ( psp_seg ) ; // MCB of the command shell psp
pspmcb . SetSize ( 0x10 + 2 ) ;
pspmcb . SetType ( 0x4d ) ;
DOS_MCB envmcb ( ( Bit16u ) ( env_seg - 1 ) ) ;
envmcb . SetPSPSeg ( psp_seg ) ; // MCB of the command shell environment
envmcb . SetSize ( DOS_MEM_START - env_seg ) ;
envmcb . SetType ( 0x4d ) ;
2021-02-06 16:06:31 +01:00
2021-02-06 09:39:32 +01:00
/* Setup environment */
PhysPt env_write = PhysMake ( env_seg , 0 ) ;
MEM_BlockWrite ( env_write , path_string , ( Bitu ) ( strlen ( path_string ) + 1 ) ) ;
env_write + = ( PhysPt ) ( strlen ( path_string ) + 1 ) ;
MEM_BlockWrite ( env_write , comspec_string , ( Bitu ) ( strlen ( comspec_string ) + 1 ) ) ;
env_write + = ( PhysPt ) ( strlen ( comspec_string ) + 1 ) ;
mem_writeb ( env_write + + , 0 ) ;
mem_writew ( env_write , 1 ) ;
env_write + = 2 ;
MEM_BlockWrite ( env_write , full_name , ( Bitu ) ( strlen ( full_name ) + 1 ) ) ;
DOS_PSP psp ( psp_seg ) ;
psp . MakeNew ( 0 ) ;
dos . psp ( psp_seg ) ;
2021-02-06 16:06:31 +01:00
2021-02-06 09:39:32 +01:00
/* The start of the filetable in the psp must look like this:
* 01 01 01 00 02
* In order to achieve this : First open 2 files . Close the first and
* duplicate the second ( so the entries get 01 ) */
Bit16u dummy = 0 ;
DOS_OpenFile ( " CON " , OPEN_READWRITE , & dummy ) ; /* STDIN */
DOS_OpenFile ( " CON " , OPEN_READWRITE , & dummy ) ; /* STDOUT */
DOS_CloseFile ( 0 ) ; /* Close STDIN */
DOS_ForceDuplicateEntry ( 1 , 0 ) ; /* "new" STDIN */
DOS_ForceDuplicateEntry ( 1 , 2 ) ; /* STDERR */
DOS_OpenFile ( " CON " , OPEN_READWRITE , & dummy ) ; /* STDAUX */
2021-02-06 16:06:31 +01:00
DOS_OpenFile ( " PRN " , OPEN_READWRITE , & dummy ) ; /* STDPRN */
2021-02-06 09:39:32 +01:00
psp . SetParent ( psp_seg ) ;
/* Set the environment */
psp . SetEnvironment ( env_seg ) ;
/* Set the command line for the shell start up */
CommandTail tail ;
tail . count = ( Bit8u ) strlen ( init_line ) ;
2021-02-06 16:06:31 +01:00
memset ( & tail . buffer , 0 , 127 ) ;
2021-02-06 09:39:32 +01:00
strcpy ( tail . buffer , init_line ) ;
MEM_BlockWrite ( PhysMake ( psp_seg , 128 ) , & tail , 128 ) ;
2021-02-06 16:06:31 +01:00
2021-02-06 09:39:32 +01:00
/* Setup internal DOS Variables */
dos . dta ( RealMake ( psp_seg , 0x80 ) ) ;
dos . psp ( psp_seg ) ;
2021-02-06 16:06:31 +01:00
SHELL_ProgramStart_First_shell ( & first_shell ) ;
2021-02-06 09:39:32 +01:00
first_shell - > Run ( ) ;
delete first_shell ;
first_shell = 0 ; //Make clear that it shouldn't be used anymore
}