/**************************************************************************** ** File: ID-handler.c ** Program: ID-handler - an AmigaDOS handler for generating unique names ** Version: 1.0 ** Author: Ed Puckett qix@mit-oz ** ** Copyright 1987 EpAc Software. All Rights Reserved. ** ** History: 02-Feb-87 Original Version */ #include #include #include #include #include /*--------------------------------------------------------------------------- ** References to system */ extern struct Library *OpenLibrary (); extern void CloseLibrary (); extern struct Task *FindTask (); extern ULONG Wait (); extern struct Message *GetMsg (); extern void PutMsg (); extern BYTE *AllocMem (); extern void FreeMem (); extern struct Library *AbsExecBase; /*--------------------------------------------------------------------------- ** These are new to the 1.2 release */ #ifndef MODE_READWRITE # define MODE_READWRITE 1004 #endif MODE_READWRITE #ifndef MODE_READONLY # define MODE_READONLY MODE_OLDFILE #endif MODE_READONLY #ifndef ACTION_END # define ACTION_END 1007 /* not really new, just missing */ #endif ACTION_END /*--------------------------------------------------------------------------- */ #define ALLOCMEM_FLAGS MEMF_PUBLIC #define ID_DIGITS 16 typedef struct opendata { char id[ID_DIGITS]; UBYTE pos; } OPENDATA; struct Library *SysBase = NULL; struct Library *DOSBase = NULL; static char ID[ID_DIGITS]; /*--------------------------------------------------------------------------- */ #define BPTRtoCptr(Bp) ((char *) ((ULONG) (Bp) << 2)) #define CptrtoBPTR(Cp) ((BPTR) ((ULONG) (Cp) >> 2)) #define ReplyPkt(pkt) PutMsg ((pkt)->dp_Port, (pkt)->dp_Link) /*--------------------------------------------------------------------------- ** handler() performs initialization, replies to startup packet, and ** dispatches incoming request packets to the apropriate functions. ** Our DeviceNode Task field is patched with our process ID so that this ** process is used for subsequent handler requests. The function exits only ** if there is some initialization error. */ void handler (StartPkt) struct DosPacket *StartPkt; { struct Task *Task; struct MsgPort *IDPort; ULONG WakeupMask, SigMask; struct DeviceNode *DevNode; struct DosPacket *pkt, *GetPkt(); unsigned i; void OpenID(), CloseID(), ReadID(); SysBase= AbsExecBase; if ((DOSBase= OpenLibrary (DOSNAME, 0)) == NULL) goto QUIT; Task= FindTask (0); IDPort= (struct MsgPort *) ((ULONG) Task + sizeof (struct Task)); ((struct Process *) Task)->pr_CurrentDir= 0; /* initial file system root */ WakeupMask= (1L << IDPort->mp_SigBit); DevNode= (struct DeviceNode *) BPTRtoCptr (StartPkt->dp_Arg3); DevNode->dn_Task= IDPort; ReplyPkt (StartPkt); for (i= 0; i < ID_DIGITS; ++i) ID[i]= '0'; LOOP: SigMask= Wait (WakeupMask); if (SigMask & WakeupMask) while ((pkt= GetPkt (IDPort)) != NULL) switch (pkt->dp_Type) { case MODE_READWRITE: OpenID (pkt); break; case MODE_NEWFILE: /* syn: ACTION_FINDOUTPUT */ pkt->dp_Res1= 0; pkt->dp_Res2= ERROR_WRITE_PROTECTED; ReplyPkt (pkt); break; case MODE_READONLY: /* syn: MODE_OLDFILE, ACTION_FINDINPUT */ OpenID (pkt); break; case ACTION_END: CloseID (pkt); break; case ACTION_READ: ReadID (pkt); break; case ACTION_WRITE: pkt->dp_Res1= -1; pkt->dp_Res2= ERROR_WRITE_PROTECTED; ReplyPkt (pkt); break; default: pkt->dp_Res1= 0; pkt->dp_Res2= ERROR_ACTION_NOT_KNOWN; ReplyPkt (pkt); } goto LOOP; QUIT: DevNode->dn_Task= NULL; /* bad if someone in process of accessing us . . . */ if (DOSBase != NULL) CloseLibrary (DOSBase); } /*--------------------------------------------------------------------------- ** GetPkt() returns the DosPacket associated with the next message on ** "port", or NULL if the port is empty. The message is removed from the ** port. A related macro, ReplyPkt(), is provided above. */ static struct DosPacket *GetPkt (port) register struct MsgPort *port; { register struct Message *msg; return ((msg= GetMsg (port)) == NULL) ? NULL : (struct DosPacket *) msg->mn_Node.ln_Name; } /*--------------------------------------------------------------------------- */ static void OpenID (pkt) struct DosPacket *pkt; { struct FileHandle *handle; OPENDATA *OpenData = NULL; unsigned i; void NextID(); if ((OpenData= (OPENDATA *) AllocMem (sizeof (OPENDATA), ALLOCMEM_FLAGS)) == NULL) { pkt->dp_Res1= 0; pkt->dp_Res2= ERROR_NO_FREE_STORE; ReplyPkt (pkt); } for (i= 0; i < ID_DIGITS; ++i) OpenData->id[i]= ID[i]; OpenData->pos= 0; NextID (); handle= (struct FileHandle *) BPTRtoCptr (pkt->dp_Arg1); handle->fh_Arg1= (LONG) OpenData; /* for identification on Read, Close */ pkt->dp_Res1= 1; pkt->dp_Res2= 0; /* for successful open */ ReplyPkt (pkt); } /*--------------------------------------------------------------------------- */ static void CloseID (pkt) struct DosPacket *pkt; { OPENDATA *OpenData; OpenData= (OPENDATA *) pkt->dp_Arg1; FreeMem (OpenData, sizeof (OPENDATA)); pkt->dp_Res1= 1; pkt->dp_Res2= 0; ReplyPkt (pkt); } /*--------------------------------------------------------------------------- */ static void ReadID (pkt) struct DosPacket *pkt; { OPENDATA *OpenData; unsigned n; OpenData= (OPENDATA *) pkt->dp_Arg1; pkt->dp_Res1= 0; if (OpenData->pos < ID_DIGITS) { if ((n= pkt->dp_Arg3) > (ID_DIGITS - OpenData->pos)) n= (ID_DIGITS - OpenData->pos); for ( ; pkt->dp_Res1 < n; ++(pkt->dp_Res1), ++(OpenData->pos)) ((char *) pkt->dp_Arg2)[pkt->dp_Res1]= OpenData->id[OpenData->pos]; } pkt->dp_Res2= 0; ReplyPkt (pkt); } /*--------------------------------------------------------------------------- */ static void NextID () { int i; for (i= ID_DIGITS - 1; (i >= 0) && (++(ID[i]) > '9'); --i) ID[i]= '0'; }