[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference 7.286::atarist

Title:Atari ST, TT, & Falcon
Notice:Please read note 1.0 and its replies before posting!
Moderator:FUNYET::ANDERSON
Created:Mon Apr 04 1988
Last Modified:Tue May 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:1433
Total number of notes:10312

814.0. "Pexec(),scrap manager and disk organization" by CSOGAT::BISSON () Fri Mar 30 1990 08:14

    Hi,
    
    	I am new,here at DEC and I discovered this fantastic conference a
    few time ago.
    
    	I work in Evry (France).
    
    	I have an Atari 520 STf,one external drive (720K) and a B&W monitor.
    
    	At the beginning (Two years ago) I was interrested only by
    games.But now I spend most of the time writing programs in C using GEM
    AES and GEM VDI functions (Very serious isn't it?).
    
    	Now you know me a little better I'd like to ask you three
    questions.
    
    		1)Pexec()
    		  -------
    
    		Does anybody knows what Pexec() can really do?.This
    function accepts a parameter specifying what action Pexec will perform
    (i.e. run a program,load a program,load & run a program...).
    		
    		 The load & run function works fine but I can't load a
    program and then run this program.
    
    		 It would be very interesting to have many programs loaded
    in memory and to be able to call any of them when you wish.
    
    
    		2)Scrap manager
    		  -------------
    
    		What I understand is that the scrap manager allows
    applications to communicate.Should this mean that a main programm could
    "speak" whith Desk Accessoiries? How does it work?
    
    
                3)Disk organization
    		  -----------------
    
    		When you write a file on a disk,the blocks are not
    contiguous.For example the file can be written on Track 20 sector 3,4,5
    then track 46 sector 8,9,10 and so on...
    
    		My question is:How does TOS know that it has to go from
    track 20 sector 5 to track 46 sector 8 when it reads the file? 
    
    
    	Thank You for your help and excuse me for my bad english.
    
    	
    		Pierre-Yves
                                                     
T.RTitleUserPersonal
Name
DateLines
814.1PRNSYS::LOMICKAJJeffrey A. LomickaFri Mar 30 1990 12:5932
The answers to 1) and 2) are spelled out in supplements to the
"developer documentation".  If nobody else answers first, I will try to
remember to look up the answer.

Regarding 2), the best way to do this is to send messages between the
applications with the AES massage facility, so you can pick up the
messages with event_multi().  The primitive for sending messages is
"appl_write".  The only hard part is figuring out the application ID of
the target process.  Perhaps there is some way the accessories could
leave their application ID's in an environment variable that can be
picked up by the main line application.  I don't have any cookbook
solution handy.

Regarding 3.  Now THIS I know something about.  Atari disks use the same
file system as MS-DOS.  The disk is divided into a number of equal sized
blocks called "clusters".  This is usually two sectors of 512 bytes.

Block 0 of the disk contains information about what the cluster size is
and where the root directory and the "file allocation table" (FAT) is. 
(See "Getbpb()") After looking up a filename in the directory, you know
the "cluster number" of the first block of the file.  If you index into
the "file allocation table" with this block number, it will give you
the block number of the next block.  Likewise for subsequent blocks. 
In this way, the entire file can be pieced together.  Unused blocks
have a 0 in the file allocation table, so when you are extending a
file, you can just look in the FAT to find a free block, and link it
into the chain.

A good reference for this is Microsoft's book on Advanced MSDOS.

(Your typewritten English is indistinguishable from that of a native.  If
you have a French accent, I can not tell from here.)
814.2How to use Pexec()CSOGAT::BISSONMon May 21 1990 13:32149
      I answer my own question about Pexec().Here is what I found on USENET.
    
    This is quite long, but I think it's worth taking some time reading
    it.
    
    		Pierre-Yves.
    
    ----------------------------------------------------------------
From: leo@philmds.UUCP (Leo de Wit)
Newsgroups: comp.sys.atari.st
Subject: Re: preloading programs
Keywords: Preload, Ramdisk, Pexec
Message-ID: <482@philmds.UUCP>
Date: 16 May 88 11:28:03 GMT
References: <8804141742.AA01455@decwrl.dec.com> <693@ast.cs.vu.nl>
<474@philmds.UUCP> <219@obie.UUCP>
Reply-To: leo@philmds.UUCP (L.J.M. de Wit)
Organization: Philips I&E DTS Eindhoven
Lines: 139
Posted: Mon May 16 12:28:03 1988
 
 I have had some time to figure things out (disassembled Pexec and several 
others) and managed to get a reusable load image in core that can be run over 
and over.
A word of caution: the program should not depend on initialized data, unless
this data will not change (is 'readonly'). An example:
 
#define INTERACTIVE 1
 
int option = 0;
 
main(argc,argv)
int argc;
char *argv[];
{
   if ((argc > 1) && (!strcmp(argv[1],"-i"))) {
      option |= INTERACTIVE;
   }
   /* REST OF CODE ... */
}
 
After one run with -i flag option 'has the INTERACTIVE bit set' and will have
it too on the next run. So option must be explicitly initialized:
 
main(argc,argv)
int argc;
char *argv[];
{
   option = 0;
   /* REST OF CODE ... */
 
Before I give the prescription I will give a more detailed explanation of the 
Pexec call, Pexec(mode,path,tail,env); mainly because most books about GEMDOS 
are much too terse about the subject (please correct me if I'm wrong, I had
to find out things the hard way, like so many of us).
Which functions will be performed within Pexec depends on the mode word; this
can be either 0, 3, 4 or 5.
The following actions are performed:
1) mode 0 and 3: searchfile. If the program file 'path' does not exist, Pexec
returns error -32 (file not found).
2) mode 0, 3 and 5: 'basepage initializations':
   a) create environment string. If 'env' is null a copy of the parent's
environment string is made, else a copy of 'env' is made. 'env' is terminated
by two '\0' 's. The new environment space is allocated and bp[11] is set to
point to it (consider bp a (char **), it is the start of the basepage).
   b) allocate program space. The maximum available space is claimed (that
returned by Malloc(-1)).
   c) If mode == 0, the environment and program spaces are owned by the child
(in the memory parameter blocks the owner is the new basepage); if mode == 3 or
mode == 5, the parent owns the memory blocks. This fact ensures that the
program area is not automatically reclaimed when the child exits (but space
Malloced by the child is).
   d) bp[0] is set to the basepage, bp[1] is set to basepage + length of 
program block (i.e. the first location above the program).
   e) Initiate (redirected) file descriptors 0 - 5 (bytes 48 through 53 on the
basepage).
   f) Initiate current working directories: for each drive one (bytes 64 
through 79 on the basepage). Note that e) and f) involves more than simply
assigning a value.
   g) Initiate current drive (byte 55 on the basepage). This is copied from the
parent.
   h) Copy tail to basepage + 128 (max. 0x7d bytes). bp[8] is set to point to
this location.
3) mode 0 and 3: load program. This is a function on its own, and I will not
explain all details. Generally speaking, the function performs some checks on
the program format, it loads program and data, does relocation, null fills
all above data and sets bp[2]: text start, bp[3]: text length, bp[4]: data 
start, bp[5]: data length, bp[6]: bss start, bp[7]: bss length.
4) mode 0 and 4: final initializations and run.
   a) bp[9] is set to the current basepage (parent).
   b) A save area for registers is initialized at the last 50 locations of the
program; bp[30] and bp[31] are set to point to this area; bp[26] through bp[30]
are for saving other registers.
   c) switch process: the new basepage is entered into the long at 0x602c and
registers are loaded using the save area and bp[26]..bp[30] mentioned in b).
 
So far for the 'preliminary meditations'; here's the recipe:
 
A) First preload using mode 3:
bp = (char **)Pexec(3,"program","",0);
B) Return unused memory to the system:
Calculate the memory needed, e.g.
memneed = 0x100 + (int)bp[3] + (int)bp[5] + (int)bp[7] + 0x800 + 0x800;
          basepage     text         data         bss     heap    stack.
(the values needed for heap and stack depend on your program/your needs).
Now:
Mshrink(bp,mneed); /* return unused memory to the system */
Mfree(bp[11]);     /* free the new environment space, we won't use it */
bp[1] = (char *)bp + mneed; /* first free location is lower now */
C) Prepare to run:
bp2 = Pexec(5,0,"arguments",0);
Mshrink(bp2,0x100); /* only keep a basepage */
for (i = 1; i < 8; i++) bp2[i] = bp[i]; /* set pointers and lengths correctly*/
D) Now run it:
code = Pexec(4,0,bp2,0);
Mfree(bp2[11]); /* frees the environment space */
Mfree(bp2); /* frees the new basepage */
 
For each run, do C) and then D). Hey, it works!
Some remarks:
a) the environment is not used (0, so the parent's is used). You can use an
environment string, in C): Pexec(5,0,"arguments","environment\0");
note that the environment string must end on a double '\0', as in the example.
b) Although the arguments string is simply copied, it is a convention that the
first byte of the args string contains its byte count. This is probably due
to the fact that the GEMDOS readline function (0xa) also returns the count in
the string (and probably GEM uses this type of string for Pexec when starting
TTP applications). So:
 
char newtail[128];
 
strncpy(newtail,tail,0x7d);
newtail[0] = strlen(newtail + 1);
Pexec(5,0,newtail,0);
 
c) The bp[..] and bp2[..] mentioned are longs (char *, to be precise).
d) Preload could be used to provide more than 128 characters arguments string.
The arguments can be placed on the child's stack; the child can find them using
bp[8] (this will break existing code that uses simply (char *)bp + 128). I
suggest that we use bp[8] as a char *[], as is argv; and use a startup module
that uses this scheme if bp[8] != (char *)bp + 128 and the old one if it
equals.
e) A similar scheme can be used for the 'env', bp[11].
f) I'm sure d) and e) start up new discussions!
 
    Hope this clarifies some things about Pexec and makes it better usable.
    I'm waiting for your responses, questions, remarks, experiences...
 
    Leo (Swimming in the C..)