1
0
Fork 0
dosbox-staging/src/misc/programs.cpp
2002-08-19 13:02:09 +00:00

174 lines
5 KiB
C++

/*
* Copyright (C) 2002 The DOSBox Team
*
* 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 Library General Public License for more details.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "programs.h"
#include "callback.h"
#include "regs.h"
#include "support.h"
#include "cross.h"
Bitu call_program;
/* This registers a file on the virtual drive and creates the correct structure for it*/
static Bit8u exe_block[]={
0xbc,0x00,0x03, //MOV SP,0x300 decrease stack size
0xbb,0x30,0x00, //MOV BX,0x030 for memory resize
0xb4,0x4a, //MOV AH,0x4A Resize memory block
0xcd,0x21, //INT 0x21
//pos 12 is callback number
0xFE,0x38,0x00,0x00, //CALLBack number
0xb8,0x00,0x4c, //Mov ax,4c00
0xcd,0x21, //INT 0x21
};
#define CB_POS 12
void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main) {
Bit8u * comdata=(Bit8u *)malloc(128);
memcpy(comdata,&exe_block,sizeof(exe_block));
comdata[CB_POS]=call_program&0xff;
comdata[CB_POS+1]=(call_program>>8)&0xff;
/* Copy the pointer this should preserve endianes */
memcpy(&comdata[sizeof(exe_block)],&main,sizeof(main));
Bit32u size=sizeof(exe_block)+sizeof(main);
VFILE_Register(name,comdata,size);
}
static Bitu PROGRAMS_Handler(void) {
/* This sets up everything for a program start up call */
/* First get the current psp */
PROGRAM_Info * info=new PROGRAM_Info;
info->psp_seg=dos.psp;
MEM_BlockRead(PhysMake(dos.psp,0),&info->psp_copy,sizeof(PSP));
/* Get the file name cmd_line 0 */
PhysPt envblock=PhysMake(info->psp_copy.environment,0);
do {} while (mem_readw(envblock++));
envblock+=3;
MEM_StrCopy(envblock,info->full_name,32);
info->psp_copy.cmdtail.buffer[info->psp_copy.cmdtail.count]=0;
info->cmd_line=info->psp_copy.cmdtail.buffer;
/* Find the program handler somewhere reference in the file */
Bit16u handle;
DOS_OpenFile(info->full_name,0,&handle);
Bit32u pos=sizeof(PROGRAMS_Main *);
DOS_SeekFile(handle,&pos,DOS_SEEK_END);
PROGRAMS_Main * handler;
Bit16u size=sizeof(PROGRAMS_Main *);
DOS_ReadFile(handle,(Bit8u *)&handler,&size);
DOS_CloseFile(handle);
(*handler)(info);
free(info);
return CBRET_NONE;
};
/* Main functions used in all program */
Program::Program(PROGRAM_Info * program_info) {
prog_info=program_info;
}
void Program::WriteOut(char * format,...) {
char buf[1024];
va_list msg;
va_start(msg,format);
vsprintf(buf,format,msg);
va_end(msg);
Bit16u size=strlen(buf);
DOS_WriteFile(STDOUT,(Bit8u *)buf,&size);
}
char * Program::GetEnvStr(char * env_str) {
/* Walk through the internal environment and see for a match */
/* Taking some short cuts here to not fuck around with memory structure */
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
size_t len=strlen(env_str);
while (*envstart) {
if (strncasecmp(env_str,envstart,len)==0 && envstart[len]=='=') {
return envstart;
}
envstart+=strlen(envstart)+1;
}
return 0;
};
char * Program::GetEnvNum(Bit32u num) {
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
while (*envstart) {
if (!num) return envstart;
envstart+=strlen(envstart)+1;
num--;
}
return 0;
}
Bit32u Program::GetEnvCount(void) {
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
Bit32u num=0;
while (*envstart) {
envstart+=strlen(envstart)+1;
num++;
}
return num;
}
bool Program::SetEnv(char * env_entry,char * new_string) {
MCB * env_mcb=(MCB *)HostMake(prog_info->psp_copy.environment-1,0);
upcase(env_entry);
Bit32u env_size=env_mcb->size*16;
if (!env_size) E_Exit("SHELL:Illegal environment size");
/* First try to find the old entry */
size_t len=strlen(env_entry);
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
while (*envstart) {
if (strncasecmp(env_entry,envstart,len)==0 && envstart[len]=='=') {
/* Now remove this entry */
memmove(envstart,envstart+strlen(envstart)+1,env_size);
} else {
envstart+=strlen(envstart)+1;
env_size-=(strlen(envstart)+1);
}
}
/* Now add the string if there is space available */
if (env_size<(strlen(env_entry)+strlen(new_string)+2)) return false;
if (!*new_string) return true;
sprintf(envstart,"%s=%s",env_entry,new_string);
envstart+=strlen(envstart)+1;
*envstart++=0;*envstart++=0;*envstart++=0;
return true;
}
//TODO Hash table :)
void PROGRAMS_Init(void) {
/* Setup a special callback to start virtual programs */
call_program=CALLBACK_Allocate();
CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF);
}