An alternative approach would be to use this C code and some XS magic, or Inline::C. Assuming, of course, that getting a DOSsy perl and C to talk to each other is practical:
/* Call the set() function with two pointers to char as the
+ parameters. The first points to the environment variable
+ NAME, the second to the VALUE. The NAME is made
+ upper-case automatically.
*/
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#define VLEN 80
#define BUFLEN 1000
unsigned int _psp;
unsigned short peekw();
unsigned char peekb();
void pokeb();
set (char *varname, char *value)
{ unsigned short x, p, y, envsize, free;
int found;
char c, var[VLEN+BUFSIZ+1];
int i, varlen;
varlen = strlen(varname);
for (i=0; i <= varlen; i++) var[i] = toupper(varname[i]);
strcat(var,"=");
varlen++;
p = _psp;
do
{ x = p;
p = peekw(x,0x16);
} while (p != x);
if (peekb(x-1,0) != 0x4d)
{ cputs("Wrong DOS segment - weirdness is occuring - PANIC!\n\01
+5");
exit(2);
}
p = peekw(x,0x2c);
envsize = peekw(p-1, 3) << 4;
x = 0;
found = 0;
do
{ if (mystrncmp(p,x,var,varlen) == 0)
{ y = x;
found = 1;
}
while (c=peekb(p,x))
{ if (found == 2)
{ pokeb(p,y,c);
y++;
}
x++;
}
switch (found)
{ case 1: found=2; break;
case 2: pokeb(p,y,c); y++; break;
}
} while (peekb(p,++x));
if (found)
{ pokeb(p,y,'\0');
x = y;
}
free = envsize - x - 1;
for (i=2; i < strlen(value) + 2; i++) value[i] = tolower(value[i])
+;
strcat(var,value);
y = strlen(var);
if (y+1 > free)
{ cputs("Sorry, your environment space is full, program abort.\n
+\015");
cputs("Try \"shell=c:\command.com /p /e:62\" in config.sys to\
+n\015");
cputs("increase your environment space to 992 bytes\n\015");
exit(3);
}
for (i=0; i <= y; i++) pokeb(p, x++, var[i]);
pokeb(p, x, 0);
}
mystrncmp(seg,offset,source,n)
short seg,offset;
int n;
char *source;
{
int i, dif;
for (i=0; i < n; i++) {
dif = peekb(seg,offset+i) - source[i];
if (dif) return dif;
};
return 0;
}
unsigned char peekb(seg,offset)
short seg,offset;
{
char far *fptr;
FP_SEG(fptr) = seg;
FP_OFF(fptr) = offset;
return *fptr;
}
void pokeb(seg,offset,what)
short seg,offset;
char what;
{
char far *fptr;
FP_SEG(fptr) = seg;
FP_OFF(fptr) = offset;
*fptr = what;
}
unsigned short peekw(seg,offset)
short seg,offset;
{
unsigned far *fptr;
FP_SEG(fptr) = seg;
FP_OFF(fptr) = offset;
return *fptr;
}
Note that I have only used that with MS Quick C, it may or may not work with other compilers. No, I no longer have any idea how it works. There are probably cut n' paste errors. It may turn your cat into an almond. Caveat Programmer.