Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!columbia!rutgers!clyde!bellcore!wind!tr From: tr@wind.bellcore.com (tom reingold) Newsgroups: comp.lang.pascal,comp.sys.ibm.pc Subject: Re: Environment variables in Turbo Pascal Message-ID: <1690@bellcore.bellcore.com> Date: Tue, 28-Jul-87 18:29:05 EDT Article-I.D.: bellcore.1690 Posted: Tue Jul 28 18:29:05 1987 Date-Received: Sat, 1-Aug-87 03:00:39 EDT References: <151@ivory.SanDiego.NCR.COM> Sender: news@bellcore.bellcore.com Reply-To: tr@wind.UUCP (tom reingold) Distribution: world Organization: BellCoRe (Bell Communications Research) Lines: 155 Xref: mnetor comp.lang.pascal:223 comp.sys.ibm.pc:6159 In article <151@ivory.SanDiego.NCR.COM> mike@ivory.UUCP (Michael Lodman) writes: $ Could someone please email and tell me how to read the DOS environment $ variables with Turbo Pascal? $ $ Thanks. $ $ $ -- $ Michael Lodman (619) 485-3335 Mike Morearty posted this to the net a while back. I made very minor changes. Where I did so, I put my first name (Tom) on the line. The program should be pretty clear. ------------------------------------------------------------ (* Path: seismo!lll-crg!nike!ucbcad!zen!cory.Berkeley.EDU!morearty From: morearty@cory.Berkeley.EDU (Mike Morearty) Newsgroups: net.micro.pc Subject: You can get argv[0] in DOS 3.x Message-ID: <468@zen.BERKELEY.EDU> Date: Mon, 6-Oct-86 06:18:52 EDT Date-Received: Mon, 6-Oct-86 19:20:50 EDT Sender: news@zen.BERKELEY.EDU Reply-To: morearty@cory.Berkeley.EDU (Mike Morearty) Organization: University of California, Berkeley Lines: 111 I just discovered an undocumented feature of the more recent versions of DOS: it is at last possible to obtain argv[0]. I discovered this because I was surprised to read in the DOS 3.2 manual that XCOPY.EXE behaves differently if you rename it as MCOPY.EXE. So I disassembled it, and found the following method to determine the name of the program that is being run. As you probably know, in all versions of DOS from 2.0 on, there is an environment area in memory with strings that can be created with the SET command, such as "set PATH=\". The segment of this environment area is stored as a word at offset 2Ch into the Program Segment Prefix. If, for example, the word at address 2Ch is 1000, then the environment area begins at offset 1000:0000. This environment area consists of null-terminated strings of the form "NAME=value" (with NAME all upper case), followed by a null byte. If the next byte is also a null, then that marks the end of the environment area. (Thus, if the very first byte in the environment area is a null, there are no strings present.) Now, the good stuff: in DOS 3.1 and 3.2, and possibly in 3.0 (I haven't been able to test it), this environment area is followed by the complete path and filename of the program that has been invoked. Here is the exact format (#x indicates a byte with value x): NAME=value#0 ;one or more null-terminated strings #0 ;the terminating null byte #1 ;followed by a byte with value one #0 ;followed by another null byte C:\PAS\ENV.COM#0 ;argv[0], null-terminated Note the following changes from older versions of DOS: 1. There are always TWO null bytes at the end of the environment area. In older versions, there may have been only one null byte if there were no environment strings present. 2. The environment area is immediately followed by a 1 and then a 0. If this is not present, assume that argv[0] is not present either. Note that the drive specifier and/or certain subdirectory names in the path may be lower case, and there may be "." and/or ".." entries in the path, depending on the line that the user typed to invoke the program. Some examples follow, assuming that the user is in the directory C:\DIR, and there is a program in that directory called PROGRAM.COM: User typed argv[0] contains ---------- ---------------- program C:\DIR\PROGRAM.COM PROGRAM C:\DIR\PROGRAM.COM .\program C:\DIR\.\PROGRAM.COM \dir\program C:\dir\PROGRAM.COM c:program c:\DIR\PROGRAM.COM program.exe C:\DIR\PROGRAM.COM Here is a sample program written in Turbo Pascal (version 3.x), to display argv[0]. ================================================================= *) { Argv0.pas - Display argv[0], in other words, the path and filename that invoked this program. Works under DOS 3.1 and 3.2, and possibly 3.0. } program Argv0; {$p512} var env: integer absolute cseg:$2C; (* segment of environment *) cp: integer; (* pointer into environment segment *) r: record (* record of registers *) ax,bx,cx,dx,bp,si,di,ds,es,flags: integer; end; ch: char; begin r.ax := $3000; MsDos(r); (* get DOS version number *) if (lo(r.ax) <> 3) or (hi(r.ax) > $20) then begin writeln('Needs DOS 3.0, 3.1, or 3.2'); halt; end; cp := 0; (* point to beginning of segment *) (* find the end of the environment space, e.g., where two nulls are found in a row. *) while (memw[env:cp] <> 0) do begin ch := chr(memw[env:cp]); (* Tom *) if ord(ch) <> 0 then (* Tom *) write(ch) else (* Tom *) writeln; cp := cp + 1; end; cp := cp + 2; (* move past the two nulls *) (* If this version of DOS has argv[0], then the two nulls are immediately followed by an ASCII 1 and then another null. *) if (memw[env:cp] <> 1) then begin writeln('Invalid memory format'); end else begin cp := cp + 2; (* move past the 1 and the 0 *) writeln; (* Tom *) writeln; (* Tom *) while mem[env:cp] <> 0 do begin (* argv[0] is null-terminated *) write(chr(mem[env:cp])); cp := cp+1; end; writeln; (* Tom *) end; end. -- Mike Morearty Tom Reingold INTERNET: tr@bellcore.bellcore.com UUCP: {seismo,ihnp4,ucbvax,decvax}!bellcore!tr {ulysses,allegra,clyde,princeton}!bellcore!tr