Path: utzoo!utgpu!watserv1!watmath!att!linac!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!wuarchive!emory!gatech!mcnc!rti!mozart!walker From: walker@unx.sas.com (Doug Walker) Newsgroups: comp.sys.amiga.tech Subject: Re: How do you send a DosPacket to a handler directly? Message-ID: <1990Nov28.201648.3250@unx.sas.com> Date: 28 Nov 90 20:16:48 GMT References: <1990Nov7.185224.4215@cbnewsc.att.com> Organization: SAS Institute Inc. Lines: 198 In article 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 #include #include #include #include #include #include #include #include #include #include #include #include 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