Mail Archives: djgpp/2011/12/04/12:45:10
I finally found a way to retrieve the absolute path to the current
program. It seems that the pointer to the environment in the PSP when
using DJGPP is wrong for whatever reason. There is a KB16 program
which has the correct pointer to the environment I am looking for in
its PSP though.
So I walked through the MCB chain to find the environment block in
there. There are two entries in there with the same PSP, one is the
environment block, the other is the program code. The latter has the
PSP right after the MCB so if that is not the case you have found the
environment block. The absolute path is then located behind the size
given in the MCB of the environment block. Here is my code:
#include <stdio.h>
#include <sys/movedata.h>
#include <dpmi.h>
#include <go32.h>
main(int argc,char **argv)
{
unsigned int es,peekword,blocksize,pspseg,environment;
unsigned short mcbid=0x4d;
unsigned long the_psp = 0;
static unsigned mcbseg; //first mcb
unsigned mcbs;
char* buff[256];
__dpmi_regs regs;
regs.x.ax = 0x5200; /* AH = 52h, AL = 00h */
__dpmi_int (0x21, ®s); /* call DOS */
if (regs.x.flags & 1) /* is carry flag set? */
{;} /* The call failed*/
else
{
es = regs.x.es;
es <<= 4;
es += regs.x.bx;
_dosmemgetw(es-2, 1, &mcbseg);
mcbseg <<= 4;
}
the_psp = _go32_info_block.linear_address_of_original_psp;
while (mcbid==0x4d){
mcbs=mcbseg;
printf("\nMCB:%X \t",mcbs);
_dosmemgetb(mcbs,1,&mcbid);
printf("%c ",mcbid);
_dosmemgetw(mcbs+1,1,&pspseg);
printf("PSP:%X \t",pspseg);
environment=pspseg<<4;
environment += 0x2C;
_dosmemgetw(mcbs+3,1,&blocksize);
printf("Blocksize:%X \t",blocksize);
if ((mcbseg+16)==pspseg*16){ //is it a program code mcb?
_dosmemgetw(environment,1,&peekword);
printf("ENV:%X ",peekword); //only print if program code
dosmemget(mcbs+8,30,&buff);
printf(" Program:%s",buff);
}
if (pspseg*16==the_psp) { //found the right PSP?
//not the code but the environment block?
if ((mcbseg+16)!=the_psp){
dosmemget(mcbs+blocksize*16-18,30,&buff);
printf("Path:%s",buff);
}
}
//retrieve next mcb
_dosmemgetw(mcbs+3,1,&peekword);
peekword <<=4;
mcbseg += peekword+0x10;
}
return 0;
}
I should have used a different variable name instead of mcbseg but I
leave it now as it is.
Rayer may have pointed out correctly that this is all too complicated
and could be replaced by reading the value in argv[0]. But I observed
that when I start my code with "redir" argv[0] will not return the
full path. Plus DJ Delorie's post made me uncertain whether I should
use argv[0].
Georg
- Raw text -