home *** CD-ROM | disk | FTP | other *** search
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* |_o_o|\\ Copyright (c) 1986 The Software Distillery. All Rights Reserved */
- /* |. o.| || This program may not be distributed without the permission of */
- /* | . | || the authors. BBS: */
- /* | o | || Dave Baker Ed Burnette Stan Chow (919)-471-6436 */
- /* | . |// Jay Denebeim Gordon Keener Jack Rouse Voice: */
- /* ====== John Toebes Mary Ellen Toebes Doug Walker (919)-469-4210 */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* This program watches the first 0x100 bytes of memory for random trashing, */
- /* attempts repair of the damage and then puts up an alert indicating the */
- /* damage that was done. Many thanks to EA for suggesting this program at */
- /* the developer's conference. */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- /* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */
- #include <exec/types.h>
- #include <exec/nodes.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
- #include <exec/ports.h>
- #include <exec/libraries.h>
- #include <exec/io.h>
- #include <exec/tasks.h>
- #include <exec/execbase.h>
- #include <exec/devices.h>
- #include <devices/timer.h>
- #include <intuition/intuition.h>
- #include <libraries/dosextens.h>
-
- /* * * * * * * * * * * STRUCTURES * * * * * * * * * * * * */
- typedef struct stomped
- {
- long data; /* value that was thrown into address wildly */
- long address; /* address that was changed */
- } STOMPED;
-
- /* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
- #define TIMEINTERVAL 2500L /* in micro seconds */
- #define LOWLIMIT 20L /* smallest safe interval */
- #define BANNER "\x9B0;33mMemWatch\x9B0m by John Toebes - Copyright © 1986 The Software Distillery\n 235 Trillingham Ln, Cary NC 27511 BBS:(919)-471-6436\n"
- #define BANNER1 "Usage: \x9B1mRUN MemWatch\x9B0m [n]\nWhere n is the optional interval between watch checks (Default 2500ms)\n"
-
- /* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */
- struct IntuitionBase *IntuitionBase = NULL;
- extern APTR AllocMem(long, long);
- /* ok so I lied about these tasks - it is true as long as we are working with */
- /* DOS processes */
- extern struct Process *FindTask(char *);
- extern void SetTaskPri(struct Process *, long);
- extern long OpenDevice(char *, long, struct IORequest*, long);
- extern void SaveMem();
- extern int ValidateMem(struct stomped *);
- int DOSBase;
-
- /* * * * * * * * * * * Alert definition structure* * * * * * * * * */
- /* we want to display the message: */
- /* Someone stepped on Low memory $nnnnnnnn with $nnnnnnnn cccc! */
- /* Press either Mouse button to continue */
- /* 345678901234567890123456789012345678901234567890123456789012 */
- /* 11111111112222222222333333333344444444445555555555666 */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- #define ALERTHEIGHT 25 /* height of alert in pixals */
- #define ADDR_OFF 34 /* location of address substitution */
- #define DATA_OFF 49 /* Location of data val substitution */
- #define CHAR_OFF 58 /* Location of data text substitution */
- static char AlertString[] = {
- 0, 84, /* 2 byte x absolute offset of first string */
- 10, /* 1 byte y absolute offset of first string */
- 'S', 'o', 'm', 'e', 'o', 'n', 'e', ' ', /* first message string */
- 'S', 't', 'e', 'p', 'p', 'e', 'd', ' ',
- 'o', 'n', ' ', 'L', 'o', 'w', ' ',
- 'm', 'e', 'm', 'o', 'r', 'y', ' ',
- '$', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', ' ', /* address we substitute */
- 'w', 'i', 't', 'h', ' ',
- '$', 'h', 'h', 'h', 'h', 'h', 'h', 'h', 'h', ' ', /* data we substitute */
- 'c', 'c', 'c', 'c', '!', /* chars we substitute */
- 0, /* null terminator on string */
- 1, /* flag to indicate another alert string */
- 0, 164, /* 2 byte x absolute offset of second string */
- 18, /* 1 byte y absolute offset of second string */
- 'P', 'r', 'e', 's', 's', ' ', /* second message string */
- 'e', 'i', 't', 'h', 'e', 'r', ' ',
- 'M', 'o', 'u', 's', 'e', ' ',
- 'B', 'u', 't', 't', 'o', 'n', ' ',
- 't', 'o', ' ',
- 'c', 'o', 'n', 't', 'i', 'n', 'u', 'e',
- 0, /* null terminator on string */
- 0 }; /* flag to indicate no more strings */
-
- /************************************************************************/
- /* The main program to watch the memory */
- /************************************************************************/
- void _main(cmd)
- char *cmd;
- {
- register struct timerequest *timerreq = NULL;
- /* request structure for timer waits*/
- struct stomped rslt; /* information on memory stomps */
- register int i; /* general index variable */
- register long v; /* temporary for formatting display */
- register long interval = TIMEINTERVAL;
- /* how long to wait between checks */
- register char *p; /* display formatting index */
- /* NOTE: The declarations for i anv v MUST come before that of interval */
- /* because DOIO trashes D6 and D7 which are the first ones selected for */
- /* register variables. It doesn't matter if i and v are trashed but */
- /* interval MUST be maintained across the lifetime of the loop */
-
- /* if we were run from CLI then output our banner and process parameters */
- if (cmd)
- {
- /* get our default output device */
- v = Output();
-
- /* display our copyright */
- Write(v, BANNER, sizeof(BANNER));
-
- /* skip over any leading spaces in the command line */
- while(*cmd == ' ')
- cmd++;
-
- /* now see if they gave us a number to control the interval of checking */
- interval = 0;
-
- while ((*cmd >= '0') && (*cmd <= '9'))
- interval = ((short)interval*(short)10) + *cmd++ - '0';
-
- /* if they gave us nothing (or something we didn't parse well */
- /* such as a VERY large number or just plain trash, give them a */
- /* short usage message for the program */
- if (interval <= 0)
- Write(v, BANNER1, sizeof(BANNER1));
-
- /* now do the magic that allows the window to be closed */
- if (v != Input())
- Close(Input());
- Close(v);
-
- /* just incase we got a very low number (or a 0) from the command line */
- /* apply a minimum rule to keep from killing the system performance */
- /* note that since tasks switch at about every 20mili seconds or so */
- /* (not sure where that information is from) making it less than 20000 */
- /* really isn't much of a gain (but it sure feels nice) */
- if (interval < LOWLIMIT) interval = LOWLIMIT;
- }
-
- /* now we are ready to go - push up our priority with the best of them */
- SetTaskPri( FindTask(NULL), 20);
-
- /* open up intuition - we only use this for the alert but we must do it */
- /* anyway */
- if ((IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 0)) == NULL)
- goto abort;
-
- /* create a request structure to send the messages with */
- if ((timerreq = (struct timerequest *)
- AllocMem(sizeof(struct timerequest),
- MEMF_CLEAR | MEMF_PUBLIC)) == NULL)
- goto abort;
-
- /* fill in the struture with what we are dealing with */
- timerreq->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
- timerreq->tr_node.io_Message.mn_Node.ln_Pri = 0;
- timerreq->tr_node.io_Message.mn_ReplyPort = &(FindTask(NULL)->pr_MsgPort);
-
- /* and open us a timer. Note that we are using VBLANK since it is the */
- /* lowest system overhead. We are not critical on the timing and only */
- /* want to run as often as possible without killing the system */
- if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest*)timerreq, 0))
- goto abort;
-
- /* let our assembler stub squirel away a copy of the low memory */
- SaveMem();
-
- /* go until they hit us with a ^C - kind of a simple way to stop it */
- while(!(SetSignal(0,0) & SIGBREAKF_CTRL_C))
- {
- /* Use the timer to wait our required number of seconds */
- timerreq->tr_node.io_Command = TR_ADDREQUEST;
- timerreq->tr_time.tv_secs = 0; /* seconds */
- timerreq->tr_time.tv_micro = interval; /* micro seconds */
- DoIO(timerreq);
-
- /* Now have our buddy check and fix any memory */
- /* if something was wrong, he will tell us about it */
- if (ValidateMem(&rslt))
- {
- /* format the failure data to be displayed */
- *(long *)(&AlertString[CHAR_OFF]) = rslt.data;
-
- /* replace any nulls so they don't screw up the message */
- for (i=CHAR_OFF; i<CHAR_OFF+4; i++)
- if (!AlertString[i]) AlertString[i] = '.';
-
- /* format the address for them */
- p = &AlertString[ADDR_OFF+7];
- v = rslt.address;
- for (i = 7; i>= 0; i--)
- {
- *p-- = "0123456789ABCDEF"[v&15];
- v >>= 4;
- }
-
- /* format the data value for them */
- p = &AlertString[DATA_OFF+7];
- v = rslt.data;
- for (i = 7; i>= 0; i--)
- {
- *p-- = "0123456789ABCDEF"[v&15];
- v >>= 4;
- }
-
- /* put up a requester to indicate it failed */
- DisplayAlert(0xBADC0DE, AlertString, ALERTHEIGHT);
- }
- }
-
- CloseDevice(timerreq);
- abort:
- if (timerreq != NULL) FreeMem (timerreq, sizeof(struct timerequest));
- if (IntuitionBase != NULL) CloseLibrary(IntuitionBase);
- XCEXIT(-1);
- }
-