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