| [reply] |
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. | [reply] [d/l] |
I'm not sure about DOS, but in Unix a Perl script can't change the environment of the shell it's executed from. You could set the variable in Perl using $ENV{whatever} and then execute the program from within Perl, which would have the new environment, or you could communicate via temp files, or perhaps you could print out the variable to be set and pull it into DOS somehow (in Unix you'd do this with backticks).
As far as starting and restarting the program, it shouldn't be a problem, although I'm not sure exactly what you want to do.
Perhaps posting some code of what you've tried and what didn't work would be helpful.
| [reply] [d/l] |