Microsoft C 5.1 question
Scott Garfinkle
seg at smsdpg.uu.net
Fri Jan 27 05:11:44 AEST 1989
>From article <617 at uceng.UC.EDU>, by mfinegan at uceng.UC.EDU (michael k finegan):
> What I am trying to do is put an address into a far data pointer
> (unsigned char far * ptr), which works okay at first, but when the global
> pointer gets accessed in a subroutine, low and behold - it is different! It
> appears that the high order word is zeroed out ... My question: has anyone out
> there in net land put addresses into far pointers in medium model with success?
> Is there a trick?
No. I've done it. It works. It's just a real pain.
Following code to set an arbitrary string in the DOS environment works
in all models:
Scott E. Garfinkle
SMS Data Products Group, Inc.
uunet!smsdpg!seg (seg at smsdpg.uu.net)
----------
/* Demo of how to set a string in parent environment.
* By Scott E. Garfinkle -- No rights reserved, no responsibility assumed.
*
* This program can be very unhealthy for your environment. In particular,
* it does not do the following:
* 1. Check for theoretically illegal characters, like '=' in the
* environment.
* 2. Remove old definitions that you're redefining.
* 3. Check to see if you've hit the limit of the environment size.
* 4. Force the new variable into uppercase.
* Some of the above aren't bugs, depending on your point of view. If you
* don't like something, change it.
*/
#include <stdio.h>
extern unsigned _psp; /* set to segment of our psp by MSC init routines */
/* from dos.h */
#define FP_SEG(fp) (*((unsigned *)&(fp) + 1))
#define FP_OFF(fp) (*((unsigned *)&(fp)))
main(int argc, char **argv)
{
char far *env_ptr;
int count;
unsigned far *psp_ptr;
extern char *getenv(const char *);
if(argc != 3) {
fprintf(stderr,"Usage: %s <variable> <value>\n", *argv);
exit(1);
}
psp_ptr = (unsigned far *) (((long) _psp << 16 ) + 0x16L);
/* now psp_ptr points to DOS PSP segment */
psp_ptr = (unsigned far *) (((long) *psp_ptr << 16 ) + 0x2cL);
/* now psp_ptr points to DOS environ segment */
env_ptr = (char far *) ((long) *psp_ptr << 16 );
/* now env_ptr points to DOS environ */
while(*env_ptr) /* skip past the current strings */
env_ptr += strlen(env_ptr)+1;
/* usually, sprintf returns number of characters written, excluding
* the null. This is true, e.g. for msc.
*/
#ifndef SPRINTF_RETURNS_CHAR
{
int count;
char buffer[512]; /* arbitrary */
count = sprintf(buffer,"%s=%s",argv[1],argv[2]);
movedata( /* of course microsoft does this backwards */
(unsigned) (( (long) (char far *) buffer) >> 16), /* yech */
(unsigned) buffer,
FP_SEG(env_ptr), FP_OFF(env_ptr),
++count
);
env_ptr[count] = '\0';
}
#else
(void) sprintf(env_ptr,"%s=%s",argv[1],argv[2]);
env_ptr[strlen(env_ptr)+1] = '\0'; /* need two nulls to terminate env */
#endif
exit(0);
}
More information about the Comp.lang.c
mailing list