phil@kcl-cs.UUCP (Phil Thompson) (08/08/85)
<> Is there any way that I can find out the address of the PSP from within a C program using the DeSmet compiler? The initialisation code throws away the segment registers. (I'm actually trying to write getenv() so if somebody has already done it.....) Thanks, Phil Thompson
bet@ecsvax.UUCP (Bennett E. Todd III) (08/12/85)
In article <192@westo.kcl-cs.UUCP> phil@kcl-cs.UUCP (Phil Thompson) writes: >Is there any way that I can find out the address of the PSP from within >a C program using the DeSmet compiler? The initialization code throws away >the segment registers. (I'm actually trying to write getenv() so if >somebody has already done it.....) DeSmet's startup leaves the CS where it starts up -- right after the PSP. The PSP is 100H bytes long, so subtract 10H from the CS and you have the offset of the PSP. It works; I've used it. Here follows getenv.c; those of you not using DeSmet will need to find some way to get the segment address of the PSP (I used DeSmet's builtin _showcs() which returns the value of CS, and subtracted 0x10) and write _peek(), whose definition should be obvious. ------------- start of getenv.c ----------------- #include <stdio.h> char *getenv(name) char *name; { char *found, *malloc(); char *offset, *tmp, _peek(), toupper(); int i; unsigned segment, _showcs(); /* PSP is at CS-10H */ segment = _showcs() - 0x10; /* ** The environment is stored starting at a segment whose segment address ** can be found 2Ch into the PSP -- a word address... */ segment = _peek(0x2c, segment) + 256*_peek(0x2d, segment); /* Look for the string NAME= in the environment */ for (offset=NULL; _peek(offset, segment) != NULL; offset++) { i = 0; /* i scans through name */ while (name[i] != NULL && toupper(_peek(offset, segment)) == toupper(name[i])) { i++; offset++; } if (name[i] == NULL && _peek(offset, segment) == '=') { /* then we found it -- get it and return it */ tmp = ++offset; while (_peek(tmp, segment) != NULL) tmp++; found = malloc(1 + tmp-offset); if (found == NULL) { fprintf(stderr, "getenv: malloc failed. Bye....\n"); exit(1); } tmp = found; while ((*tmp++ = _peek(offset++, segment)) !=NULL) /* NULL BODY */; return(found); } /* We didn't found it -- clean up and try next entry */ while (_peek(offset, segment) != NULL) offset++; } /* Ain't no sech beastie. Sorry, boss... */ return((char *) NULL); } ---------------- end of getenv.c ------------ Note: the code is indented with tabstops every 4 columns. This routine is obviously nonportable. That's life in the rewriting-system-calls business. It isn't pretty. Sorry, I never wrote this for public consumption, just so I could understand it. Here is a Q&D driver I used to exercise it -- printenv. Usage is like A>printenv comspec comspec=A:\COMMAND.COM It's even uglier than getenv. I didn't even care if *I* could understand it! (throwaway test drivers, and like that). ------------- start of printenv.c ---------------- #include <stdio.h> extern char *getenv(); main(argc, argv) int argc; char **argv; { for (argc--, argv++; argc; argc--, argv++) printf("%s=%s\n", *argv, getenv(*argv)); } ---------------- end of printenv.c ----------------- Hope this helps someone, somewhere. I would be delighted to hear any bug reports (I use this occasionally myself) but I might not do anything about them. -Bennett -- "Some people are lucky; the rest of us have to work at it." Bennett Todd -- Duke Computation Center, Durham, NC 27706-7756; (919) 684-3695 ...{decvax,seismo,philabs,ihnp4,akgua}!mcnc!ecsvax!bet or dbtodd@tucc.BITNET
broehl@watdcsu.UUCP (Bernie Roehl) (08/13/85)
No problem. The program segment prefix is at _showcs() - 0x10 (since the CS register is offset by 100 hex from the PSP). I used this in writing a getenv(); I'd post it if I had it handy... may yet do it, if I get a chance.