home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!munnari.oz.au!metro!grivel!metz.une.edu.au!ddavidso
- From: ddavidso@metz.une.edu.au (Dean Davidson)
- Newsgroups: comp.lang.pascal
- Subject: Re: Network Programming....
- Keywords: Netbios Netware TCP/IP
- Message-ID: <1682@grivel.une.edu.au>
- Date: 20 Aug 92 23:15:07 GMT
- References: <12AUG199221531849@gergo.tamu.edu>
- Sender: usenet@grivel.une.edu.au
- Organization: University of New England, Armidale, Australia
- Lines: 622
-
- In article <12AUG199221531849@gergo.tamu.edu> chris@gergo.tamu.edu (Chris King) writes:
- >Does anyone out there know how to program networks with Turbo Pascal,
- >and If so are you willing to share the information.
- >
-
- I have been waiting for someone more knowledgeable than me to reply to
- this, but no one did. For some reason network programming is kept as a
- deep dark secret by those in the know. The rest of us just have to muddle
- through.
-
- For what it is worth, here is my experiences etc.
-
- As another poster mentioned, first run your programs, and use the data from,
- one common directory on the server disk, eg F:\COMMON
-
- Make sure that the server loads SHARE - I do it in CONFIG.SYS with:
- INSTALL=C:\DOS\SHARE.EXE/L:200/F:2048
-
- The next thing is a magic line in you program somewhere that says:
- filemod := 66;
-
- This allows shared acces to your files. (see article by John Wulff, appended
- to this post)
-
- Having done this, you are up and running! That is, one workstation can read
- a data file while another writes to it.
-
- You may however want to try record locking. In one application I have,
- a log file is maintained of certain status functions. Naturally I don't
- want two workstations writing to this at the same time. Have a look at
- Karl Brendel's article (appended) about a DOS method, but I do it using
- TP.
-
- Following is three inclusions. First, my method of locking
- Second John Wullf's article, third Karl Brendel's posting.
-
- I hope this is useful and takes some of the mystery out of network programming
-
- Cheers,
- Dean
-
- -----------------------------------------------------------------------------
-
- { Record locking program fragment}
-
- type
- masty = record
- log : boolean;
- {locks for other files}
- end;
-
- function log_is_locked : boolean;
- {check if log file is locked}
-
- var
- fmast : file of masty;
- mastrec : masty;
-
- begin
- assign(fmast,mastnam);
- reset(fmast);
- read(fmast,mastrec);
- log_is_locked := mastrec.log;
- close(fmast);
- end;
-
- procedure lock_log;
- {lock log file}
- var
- fmast : file of masty;
- mastrec : masty;
-
- begin
- assign(fmast,mastnam);
- reset(fmast);
- read(fmast,mastrec);
- mastrec.log := True;
- reset(fmast);
- write(fmast,mastrec);
- close(fmast);
- end;
-
- procedure unlock_log;
- {unlock log file}
- var
- fmast : file of masty;
- mastrec : masty;
-
- begin
- assign(fmast,mastnam);
- reset(fmast);
- read(fmast,mastrec);
- mastrec.log := False;
- reset(fmast);
- write(fmast,mastrec);
- close(fmast);
- end;
-
- procedure open_logfile(lock : boolean);
- {open log file, optionally lock it if lock is true}
-
- begin
- while log_is_locked do {dont let anyone else on the network at it}
- delay(random(2000)); {retry randomly at an average of 1 second intervals}
-
- if lock then {going to be writing to it}
- lock_log;
- assign(flog,flognam);
- reset(flog);
- end;
-
- procedure close_logfile;
- {close the log file, removing any locks}
- begin
- close(flog);
- unlock_log;
- end;
-
- {initialisation}
- var
- fmast : file of masty;
- mastrec : masty;
-
- begin
- {set the master file holding the locks, so that none are on}
- assign(fmast,mastnam);
- rewrite(fmast);
- mastrec.log := False;
- {other locks here}
- write(fmast,mastrec);
- close(fmast);
- end.
-
- ------------------------------------------------------------------------------
-
-
- Methods for Dealing with Shared Files
- in TURBO Pascal Version 5.0
- by
- John W. Wulff
- Wulff Enterprises, Inc.
- 260 Terranova Drive
- Warrenton, VA 22186-9227
- (703) 349-8805
-
- Revised May 15, 1989
-
- This paper was first written January 19, 1987 as a means of
- demonstrating how to modify Turbo Pascal 3.x to handle the
- opening of READ-ONLY files and to make it able to deal with files
- in a Shared, network environment. It provided a means of finding
- an undocumented byte known as the "Open Mode Byte". Since then,
- Turbo Pascal 5.0 has been released and this byte has been
- globally declared as the FILEMODE variable. Even so, Turbo
- Pascal 5.0 ignores the variable when opening TEXT files. While
- there is a small explanation in the Turbo Pascal Reference Guide
- as to its use, the information in this paper is still valid today
- and has been updated to reflect its relevance to Turbo Pascal
- 5.0. For those wishing to continue to work in Turbo Pascal 3.0,
- I have included the locations for this byte in appendix A.
-
- There have been many innovations in the development of PCBoard
- software for BBS's. One of which is the network environment that
- the authors have included in the code. While this is wonderful
- for the multi-node system, it does pose certain problems and
- restrictions on application programs and utilities that are being
- written for it, especially those written in Borland's Turbo
- Pascal.
-
- One problem that plagues most authors writing application
- programs that eventually become used in network environments is
- coping with the Share utility that DOS uses to protect files.
- Any file opened for reading under Turbo Pascal will cause a
- Sharing violation if running under a DOS 3.x and 4.x networking
- mode. This is because Turbo Pascal opens all files in what is
- known as "Inherited by Child Processes, Compatibility Mode,
- Read/Write access".
-
- I have written a utility for PCBoard systems, PCBFile, and since
- it is extremely file intensive, I've had to do some research on
- the technical aspects of DOS in the network mode. Because of
- this research, I've been able to get Turbo Pascal to cooperate
- and have written this paper to help other authors who are
- struggling with the same problems.
-
- As documented in the Turbo Pascal instructions, the FILEMODE
- variable has a value of 2 when opening files for RESET or REWRITE
- which allows both reading and writing. The instructions suggest
- that you should assign a value of 0 to the variable to RESET or
- REWRITE read-only files. While this works for READ-ONLY files,
- it is not the only value to consider when running an application
- in a network environment, especially one with PCBoard software
- upon which I will focus my attention for the remainder of the
- document.
-
- One thing to consider, if using other languages, especially
- assembly language, is that this FILEMODE variable, corresponds to
- the AL register. All references to that byte and its decimal
- number can be applied to assembly in this way:
-
- AH contains 3DH - the function call
- DS:DX points to an ASCIIZ path name
- AL will be loaded with the 8 bit number that the
- FILEMODE variable contains.
-
- When the function returns, AX will contain error codes or a 16
- bit file handle if successful. (See DOS manual for details.) I
- don't profess to be anywhere close to fluent in assembly so I
- will leave this information with those who are best suited to
- take advantage of it.
-
- This variable is GLOBALLY pre-declared in Turbo Pascal, so all
- you have to do is refer to it as FILEMODE. Then a simple check
- is necessary to see if the variable contains a 2 and if so, load
- it with a 0:
-
- begin
- if FILEMODE = 2 then
- FILEMODE := 0;
- end;
-
- The completed routine would look like this:
-
- Procedure OpenMode(Var OpenFile : text;
- InFileName : string
- Var GoAhead : boolean);
-
- {Remember, FILEMODE is a GLOBALLY declared variable of type
- byte. No other declaration is necessary on your part}
-
- begin
- if FILEMODE = 2 then
- FILEMODE := 0; (* allows reading of READ-ONLY files *)
- assign(OpenFile,InFileName);
- {$I-} reset(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if GoAhead then
- writeln(InFileName,' opened!')
- else
- writeln(InFileName,' failed to open!');
- end; { of Procedure OpenMode }
-
- Now we need to determine just what is going on with PCBoard and
- how it opens files using DOS's SHARE. The DIR files, or the
- files that contain the filenames of the available files for the
- user to download, are opened in READ SHARED mode which in
- QuickBASIC would be:
-
- OPEN "<filename>" FOR INPUT ACCESS READ SHARED AS #1.
-
- Upload DIR files are opened for APPEND in a LOCKED WRITE mode.
- This keeps other nodes from writing at that particular moment but
- allows other nodes to read this file.
-
- In order to accomplish these same modes in Turbo Pascal we must
- look into the DOS Technical Reference Manual (groan!). The
- following is reprinted from that manual with some additions by
- me.
-
- The OPEN mode consists of 4 bit-oriented fields:
- * INHERITANCE FLAG
- * SHARING MODE FIELD
- * RESERVED FIELD
- * ACCESS FIELD
- The INHERITANCE FLAG determines if the file will ever be
- inherited by another process, which in the case of a network is
- usually the desired effect. The SHARING FIELD defines what
- operations may be performed on the file by other nodes. The
- ACCESS FIELD defines what operations THIS node may perform on the
- file.
-
- The bit fields are mapped as follows:
- <I> < S > <R> < A >
- Open Mode bits 7 6 5 4 3 2 1 0
- I INHERITANCE FLAG
- If I = 0; File is inherited by child processes
- If I = 1; File is private to the current process
-
- S SHARING MODE
- The file is opened like this:
- if S = 000; Compatibility mode - The default open mode - it
- denies ALL OTHER processes access to the file.
- Since this is the mode that Turbo Pascal uses to
- open a file, what do you think will happen on the
- BBS side if you have a file open on your end and
- the BBS tries to open it?
- if S = 001; Deny Read/Write mode (Exclusive). This would
- actually be the same as setting the I flag to 1.
- if S = 010; Deny Write mode - you should open a file in this
- mode if you wish to protect it. It will allow
- other processes to read it but not write.
- if S = 011; Deny Read mode
- if S = 100; Deny None mode - Who cares what happens!
-
- It is important to specify what operations you want to perform
- (access mode). The default access mode is Read/Write and causes
- the open request to fail if another process has the file opened
- with any sharing mode other than Deny None. File sharing
- requires cooperation of both sharing processes. This is
- communicated through the sharing and access modes.
-
- R RESERVED (set third bit field to 0)
-
- A ACCESS - The file access is assigned as follows:
-
- If A = 000; Read Access
- if A = 001; Write Access
- if A = 010; Read/Write access
-
- If all this seems a bit involved, I'm sorry. I don't know of any
- way to give you the background for all this hocus-pocus except
- with the above info. I also recommend picking up a Tech Ref
- manual for more detailed study of the 3DH function call.
-
- OK! With all these numbers in hand, let's see how to get Turbo
- Pascal to duplicate these modes. Earlier I said that other gurus
- had stated that Turbo Pascal opens files in COMPATIBILITY MODE
- with READ/WRITE ACCESS and INHERITANCE BY CHILD PROCESSES and the
- magic value for the FILEMODE variable is 2. Let's look at how
- that was done:
-
- Compatibility mode: 000 {S}
- Read/Write ACCESS : 010 {A}
- Inherited by child: 0 {I}
- Reserved as ALWAYS: 0 {R}
-
- Remember the bit fields are:
- <I> < S > <R> < A >
- Open Mode bits 7 6 5 4 3 2 1 0 Let's plug in
- 0 0 0 0 0 0 1 0 the numbers.
- Using binary arithmetic:
- <I> < S > <R> < A >
- 128 64 32 16 8 4 2 1
- 0 0 0 0 0 0 1 0 = 00000010 = 2
-
- By using a FILEMODE value of 0 we change the ACCESS field to 000,
- READ ACCESS, which allows us to read a READ-ONLY file.
-
- PCBoard is opening its DIR files as READ ACCESS SHARED and
- actually opening the file with a SHARING MODE of Deny/Write which
- would be a SHARE <S> field of 010. The value for the FILEMODE
- variable then becomes:
- <I> < S > <R> < A >
- 128 64 32 16 8 4 2 1
- 0 0 1 0 0 0 0 0 = 00100000 = 32
-
- This is how I open ALL my files for reading or for general
- ASSIGNING for RESET in Turbo Pascal for my program PCBFile. I
- have some procedures written for TEXT files, and files of type
- BYTE. I have reproduced the code below:
- (* This procedure, KeepOn, is used to determine if the file has
- been locked out. I try a file for 10 times as determined by
- OpenAtt variable before I give up *)
-
- Procedure KeepOn(OpenAtt : byte; var GA : boolean);
- begin
- if OpenAtt <= 10 then
- GA := TRUE (* GoAhead Flag - if within 10 go for it *)
- else GA := FALSE; (* forget it! *)
- end; {of Procedure KeepOn}
-
- Procedure SetResetMode(Var OpenFile : text; (* OPEN MODE FOR
- InFileName : string; TEXT FILES *)
- Var GoAhead : boolean);
- var
- OpenAttempts : byte;
-
- begin
- OpenAttempts := 1;
- FILEMODE := 32; (* this is Deny Write
- Mode/Read Access *)
- assign(OpenFile,InFileName);
- repeat
- {$I-} reset(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if not GoAhead then
- OpenAttempts := OpenAttempts + 1;
- until (GoAhead) OR (OpenAttempts > 10); (* keep trying *)
- KeepOn(OpenAttempts,GoAhead);
- end; {of Procedure SetResetMode}
-
- Procedure SetResetModeFile(Var OpenFile : file of byte
- InFileName : string;
- var GoAhead : boolean);
- var
- OpenAttempts : byte;
- begin
- OpenAttempts := 1;
- if FILEMODE := 32; (* this is Deny Write
- Mode/Read Access *)
- assign(OpenFile,InFileName);
- repeat
- {$I-} reset(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if not GoAhead then OpenAttempts := OpenAttempts + 1;
- until GoAhead OR (OpenAttempts > 10);
- KeepOn(OpenAttempts,GoAhead);
- end; {of Procedure SetResetModeFile}
-
- Now here comes a little zinger to change things up. I want to
- create a file that I don't want the other nodes to damage. I
- elect to open the file for READ/WRITE ACCESS for myself and give
- the other nodes READ capability and deny them the ability to
- write to my file. This would be Deny/Write Mode under the <S> or
- SHARING FIELD and would be coded 010. For READ/WRITE ACCESS the
- <A> or ACCESS FIELD is coded 010 also. This is the same mode
- that PCBoard uses for writing to the Upload directory. Using our
- binary formulae, the FILEMODE value then becomes:
- <I> < S > <R> < A >
- 128 64 32 16 8 4 2 1
- 0 0 1 0 0 0 1 0 = 00100010 = 34
-
- With the magic number of 34 the SetFileLock procedure was born.
-
- Procedure SetFileLock(Var OpenFile : text;
- InFileName : string;
- var GoAhead : boolean);
- var
- OpenAttempts : byte;
-
- begin
- OpenAttempts := 1;
- FILEMODE := 34; (* Deny Write Mode/Read-Write Access *)
- assign(OpenFile,InFileName);
- repeat
- {$I-} rewrite(Openfile) {$I+};
- GoAhead := (ioresult = 0);
- if not GoAhead then
- OpenAttempts := OpenAttempts + 1;
- until GoAhead or (OpenAttempts > 10);
- KeepOn(OpenAttempts,GoAhead);
- end; {of Procedure SetFileLock}
-
- Finally, a little walk around the park to insure that the
- FILEMODE variable is returned to Borland's normal mode.
-
- Procedure ReleaseOpenMode;
-
- begin
- FILEMODE := 2;
- end;
-
- So it's really simple to change the Turbo Pascal Open mode to
- exactly what you want, you just have to know what results you
- desire from the program. Just remember these definitions of the
- fields that make up the magic number for DOS Function call 3DH.
-
- * INHERITANCE FLAG I = 0; Inherited (usually the case)
- I = 1; Private
-
- * SHARING MODE FIELD (Other node or process)
- S = 000; Compatibility mode
- S = 001; Deny Read/Write mode
- (Exclusive)
- S = 010; Deny Write mode
- S = 011; Deny Read mode
- S = 100; Deny None mode
-
- * RESERVED FIELD R = 0; Always
-
- * ACCESS FIELD (Your node or process)
- A = 000; Read Access
- A = 001; Write Access
- A = 010; Read/Write Access
- The bit fields:
- <I> < S > <R> < A >
- Open Mode bits 7 6 5 4 3 2 1 0
-
- Even though a DOS Technical Reference Manual gives a more
- thorough discussion of Function Call 3DH, I will attempt to
- create a matrix with the number for the FILEMODE variable based
- on the SHARE and ACCESS fields.
-
- ACCESS |SHARE-> Compat Deny/RW Deny/W Deny/R Deny/N
- | 000 001 010 011 100
- v -------------------------------------------
- Read 000 | 0 | 16 | 32 | 48 | 64 |
- |--------|-------|-------|-------|--------|
- Write 001 | 1 | 17 | 33 | 49 | 65 |
- |--------|-------|-------|-------|--------|
- Read/ 010 | 2 | 18 | 34 | 50 | 66 |
- Write -------------------------------------------
-
- I know that this is probably more than a human can bear to
- assimilate at any one time but I hope that you will be able to
- see the logic behind my system and be able to use Turbo Pascal to
- its full potential.
-
- PCBoard (c) Clark Development Company, Inc., Murray, UT
- Turbo Pascal (c) Borland International, Scotts Valley, CA
- PCBFile (c) John W. Wulff
- Compuserve (c) Compuserve, Inc., Columbus, OH
-
- Appendix
-
- For Turbo Pascal 3.x Die-Hards:
-
- Bela Lubkin published a text article, ACMODE.DOC, which is on
- Compuserve in the Borland Sig that gives the locations of a
- little gem known as the "Open Mode Byte". This byte is at an
- absolute address for the various editions of Turbo Pascal and
- communicates to DOS, via Function call 3DH, how the file is to be
- accessed and what access to give other processes. It also
- becomes very handy for us in trying to use Turbo Pascal in a
- network environment. These locations are:
- Open mode byte for Reset & Rewrite for Turbo 3.00x (PC-DOS)
- TURBO.COM CSEG:$248D
- TURBO-87.COM CSEG:$1F3C
- TURBOBCD.COM CSEG:$2393
- Open mode byte for Reset & Rewrite for Turbo 3.00x (MS-DOS)
- TURBO.COM CSEG:$2182
- TURBO-87.COM CSEG:$1C31
- TURBOBCD.COM CSEG:$2088
- Open mode byte for Reset & Rewrite for Turbo 3.01x (PC-DOS)
- TURBO.COM CSEG:$24FC
- TURBO-87.COM CSEG:$1FAB
- TURBOBCD.COM CSEG:$2402
- Open mode byte for Reset & Rewrite for Turbo 3.01x (MS-DOS)
- TURBO.COM CSEG:$21D4
- TURBO-87.COM CSEG:$1C83
- TURBOBCD.COM CSEG:$20DA
- Open mode byte for Reset & Rewrite for Turbo 3.02x (PC-DOS)
- TURBO.COM CSEG:$24C6
- TURBO-87.COM CSEG:$1F75
- TURBOBCD.COM CSEG:$23CE
-
- Another valuable document is Robert K. Blaine's RES_MODE.INC,
- also available on CSERV. It details the procedure for finding
- out the location of this byte, using DEBUG.
-
- ------------------------------------------------------------------------------
-
-
- From: CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel)
- Subject: Re: Share
-
- In article <sLD243w164w@dat1hb.north.de>, lion@dat1hb.north.de
- (Daniel Tietze) wrote:
-
- > I have a question about using SHARE (as supplied with MS-DOS) with
- >Turbo Pascal programs. How can I check SHARE violations in my
- >program? What exactly does SHARE do when it encounters a sharing
- >violation? I believe the IOResult is set to an appropriate value,
- >but I don't know exactly which result is to be expected.
-
- Sharing and locking are separate but related matters.
-
- Sharing concerns opening the file with the necessary access rights.
- In Turbo Pascal, this involves setting the FileMode variable before
- opening the file. I believe the details have already been posted to
- you. If not, refer to a DOS technical reference on INT $21 function
- $3D (you should have such a reference even if you get the essential
- information from the net) and set FileMode := the required value of
- the AL register in this call.
-
- In addition to the normally expected values, Reset and Rewrite will
- cause an IOResult of 1 if sharing is not available (i.e., SHARE has
- not been loaded); 5 if you can't open the file with the mode you
- requested (e.g., another process has opened it with Deny Write and
- you are trying to open it with ReadWrite access); or $C if you have
- messed up the FileMode value. (What happened to Append? Append is
- for text files. Your life with networked Turbo Pascal will be very
- much easier if you don't use text files.)
-
- MS-DOS locking concerns denying other processes the right to write
- _or_ read a specified byte sequence in the file. A lock is placed by
- calling INT $21 function $5C with AH := $5C; $AL := 0;$BX := the
- file handle; CX,DX := (high,low) word of the byte sequence offset
- into the file; SD,DI := (high,low) word of the length of the
- sequence. (I.e, the offset and length are double length words, so
- they are passed in two registers each.) To remove a lock, you make
- the same call you made to place it, with (important!) exactly the
- same parameters except that $AL := 1. (So you have to make one
- unlock call for every lock you place.) If the lock fails, the carry
- flag will be set, and AX will be 1 for "invalid function code"
- (probably SHARE not loaded); or $21 if all or part of that region is
- already locked.
-
- Note that it is a _serious_ mistake to end your program without
- removing all locks, so you want to create an exit proc that will
- remove all locks. You should also document that if your users crash
- one node, they should immediately reboot that node (if required) and
- log back onto their network, in the hopes that the network will
- recognize any remaining locks as obsolete and clear them. Otherwise,
- other nodes may be continue to be denied access to the locked
- regions.
-
- > How can I get the program to retry after a sharing violation. Do I
- >have to code it explicitly (i.e. repeat .... until (share_ok OR
- >computer_switched_off; :-) ) or does SHARE take care of that?
-
- You have to do it yourself.
-
- > By the way, when exactly does a sharing violation occur? In
- >Read/Read, Read/Write or Write/Write situations?
-
- As described above, plus whenever a Read or Write is attempted which
- is not allowed by the acquired access and/or locks. E.g., if you try
- to access a record which is locked by another process, you will get
- a violation on every read or write.
-
- My personal recommendations for reference material are _Advanced MS-
- DOS_, Ray Duncan, MicroSoft Press, and _MS-DOS Encyclopedia_, Ray
- Duncan ed., MicroSoft Press. Of course, my employer makes no such
- recommendations. ;)
-
- Cheers-- --Karl
-
- +====================================================================+
- | Karl Brendel Centers for Disease Control |
- | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office |
- | Bitnet: CDCKAB@EMUVM1 Atlanta GA 30333 USA |
- | Home of Epi Info 5.0 |
- +====================================================================+
-
-
-
- --
- Dean Davidson ddavidso@metz.une.oz.au
- Dept Psychology Phone 61 67 73 2585
- University of New England Fax 61 67 72 9816
- Armidale NSW 2351 Australia VK2 ZID
-