[comp.sys.amiga.tech] How do you send a DosPacket to a handler directly?

gregg@cbnewsc.att.com (gregg.g.wonderly) (11/08/90)

Let's try this again, surely someone out there has experience with this
sort of thing!

I am trying to put together some code that will send ACTION_READ
packets to a handler after opening a file with Open().  I need to
double buffer file reads with other I/O using separate tasks.

Basically I need to do three things at once.  One is read a file.  Two
is send the segments of the file to another task to process and the
third is the main routine which needs to be able to tell the other
tasks to stop.  Does anybody have some pointers on why the code below
doesn't work?

Background...

The assignment of packet->dp_Arg1 = handle->fh_Args came from looking
at the MSH handler.  I do not know what is really required here.  If I
put something like handle, or BTOC(handle) in packet->dp_Arg1 it
GURUs.  With the handle->fh_Args value, the PutMsg() succeeds, but
there is no response via Wait().  I do not have the AmigaDos manual
which supposedly documents this sort of thing (does it?).  The Autodocs
and RKM do not contain any real DOS.LIBRARY information.  I am at a
loss as to exactly what is required.  The headers (dosextens.h) give
hints, but obviously I am missing something.

Thanks for any information you can provide.

------------------------------- Test Program -------------------------------
#include <stdio.h>
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <exec/memory.h>

typedef struct FileHandle HANDLE;
typedef struct DosPacket PACKET;

#define BTOC(x) (void *)((long)(x) << 2)
#define CTOB(x) (void *)((long)(x) >> 2)

main( argc, argv )
    int argc;
    char **argv;
{
    long n, fh;
    int sig;
    HANDLE *handle;
    PACKET *packet;
    struct MsgPort *msgpt;
    struct Message *msg, *tmsg;
    char buf[1024];

    if( (fh = Open( argv[1], MODE_OLDFILE )) == NULL )
    {
        fprintf( stderr, "Can not open %s\n", argv[1]);
        exit( 1 );
    }

    /* Read something and write it out. */

    n = Read( fh, buf, 1024 );
    Write( Output(), buf, n );

    /* Get real pointer to DosFileHandle */

    handle = BTOC(fh);

    /* Get the msgport to send to. */

    msgpt = (struct MsgPort *) handle->fh_Type;

    /* Allocate a dos packet. */

    if(( packet = (PACKET *)AllocMem( sizeof( PACKET ),
                                        MEMF_PUBLIC | MEMF_CLEAR ) ) == NULL )
    {
        fprintf( stderr, "alloc failed\n");
        Close( fh );
        exit( 1 );
    }

    /* Put together the packet. */

    packet->dp_Action = ACTION_READ;

    /* Is this what is really required? */

    packet->dp_Arg1   = (LONG) handle->fh_Args;
    packet->dp_Arg2   = (LONG) buf;
    packet->dp_Arg3   = (LONG) sizeof(buf);

    /* Get a port */

    if( (packet->dp_Port = (struct MsgPort *) CreatePort( 0L, 0 )) == NULL)
    {
        fprintf( stderr, "can get port\n");
        Close( fh );
        FreeMem( packet, sizeof( PACKET ) );
        exit( 1 );
    }

    /* Allocate a message to send. */

    if ((packet->dp_Link = (struct Message *)
        AllocMem( sizeof( struct Message ),
                                        MEMF_PUBLIC | MEMF_CLEAR ) ) == NULL )
    {
         fprintf( stderr, "alloc failed\n");
        Close( fh );
        FreeMem( packet, sizeof( PACKET ) );
        exit( 1 );
    }

    /* Fill in the message */

    tmsg = packet->dp_Link;
    tmsg->mn_Node.ln_Name = (char *) packet;  /* MSH looks here */
    tmsg->mn_Node.ln_Succ = NULL;
    tmsg->mn_Node.ln_Pred = NULL;
    tmsg->mn_ReplyPort    = packet->dp_Port;  /* Required? */
    tmsg->mn_Length       = sizeof( *packet ); /* Correct Length? */

    /* Send the message */

    if( (long)msgpt < 0)
        PutMsg( -(long)msgpt, tmsg );
    else
        PutMsg( msgpt, tmsg );

    /* Wait for the return */

    sig = Wait( (1 << packet->dp_Port->mp_SigBit) | SIGBREAKF_CTRL_C );

    if( sig & (1<<packet->dp_Port->mp_SigBit) )
    {
        msg = (struct Message *)GetMsg( packet->dp_Port );
        printf( "%d bytes read\n", packet->dp_Res1 );
        Write( Output(), buf, packet->dp_Res1 );
    }
    else
    {
        printf( "\n***BREAK***\n");
    }

    /* Clean up */

    DeletePort( packet->dp_Port );
    FreeMem( tmsg, sizeof( struct Message ) );
    FreeMem( packet, sizeof( PACKET ) );

    Close( fh );
    exit(0);
}
-- 
-----
gregg.g.wonderly@att.com   (AT&T bell laboratories)
-- 
-----
gregg.g.wonderly@att.com   (AT&T bell laboratories)

deven@rpi.edu (Deven T. Corzine) (11/09/90)

On 7 Nov 90 18:52:24 GMT, gregg@cbnewsc.att.com (gregg.g.wonderly) said:

gregg> The assignment of packet->dp_Arg1 = handle->fh_Args came from
gregg> looking at the MSH handler.  I do not know what is really
gregg> required here.

According to the AmigaDOS Technical Reference Manual, (yes, it exists,
but is very hard to read and understand) dp_Arg1 should be the BPTR to
the file handle.  That is, that field should contain your return value
from Open().  Apart from that, I don't know what may be wrong with
your code without trying it...  But the documentation says the file
handle.  (and remember, MSH is a handler; it's on the other end of the
transaction.)

Deven
-- 
Deven T. Corzine        Internet:  deven@rpi.edu, shadow@pawl.rpi.edu
Snail:  2214 12th St. Apt. 2, Troy, NY 12180   Phone:  (518) 271-0750
Bitnet:  deven@rpitsmts, userfxb6@rpitsmts     UUCP:  uunet!rpi!deven
Simple things should be simple and complex things should be possible.

rhialto@cs.kun.nl (Olaf Seibert) (11/10/90)

In article <DEVEN.90Nov8180332@netserv2.rpi.edu> deven@rpi.edu (Deven T. Corzine) writes:
>
>On 7 Nov 90 18:52:24 GMT, gregg@cbnewsc.att.com (gregg.g.wonderly) said:
>
>gregg> The assignment of packet->dp_Arg1 = handle->fh_Args came from
>gregg> looking at the MSH handler.  I do not know what is really
>gregg> required here.
>
>According to the AmigaDOS Technical Reference Manual, (yes, it exists,
>but is very hard to read and understand) dp_Arg1 should be the BPTR to
>the file handle.  That is, that field should contain your return value
>from Open().
>Deven

This is when one of the ACTION_FINDwhatever packets is sent. The
dp_Arg1 field (i.e., the first argument of the PACKET) points to the
filehandle that you are supposed to fill in.  Further, the manual
claims that whatever is put into the fh_Arg1 (or fh_Args, whatever)
field of the FILEHANDLE, is passed as the first argument of the
ACTION_READ, -WRITE, -SEEK and -END packets.

What MSH does is that it puts a pointer to its own private kind of
filehandle in this field, since it usually does not need the AmigaDos
FileHandle in those functions. The SFS and FFS might use the address
of the FileHandle itself; I don't know or care.
--
Olaf 'Rhialto' Seibert                               rhialto@cs.kun.nl
How can you be so stupid if you're identical to me? -Robert Silverberg

andy@cbmvax.commodore.com (Andy Finkel) (11/11/90)

In article <root.658802253@tirith.UUCP> root@tirith.UUCP (Root) writes:
>about those fh_Buffer and related fields - how are they used?".  My best
>answer is that beyond the fh_Task and fh_Arg1 fields, the filesystem is
>not supposed to change anything.  And the application program isn't
>supposed to change anything period.  So I presume they're dead space,
>left over from BCPL and TriPos.  (My money says ed and/or edit use
>them though). 

Close, but not quite; there's another entity around involved in
creating file handles...our friend, the dos.library.  Those fields
are used for the BCPL buffered IO calls.

Which, under 2.0, are now available for use by non-BCPL programs
as well.

Anyway, those fields are private to dos.library and the shell...and
under 2.0 finally can give any program that needs it buffered IO
easily.

		andy
-- 
andy finkel		{uunet|rutgers|amiga}!cbmvax!andy
Commodore-Amiga, Inc.

"It is much easier to suggest solutions when you know nothing about the
 problem."

Any expressed opinions are mine; but feel free to share.
I disclaim all responsibilities, all shapes, all sizes, all colors.

jesup@cbmvax.commodore.com (Randell Jesup) (11/11/90)

In article <root.658802253@tirith.UUCP> root@tirith.UUCP (Root) writes:
>Noteworthy detail: You allocate the memory for the file handle, and pass
>it to the filehandler, which will initialize its contents.  You must
>free this memory as well after you close the file.

	NOTE: if you must do this (instead of calling Open()), then as
the original Dos Tech Ref Manual states, you MUST initialize all fields
to 0, except fh_Pos and fh_End, which must be -1.  I advise against
allocating filehandles if there is a way to avoid it.  Copying the contents
of filehandles is right out.

	There was one totally unused field in a FileHandle that I have
laid retroactive claim to (since it never did anything, and as mentioned
above you had to initialize it to 0).  This is fh_Link, soon to be known
as fh_Flags.

>Now, if you'll all carefully consult dosextens.h, you'll next ask "what
>about those fh_Buffer and related fields - how are they used?".  My best
>answer is that beyond the fh_Task and fh_Arg1 fields, the filesystem is
>not supposed to change anything.  And the application program isn't
>supposed to change anything period.  So I presume they're dead space,
>left over from BCPL and TriPos.  (My money says ed and/or edit use
>them though). 

	All BCPL buffered IO uses them, as does the shell, etc.  Under 2.0,
all the buffered input/output routines use them.  Don't touch.  BTW, fh_Arg2
belongs to the filesystem also, though in reality it's almost useless since
it's never passed anywhere.

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
Common phrase heard at Amiga Devcon '89: "It's in there!"

jesup@cbmvax.commodore.com (Randell Jesup) (11/12/90)

In article <ggk.658908407@tirith.UUCP> ggk@tirith.UUCP (Gregory Kritsch) writes:
>This doesn't quite make sense, unless I make the assumption that an
>asynchronous io call is defined as not buffered, or that asynchronous io
>isn't possible.

	Buffering is done in dos.library in the buffered I/O calls.  Packets
are by definition not buffered.

>Is it not true that I can create and open a file handle myself using
>only DeviceProc() to find the filesystem?

	Yes, though see my earlier message about initialization! (all 0,
except fh_Pos and fh_End which are -1).

>>Which, under 2.0, are now available for use by non-BCPL programs
>>as well.
>
>Thank you, whoever is responsible for this!  I can't wait to get 2.0 on
>my A1000 so I can have fun with those.  I know several projects that
>will benefit greatly.
>
>Hmm, I don't have 2.0 autodocs (yet), how does one request buffering, and
>will it break under 1.3?

	Buffering is done by calling buffered I/O routines that are new
in 2.0.

>They should still be documented somewhere - what if I'm writing my own
>shell?  This is the thing that annoys me the most about AmigaDOS - the
>undocumented magic parts.

	We are documenting and making available a lot of things that were
private/undocumented before.  Certain things should remain private, however,
so that we can avoid incompatibility problems if we need to change some
side-effect in the future.  Where there is a need, we will provide a defined
interface for the needed function (such as the buffered I/O calls).   We
have immense problems already trying to support some of the trickier things
people who figured Dos out do (such as Bill Hawes).

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
Common phrase heard at Amiga Devcon '89: "It's in there!"

jesup@cbmvax.commodore.com (Randell Jesup) (11/16/90)

In article <ggk.658649929@tirith.UUCP> ggk@tirith.UUCP (Gregory Kritsch) writes:
>jesup@cbmvax.commodore.com (Randell Jesup) writes:
>>	Yes, though see my earlier message about initialization! (all 0,
>>except fh_Pos and fh_End which are -1).
>
>Please mail me a copy - I haven't seen this one yet.

	You should see it.  In any case, since before 1.0 the Dos Tech ref
manual has said that filehandles (if allocated by an application) MUST be
cleared to 0, except fh_Pos and fh_End which MUST be -1 (this is before
sending the open packet).

>Are there any changes in functionality to the actual dos.library calls
>(even some of the strange functions)?  Most importantly, does
>Execute("",Input(),NULL) still work to create a subshell in the same
>window, and return when the user types "endcli".

	In general, all old calls work as before.

>What about command lists passed to Execute?
>(eg: Execute("emacs T:xxxx\nendcli",Input(),NULL)).

	Works fine.  Of course, there's no need to be so tricky.

>One thing I'd really like to see someday is the original CBM developed
>AmigaDOS... Just to see what we missed out on.  It was supposedly object
>oriented, which, it occurs to me, was at a time long before "object
>oriented" was a common word.

	Read the Xinu books - that's what it was based on (more or less, or
at least some of the Exec stuff).  It really wasn't that wonderful (not
that Tripos was wonderful, at least in its original form).

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
Common phrase heard at Amiga Devcon '89: "It's in there!"

walker@unx.sas.com (Doug Walker) (11/21/90)

In article <1990Nov7.185224.4215@cbnewsc.att.com> gregg@cbnewsc.att.com (gregg.g.wonderly) writes:
>Let's try this again, surely someone out there has experience with this
>sort of thing!

Yes, but most of us don't care to admit it :-)

>The assignment of packet->dp_Arg1 = handle->fh_Args came from looking
>at the MSH handler.  I do not know what is really required here.  If I

This is correct.  If you look at the AmigaDOS packet-level documentation,
or the article John Toebes and I wrote for Amiga Transactor a couple of
years ago on filesystems, you will see that the FileHandle structure
field Arg1 is what's supposed to be passed for reads and so on.

>put something like handle, or BTOC(handle) in packet->dp_Arg1 it
>GURUs.  With the handle->fh_Args value, the PutMsg() succeeds, but
>there is no response via Wait().  

It works for me!  What you have should work just find.  Actually, 
using a WaitPort() on your reply port would work just as well.

You do have one problem, however - DOS packet messages are not like
other exec messages - DOS feels free to mess around with the linkage
fields in the structure.  You are setting dp_Port to your allocated
replyport;  instead of this, you need to allocate a local variable
of type struct MsgPort * to keep your reply port in and set dp_Port
from that.  Once the message is sent off to DOS, DOS will change
the value in that field.

Change your program as follows:

>#define CTOB(x) (void *)((long)(x) >> 2)
>
>main( argc, argv )
>    int argc;
>    char **argv;
>{
>    long n, fh;
>    int sig;
>    HANDLE *handle;
>    PACKET *packet;
>    struct MsgPort *msgpt, *replyport;;
>    struct Message *msg, *tmsg;
>    char buf[1024];
>
...

>    /* Get a port */
>
>    if( (replyport = packet->dp_Port = 
                    (struct MsgPort *) CreatePort( 0L, 0 )) == NULL)
>    {
>        fprintf( stderr, "can get port\n");
>        Close( fh );
>        FreeMem( packet, sizeof( PACKET ) );
>        exit( 1 );
>    }
>
>    /* Allocate a message to send. */
>
>    if ((packet->dp_Link = (struct Message *)
>        AllocMem( sizeof( struct Message ),
>                                        MEMF_PUBLIC | MEMF_CLEAR ) ) == NULL )
>    {
>         fprintf( stderr, "alloc failed\n");
>        Close( fh );
>        FreeMem( packet, sizeof( PACKET ) );
>        exit( 1 );
>    }
>
>    /* Fill in the message */
>
>    tmsg = packet->dp_Link;
>    tmsg->mn_Node.ln_Name = (char *) packet;  /* MSH looks here */
>    tmsg->mn_Node.ln_Succ = NULL;
>    tmsg->mn_Node.ln_Pred = NULL;
>    tmsg->mn_ReplyPort    = packet->dp_Port;  /* Required? */
>    tmsg->mn_Length       = sizeof( *packet ); /* Correct Length? */
>
>    /* Send the message */
>
>    if( (long)msgpt < 0)
>        PutMsg( -(long)msgpt, tmsg );
>    else
>        PutMsg( msgpt, tmsg );
>
>    /* Wait for the return */
     WaitPort(replyport);
>    msg = (struct Message *)GetMsg( packet->dp_Port );
>    printf( "%d bytes read\n", packet->dp_Res1 );
>    Write( Output(), buf, packet->dp_Res1 );
>
>    /* Clean up */
>
>    DeletePort( replyport);
>    FreeMem( tmsg, sizeof( struct Message ) );
>    FreeMem( packet, sizeof( PACKET ) );
>
>    Close( fh );
>    exit(0);
>}

For your edification, here's a routine that will send a DOS packet
anywhere you want:

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <proto/exec.h>
#include <proto/dos.h>


LONG sendpkt(pid,action,args,nargs,res)
struct MsgPort *pid;  /* process indentifier ... (handlers message port ) */
LONG action,	      /* packet type ... (what you want handler to do )   */
     args[],	      /* a pointer to a argument list		*/
     nargs,	      /* number of arguments in list		*/
     res[];	      /* pointer to 2 longs for result, or NULL */
   {
   struct MsgPort	 *replyport;
   struct StandardPacket *packet;

   LONG  count, lres, *pargs;

   replyport = (struct MsgPort *) CreatePort(NULL,0);
   if(!replyport) return(0L);

   packet = (struct StandardPacket *)
      AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
   if(!packet)
      {
      DeletePort(replyport);
      return(0L);
      }

   packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
   packet->sp_Pkt.dp_Link	  = &(packet->sp_Msg);
   packet->sp_Pkt.dp_Port	  = replyport;
   packet->sp_Pkt.dp_Type	  = action;

   /* copy the args into the packet */
   pargs = &(packet->sp_Pkt.dp_Arg1);       /* address of first argument */
   for(count=0;count < nargs;count++)
      pargs[count]=args[count];

   PutMsg(pid,(struct Message *)packet); /* send packet */

   WaitPort(replyport);
   GetMsg(replyport);

   if(res)
   {
      lres = res[0] = packet->sp_Pkt.dp_Res1;
      res[1] = packet->sp_Pkt.dp_Res2;
   }

   FreeMem((char *)packet,(long)sizeof(struct StandardPacket));
   DeletePort(replyport);

   return(lres);
}

  *****
=*|_o_o|\\=====Doug Walker, Software Distiller====== BBS: (919)460-7430 =
 *|. o.| ||                                          1200/2400/9600 Dual
  | o  |//     For all you do, this bug's for you!
  ====== 
usenet: ...mcnc!rti!sas!walker   plink: dwalker  bix: djwalker 

walker@unx.sas.com (Doug Walker) (11/29/90)

In article <DEVEN.90Nov8180332@netserv2.rpi.edu> deven@rpi.edu (Deven T. Corzine) writes:
>
>On 7 Nov 90 18:52:24 GMT, gregg@cbnewsc.att.com (gregg.g.wonderly) said:
>
>gregg> The assignment of packet->dp_Arg1 = handle->fh_Args came from
>gregg> looking at the MSH handler.  I do not know what is really
>gregg> required here.
>
>According to the AmigaDOS Technical Reference Manual, (yes, it exists,
>but is very hard to read and understand) dp_Arg1 should be the BPTR to
>the file handle.  That is, that field should contain your return value
>from Open().  

Wrong, wrong, wrong.  The tech manual doesn't say anything like this,
and it won't work anyway.  

I already replied to this question, but apparently it didn't make
the rounds or something.  I've enclosed a copy of the original
reply below.

--------------------------

In article <1990Nov7.185224.4215@cbnewsc.att.com> gregg@cbnewsc.att.com (gregg.g.wonderly) writes:
>Let's try this again, surely someone out there has experience with this
>sort of thing!

Yes, but most of us don't care to admit it :-)

>The assignment of packet->dp_Arg1 = handle->fh_Args came from looking
>at the MSH handler.  I do not know what is really required here.  If I

This is correct.  If you look at the AmigaDOS packet-level documentation,
or the article John Toebes and I wrote for Amiga Transactor a couple of
years ago on filesystems, you will see that the FileHandle structure
field Arg1 is what's supposed to be passed for reads and so on.

>put something like handle, or BTOC(handle) in packet->dp_Arg1 it
>GURUs.  With the handle->fh_Args value, the PutMsg() succeeds, but
>there is no response via Wait().  

It works for me!  What you have should work just find.  Actually, 
using a WaitPort() on your reply port would work just as well.

You do have one problem, however - DOS packet messages are not like
other exec messages - DOS feels free to mess around with the linkage
fields in the structure.  You are setting dp_Port to your allocated
replyport;  instead of this, you need to allocate a local variable
of type struct MsgPort * to keep your reply port in and set dp_Port
from that.  Once the message is sent off to DOS, DOS will change
the value in that field.

Change your program as follows:

>#define CTOB(x) (void *)((long)(x) >> 2)
>
>main( argc, argv )
>    int argc;
>    char **argv;
>{
>    long n, fh;
>    int sig;
>    HANDLE *handle;
>    PACKET *packet;
>    struct MsgPort *msgpt, *replyport;;
>    struct Message *msg, *tmsg;
>    char buf[1024];
>
...

>    /* Get a port */
>
>    if( (replyport = packet->dp_Port = 
                    (struct MsgPort *) CreatePort( 0L, 0 )) == NULL)
>    {
>        fprintf( stderr, "can get port\n");
>        Close( fh );
>        FreeMem( packet, sizeof( PACKET ) );
>        exit( 1 );
>    }
>
>    /* Allocate a message to send. */
>
>    if ((packet->dp_Link = (struct Message *)
>        AllocMem( sizeof( struct Message ),
>                                        MEMF_PUBLIC | MEMF_CLEAR ) ) == NULL )
>    {
>         fprintf( stderr, "alloc failed\n");
>        Close( fh );
>        FreeMem( packet, sizeof( PACKET ) );
>        exit( 1 );
>    }
>
>    /* Fill in the message */
>
>    tmsg = packet->dp_Link;
>    tmsg->mn_Node.ln_Name = (char *) packet;  /* MSH looks here */
>    tmsg->mn_Node.ln_Succ = NULL;
>    tmsg->mn_Node.ln_Pred = NULL;
>    tmsg->mn_ReplyPort    = packet->dp_Port;  /* Required? */
>    tmsg->mn_Length       = sizeof( *packet ); /* Correct Length? */
>
>    /* Send the message */
>
>    if( (long)msgpt < 0)
>        PutMsg( -(long)msgpt, tmsg );
>    else
>        PutMsg( msgpt, tmsg );
>
>    /* Wait for the return */
     WaitPort(replyport);
>    msg = (struct Message *)GetMsg( packet->dp_Port );
>    printf( "%d bytes read\n", packet->dp_Res1 );
>    Write( Output(), buf, packet->dp_Res1 );
>
>    /* Clean up */
>
>    DeletePort( replyport);
>    FreeMem( tmsg, sizeof( struct Message ) );
>    FreeMem( packet, sizeof( PACKET ) );
>
>    Close( fh );
>    exit(0);
>}

For your edification, here's a routine that will send a DOS packet
anywhere you want:

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <proto/exec.h>
#include <proto/dos.h>


LONG sendpkt(pid,action,args,nargs,res)
struct MsgPort *pid;  /* process indentifier ... (handlers message port ) */
LONG action,	      /* packet type ... (what you want handler to do )   */
     args[],	      /* a pointer to a argument list		*/
     nargs,	      /* number of arguments in list		*/
     res[];	      /* pointer to 2 longs for result, or NULL */
   {
   struct MsgPort	 *replyport;
   struct StandardPacket *packet;

   LONG  count, lres, *pargs;

   replyport = (struct MsgPort *) CreatePort(NULL,0);
   if(!replyport) return(0L);

   packet = (struct StandardPacket *)
      AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
   if(!packet)
      {
      DeletePort(replyport);
      return(0L);
      }

   packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
   packet->sp_Pkt.dp_Link	  = &(packet->sp_Msg);
   packet->sp_Pkt.dp_Port	  = replyport;
   packet->sp_Pkt.dp_Type	  = action;

   /* copy the args into the packet */
   pargs = &(packet->sp_Pkt.dp_Arg1);       /* address of first argument */
   for(count=0;count < nargs;count++)
      pargs[count]=args[count];

   PutMsg(pid,(struct Message *)packet); /* send packet */

   WaitPort(replyport);
   GetMsg(replyport);

   if(res)
   {
      lres = res[0] = packet->sp_Pkt.dp_Res1;
      res[1] = packet->sp_Pkt.dp_Res2;
   }

   FreeMem((char *)packet,(long)sizeof(struct StandardPacket));
   DeletePort(replyport);

   return(lres);
}

  *****
=*|_o_o|\\=====Doug Walker, Software Distiller====== BBS: (919)460-7430 =
 *|. o.| ||                                          1200/2400/9600 Dual
  | o  |//     For all you do, this bug's for you!
  ====== 
usenet: ...mcnc!rti!sas!walker   plink: dwalker  bix: djwalker 

ggk@tirith.UUCP (Gregory Kritsch) (11/15/20)

jesup@cbmvax.commodore.com (Randell Jesup) writes:
>	Buffering is done in dos.library in the buffered I/O calls.  Packets
>are by definition not buffered.

Well, I guess that answers that.  Probably not too significant, for most
packet io applications.

>	Yes, though see my earlier message about initialization! (all 0,
>except fh_Pos and fh_End which are -1).

Please mail me a copy - I haven't seen this one yet.

>	Buffering is done by calling buffered I/O routines that are new
>in 2.0.

Sniff.  Oh well.

>	We are documenting and making available a lot of things that were
>private/undocumented before.  Certain things should remain private, however,
>so that we can avoid incompatibility problems if we need to change some
>side-effect in the future.  Where there is a need, we will provide a defined
>interface for the needed function (such as the buffered I/O calls).   We
>have immense problems already trying to support some of the trickier things
>people who figured Dos out do (such as Bill Hawes).

Great, should be some interesting reading.  I just reread some really
old stuff about AmigaDOS the other day, and it was quite interesting to
see some of the reasons behind some of the "things" AmigaDOS does.

Are there any changes in functionality to the actual dos.library calls
(even some of the strange functions)?  Most importantly, does
Execute("",Input(),NULL) still work to create a subshell in the same
window, and return when the user types "endcli".

What about command lists passed to Execute?
(eg: Execute("emacs T:xxxx\nendcli",Input(),NULL)).

One thing I'd really like to see someday is the original CBM developed
AmigaDOS... Just to see what we missed out on.  It was supposedly object
oriented, which, it occurs to me, was at a time long before "object
oriented" was a common word.

>Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
>{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
>Common phrase heard at Amiga Devcon '89: "It's in there!"
--
  Gregory Kritsch                          | University of Waterloo
    Fido:  1:221/208.11110  [1:163/109.30] | 1A Computer Engineering
    UUCP:  ggk@tirith.UUCP                 |--------------------------
           ...!watmath!xenitec!tirith!ggk  | Amiga Fanatic

root@tirith.UUCP (Root) (11/17/20)

deven@rpi.edu (Deven T. Corzine) writes:

>On 7 Nov 90 18:52:24 GMT, gregg@cbnewsc.att.com (gregg.g.wonderly) said:

>According to the AmigaDOS Technical Reference Manual, (yes, it exists,
>but is very hard to read and understand) dp_Arg1 should be the BPTR to
>the file handle.  That is, that field should contain your return value
>from Open().  Apart from that, I don't know what may be wrong with
>your code without trying it...  But the documentation says the file
>handle.  (and remember, MSH is a handler; it's on the other end of the
>transaction.)

I've written one file handler myself (L:NetworkFileSystem was my name
for it, actually, but its not NFS from Unix), and studied others, and I
can tell you from all the weird things I had to do to make it work
exactly what is going on. 

When you call to open a file, via ACTION_OPENOLD, ACTION_OPENNEW, or
ACTION_OPENRW (not sure that these are the actual names, or if they're
even included in the .h files, but they correspond exactly to the MODE_*
that you pass to Open()), dp_Arg1 is a BPTR to a (struct FileHandle).

When you call any other action on that file (ie ACTION_READ,
ACTION_SEEK, ACTION_CLOSE, &c) you pass the fh_Arg1 field of the file
handle in dp_Arg1.  This field was set by the open call. 

Noteworthy detail: You allocate the memory for the file handle, and pass
it to the filehandler, which will initialize its contents.  You must
free this memory as well after you close the file.

Now, if you'll all carefully consult dosextens.h, you'll next ask "what
about those fh_Buffer and related fields - how are they used?".  My best
answer is that beyond the fh_Task and fh_Arg1 fields, the filesystem is
not supposed to change anything.  And the application program isn't
supposed to change anything period.  So I presume they're dead space,
left over from BCPL and TriPos.  (My money says ed and/or edit use
them though). 

>Deven T. Corzine        Internet:  deven@rpi.edu, shadow@pawl.rpi.edu
>Snail:  2214 12th St. Apt. 2, Troy, NY 12180   Phone:  (518) 271-0750
>Bitnet:  deven@rpitsmts, userfxb6@rpitsmts     UUCP:  uunet!rpi!deven
>Simple things should be simple and complex things should be possible.
--
  Gregory Kritsch                          | University of Waterloo
    Fido:  1:221/208.11110  [1:163/109.30] | 1A Computer Engineering
    UUCP:  ggk@tirith.UUCP                 |--------------------------
           ...!watmath!xenitec!tirith!ggk  | Amiga Fanatic

ggk@tirith.UUCP (Gregory Kritsch) (11/17/20)

jesup@cbmvax.commodore.com (Randell Jesup) writes:
>>What about command lists passed to Execute?
>>(eg: Execute("emacs T:xxxx\nendcli",Input(),NULL)).

>	Works fine.  Of course, there's no need to be so tricky.

Well, the only reason for it is I haven't got 2.0 on my A1000 yet.  So I
can't really test my software very well if I use 2.0 calls...  Besides,
my software is directed at more the general public than A3000 owners.

Plus, it was fun finding it.  I used true hacker techniques, rather than
looking up the function, I sort-of guessed at what might work, and tryed
it.  I was really suprised when it worked (although I wish I could get
rid of the double prompt at the beginning).

BTW: Dumb question which someone from Commodore should answer: What is
the final word on getting 2.0 for A2500, A2000, A500 and A1000 machines,
or is there one yet? (Or is Commodore not saying yet)?

>Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
>{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
>Common phrase heard at Amiga Devcon '89: "It's in there!"
--
  Gregory Kritsch                          | University of Waterloo
    Fido:  1:221/208.11110  [1:163/109.30] | 1A Computer Engineering
    UUCP:  ggk@tirith.UUCP                 |--------------------------
           ...!watmath!xenitec!tirith!ggk  | Amiga Fanatic

ggk@tirith.UUCP (Gregory Kritsch) (11/18/20)

andy@cbmvax.commodore.com (Andy Finkel) writes:
>Close, but not quite; there's another entity around involved in
>creating file handles...our friend, the dos.library.  Those fields
>are used for the BCPL buffered IO calls.

This doesn't quite make sense, unless I make the assumption that an
asynchronous io call is defined as not buffered, or that asynchronous io
isn't possible.

Is it not true that I can create and open a file handle myself using
only DeviceProc() to find the filesystem?

>Which, under 2.0, are now available for use by non-BCPL programs
>as well.

Thank you, whoever is responsible for this!  I can't wait to get 2.0 on
my A1000 so I can have fun with those.  I know several projects that
will benefit greatly.

Hmm, I don't have 2.0 autodocs (yet), how does one request buffering, and
will it break under 1.3?

>Anyway, those fields are private to dos.library and the shell...and
>under 2.0 finally can give any program that needs it buffered IO
>easily.

They should still be documented somewhere - what if I'm writing my own
shell?  This is the thing that annoys me the most about AmigaDOS - the
undocumented magic parts.

>		andy
>-- 
>andy finkel		{uunet|rutgers|amiga}!cbmvax!andy
>Commodore-Amiga, Inc.
--
  Gregory Kritsch                          | University of Waterloo
    Fido:  1:221/208.11110  [1:163/109.30] | 1A Computer Engineering
    UUCP:  ggk@tirith.UUCP                 |--------------------------
           ...!watmath!xenitec!tirith!ggk  | Amiga Fanatic