/* MEM.C --walks DOS MCB chain(s) : simple version */
# include <stdio.h>
# include <stdlib.h>
# include <ctype.h>
# include <string.h>
# include <dos.h>
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long ULONG;
typedef enum {FALSE,TRUE} BOOL;
typedef void far *FP;
#define MCB_FM_SEG(seg) ((seg)-1)
#define IS_PSP(mcb) (FP_SEG(mcb)+1==(mcb)->owner)
#define ENV_FM_PSP(psp_seg) *((WORD far *)MK_FP(psp_seg,0x2c))
#pragma pack (1)
typedef struct {
BYTE type; /* M=in chain , Z=at end */
WORD owner; /* PSP of the owner */
WORD size; /* in 16-byte paragraphs */
BYTE unused [3];
BYTE dos4 [8];
} MCB;
void fail (char *s) {puts (s);exit(1);}
MCB far *get_mcb (void)
{
__emit__(0xB4,0x52); /* MOV AH,52 */
__emit__(0xCD,0x21); /* INT 21 */
__emit__(0x26); /* ES: */
__emit__(0x8B,0x57,0xFE); /* MOV DX,[BX-02] */
__emit__(0x31,0xC0); /* XOR AX,AX */
}
unsigned fstrlen (char far *s)
{
unsigned len = 0;
while (*s++)
len ++;
return len;
}
char far *env(MCB far *mcb)
{
char far *e;
unsigned env_mcb;
unsigned env_owner;
if (IS_PSP(mcb))
e=MK_FP (ENV_FM_PSP(mcb->owner),0);
else
return (char far *) 0;
env_mcb = MCB_FM_SEG (FP_SEG(e));
env_owner = ((MCB far *)MK_FP(env_mcb,0))->owner;
return (env_owner==mcb->owner)?e:(char far *)0;
}
char far *progname_fm_psp (unsigned psp)
{
char far *e;
unsigned len;
if (!(e=env(MK_FP(MCB_FM_SEG(psp),0))))
return (char far *)0;
if (_osmajor>=3)
{
do e+=(len=fstrlen(e))+1;
while (len);
if ((*((signed far *)e)>=1)&&(*((signed far *)e)<10))
{
e+=sizeof (signed);
if (isalpha(*e))
return e;
}
}
return (char far *) 0;
}
void display_progname (MCB far *mcb)
{
char far *s;
if (IS_PSP(mcb))
if (s=progname_fm_psp ((FP_SEG(mcb)+1)))
printf (" %Fs",s);
}
BOOL belongs (void far *vec,unsigned start,unsigned size)
{
unsigned seg = FP_SEG (vec) + (FP_OFF(vec)>>4);
return (seg>=start)&&(seg<=(start+size));
}
void display_cmdline (MCB far *mcb)
{
int len=*((BYTE far *)MK_FP(mcb->owner,0x80));
char far *cmdline=MK_FP(mcb->owner,0x81);
printf ("%.*Fs",len,cmdline);
}
void display_vectors (MCB far *mcb)
{
static void far **vec=(void far **) 0;
WORD vec_seg;
int i;
int did_one=0;
if (!vec)
{
if (!(vec=calloc(256,sizeof(void far *))))
fail ("insufficient memory .");
for (i=0;i<256;i++)
vec[i]=getvect(i);
}
for (i=0;i<256;i++)
if (vec[i]&&belongs(vec[i],FP_SEG (mcb),mcb->size))
{
if (!did_one) {did_one++; printf ("[");}
printf ("%02X ",i);
vec[i]=0;
}
if (did_one) printf ("]");
}
void display (MCB far *mcb)
{
static void far *vect_2e=(void far *)0;
unsigned env_seg;
printf ("%04X %04X %04X(%6lu) ",
FP_SEG (mcb),mcb->owner,mcb->size,(long)mcb->size<<4);
if (IS_PSP(mcb)) {
void far *e=env (mcb);
if (env_seg = FP_SEG(e)) printf ("%04X",env_seg);
else printf (" ");
display_progname (mcb);
}
if (!vect_2e)
vect_2e = getvect (0x2e);
if (!mcb->owner)
printf ("free ");
else if (mcb->owner == 8)
printf ("config ");
else if (belongs (vect_2e,FP_SEG(mcb),mcb ->size))
printf (" %s",getenv ("COMSPEC"));
if (IS_PSP(mcb))
display_cmdline (mcb);
display_vectors (mcb);
printf ("\n");
}
void walk (MCB far *mcb)
{
printf ("Seg Owner Size Env\n");
for (;;)
switch (mcb->type)
{
case 'M' :
display (mcb);
mcb=MK_FP (FP_SEG (mcb)+mcb->size+1,0);
break;
case 'Z' :
display (mcb);
return;
default :
fail ("error in MCB chain ");
}
}
main (int argc,char *argv[])
{
if (argc<2)
walk (get_mcb());
else
{
unsigned seg;
sscanf (argv[1],"%04X",&seg);
walk (MK_FP(seg,0));
}
printf (" total memory %dK bytes\n",biosmemory());
return 0;
}