[comp.sources.amiga] v89i124: virusx - virus exterminator v3.2

page%swap@Sun.COM (Bob Page) (05/10/89)

Submitted-by: (lots of people)
Posting-number: Volume 89, Issue 124
Archive-name: dos/virusx32.1

8 new viruses, and one new option - CHECK.  If you say
VirusX CHECK, VirusX will check RAM and installed disks, then
quit.  Great for including VirusX with release disks.

# This is a shell archive.
# Remove anything above and including the cut line.
# Then run the rest of the file through 'sh'.
# Unpacked files will be owned by you and have default permissions.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: SHell ARchive
# Run the following text through 'sh' to create:
#	Makefile
#	README
#	virusx.c
#	virusx.i
# This is archive 1 of a 1-part kit.
# This archive created: Tue May  9 22:10:25 1989
echo "extracting Makefile"
sed 's/^X//' << \SHAR_EOF > Makefile
Xall : virusx
X
Xvirusx : virusx.c virusx.i
X	lc -v -cfwumsc -d -rr virusx
X	blink define @_exit=@XCEXIT @exit=@XCEXIT @_main=@_tinymain from lib:cback.o virusx.o to virusx lib lib:lcr.lib SC SD ND
X
Xvirusx.i : virusx.c
X	lc1b -pr -j100i -cwumsc virusx 
X
SHAR_EOF
echo "extracting README"
sed 's/^X//' << \SHAR_EOF > README
XVirusX 3.2 is created using the Lattice compiler.  It will still compile
Xand run under Manx, but Lattice 5.0 gave me an executable almost
X4K smaller than the Manx one, more than enough reason to switch.
X
XThe Makefile included is for the Manx make utility.  LMK doesn't like
Xme, so I'm using the manx one for now - any generic make should do,
Xthe reason it's included at all is so you can pick up the correct
Xcommand line switches and BLINK command line.
X
XThe virusx.i file is included by virusx.c and contains the prototype
Xdefinitions necessary to make registerized parameter passing possible
Xunder Lattice 5.
X
XNote that you'll get lots of warnings.  Ignore them.  Ignore the error
Xat the end of the link, too.
X
X		...Steve
SHAR_EOF
echo "extracting virusx.c"
sed 's/^X//' << \SHAR_EOF > virusx.c
X/************************************************************************/
X/*                                                                      */
X/*                                                                      */
X/*                                VirusX                                */
X/*                                                                      */
X/*                           by Steve Tibbett                           */
X/*                                                                      */
X/*                                                                      */
X/*              Please - if you find a new virus, Send me a copy!       */
X/*              (And warn me it's on the disk!).  I want to keep        */
X/*              this program current.  (Feel free to put something      */
X/*              neat on the disk also!)                                 */
X/*                                                                      */
X/*  This version of VirusX is done with the Lattice 5.0                 */
X/*  compiler.  The Lattice compiler, with the help of John Toebes,      */
X/*  gave me an executable almost 4K smaller than the best I could       */
X/*  get out of Manx.  Reason enough for me to switch!                   */
X/*                                                                      */
X/*  The Makefile included in the "source.zoo" file you should have      */
X/*  gotten in the VirusX.Zoo file this came from, is set up for the     */
X/*  MANX Make Utility.  Switching to Lattice's LMK should be easy,      */
X/*  but I've had no reason to.  The important thing is the command      */
X/*  line switches and the BLINK command line.                           */
X/*                                                                      */
X/*  Thanks to John Toebes for a lot of help getting it going, and       */
X/*  thanks to Dan James for providing the routine down at the bottom    */
X/*  that actually takes the IRQ Virus out of executable files.          */
X/*                                                                      */
X/************************************************************************/
X/*                                                                      */
X/*  History:                                                            */
X/*  --------                                                            */
X/*      April '88 or so:  V1.0 written and released.                    */
X/*     A few days later:  V1.01 released.  V1.0 wrote garbage to the    */
X/*                        disk if it was write protected then fixed.    */
X/*          27-March-88:  V1.2 released.  V1.2's purpose in life was    */
X/*                        to deal with the Byte Bandit virus.           */
X/*                        (Actually, it's well after midnight - make    */
X/*                        that March 28th. :)                           */
X/*          28-March-88:  Oops, V1.2 was 3K or so bigger than it needed */
X/*                        to be.  Fix it, release v1.21.                */
X/*           15-June-88:  V1.3, V1.2 cleaned up and made smaller.       */
X/*            8-July-88:  V1.4.  Revenge virus checking, Viewbooting,   */
X/*                        check for SCA in RAM, more cleaning up.       */
X/*           24-July-88:  V1.5, only change was the addition of the     */
X/*                        Byte Warrior virus.                           */
X/*             1-Aug-88:  V1.6 (busy week), Dan Mosedale sent me the    */
X/*                        Northstar Virus.  Nuked it.                   */
X/*            18-Aug-88:  V1.7 - after 2 weeks off, got the Obelisk     */
X/*                        Softworks crew virus.                         */
X/*     a few days later:  V1.71, can't remember why.                    */
X/*   September Sometime:  Biggest mistake of my life, released V2.0.    */
X/*         3 days later:  Bigger mistake:  Released V2.01 - which was   */
X/*                        2.0 with another bug added.  Argh.            */
X/*             6-Nov-88:  Finally got some time to clean things up,     */
X/*                        check out the startup code bugs, clean up the */
X/*                        docs and source, and release V2.1.  There     */
X/*                        haven't been any new viruses in about a month */
X/*                        now, but I hear one or two are on the way.    */
X/*            31-Dec-88:  Got the IRQ virus yesterday.  Neat one!       */
X/*                        Releasing V3.0 tonite or tomorrow to handle   */
X/*                        it.  See description below.                   */
X/*            04-Jan-89:  Got 2 new viruses, released 3.1.              */
X/*            18-Feb-89:  And boy, am I tired.  8 (count 'em) 8 new     */
X/*                        viruses in this version.  Ack!  DOUBLE        */
X/*                        the last version.  New option: CHECK, good    */
X/*                        for including VirusX with a commercial        */
X/*                        program.  V3.20                               */
X/*                                                                      */
X/************************************************************************/
X/*                                                                      */
X/*  Viruses Dealt With:                                                 */
X/*  -------------------                                                 */
X/*                                                                      */
X/*      SCA             - The SCA is the simplest virus to deal with,   */
X/*                        as it's not actually DOING anything except    */
X/*                        hiding in memory, until you reboot.           */
X/*                        We just look at CoolCapture and fix it to get */
X/*                        it out of RAM.                                */
X/*                                                                      */
X/*      Byte Bandit     - The Byte Bandit virus takes the DoIO() vector */
X/*                        and redirects it through itself.  Thus, any   */
X/*                        attempt to read or write the boot block (ie,  */
X/*                        AmigaDOS trying to figure out what kind of    */
X/*                        disk it is) results in the BB writing itself  */
X/*                        onto that disk.  VirusX couldn't just rewrite */
X/*                        the boot block, we have to get him out of RAM */
X/*                        first.  This virus also has an interrupt that */
X/*                        crashes the machine every 5 minutes or so     */
X/*                        after it's infected a few of your disks.  Ow. */
X/*                        It stays in memory not via the Capture        */
X/*                        vectors, but by a Resident module.            */
X/*                                                                      */
X/*      Revenge         - Basically, a Byte Bandit clone except it will */
X/*                        bring up an obscene pointer a few minutes     */
X/*                        after you reboot.  We treat it much like the  */
X/*                        byte bandit.                                  */
X/*                                                                      */
X/*      Byte Warrior    - Jumps right into 1.2 Kickstart.  Won't work   */
X/*                        under 1.3.  Hangs around via Resident struct, */
X/*                        doesn't do any damage.                        */
X/*                                                                      */
X/*      North Star      - Like SCA, hangs around via CoolCapture,       */
X/*                        killing CoolCapture kills the North Star.     */
X/*                                                                      */
X/*      Obelisk Softworks Crew                                          */
X/*                      - Hangs around via CoolCapture, also            */
X/*                        watches reads of DoIO() (but doesn't          */
X/*                        infect EVERY disk - onlyt ones you boot       */
X/*                        off of)                                       */
X/*                                                                      */
X/*       IRQ            - This is the FIRST Non-Bootblock Virus.        */
X/*                        It copies itself from place to place via the  */
X/*                        first executable program found in your        */
X/*                        startup-sequence.  It SetFunction's           */
X/*                        OldOpenLibrary(), has a KickTagPtr,           */
X/*                        and lives in the first hunk of an             */
X/*                        infected program.                             */
X/*                        THANKS! to Gary Duncan and Henrik Clausen for */
X/*                        being the first to send this one to me!       */
X/*                                                                      */
X/*  Pentagon Circle     - This one looks at the DoIO vector, and has    */
X/*                        a CoolCapture vector.  It will write itself   */
X/*                        over any virus inserted, but not onto         */
X/*                        anything else.  (Neat idea!).  No danger,     */
X/*                        easy to eliminate.  Holding left button       */
X/*                        while booting with this one shows different   */
X/*                        screen colour, but doesn't get rid of it.     */
X/*                        Thanks to Bill at CMI (CMI*BILL on Plink)     */
X/*                        for sending me this one!                      */
X/*                                                                      */
X/*  SystemZ Virus Protector                                             */
X/*                      - I took this one out.  It's not really a       */
X/*                        'Virus' in that it won't overwrite a disk     */
X/*                        without asking you first.  Besides, it seems  */
X/*                        a lot of people LIKE the SystemZ Virus        */
X/*                        Protector (though it isn't perfect).          */
X/*                                                                      */
X/*   Lamer Exterminator - THIS one was a bugger.  Yet another virus     */
X/*                        aimed at hurting people.  Y'see, a Lamer      */
X/*                        is apparently the worst kind of pirate -      */
X/*                        one who doesn't crack software, doesn't       */
X/*                        write software, just collects names and       */
X/*                        addresses and collects and spreads software.  */
X/*                        Lamers don't do anybody any good - and the    */
X/*                        guy behind this Virus took it upon himself    */
X/*                        to make their (and our) lives miserabler.     */
X/*                        Anyway, this virus loads into RAM into a      */
X/*                        different location every time (using a        */
X/*                        random location).  It is encrypted on the     */
X/*                        disk so you can't SEE the name of it, and     */
X/*                        it never actually SHOWS the name (but it's    */
X/*                        definately there).  It changes the            */
X/*                        encryption key used each time it is written   */
X/*                        back to disk.  It has a counter and will      */
X/*                        wait until the machine has been reset 2 times */
X/*                        OR until 3 disks have been infected, and will */
X/*                        then pick a DATA block (Only a DATA block -   */
X/*                        FFS disks are safe, I guess), randomly, and   */
X/*                        will write the word 'LAMER!' all through it.  */
X/*                        This is obviously not good, and will cause    */
X/*                        random disk errors.  This is the worst kind   */
X/*                        of havoc to wreak on the new user - and this  */
X/*                        virus is EVERYWHERE!  I've gotten it from 5   */
X/*                        people in the last week alone (all from       */
X/*                        different countries!  Ack!).  Anyways, credit */
X/*                        for being the first with this one is          */
X/*                        Christian Schneider.  Thanks, Christian!      */
X/*  Might as well break the margin convention here, eh?  Anyways,       */
X/*  something else I thought of about this virus:  It introduces a NEW  */
X/*  way for a Virus to stay in RAM.  Y'see, if ExecBase is okay at      */
X/*  reboot time (Exec keeps a checksum, among other things, and checks  */
X/*  to see if anything has been corrupted quite carefully).  Anyways,   */
X/*  if Exec thinks ExecBase is okay, it doesn't bother rebuilding it.   */
X/*  Sooo, this virus sets the SumKickData() vector to point at itself.  */
X/*  Then at Reboot when this vector gets called after reset, the virus  */
X/*  ReInstalls himself.  At least this is what I think is happening.    */
X/*  This virus sets up a Resident structure, but never sets the Match   */
X/*  Word - either this means we don't need the MatchWord or it means    */
X/*  his SumKickData() is doing the recovery job - either way, it's      */
X/*  new!  3 points for originality.                                     */
X/*                                                                      */
X/*  Graffiti - The first virus to come with rotating 3-d graphics!      */
X/*             It's neat - you might want to trigger it (I'm not sure   */
X/*             how) before nuking it.  Anyway, this one just sets       */
X/*             CoolCapture(), does something with DoIO() during the     */
X/*             reboot but sets it back to normal before anybody gets    */
X/*             to look at it.  Lots of code is taken by the graphics    */
X/*             stuff.  I just clear the CoolCapture vector.  [yawn]     */
X/*                                                                      */
X/*  Old Northstar - Poof.						*/
X/*                                                                      */
X/*  16 Bit Crew - Well, I didn't actually have to DO anything to get    */
X/*		 VirusX to recognize it... because it seems to operate  */
X/*               like the Graffiti Virus.  If the 16 bit crew is in     */
X/*               RAM, VirusX will say it removed the Graffiti virus.    */
X/*               Oh well.  8-)                                          */
X/*                                                                      */
X/*  DiskDoktor - I spent more time on this one than on any other.       */
X/*               Y'see, this virus does lots of things.  The first one  */
X/*               for some reason was quite funny to me.  heh            */
X/*               What it would do is after you have rebooted 5 times,   */
X/*               each time you reboot after that, the virus would eat   */
X/*               10K times the total number of reboots - so after       */
X/*               rebooting 10 times, you would be short about 100K.     */
X/*               This virus also starts up another TASK.  I'm not       */
X/*               exactly sure when it happens, but another task named   */
X/*               'clipboard.device' will appear at a priority of -120,  */
X/*               and will continually bash the Virus' vectors into the  */
X/*               Coldcapture, Coolcapture, Warmcapture (which it sets   */
X/*               to $ff000000 just to annoy), and the DoIO() vector.    */
X/*               When I was working on this one, I figured I just had   */
X/*               to restore the old values to the DoIO() vector, but as */
X/*               soon as I did so, the Virus restored them - and since  */
X/*               I didn't disassemble the entire thing, I didn't realize*/
X/*               this until I wasted time looking for other faults.     */
X/*               This one also allocates some memory, copies some code  */
X/*               out of Exec into this memory, and executes it.  I      */
X/*               never bothered to figure out why - Once it's gone, it's*/
X/*               gone.                                                  */
X/*                                                                      */
X/*  Thanks also to Robb Walton for being the first to send one of the   */
X/*  other ones, (but I can't remember which one anymore... 8-(  )       */
X/************************************************************************/
X/*                                                                      */
X/*  Notes on making VirusX yourself:  The source is included mainly     */
X/*  for your perusal, not so that you can modify it and redistribute    */
X/*  it.  I've modified Manx's _main.c module to make the detach         */
X/*  from the initial CLI work properly.  I can't redistribute this      */
X/*  module since it's copyright manx, so here's VirusX without it.      */
X/*  It will compile and run, but if you run it from WB, it won't quit.  */
X/*  The version I've supplied should do everything just fine.           */
X/*                                                                      */
X/************************************************************************/
X
X
X#include <stdio.h>
X#include <ctype.h>
X#include <stdlib.h>
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include <devices/bootblock.h>
X#include <devices/trackdisk.h>		/*   /		       */
X#include <exec/execbase.h>		/*  <-- include files  */
X#include <exec/memory.h>		/*   \		       */
X#include <libraries/dos.h>		
X#include <libraries/dosextens.h>
X#include <pragmas/all.h>
X#include <proto/all.h>
X#include <String.h>
X#include "virusx.i" /* Virusx.i is an ANSI thing.  It's got Protoypes. */
X		    /* (or used to anyway) 			       */
X
X/* Latticeisms */
X
X/* What's that you say?  C is hard to read? */
X
Xvoid MemCleanup() {}
Xvoid RawDoFmt(char *, long *, void (*)(), char*);
X#pragma syscall RawDoFmt 20a ba9804
Xvoid __regargs prbuf(char c);
Xint __regargs sprintf(char *buf, char *ctl, char *args) { RawDoFmt(ctl, (long *)&args, prbuf, buf); return(strlen(buf)); }
Xvoid __regargs prbuf(char c) {__builtin_emit(0x16c0);}
X
X/******************************************************************/
X/* In case you're interested, that little mess above is a routine */
X/* supplied by John Toebes which changes sprintf() from using the */
X/* compiler's library into something that uses the ROM code found */
X/* in Kickstart.  Sooo, it made VirusX about 1.2K or so smaller!! */
X/* Feel free to steal this and use it wherever.  However, the new */
X/* sprintf function can't handle a lot of things - check the Exec */
X/* manual (I believe) for details.  Neat formatting here, eh? 8-) */
X/******************************************************************/
X
Xchar WhatHappened;	/* huh?? */
X
X/******************************************************************/
X/* These string constants are used in multiple places, and thus   */
X/* save bytes by having only one copy of them.                    */
X/******************************************************************/
Xchar TITLETEXT[]        = "VirusX 3.20 by Steve Tibbett";
Xchar TDName[]           = "trackdisk.device";
Xchar copystring[]       = "(Copy Count on this disk: %ld)";
Xchar ITBodyText[80];
Xchar CaptureStr[]       = "Capture is pointing at $";
Xchar text[]             = "DF6: Boot Sectors";
Xchar VN_OBELISK[]       = "Obelisk";
Xchar VN_NORTHSTAR[]     = "North Star";
Xchar VN_SCA[]           = "SCA";
Xchar VN_BYTEBANDIT[]    = "Byte Bandit";
Xchar VN_BYTEWARRIOR[]   = "Byte Warrior";
Xchar VN_REVENGE[]       = "Revenge";
Xchar VN_IRQ[]           = "IRQ";
Xchar VN_PENTAGON[]      = "Pentagon Circle";
Xchar VN_LAMER[]		= "Lamer Exterminator";
Xchar VN_HCS[]		= "H.C.S.";
Xchar VN_UFOX[]		= "UltraFox";
Xchar VN_DDOC[]		= "DiskDoc";
Xchar VN_GRAFFITI[]	= "Graffiti";
Xchar VN_Bit16[]		= "16 Bit Crew";
Xchar VN_PHANTASM[]	= "Phantasmumble";	/* Can't remember the whole name */
Xchar VN_OLDNSTAR[]	= "Old Northstar";
X
X
X/********************************************************************/
X/* These counters are for the Info window, one for each virus.      */
X/********************************************************************/
Xint     ObeliskCount;
Xint     NorthStarCount;
Xint     SCACount;
Xint     ByteBanditCount;
Xint     ByteWarriorCount;
Xint     RevengeCount;
Xint     IRQFound;
Xint	PentagonCount;
Xint 	LamerXCount;
Xint	HCSCount;
Xint	UFoxCount;
Xint	DDocCount;
Xint	GRAFFITICount;
Xint	Bit16Count;
Xint	PhantasmCount;
Xint 	OldNStarCount;
X
X
X/*******************************************************************/
X/*  Miscellaneous variables.                                       */
X/*******************************************************************/
Xlong    ChangeCount[4];                 /* TD_CHANGECOUNT for 4 drives  */
Xlong    LastSum;                        /* Used in the checksumming     */
Xlong    error;                          /* sort of a temporary variable */
Xchar    WindowBig;                      /* TRUE if the window is big    */
Xstruct  Port *diskport;                 /* trackdisk's port.            */
Xstruct  IOStdReq *diskreq;              /* trackdisk's IOStdReq         */
Xlong    DisksChecked, DisksInstalled;   /* for title bar info           */
Xlong    VirusBase;                      /* ick, whatta name!            */
X
Xstruct IntuitionBase    *IntuitionBase; /* For Library Bindings         */
Xstruct GfxBase          *GfxBase;
Xstruct Window           *Window;
Xstruct IntuiMessage     *Message;
Xstruct ExecBase         *ExecBase;
X
Xstruct IOStdReq         *TimerReq;
Xstruct MsgPort          *TimerPort;
X
Xstatic long fp;
X
Xchar Keepgoing;         /* A flag.  It's false when we want out.        */
Xlong x, y, i;           /* Left over from my using Basic                */
Xchar flag;              /* Another flag.  Lets start our own country.   */
XLONG thing1, thing2;
X
Xstruct NewWindow NewWindow =
X        {
X        128,0,  309,10,  0,1,
X        DISKINSERTED | CLOSEWINDOW |VANILLAKEY | NEWSIZE | MOUSEBUTTONS,       /* IDCMP Flagz */
X        WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
X        NULL, NULL,TITLETEXT,
X        NULL,NULL,0,0,0,0,WBENCHSCREEN,
X        };
X
Xstruct RastPort *RP;
X
X#define BSIZE 40        /* Ha!  I'm not telling what this is! */
X
X
X/*******************************************************************/
X/*  diskbuffer is where all disk io goes to.  it's 3*512 rather    */
X/*  than 2*512, because I believe one of the viruses watches for   */
X/*  reads of 1024 bytes, so I'm just being safe.                   */
X/*******************************************************************/
XUBYTE *diskbuffer;
X
X
X/************************************************************************/
X/* Warning messages.  These messages get modified before being          */
X/* displayed (Unless you DO have a DF9:)                                */
X/************************************************************************/
Xchar TEXTPTR[] = "Danger:  The disk in DF9: is";
Xchar NBCTEXT[] = "Danger:  The disk in DF9: has";  /* What a waste, eh? */
Xchar CopyText[40];
X
X/*************************************************************************/
X/*   This is a byte by byte copy of working boot block code.  Check it   */
X/*   out if you like.  This is what gets written back to the disk when   */
X/*   you ask VirusX to fix a disk.                                       */
X/*************************************************************************/
Xunsigned char bootblock[] = { 'D', 'O', 'S', 0,
X0xc0, 0x20, 0x0f, 0x19, 0x00, 0x00, 0x03, 0x70, 0x43, 0xfa, 0x00, 0x18,
X0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
X0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64, 0x6f,
X0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x00, 0x00, 0x00,
X0x00, 0x00};
X
X
X/********************************************************************/
X/*  My intuition defines.  There's lots of 'em - theyre self explan.*/
X/********************************************************************/
X
Xstruct TextAttr TxtAt_Plain =
X        {
X        "topaz.font", 8, FS_NORMAL, FPF_ROMFONT
X        };
X
X/***  Non SCA warning requester IntuiText's ***/
X
Xstruct IntuiText Body2 =
X        {
X        0, 1,  JAM2, 20,18, &TxtAt_Plain, "Nonstandard Boot Code!", NULL
X        };
X
Xstruct IntuiText Body1 =
X        {
X        0,1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2
X        };
X
X/*-  This one says "The disk in DFx: is"  -*/
X
Xstruct IntuiText GenericFirstBody =
X        {
X        0,1, JAM2, 20,8,&TxtAt_Plain, (UBYTE *)TEXTPTR, 0
X        };
X
X
X/***** Generic IntuiTexts used as of V1.7 ******/
Xstruct IntuiText GenericDiskBody =
X        {
X        0,1, JAM2, 20,18, &TxtAt_Plain,ITBodyText, &GenericFirstBody
X        };
X
Xstruct IntuiText SCAPos =
X        {
X        0,1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL
X        };
X
Xstruct IntuiText Repair =
X        {
X        0,1, JAM2, 7,3, &TxtAt_Plain, "Repair it", NULL
X        };
X
Xstruct IntuiText SCANeg =
X        {
X        0,1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL
X        };
X
X/*  Special cases (display copy count) */
X
X/***** BBANDIT Requester IntuiText's ******/
Xstruct IntuiText BBDiskbody2 =
X        {
X        0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
X        };
X
Xstruct IntuiText BBDiskbody =
X        {
X        0,1, JAM2, 20,18, &TxtAt_Plain, ITBodyText, &BBDiskbody2
X        };
X
X/***** Revenge on Disk Requester IntuiText's ******/
Xstruct IntuiText RevDiskbody3 =
X        {
X        0,1, JAM2, 20,30, &TxtAt_Plain, CopyText, &GenericFirstBody
X        };
X
Xstruct IntuiText RevDiskbody =
X        {
X        0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with the -Revenge- VIRUS!", &RevDiskbody3
X        };
X
X
X/***** Generic Notice - Removed from Memory ****/
Xstruct IntuiText GRB3 =
X        {
X        0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled.  See the", NULL
X        };
X
Xstruct IntuiText GRB2 =
X        {
X        0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "documentation for more information!", &GRB3
X        };
X
Xstruct IntuiText GenericRAMBody =
X        {
X        0,1, JAM2, 20, 8, &TxtAt_Plain, ITBodyText, &GRB2
X        };
X
Xstruct IntuiText BBMPos =
X        {
X        0,1, JAM2,  7, 3, &TxtAt_Plain, " Thanks! ", NULL
X        };
X
Xstruct IntuiText Mem3 =
X        {
X        0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "some other utility is the cause of it.", NULL
X        };
X
Xstruct IntuiText Mem2 =
X        {
X        0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "This could mean a new Virus is in RAM, or", &Mem3
X        };
X
Xstruct IntuiText Mem1 =
X        {
X        0,1, JAM2, 20, 8, &TxtAt_Plain, 0 , &Mem2
X        };
X
X
X/***** Write Protect Error Requester IntuiText's ******/
Xstruct IntuiText ERRBody2 =
X        {
X        0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL
X        };
X
Xstruct IntuiText ERRBody =
X        {
X        0,1, JAM2, 20,8, &TxtAt_Plain, (UBYTE *)"DISK ERROR:  Disk is", &ERRBody2
X        };
X
Xstruct IntuiText ERRPos =
X        {
X        0,1, JAM2, 7,3, &TxtAt_Plain, "Retry", NULL
X        };
X
Xstruct IntuiText ERRNeg =
X        {
X        0,1, JAM2, 7,3, &TxtAt_Plain, "Cancel", NULL
X        };
X
X
X/***** Rewrite block?  Really? ******/
Xstruct IntuiText REWBody3 =
X        {
X        0,1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL
X        };
X
Xstruct IntuiText REWBody2 =
X        {
X        0,1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3
X        };
X
Xstruct IntuiText REWBody =
X        {
X        0,1, JAM2, 20,8, &TxtAt_Plain,      (UBYTE *)"Are you sure you want to", &REWBody2
X        };
X
Xstruct IntuiText REWPos =
X        {
X        0,1, JAM2, 7,3, &TxtAt_Plain, "Yes", NULL
X        };
X
Xstruct IntuiText REWNeg =
X        {
X        0,1, JAM2, 7,3, &TxtAt_Plain, "No!", NULL
X        };
X
X
X/*********************Da Beginnin*************************/
X
Xvoid main(argc, argv)
Xint argc;
Xchar **argv;
X{
X
Xif (argc == 3)
X	{
X        NewWindow.LeftEdge = atoi(argv[1]);
X        NewWindow.TopEdge = atoi(argv[2]);
X        };
X
XWindowBig = FALSE;
X
X/* Come on, folks, is intuition ever NOT going to be available???? */
XIntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0L);
X
X/* Same with GfxBase.  If GfxBase is gone, we DESERVE to crash. */
XGfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
X
XExecBase = (struct ExecBase *)OpenLibrary("exec.library", 0);
X
Xdiskbuffer = AllocMem((long)3*512, (long)MEMF_CHIP|MEMF_CLEAR);
Xif (diskbuffer == 0)
X        {
X        /* Okay, okay, it's messy and doesn't close the libraries it
X           opens.  Look, if we can't get a measley 1.5K, then the
X           system is probably going to crash before the user finds out
X           what hit him, and he probably won't blame me.      */
X           exit(10);
X        };
X
X/*  We use the same port/request through the whole program.  Works OK. */
Xdiskport = CreatePort(0L,0L);
Xdiskreq = CreateStdIO(diskport);
X
XWindow = OpenWindow(&NewWindow);
Xif (Window == NULL)
X        goto Quitter;   /* No memory to open little window! */
X
XRP = Window->RPort;
X
X/* This does some setup stuff, I guess, eh? */
XSetUp();
X
X/*  Check for Byte Bandit, SCA, Revenge and ByteWarrior, etc. in RAM.  */
XCheckMemoryForViruses();
X
X/*  Hmmm, wonder what this does. */
XCheckMemoryForIRQVirus();
X
XCheckBlock();
X
Xif (argc != 2) 	/* New Feature:  Virusx CHECK will only check disks then quit */
X	DoLittle();     /* The main loop.  Do Little.  Ya. */
X
XQuitter:
X
Xif (Window != 0) CloseWindow(Window);
X
Xif (diskport != 0) DeletePort(diskport);
Xif (diskreq != 0) DeleteStdIO(diskreq);
X
X
XCloseLibrary(GfxBase);									/*
XCloseDoor(DoorBase);
XCloseLibrary(IntuitionBase);								hahah bet I fooled you */  
XCloseLibrary((struct Library *)ExecBase);
XFreeMem(diskbuffer, (long)3*512);
Xexit(0);
X
X/* DoorBase?? */
X}
X
X/*********************/
XDoLittle()
X{
Xlong Code;     /* for storing our IntuiMessage stuff */
Xlong Class;
Xchar KG2;      /* KeepGoing 2.  Another booleean. */
X
XKG2 = TRUE;
X
XSetAPen(RP, 1L);
XSetBPen(RP, 0L);
XSetDrMd(RP, (long)JAM2);
X
Xwhile (KG2 == TRUE)
X        {
X        Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
X        if (Message == 0)
X                {
X                CheckMemoryForIRQVirus();
X                Delay(50);
X                continue;
X                };
X
X        Class = Message->Class;
X        Code = Message->Code;
X        ReplyMsg((struct Message *)Message);
X
X        if (Class == CLOSEWINDOW)
X                {
X                KG2 = FALSE;
X                continue;
X                };
X
X        if (Class == MOUSEBUTTONS)
X                if (Code == MENUDOWN)
X                        {
X                        Class = VANILLAKEY;
X                        Code = 'i';
X                        }
X                        else continue;
X
X        if (Class == VANILLAKEY)
X                {
X                char flag;
X
X                switch (toupper(Code))
X                        {
X                        case 'I':
X                                if (WindowBig == TRUE) WindowBig = FALSE;
X                                        else WindowBig = TRUE;
X
X                                if (WindowBig == TRUE)
X                                        {
X                                        if (Window->TopEdge > 0) MoveWindow(Window, 0L, (long)-Window->TopEdge);
X                                        SizeWindow(Window, 0L, 200-(Window->Height));
X                                        } else SizeWindow(Window, 0L, -Window->Height + 10);
X
X                                WaitForNewSize();
X                                break;
X
X
X                        case 'C':
X                                for (x=0; x<4; x++) ChangeCount[x] = 10000;
X                                CheckBlock();
X
X                        default:
X                                flag = ShowAscii(Code);
X                                if (flag == 1) CheckBlock();
X                        };
X                if (WindowBig == TRUE) DoStats();
X                };
X
X        if (Class == DISKINSERTED)
X                {
X                CheckBlock();
X                if (WindowBig == TRUE) DoStats();
X                };
X        };
X
X}
X
X
X/************************************************/
X/* Opens trackdisk, finds out who's out there,  */
X/* and sets Changecount up accordioningly.      */
X/************************************************/
XSetUp()
X{
Xlong x;
X
Xfor (x = 0; x < 4; x++) /* go thru all 4 possible drives */
X        {
X        ChangeCount[x] = 1000;
X        error = OpenDevice(TDName,(long)x,diskreq,0L);
X        if (error > 0)
X                {
X                ChangeCount[x] = -1;
X                } else CloseDevice(diskreq);
X        };
X
X}
X
X/*********************************************************/
X/* This routine returns which drive changed disks lately */
X/*********************************************************/
XWhoChanged()
X{
Xchar RetVal = -1;       /* The value we'll return */
X
Xfor (x = 0; x < 4; x++)
X        {
X        if (ChangeCount[x] == -1)
X                continue;       /* no drive here */
X        error = OpenDevice(TDName,(long)x,diskreq,(long)0);
X        if (error > 0)
X                continue;       /* no drive here */
X
X        diskreq->io_Command = TD_CHANGESTATE;
X        DoIO(diskreq);
X        if (diskreq->io_Actual != 0)
X                {
X                CloseDevice(diskreq);
X                continue;
X                };
X
X        diskreq->io_Command = TD_CHANGENUM;
X        DoIO(diskreq);
X        if (diskreq->io_Actual != ChangeCount[x])
X                {
X                RetVal = x;
X                ChangeCount[x] = diskreq->io_Actual;
X                CloseDevice(diskreq);
X                break;
X                };
X
X        CloseDevice(diskreq);
X        };
X
Xreturn(RetVal);
X}
X
X/****************************************************************/
X/*  Figures out which drive changed disks (using WhoChanged(),  */
X/*  And checks it.  Calling this after every DISKINSERTED is OK.*/
X/****************************************************************/
XCheckBlock()
X{
X/*  How many register vars can I use, anyway? */
Xregister long Sum, Virus;
Xregister long a, Unit;
Xchar SCA, ByteWarrior, Revenge, BBandit;
Xchar NorthStar, Obelisk, Pentagon, LamerX, HCS;
Xchar DDoc, GRAFFITI, Bit16, Phantasm, OldNStar;
Xchar UFox;
Xunsigned long *iptr;
Xunsigned long *ptr;
Xchar drivename[10];
X
Xwhile ((Unit = WhoChanged()) != -1)
X        {
X        strcpy(drivename, "DF0:");
X        drivename[2] = '0'+Unit;
X
X        SCA = FALSE;
X        BBandit = FALSE;
X        Revenge = FALSE;
X        ByteWarrior = FALSE;
X        NorthStar = FALSE;
X        Obelisk = FALSE;
X	Pentagon = FALSE;
X	LamerX = FALSE;
X	UFox = FALSE;
X	HCS = FALSE;
X	DDoc = GRAFFITI = Bit16 = Phantasm = OldNStar = FALSE;
X		
X        /* Unit # to open is returned by "WhoChanged()" up above. */
X        if (Unit == -1) return;
X        error = OpenDevice(TDName,(long)Unit,diskreq,0L);
X        if (error > 0) return;
X
X        DisksChecked++;
X
X        error = ReadBlock();
X        CloseDevice(diskreq);
X        if (error == FALSE) return;
X
X        ptr = (long *)diskbuffer;
X        iptr = (long *)diskbuffer;
X
X        if (iptr[0] != ID_DOS_DISK) return;     /* No DOS/0 */
X	
X        Sum = 0;
X        for (a=0; a<256; a++)
X                {
X                LastSum = Sum;
X                Sum = Sum + ptr[a];
X                if (LastSum > Sum) Sum++;  /* took me a while to figger this out */
X                }
X
X        if (Sum != 0)
X                {
X                CheckDriveForIRQ(drivename);
X                return; /* if it's not bootable, we DONT want it! */
X                };
X
X        if (diskbuffer[0x40] == 0xff)
X                if (diskbuffer[0x41] == 0xa0)
X                        if (diskbuffer[0x42] == 0x20)
X                                if (diskbuffer[0x43] == 0x40)
X		{
X		PentagonCount++;
X		Pentagon = TRUE;
X		}
X
X        if (iptr[0x40/4] == 0x13fc00a0)
X		{
X		DDocCount++;
X		DDoc = TRUE;
X		}
X
X        if (iptr[0x150/4] == 0x000100bf)
X		{
X		GRAFFITICount++;
X		GRAFFITI = TRUE;
X		}
X
X        if (iptr[0x150/4] == 0x3fff2c78)
X		{
X		Bit16Count++;
X		Bit16 = TRUE;
X		}
X
X        if (iptr[0x40/4] == 0x4240323c)
X		{
X		PhantasmCount++;
X		Phantasm = TRUE;
X		}
X
X        if (iptr[0x40/4] == 0x0007ec1a)
X		{
X		OldNStarCount++;
X		OldNStar = TRUE;
X		}
X
X        if (iptr[0x1d0/4] == 0x83353ef0)
X        /*
X        diskbuffer[0x1d0] == 0x83)
X                if (diskbuffer[0x1d1] == 0x35)
X                        if (diskbuffer[0x1d2] == 0x3e)
X                                if (diskbuffer[0x1d3] == 0xf0)
X	*/
X		{
X		UFoxCount++;
X		UFox = TRUE;
X		}
X
X        if (diskbuffer[0x40] == 0x51)
X                if (diskbuffer[0x41] == 0xc8)
X                        if (diskbuffer[0x42] == 0xff)
X                                if (diskbuffer[0x43] == 0xfc)
X		{
X		HCSCount++;
X		HCS = TRUE;
X		}
X
X        if (diskbuffer[0x40] == 0x03)
X                if (diskbuffer[0x41] == 0x61)
X                        if (diskbuffer[0x42] == 0x34)
X                                if (diskbuffer[0x43] == 0x3c)
X		{
X		LamerXCount++;
X		LamerX = TRUE;
X		}
X					
X       if (diskbuffer[0x34] == 100)
X                if (diskbuffer[0xc4] == 48)
X                        if (diskbuffer[0xc0] == 68)
X                                if (diskbuffer[0xf1] == 7)
X                                        {
X                                        ByteWarriorCount++;
X                                        ByteWarrior = TRUE;
X                                        };
X
X        if (diskbuffer[0x2b] == '9')
X                if (diskbuffer[0x2c] == '.')
X                        if (diskbuffer[0x2d] == '8')
X                                if (diskbuffer[0x2e] == '7')
X                                        {
X                                        ByteBanditCount++;
X                                        BBandit = TRUE; /* 9.87 is part of BBandit Virus */
X                                        };
X
X        /* check specifically for SCA virus */
X        if (diskbuffer[0x149] == 0x28)
X                if (diskbuffer[0x14a] == 0x23)
X                        if (diskbuffer[0x14b] == 0x7c)
X                                        {
X                                        SCA = TRUE;     /* CHW is part of SCA virus */
X                                        SCACount++;
X                                        };
X
X        if (diskbuffer[0xe] == 'I')
X                if (diskbuffer[0xf] == 'D')
X                        if (diskbuffer[0x10] == '9')
X                                if (diskbuffer[0x1a6] == 'f')
X                                        {
X                                        Revenge= TRUE;
X                                        RevengeCount++;
X                                        };
X
X        if (diskbuffer[0x12] == 78)
X                if (diskbuffer[0x13c] == 68)
X                        if (diskbuffer[0x18] == 83)
X                                if (diskbuffer[0x19] == 116)
X                                        {
X                                        NorthStar = TRUE;
X                                        NorthStarCount++;
X                                        };
X
X
X        if (diskbuffer[0x38] == 71)
X                if (diskbuffer[0xbc] == 83)
X                        if (diskbuffer[0x1fb] == 100)
X                                if (diskbuffer[0x2d] == 80)
X                                        {
X                                        Obelisk = TRUE;
X                                        ObeliskCount++;
X                                        };
X
X        /* compare boot block with real boot block.  If it's not, notify God. */
X        Virus = FALSE;
X
X        for (x = 0; x < 39; x++) /* num of bytes in bootblock */
X                {
X                if (diskbuffer[8+x] != bootblock[8+x])
X                        {
X                        Virus = TRUE;
X                        };
X                };
X
X        /* Oh no, a Virus! */
X        if (Virus == TRUE)
X                {
X                NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
X                TEXTPTR[23] = '0'+Unit;
X                error = FALSE;
X
X                if (SCA == TRUE)
X                        {
X                        /* OH NOOOOO, an SCA virus.  Wimpo virus, compared to BBandit
X                           but it's a lot nicer code to read. */
X                        error = MyRequest(VN_SCA, 1);
X                        }
X                else if (BBandit == TRUE)
X                        {
X                        /* The Byte Bandit Virus.  Tricky bugger, he WAS. Cheats, tho. */
X                        sprintf(CopyText, copystring, (long)(diskbuffer[74]*256)+diskbuffer[75]);
X                        BuildITBodyText(VN_BYTEBANDIT, 1);
X                        error = AutoRequest(Window, &BBDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
X                        }
X                else if (Revenge == TRUE)
X                        {
X                        /* Revenge virus.  X rated bugger, lot like Byte Bandit. */
X                        sprintf(CopyText, copystring, (long)(diskbuffer[0x3f6]*256)+diskbuffer[0x3f7]);
X                        BuildITBodyText(VN_REVENGE, 1);
X                        error = AutoRequest(Window, &RevDiskbody, &SCAPos, &SCANeg, 0L, 0L, 380L, 80L);
X                        }
X                else if (ByteWarrior == TRUE)
X                        {
X                        /* Byte Warrior.  Very 'friendly' virus.  Ez to get rid of.  */
X                        error = MyRequest(VN_BYTEWARRIOR, 1);
X                        }
X                else if (Pentagon == TRUE)
X                        {
X                        /* Pentagon Circle.  An 'AntiVirus', and not a bad one at that. */
X                        error = MyRequest(VN_PENTAGON, 1);
X                        }
X                else if (NorthStar == TRUE)
X                        {
X                        /* NorthStar.  Nice virus - alerts you to others, ez to get rid of */
X                        error = MyRequest(VN_NORTHSTAR, 1);
X                        }
X                else if (Obelisk == TRUE)
X                        {
X                        /* At least these guys are getting creative with their Graphics! */
X                        error = MyRequest(VN_OBELISK, 1);
X                        }
X                else if (LamerX == TRUE)
X                        {
X                        /* At least these guys are getting creative with their Graphics! */
X                        error = MyRequest(VN_LAMER, 1);
X                        }
X                else if (HCS == TRUE)
X                        {
X                        /* At least these guys are getting creative with their Graphics! */
X                        error = MyRequest(VN_HCS, 1);
X                        }
X                else if (UFox == TRUE)
X                        {
X                        /* yawn */
X                        error = MyRequest(VN_UFOX, 1);
X                        }
X                else if (DDoc == TRUE)
X                        {
X                        /* yawn */
X                        error = MyRequest(VN_DDOC, 1);
X                        }
X                else if (GRAFFITI == TRUE)
X                        {
X                        /* yawn */
X                        error = MyRequest(VN_GRAFFITI, 1);
X                        }
X                else if (Bit16 == TRUE)
X                        {
X                        /* yawn */
X                        error = MyRequest(VN_Bit16, 1);
X                        }
X                else if (Phantasm == TRUE)
X                        {
X                        /* yawn */
X                        error = MyRequest(VN_PHANTASM, 1);
X                        }
X                else if (OldNStar == TRUE)
X                        {
X                        /* yawn */
X                        error = MyRequest(VN_OLDNSTAR, 1);
X                        }
X                else
X                        {
X                        /* Probably just a custom boot block (or a new virus...) */
X                        error = AutoRequest(Window, &Body1, &SCAPos, &SCANeg, 0L, 0L, 320L, 70L);
X                        }
X                if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
X                };
X        CheckDriveForIRQ(drivename);
X        };  /* End of While Whochanged */
X
X}
X
X/********************************************/
X/* This is where the boot code gets changed */
X/********************************************/
XDoInstall(un)
Xint un; /* unit to write to */
X{
Xregister int x;
X
X/* Rewrite disk?  Really?  */
Xerror = AutoRequest(Window, &REWBody, &REWPos, &REWNeg, 0L, 0L, 320L, 75L);
Xif (error != TRUE) return;      /* user changed his brain. */
X
XDisksInstalled++;
X
Xerror = OpenDevice(TDName, (long)un,diskreq,0L);
Xif (error > 0) return;
X
XTryGain:
X
X        diskreq->io_Command = TD_PROTSTATUS;
X        DoIO(diskreq);          /* check if disk is write protected */
X
X        if (diskreq->io_Actual != 0)
X                {
X                error = AutoRequest(Window, &ERRBody, &ERRPos, &ERRNeg, 0L, 0L, 280L, 75L);
X                if (error == TRUE) /* error is true or false, depending on user */
X                        {
X			goto TryGain;
X                        };
X	        CloseDevice(diskreq);
X	        return; /* unrecoverable write protect error!! Panic!!!!!!! */
X		};
X
Xfor (x = 0; x < 1024; x++)
X        diskbuffer[x] = 0;      /* clear diskbuffer to zero.  clean. */
X
XCopyMem(bootblock, diskbuffer, 50L); /* Copy it over */
X
X/* Write it ! */
X
X        error = 0;
X        diskreq->io_Length = 1024; /* here we go! */
X        diskreq->io_Data = (APTR)diskbuffer;
X        diskreq->io_Command = CMD_WRITE;
X        diskreq->io_Offset = 0L;
X        DoIO(diskreq);
X        error = diskreq->io_Error;
X
Xif (error < 19)
X        {
X        diskreq->io_Command = CMD_UPDATE;       /* flush buffer to disk */
X        DoIO(diskreq);
X        error = diskreq->io_Error;
X        };
X
Xif (error < 19)
X        {
X        diskreq->io_Length = 0;
X        diskreq->io_Command = ETD_MOTOR;
X        DoIO(diskreq);                          /* turn off motor */
X        error = diskreq->io_Error;
X        };
X
XCloseDevice(diskreq);
X
Xif (error > 19)
X        {
X        SetWindowTitles(Window, "Disk Error!", (STRPTR)-1);
X        }
X    else
X        {
X        SetWindowTitles(Window, "Disk Healed.", (STRPTR)-1);
X        };
X
XDelay(150L);
XSetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
X}
X
X
X/************************/
X
XCheckMemoryForViruses()
X{
Xunsigned long *TD;
Xunsigned short *wordpointer;
Xunsigned long *LongMemPointer;  /* Used for reading FROM memory */
Xunsigned long *ptr;
Xchar linebuffer[80];
Xchar *charpointer;
Xunsigned int x;
X
X/**************- Check for Byte Bandit (look at TD Vector) *************/
X/*  (Byte Bandit isn't at a fixed location.  Depends on your RAM.      */
X
X/* LongMemPointer = &trackdisk.device */
XTD = (unsigned long *)FindName(&ExecBase->DeviceList, TDName);
X
Xx = (unsigned int) TD;
Xx = x - 0x1c;
Xptr = (unsigned long *) x;
XLongMemPointer = (unsigned long *) *ptr;
Xx = (unsigned int) LongMemPointer;
Xx = x - 0x1b8;
XLongMemPointer = (unsigned long *) x;
X
Xif (*LongMemPointer == ID_DOS_DISK)     /* klugo */
X       	{
X        /* Ok, so we don't really remove it from memory, but we DO render
X       	   it harmless. */
X        Disable();
X       	charpointer = (char *)VirusBase;
X        charpointer[0xaa] = 0x4e;
X       	charpointer[0xac] = 0x4e;
X        charpointer[0xae] = 0x4e;
X       	charpointer[0xb0] = 0x4e;
X        charpointer[0xab] = 0x71;
X       	charpointer[0xad] = 0x71;
X        charpointer[0xaf] = 0x71;    /* Isn't this code terrible?  Ick! */
X       	charpointer[0xb1] = 0x71;    /* I didn't know what I was doing when */
X        charpointer[0x1c2] = 0x60;   /* I wrote this.  (excuses... 8-)  */
X       	charpointer[0x1c3] = 0;
X        charpointer[0x2d2] = 0x60;
X       	charpointer[0x2d3] = 0;
X        charpointer[0x388] = 0x4e;
X       	charpointer[0x389] = 0x75;
X        charpointer[0x3ea] = 0;
X       	charpointer[0x3eb] = 0;
X        charpointer[0] = 0;
X       	Enable();
X
X        MyRequest(VN_BYTEBANDIT, 2);
X       	};
X	
X
XTD = (unsigned long *)FindName(&ExecBase->DeviceList, TDName);
Xx = (unsigned int) TD;
Xx = x - 0x1c;
XLongMemPointer = (unsigned long *)x;
XLongMemPointer = (unsigned long *)LongMemPointer[0];
Xx = (unsigned int)LongMemPointer;
Xx = x - 0x17c;
XLongMemPointer = (unsigned long *)x;
X
Xif (*LongMemPointer == ID_DOS_DISK)	/* ptr == VirusBase */
X	{
X	char *a;
X	long *src, *dest;
X	long *vbase;
X	
X	*LongMemPointer = 0;	/* Kill DOS\0 */
X
X	vbase = LongMemPointer;
X	
X	/* Disable, then repair vectors. */
X	Disable();
X
X	/* addr of real TD vector */
X	src = &vbase[0x3a8/4];
X	a = (char *)ExecBase;
X	a = a - 0x264;
X	dest = (unsigned long *)a;
X	*dest = *src;
X	
X	src = (unsigned long *) &vbase[0x3ac/4];
X	a = (char *)TD;
X	a = a - 0x1c;
X	dest = (unsigned long *)a;
X	*dest = *src;
X	
X	Enable();
X	
X	ExecBase->KickTagPtr = 0;	/* Sorry, I know it's cruel */
X
X        MyRequest(VN_LAMER, 2);
X
X	}
X
X	
X
X
X/****************- Look for Revenge Virus (at $7e000) ****************/
Xif ((unsigned long)ExecBase->CoolCapture == (unsigned long)516192)
X        {
X        /* Fix the CoolCapture vector */
X        ExecBase->CoolCapture = 0;
X
X        Disable();
X
X        wordpointer = (unsigned short *)(0x7e000);
X        wordpointer[0] = 0;
X
X        wordpointer = (unsigned short *)(0x7e000+0x1e0);
X        wordpointer[0] = 0x4ef9;
X        wordpointer[1] = 0x0007;
X        wordpointer[2] = 0xe066;
X
X        wordpointer = (unsigned short *)0x7e2da;
X        wordpointer[0] = 0x4ef9;
X        wordpointer[1] = 0x0007;
X        wordpointer[2] = 0xe06c;
X
X        Enable();
X
X        MyRequest(VN_REVENGE, 2);
X        };
X
X/******************** See if SCA is in RAM ***************************/
Xif ((long)ExecBase->CoolCapture == (long)0x7ec3e)
X        {
X        ExecBase->CoolCapture = 0;
X        MyRequest(VN_SCA, 2);
X        };
X
X/******************** See if Graffiti is in RAM ***************************/
Xif ((long)ExecBase->CoolCapture == (long)0x7ec58)
X        {
X        ExecBase->CoolCapture = 0;
X        MyRequest(VN_GRAFFITI, 2);
X        };
X
X/******************** How about Phantasmumble? ***************************/
Xif ((long)ExecBase->CoolCapture == (long)0x7ec74)
X        {
X        ExecBase->CoolCapture = 0;
X        MyRequest(VN_PHANTASM, 2);
X        };
X
X/******************** Yoo hoo?  HCS?  Are you here? ******************/
Xif ((long)ExecBase->CoolCapture == (long)0x7ec64)
X        {
X        /* You are, you little dickens.  */
X        
X        ExecBase->CoolCapture = 0;
X	
X	/* Scat! */
X	
X	x = (unsigned int) ExecBase;
X	x = x - 0x1c6;
X	ptr = (unsigned long *)x;
X	
X	LongMemPointer = (unsigned long *)0x7ef9c;
X	
X	*ptr = *LongMemPointer;	/* un-Step on DoIO() vector */
X
X        MyRequest(VN_HCS, 2);
X        };
X
X/**************************** DiskDoktor? ****************************/
Xwordpointer = ExecBase->CoolCapture;
Xif (*wordpointer == 0x2c79)
X	{
X	if (wordpointer[3] == 0x203c)
X		{
X		int x;
X		
X		Disable();
X		
X		x = ExecBase;
X		x = x - 0x1c6;
X		LongMemPointer = (long *)x;
X		
X		wordpointer = (UWORD *)*LongMemPointer;
X
X		x = (int)wordpointer;
X		x = x + (0x15c);
X		wordpointer = (UWORD *)x;
X		*wordpointer = 0x4e75;
X
X		x = (int)wordpointer;
X		x = x + 0x1e2;
X		wordpointer = (UWORD *)x;
X		*wordpointer = 0x4e75;
X		
X 		x = (int)ExecBase;
X		x = x - 0x1c6;
X		ptr = (long *)x;
X		
X		x = (int)*ptr;
X		x = x + 2;
X		LongMemPointer = (long *)x;
X				
X		*ptr = *LongMemPointer;
X
X		ExecBase->CoolCapture = 0;
X		ExecBase->ColdCapture = 0;
X		ExecBase->WarmCapture = 0;
X
X		Enable();
X		
X		MyRequest(VN_DDOC, 2);
X		};
X	};
X
X
X/******************** It's the Australian UltraFox  ******************/
Xif ((long)ExecBase->CoolCapture == (long)0x7ed36)
X        {
X        UWORD *wordptr;
X
X 	ExecBase->CoolCapture = 0;
X	
X	x = (unsigned int) ExecBase;
X	x = x - 0x1c6;
X	ptr = (unsigned long *)x;
X	wordptr = (UWORD *)ptr;
X	if (wordptr[0] == 0x0007)
X		{
X		LongMemPointer = (unsigned long *)0x7eb38;
X		*ptr = *LongMemPointer;	/* un-Step on DoIO() vector */
X		};
X		
X        MyRequest(VN_UFOX, 2);
X        };
X
X/***************** Check for Obelisk  *******************************/
Xif ((APTR)ExecBase->CoolCapture == (APTR)0x7e86c)
X        {
X        ExecBase->CoolCapture = 0;
X        ptr = (unsigned long *)0x7e88a;
X        Forbid();
X        ptr[0] = 10;
X        Permit();
X        MyRequest(VN_OBELISK, 2);
X        };
X
X/******************** How about North Star? **************************/
Xif ((APTR)ExecBase->CoolCapture == (APTR)0x7ec0e)
X        {
X        ExecBase->CoolCapture = 0;
X        MyRequest(VN_NORTHSTAR, 2);
X        };
X
X/********************* Check for Byte Warrior ************************/
Xwordpointer = (unsigned short *)0x7f800;
Xif ( wordpointer[0] == (0x444f) )
X        {
X        wordpointer = (unsigned short *)0x7f954;
X        if (wordpointer[0] == 0x4afc)
X                {
X                wordpointer[0] = 0;             /* Kill resident matchtag */
X
X                Forbid();
X
X                wordpointer = (unsigned short *)0x7f972;
X                wordpointer[0] = 0x4ef9;
X                wordpointer[1] = 0x00fc;
X                wordpointer[2] = 0x06dc;
X
X                wordpointer =  (unsigned short *)0x7f800;
X                wordpointer[0] = 0;
X
X                Permit();
X
X                MyRequest(VN_BYTEWARRIOR, 2);
X                };
X        };
X
X/******************** See if Pentagon is in RAM ***************************/
Xif ((long)ExecBase->CoolCapture == (long)0x7fb4c)
X        {
X        ExecBase->CoolCapture = 0;
X
X        /* He sometimes has the DoIO() setfunctioned, I can't figure out
X           when, but even if he does, he doesn't do any harm anyway, and
X           with CoolCapture set to 0, he'll be gone at next reboot.  */
X           
X        MyRequest(VN_PENTAGON, 2);
X	};
X	
X
Xif (ExecBase->CoolCapture != 0)
X        {
X        sprintf(linebuffer, "Cool%s%lx", CaptureStr, ExecBase->CoolCapture);
X        if (MyRequest(linebuffer, 3) == TRUE) ExecBase->CoolCapture = 0;
X        }
X
Xif (ExecBase->ColdCapture != 0)
X        {
X        sprintf(linebuffer, "Cold%s%lx", CaptureStr, ExecBase->ColdCapture);
X        if (MyRequest(linebuffer, 3) == TRUE) ExecBase->ColdCapture = 0;
X        }
X
Xif (ExecBase->WarmCapture != 0)
X        {
X        sprintf(linebuffer, "Warm%s%lx", CaptureStr, ExecBase->WarmCapture);
X        if (MyRequest(linebuffer, 3) == TRUE) ExecBase->WarmCapture = 0;
X        }
X}
X
X
X/**************************************************************/
X/*  This is the routine that displauys a block as ASCII text. */
X/**************************************************************/
XShowAscii(key)
Xlong key;
X{
Xint drive;
Xint x,y;
Xint deltax, deltay;
Xlong a;
Xint FLAG=0;
X
Xstruct RastPort *RP;
XRP = Window->RPort;
X
Xdrive = key - '0';
X
Xif ((drive < 0) || (drive > 3) || (ChangeCount[drive] == -1)) return;
X
Xerror = OpenDevice(TDName,(long)drive,diskreq,0L);
Xif (error > 0) return;
X
Xerror = ReadBlock();
X
XCloseDevice(diskreq);
X
Xif (error == FALSE) return;
X
X/* save the amount we moved the window */
Xdeltax = Window->LeftEdge;
Xdeltay = Window->TopEdge;
X
XMoveWindow(Window, -deltax, -deltay);
X
Xif (WindowBig == FALSE) SizeWindow(Window, 278L, 160L);
X        else SizeWindow(Window, 278L, 0L);
X
XWaitForNewSize();
X
XSetAPen(RP, 0L);
XRectFill(RP, 2, 12, 278, 167);
X
XSetAPen(RP, 3L);
XMove(RP, (long)(14+(12*8)), 165L);
XText(RP, "Block 0", 7L);
XMove(RP, (long)(324+(12*8)), 165L);
XText(RP, "Block 1", 7L);
XSetAPen(RP, 1L);
X
Xtext[2] = key;
XSetWindowTitles(Window, text, (STRPTR)-1);
X
Xx=0; y=0;
X
XSetAPen(RP, 1L);
XSetDrMd(RP, JAM2);
X
Xfor (a=0; a<512; a=a+32)
X        {
X        Move(RP, (long)(10+(x*8)), (long)20+(y*9));
X        Text(RP, &diskbuffer[a], 32L);
X
X        Move(RP, (long)(320+(x*8)), (long)20+(y*9));
X        Text(RP, &diskbuffer[a+512], 32L);
X        y++;
X        };
X
XWait(1<<Window->UserPort->mp_SigBit);
XMessage = (struct IntuiMessage *)GetMsg(Window->UserPort);
X
X/*  If a disk was inserted, we want CheckBlock() to happen later on some time */
Xif (Message->Class == DISKINSERTED) FLAG=1;
XReplyMsg((struct Message *)Message);
X
Xif (WindowBig == FALSE)
X        SizeWindow(Window, -278L, -160L);
X        else SizeWindow(Window, -278L, 0L);
X
XSetWindowTitles(Window, TITLETEXT, (STRPTR)-1);
XWaitForNewSize();
X
X/* deltas plus current position, in case dude moved the window */
XMoveWindow(Window, deltax+(-Window->LeftEdge), deltay+(-Window->TopEdge));
XDelay(2L);
Xreturn(FLAG);
X}
X
X
X/*
X When you do a SizeWindow() command, you have to wait for a NEWSIZE
X IntuiMessage before drawing in it.  That's all this routine does.
X */
XWaitForNewSize()
X{
Xwhile (TRUE)
X        {
X        WaitPort(Window->UserPort);
X        Message = (struct IntuiMessage *)GetMsg(Window->UserPort);
X        if (Message->Class != NEWSIZE)
X                {
X                ReplyMsg((struct Message *)Message);
X                continue;
X                };
X        ReplyMsg((struct Message *)Message);
X        break;
X        };
X}
X
X/*
X        type:
X
X                1 == "is infected with the xxxx VIRUS!"
X                2 == "somethin about virus in ram"
X                3 == virus in cold/cool/warm capture
X*/
X
XBuildITBodyText(text, type)
Xchar *text;
Xint type;
X{
Xswitch (type)
X        {
X        case 1:
X                strcpy(ITBodyText, "infected with the `");
X                strcat(ITBodyText, text);
X                strcat(ITBodyText, "' VIRUS!");
X                break;
X        case 2:
X                strcpy(ITBodyText, "NOTICE:  The `");
X                strcat(ITBodyText, text);
X                strcat(ITBodyText, "' VIRUS was found");
X                break;
X        };
X}
X
X/***** an attempt to save space *********/
XMyRequest(string, type)
Xchar *string;
Xint type;
X{
Xif (type != 3)
X        {
X        BuildITBodyText(string, type);
X        } else
X        {
X        Mem1.IText = string;
X        };
X
Xif (type == 1) return(AutoRequest(Window, &GenericDiskBody, &SCAPos, &SCANeg, 0L, 0L, 420L, 80L));
Xif (type == 2) return(AutoRequest(Window, &GenericRAMBody, &BBMPos, &BBMPos, 0L, 0L, 420L, 78L));
Xif (type == 3) return(AutoRequest(Window, &Mem1, &Repair, &SCANeg, 0L, 0L, 420L, 78L));
X}
X
X
X/********* DoStats() **********/
XDoStats()
X{
Xchar linebuffer[80];
X
XSetAPen(RP, 0L);
XRectFill(RP, 2L, 11L, 303L, Window->Height-13);
XSetAPen(RP, 1L);
X
Xsprintf(linebuffer, "  Disks Checked: %ld", DisksChecked);
XOut(20, linebuffer);
X
Xsprintf(linebuffer, "Disks Installed: %ld", DisksInstalled);
XOut(29, linebuffer);
X
XOut(43, "    Viruses Found:");
X
XPV(52, VN_SCA, SCACount);
XPV(61, VN_BYTEBANDIT, ByteBanditCount);
XPV(70, VN_NORTHSTAR, NorthStarCount);
XPV(79, VN_BYTEWARRIOR, ByteWarriorCount);
XPV(88, VN_REVENGE, RevengeCount);
XPV(97, VN_OBELISK, ObeliskCount);
XPV(106, VN_IRQ, IRQFound);
XPV(115, VN_PENTAGON, PentagonCount);
XPV(124, VN_HCS, HCSCount);
XPV(133, VN_DDOC, DDocCount);
XPV(142, VN_GRAFFITI, GRAFFITICount);
XPV(151, VN_Bit16, Bit16Count);
XPV(160, VN_PHANTASM, PhantasmCount);
XPV(169, VN_OLDNSTAR, OldNStarCount);
XPV(178, VN_UFOX, UFoxCount);
XPV(187, VN_LAMER, LamerXCount);
X}
X
X/****************** Ok, we're REALLY being chintzy here. */
XPV(num, name, howmany)
Xint num;
Xchar *name;
Xint howmany;
X{
Xchar linebuffer[80];
X
Xsprintf(linebuffer, "%-19s: %ld", name, howmany);
XOut(num, linebuffer);
X}
X
X/***************************************** Cheap?  Me?  Nooooo....     */
X/* This will write text to the column number in NUM, the text in Name. */
X/*  Or something like that. ********************************************/
XOut(num, name)
Xint num;
Xchar *name;
X{
Xint len;
Xlen = 0;
X
Xwhile (name[len] != 0) len++;
X
XMove(RP, 20L, (long)num);
XText(RP, name, len);
X}
X
X
XReadBlock()
X{
Xdiskreq->io_Command = CMD_READ;
Xdiskreq->io_Data = (APTR)diskbuffer;
Xdiskreq->io_Length = 3*512;
Xdiskreq->io_Offset = 0;
XDoIO(diskreq);
Xif (diskreq->io_Error > 0) return(FALSE);
Xdiskreq->io_Length = 0;
Xdiskreq->io_Command = TD_MOTOR;
XDoIO(diskreq);
Xreturn(TRUE);
X}
X
Xunsigned long *OpenLibVectorPtr;
Xunsigned long *EntryForOldOpenLib;
Xunsigned long *OldOldOpenLibVector;
X
X
XCheckMemoryForIRQVirus()
X{
Xlong *Array;
Xint Num;
X
XArray = (long *)4;
XArray = (long *)Array[0];
XNum = (int)Array;
XNum = Num - 0x196;
X
XOpenLibVectorPtr = (unsigned long *)Num;
X
XEntryForOldOpenLib = (unsigned long *)OpenLibVectorPtr[0];
XOldOldOpenLibVector = (unsigned long *)(((char *)EntryForOldOpenLib) + 0x12);
X
Xif (EntryForOldOpenLib[0] == 0x2f3a0010)
X        {
X        OpenLibVectorPtr[0] = OldOldOpenLibVector[0];
X        ExecBase->KickTagPtr = 0;
X        MyRequest(VN_IRQ, 2);
X        };
X}
X
X
X/********************************/
X
XCheckDriveForIRQ(drivename)
Xchar *drivename;
X{
Xint err;
Xchar buffer[80];
Xchar dirbuffer[80];
Xchar filebuffer[100];
Xchar tempbuffer[100];
Xchar FoundInDir;
Xchar FoundInFname;
Xchar chr;
Xint index;
Xchar pass;
X
XFoundInDir = FALSE;
XFoundInFname = FALSE;
Xfilebuffer[0] = 0;
X
Xpass = 0;
X
Xsprintf(dirbuffer, "%sC/DIR", drivename);
Xerr = CheckFileForIRQ(dirbuffer,0);
Xif (err == 1)
X        {
X        IRQFound++;
X        FoundInDir = TRUE;
X        }
X        else dirbuffer[0] = 0;
X
X
Xindex = 0;
X
Xsprintf(tempbuffer, "%ss/Startup-Sequence", drivename);
Xfp = Open(tempbuffer, MODE_OLDFILE);
Xif (fp == 0)
X        filebuffer[0] = 0;
X        else
X        {
X        while (TRUE)
X                {
X                err = Read(fp, &chr, 1);
X                if (err == 0) break;
X                if ((chr == 34) || (chr == 0x0a) || (chr == ';') || (chr == ' ')) continue;
X                break;
X                };
X
X        if (err != 0)
X                {
X                while (TRUE)
X                        {
X                        filebuffer[index++] = chr;
X                        filebuffer[index] = 0;
X                        err = Read(fp, &chr, 1);
X                        if (err == 0) break;
X                        if (chr == 34) break;
X                        if (chr == 0x0a) break;
X                        if (chr == ';') break;
X                        if (chr == 32) break;
X                        };
X                };
X
X        Close(fp);
X
X        sprintf(buffer, "%s%s", drivename, filebuffer);
X
X        err = CheckFileForIRQ(buffer, 0);
X        if (err == -1)
X                {
X                sprintf(buffer, "C:%s", filebuffer);
X                err = CheckFileForIRQ(buffer, 0);
X                };
X
X        strcpy(filebuffer, buffer);
X
X        if (err == 1)
X                {
X                FoundInFname = TRUE;
X                IRQFound++;
X                }
X                else filebuffer[0] = 0;
X        };
X
Xif (FoundInDir == FALSE && FoundInFname == FALSE) return(0);
X
XWBenchToFront();
Xfp = Open("CON:70/20/500/100/VirusX", MODE_NEWFILE);
Xif (fp == 0) return(0);
X
XWriteFP(fp, "NOTICE:  The IRQ Virus was found on volume ");
XWriteFP(fp, drivename);
XWriteFP(fp, "\n");
X
Xwhile (TRUE)
X        {
X        if (pass == 0)
X                {
X                strcpy(tempbuffer, dirbuffer);
X                }
X        else if (pass == 1)
X                {
X                strcpy(tempbuffer, filebuffer);
X                }
X        else if (pass == 2) break;
X
X        pass++;
X
X        if (tempbuffer[0] == 0) continue;
X
X        sprintf(buffer, "\nIn the command: %s\n", tempbuffer);
X        WriteFP(fp, buffer);
X        WriteFP(fp, "Okay to remove it? [Y]: ");
X        Read(fp, buffer, 3);
X        if (toupper(buffer[0]) == 'Y')
X                {
X                err = CheckFileForIRQ(tempbuffer, 1);
X                if (err == 1)
X                        {
X                        WriteFP(fp, "Virus removed.\n");
X                        } else
X                        {
X                        WriteFP(fp, "Error removing virus.  Check file.\n");
X                        }
X                };
X        };
X
XWriteFP(fp, "\nHit RETURN to continue...");
XRead(fp, buffer, 3);
XClose(fp);
X}
X
XWriteFP(fp, string)
Xint fp;
Xchar *string;
X{
XWrite(fp, string, strlen(string));
X}
X
X/********************************/
X
X#define VTAG     0x00000109L
X#define BEGIN    OFFSET_BEGINNING
X#define END              OFFSET_END
X#define OLD              MODE_OLDFILE
X#define NEW              MODE_NEWFILE
X#define SLONG    ((long)sizeof(long))
X#define OK        1                     /* no error */
X
X#define NOFILE   -1                     /* can't find file */
X#define SEEKERR  -2                     /* seek error on file */
X#define ALLOCERR -3                     /* can't allocate memory */
X#define READERR  -4                     /* error reading file */
X#define VIRUSNF  -5                     /* virus not found in file */
X#define WRITERR  -6                     /* error writing to file */
X#define OPENERR  -7                     /* error opening file for write */
X#define NOTEXE   -8                     /* not an executable file */
X
X#define GOTHIM   OK                     /* removed virus from file */
X
X#define VTAG     0x00000109L            /* virus hunk length */
X#define VSIG1    0x0000FFFEL            /* part of virus signature */
X#define VSIG2    0x61000000L            /* part of virus signature */
X
X
Xstatic long inp, *buff, size;
X
Xcleanup(val)
Xint val;
X{
X        if(inp)         Close(inp);
X        if(buff)        FreeMem(buff,size);
X        return val;
X}
X
XCheckFileForIRQ(fname, flag)
Xchar *fname;
Xint flag;
X{
X
X        int   i = 0;
X        long  nhunk;
X        long tbuff[488/4];
X
X        inp = 0L;  buff = 0L;
X
X        if((inp = Open(fname,OLD)) == 0)        /* open the desired file */
X                return NOFILE;
X
X        Read(inp,(char *)&tbuff[0],487);                                /* get the first long word */
X        if(tbuff[0] != 0x000003F3)                              /* check for executable file */
X                return cleanup(NOTEXE);
X
X        if(tbuff[5] != VTAG)
X                return cleanup(VIRUSNF);
X
X        Seek(inp,0L,END);                               /* seek to end of file */
X        size = Seek(inp,0L,BEGIN);              /* rewind the file to get size */
X        if(size <= 0L)
X                return cleanup(SEEKERR);
X
X        if((buff = AllocMem(size,0L)) == 0)     /* mem buffer for file */
X                return cleanup(ALLOCERR);
X
X        if(Read(inp,(char *)&buff[0],size) != size)     /* read entire file into buffer */
X                return cleanup(READERR);
X
X        nhunk = buff[ 2 ];              /* number of hunks in file */
X
X/*
X        the IRQ virus inserts his code as the first hunk in the file
X        we can find the first hunk in the 6th longword of the file
X*/
X        /* find the start of the virus hunk */
X        while(buff[ i++ ] != 0x000003E9)
X                ;
X/*
X        The virus checks the first hunk for it's signature to prevent
X         reinfecting an already infected program.  It actually checks for
X        0xFFFE6100 which is the lower half of a move.m instruction and
X        the upper half of a bsr instruction.  Here we do the same.
X    i points to the virus code hunk length.
X*/
X        if( ((buff[ i+1 ] & 0x0000FFFF) != VSIG1)
X     || ((buff[ i+2 ] & 0xFFFF0000) != VSIG2) )
X                return cleanup(VIRUSNF);
X
X        if (flag == 0)
X                return cleanup(1);
X
X/*
X        close the file and reopen it with write access
X        mode NEW will effectivly delete the old file contents so if a
X        file error occurs before we finish, the file will be corrupt
X*/
X        Close(inp);
X        if((inp = Open(fname,NEW)) == 0)
X                return cleanup(OPENERR);
X
X        buff[2] -= 1;   buff[4] -= 1;   /* readjust program header info */
X
X/* write new header */
X        if(Write(inp,(char *)&buff[0],5L*SLONG) != 5L*SLONG)
X                return cleanup(WRITERR);
X
X        if(Write(inp,(char *)&buff[6],nhunk*SLONG) != nhunk*SLONG)
X                return cleanup(WRITERR);
X
X/*
X        subtract length of virus hunk and overhead from file size
X        i was calculated earlier
X*/
X        i = i + 8L + VTAG;
X        size = (size/SLONG - i)*SLONG;
X
X/* and write old code out to file, ignoring virus hunk */
X        if(Write(inp,(char *)&buff[i],size) != size)
X                return cleanup(WRITERR);
X
X/* we're done, the file is clean and intact */
X        return cleanup(GOTHIM);
X}
SHAR_EOF
echo "extracting virusx.i"
sed 's/^X//' << \SHAR_EOF > virusx.i
X/* Prototypes for functions defined in virusx.c */
Xvoid MemCleanup(void);
Xint __regargs sprintf(unsigned char *buf,
X                      unsigned char *ctl,
X                      unsigned char *args);
Xvoid __regargs prbuf(unsigned char c);
Xvoid main(int argc,
X          unsigned char **argv);
Xint DoLittle(void);
Xint SetUp(void);
Xint WhoChanged(void);
Xint CheckBlock(void);
Xint DoInstall(int un);
Xint CheckMemoryForViruses(void);
Xint ShowAscii(int key);
Xint WaitForNewSize(void);
Xint BuildITBodyText(unsigned char *text,
X                    int type);
Xint MyRequest(unsigned char *string,
X              int type);
Xint DoStats(void);
Xint PV(int num,
X       unsigned char *name,
X       int howmany);
Xint Out(int num,
X        unsigned char *name);
Xint ReadBlock(void);
Xint CheckMemoryForIRQVirus(void);
Xint CheckDriveForIRQ(unsigned char *drivename);
Xint WriteFP(int fp,
X            unsigned char *string);
Xint cleanup(int val);
Xint CheckFileForIRQ(unsigned char *fname,
X                    int flag);
SHAR_EOF
echo "End of archive 1 (of 1)"
# if you want to concatenate archives, remove anything after this line
exit