/*****************************************************************
 ** ResetHandlers                                               **
 **                                                             **
 ** Shows the installed reset handlers.				**
 ** Version 1.00 April 8th, 1998  © Thomas Richter (thor)	**
 **-------------------------------------------------------------**
 ** Be warned! I would call this a !!! Hack !!!               	**
 *****************************************************************/

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <devices/keyboard.h>
#include <dos/dos.h>

#include <proto/exec.h>
#include <proto/dos.h>

#include <string.h>

static char version[]="$VER: ResetList 1.00 (8.4.98)";

struct ResetSaveback {
        struct ResetSaveback   *next,*pred;
        BYTE                    pri;
        UBYTE                   reserved;
        char                   *name;
        void                   *data;
        void                   *code;
};

int main(void);
int PrintResetHandlers(void);
int ListResetHandlers(struct Interrupt *irq);
int DummyHandler(void);

struct DosLibrary *DOSBase;

int main(void)
{
int rc=20;

        if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
                rc=PrintResetHandlers();

                CloseLibrary((struct Library *)DOSBase);
        }

        return rc;
}


int ListResetHandlers(struct Interrupt *base)
{
struct Interrupt *irq;
struct ResetSaveback *rsb;
ULONG len;
int rc=0;
struct List reslist;


        NewList(&reslist);
        Forbid();
        irq=base;
        while(irq->is_Node.ln_Pred)
                irq=(struct Interrupt *)(irq->is_Node.ln_Pred);

        for(irq=(struct Interrupt *)(irq->is_Node.ln_Succ);irq->is_Node.ln_Succ;irq=(struct Interrupt *)(irq->is_Node.ln_Succ)) {
                if (irq!=base) {
                        len=strlen(irq->is_Node.ln_Name)+1+sizeof(struct ResetSaveback);
                        if (rsb=AllocVec(len,MEMF_PUBLIC)) {
                                rsb->pri=irq->is_Node.ln_Pri;
                                rsb->code=(void *)irq->is_Code;
                                rsb->data=irq->is_Data;
                                rsb->name=(char *)(rsb+1);
                                strcpy(rsb->name,irq->is_Node.ln_Name);
                                AddTail(&reslist,(struct Node *)rsb);
                        } else  rc=5;
                }
        }

        Permit();
        if (rc) {
                Printf("ResetList: Out of memory.\n");
        } else {
                Printf("List of installed reset handlers:\n\n");
                while(rsb=(struct ResetSaveback *)RemHead(&reslist)) {
                        Printf("Pri : %3ld  Code : 0x%08lx  Data : 0x%08lx  Name : %s\n",rsb->pri,rsb->code,rsb->data,rsb->name);
                        FreeVec(rsb);
                }
        }

        while(rsb=(struct ResetSaveback *)RemHead(&reslist)) {
                FreeVec(rsb);
        }

        return rc;
}


int DummyHandler(void)
{
        return 0;
}

int PrintResetHandlers(void)
{
struct IOStdReq *iostd;
struct MsgPort *port;
struct Interrupt *irq;
int rc=10;

        if (irq=AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC|MEMF_CLEAR)) {
                if (port=CreateMsgPort()) {
                        if (iostd=(struct IOStdReq *)CreateIORequest(port,sizeof(struct IOStdReq))) {
                                if (!OpenDevice("keyboard.device",0,(struct IORequest *)iostd,0)) {
                                        irq->is_Node.ln_Type=NT_INTERRUPT;
                                        irq->is_Node.ln_Pri=-32;
                                        irq->is_Node.ln_Name="ResetList.Interrupt";
                                        irq->is_Code=(void (*)())&DummyHandler;
                                        iostd->io_Command=KBD_ADDRESETHANDLER;
                                        iostd->io_Data=(void *)irq;
                                        iostd->io_Length=sizeof(struct Interrupt);
                                        if (!DoIO((struct IORequest *)iostd)) {
                                                ListResetHandlers(irq);

                                                iostd->io_Command=KBD_REMRESETHANDLER;
                                                if (DoIO((struct IORequest *)iostd)) {
                                                        Printf("ResetList: ALERT! Can't remove dummy reset handler.\n");
                                                        return 20;
                                                } else rc=0;
                                        } else Printf("ResetList: Can't install dummy reset handler.\n");
                                        CloseDevice((struct IORequest *)iostd);
                                } else Printf("ResetList: Can't open keyboard.device.\n");
                                DeleteIORequest((struct IORequest *)iostd);
                        } else Printf("ResetList: Can't build IORequest.\n");
                        DeleteMsgPort(port);
                } else Printf("ResetList: Can't build MsgPort.\n");
                FreeMem(irq,sizeof(struct Interrupt));
        } else Printf("ResetList: Can't build Interrupt.\n");

        return rc;
}

