/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by MXM * * Name .....: Null-Handler.c * Created ..: Saturday 31-Mar-90 13:47 * Revision .: 0 * * Date Author Comment * ========= ======== ==================== * 15-Apr-90 Olsen Ported to Aztec 'C' 5.0 * 07-Jan-90 Olsen Created this file! * * Skeleton handler code by Phillip Lindsay (C) 1986 * Commodore-Amiga, Inc. You may freely distribute this source and * use it for Amiga Development, as long as the Copyright notice is * left intact. * **************************************************************************** * * This is an example how a 'real' NIL: handler could look like. * It is very loosely based on the 'my-handler' source code written * by Phillip Lindsay. Since I have no access to the source code of * the original Null-Handler I rewrote it using Lattice 'C' 5.04 * which resulted in a very small executable file (actually about * 568 bytes long, the original handler code was 908 bytes long). * Three weeks later I thought "well, why not try to bring it * back to Aztec 'C'?". And that's what I did. I can't believe it, * Aztec 'C' 5.0 does a brilliant job on the program: it's actually * 112 smaller than the Lattice version. * * $Revision Header ********************************************************/ /* Main includes. */ #include #include #include #include /* Prototypes for this module. */ LONG HandlerEntry(VOID); VOID ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc); struct DosPacket * WaitPacket(struct Process *HandlerProc); /* Some magic pragmas. */ #pragma regcall(ReturnPacket(a0,d0,d1,a1)) #pragma regcall(WaitPacket(a0)) /* Global pointer to ExecBase. */ struct ExecBase *SysBase; /* HandlerEntry(): * * The entry point for this handler. */ LONG HandlerEntry() { struct Process *HandlerProc; /* Set the ExecBase pointer. */ SysBase = (struct ExecBase *)(*(LONG *)4); /* Get a pointer to the process structure of the * handler. */ HandlerProc = (struct Process *)SysBase -> ThisTask; /* If not called from CLI (you shouldn't do that) * we'll start up as a DOS-handler. */ if(!HandlerProc -> pr_CLI) { struct DosPacket *NullPacket; struct DeviceNode *NullNode; /* Wait for startup packet (we aren't a * BCPL module). */ NullPacket = WaitPacket(HandlerProc); /* Get pointer to handler device node. */ NullNode = (struct DeviceNode *)BADDR(NullPacket -> dp_Arg3); /* Install handler task ID -> we're running. */ NullNode -> dn_Task = &HandlerProc -> pr_MsgPort; /* Return the startup packet to DOS. */ ReturnPacket(NullPacket,DOSTRUE,NullPacket -> dp_Res2,HandlerProc); /* Run forever - or until somebody lets us die. */ for(;;) { /* Wait for a packet. */ NullPacket = WaitPacket(HandlerProc); /* Check the type. */ switch(NullPacket -> dp_Type) { case ACTION_FINDINPUT: case ACTION_FINDOUTPUT: case ACTION_FINDUPDATE: case ACTION_END: ReturnPacket(NullPacket,DOSTRUE,0,HandlerProc); break; case ACTION_WRITE: ReturnPacket(NullPacket,NullPacket -> dp_Arg3,0,HandlerProc); break; case ACTION_READ: ReturnPacket(NullPacket,0,0,HandlerProc); break; case ACTION_DIE: ReturnPacket(NullPacket,DOSTRUE,0,HandlerProc); goto FallOff; default: ReturnPacket(NullPacket,DOSFALSE,ERROR_ACTION_NOT_KNOWN,HandlerProc); break; } } /* Okay, we're done, zero the task ID field * and fall through. */ FallOff: NullNode -> dn_Task = NULL; } } /* ReturnPacket(): * * Returns a packet to DOS. */ VOID ReturnPacket(struct DosPacket *Packet,ULONG Res1,ULONG Res2,struct Process *HandlerProc) { struct MsgPort *ReplyPort; /* Remember origin port. */ ReplyPort = Packet -> dp_Port; /* Fill in the result fields. */ Packet -> dp_Res1 = Res1; Packet -> dp_Res2 = Res2; /* Install our task ID. */ Packet -> dp_Port = &HandlerProc -> pr_MsgPort; /* Initialize the packet node head. */ Packet -> dp_Link -> mn_Node . ln_Name = (char *)Packet; Packet -> dp_Link -> mn_Node . ln_Succ = NULL; Packet -> dp_Link -> mn_Node . ln_Pred = NULL; /* Return the packet to the sender. */ PutMsg(ReplyPort,Packet -> dp_Link); } /* WaitPacket(): * * Wait for a DOS packet. */ struct DosPacket * WaitPacket(struct Process *HandlerProc) { struct Message *DOSMsg; /* Wait at the port... */ WaitPort(&HandlerProc -> pr_MsgPort); /* Get the packet. */ DOSMsg = (struct Message *)GetMsg(&HandlerProc -> pr_MsgPort); /* Return a pointer to its head. */ return((struct DosPacket *)DOSMsg -> mn_Node . ln_Name); }