home *** CD-ROM | disk | FTP | other *** search
- //
- // UsageLogger is a small faceless background application for system 7.
- // When run it logs application usage.
- //
- // Based on cSmallDaemon, 7/92 Greg Robbins, based on code by C.K. Haun
- //
- #include <Types.h>
- #include <QuickDraw.h>
- #include <ToolUtils.h>
- #include <AppleEvents.h>
- #include <GestaltEqu.h>
- #include <Processes.h>
- #include <Folders.h>
- #include <Files.h>
- #include <Packages.h>
- #include <Script.h>
-
- #include "UsageLogger.h"
- //
- // Globals:
- //
- // 150 ticks is about 2.5 seconds
- //
- const long gSleepVal = 150;
-
- const int gFlush_interval = 100;
- //
- // Apple event handlers to be installed
- //
- pascal OSErr DoAEOpenApplication(
- AppleEvent *theAppleEvent, AppleEvent *replyAppleEvent, long refCon)
- {
- #pragma unused( theAppleEvent, replyAppleEvent, refCon)
- return noErr;
- }
-
- pascal OSErr UnhandledAEvent(
- AppleEvent *theAppleEvent, AppleEvent *replyAppleEvent, long refCon)
- {
- #pragma unused( theAppleEvent, replyAppleEvent, refCon)
- return errAEEventNotHandled;
- }
-
- pascal OSErr DoAEQuitApplication(
- AppleEvent *theAppleEvent, AppleEvent *replyAppleEvent, long refCon)
- {
- #pragma unused( theAppleEvent, replyAppleEvent)
- *(Boolean *)refCon = true;
- return noErr;
- }
-
- pascal OSErr DoAELogText(
- AppleEvent *theAppleEvent, AppleEvent *replyAppleEvent, long refCon)
- {
- OSErr result;
- unsigned long now;
- long theSize;
- AEDesc theDesc;
-
- #pragma unused( replyAppleEvent)
-
- result = AEGetParamDesc( theAppleEvent, keyDirectObject, typeChar, &theDesc);
-
- if( result == noErr)
- {
- GetDateTime( &now);
- basicTimeStamp( refCon, 'Log:', now);
-
- theSize = GetHandleSize( theDesc.dataHandle);
-
- if( theSize != 0)
- {
- writeATab( refCon);
- HLock( theDesc.dataHandle);
- FSWrite( refCon, &theSize, *theDesc.dataHandle);
- }
- AEDisposeDesc( &theDesc);
- writeAReturn( refCon);
- }
- return result;
- }
-
- pascal OSErr DoAEFlushLog(
- AppleEvent *theAppleEvent, AppleEvent *replyAppleEvent, long refCon)
- {
- #pragma unused( theAppleEvent, replyAppleEvent)
- return FlushVol( 0, refCon);
- }
-
- OSErr InitAppleEventsStuff( Boolean *quitFlag, long foundVRefnum, short theFile)
- {
- OSErr result;
-
- result =
- AEInstallEventHandler( kCoreEventClass, kAEOpenApplication,
- (AEEventHandlerUPP) DoAEOpenApplication, 0, false)
-
- || AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments,
- (AEEventHandlerUPP) DoAEOpenDocuments, 0, false)
-
- || AEInstallEventHandler( kCoreEventClass, kAEPrintDocuments,
- (AEEventHandlerUPP) DoAEPrintDocuments, 0, false)
-
- || AEInstallEventHandler( kCoreEventClass, kAEQuitApplication,
- (AEEventHandlerUPP) DoAEQuitApplication, (long)quitFlag, false)
-
- || AEInstallEventHandler( 'Log:', 'flsh',
- (AEEventHandlerUPP) DoAEFlushLog, (long)foundVRefnum, false)
-
- || AEInstallEventHandler( 'Log:', 'log ',
- (AEEventHandlerUPP) DoAELogText, (long)theFile, false);
- return result;
- }
-
- void main( void)
- {
- OSErr retCode;
- long gestResponse;
-
- EventRecord mainEventRec;
- Boolean eventFlag;
-
- ProcessSerialNumber lastProcessSeen;
-
- int to_go_till_flush = gFlush_interval;
- long foundDirID;
- short foundVRefnum;
- short theFile;
- Boolean quitFlag = false;
-
- Handle configResource = Get1Resource( 'pref', 128);
- const config *theConfig = (config *)*configResource;
- //
- // faceless background apps only get a 2K stack by default. If necessary,
- // increase the stack size here (by calling GetApplLimit to find the current
- // heap limit, and SetApplLimit to set it to a lower address, thus reserving
- // more space for the stack)
- //
- InitGraf( &qd.thePort);
- //
- // is the Apple Event Manager available?
- //
- retCode = Gestalt( gestaltAppleEventsAttr, &gestResponse);
-
- if( (retCode != noErr) ||
- (gestResponse & (1 << gestaltAppleEventsPresent)) == 0)
- {
- NotifyUserAndQuit( needsAppleEvents);
- }
- if( FindFolder( kOnSystemDisk, theConfig->prefsFolderType,
- kCreateFolder, &foundVRefnum, &foundDirID) == noErr)
- {
- FSSpec theFileSpec;
- OSErr foutje = FSMakeFSSpec( foundVRefnum, foundDirID,
- (ConstStr255Param)*Get1Resource( 'STR ', logFileName), &theFileSpec);
- if( (foutje == noErr) || (foutje == fnfErr))
- {
- (void)FSpCreate( &theFileSpec,
- theConfig->logFileCreator, 'TEXT', smSystemScript);
- if( FSpOpenDF( &theFileSpec, fsWrPerm, &theFile) != noErr)
- {
- NotifyUserAndQuit( outputFileOpenError);
- }
- } else {
- NotifyUserAndQuit( couldNotSetDirectory);
- }
- } else {
- NotifyUserAndQuit( couldNotSetDirectory);
- }
-
- (void)SetFPos( theFile, fsFromLEOF, 0L);
-
- TimeStamp( theFile, 'strt');
- //
- // install Apple event handlers
- //
- if( InitAppleEventsStuff( &quitFlag, foundVRefnum, theFile) != noErr)
- {
- NotifyUserAndQuit( handlerInstallFailed);
- }
- //
- // main event loop
- //
- if( GetCurrentProcess( &lastProcessSeen) != noErr)
- {
- quitFlag = true;
- }
- while( !quitFlag)
- {
- ProcessSerialNumber frontProcess;
- Boolean result;
-
- eventFlag = WaitNextEvent( everyEvent, &mainEventRec, gSleepVal, nil);
-
- if( mainEventRec.what == kHighLevelEvent)
- {
- (void)AEProcessAppleEvent( &mainEventRec);
- }
-
- if( (GetFrontProcess( &frontProcess) == noErr)
- && (SameProcess( &lastProcessSeen, &frontProcess, &result) == noErr)
- && !result)
- {
- ProcessInfoRec the_info;
- unsigned char processNamebuf[ 32];
- FSSpec processFSSpec;
-
- the_info.processInfoLength = sizeof( ProcessInfoRec);
- the_info.processName = (StringPtr)processNamebuf;
- the_info.processAppSpec = &processFSSpec;
-
- lastProcessSeen = frontProcess;
- //
- // different process:
- //
- if( GetProcessInformation( &frontProcess, &the_info) == noErr)
- {
- long count = 4;
- TimeStamp( theFile, the_info.processSignature);
-
- to_go_till_flush -= 1;
-
- if( to_go_till_flush <= 0)
- {
- to_go_till_flush = gFlush_interval;
- (void)FlushVol( 0, foundVRefnum);
- }
- }
- }
- }
- TimeStamp( theFile, 'stop');
- TimeStamp( theFile, '????'); // flushes the 'cache' maintained by TimeStamp
- (void)FSClose( theFile);
- (void)FlushVol( 0, foundVRefnum);
- ExitToShell();
- }
-
- void basicTimeStamp( short theFile, OSType theType, long now)
- {
- Str255 thestring;
- long size;
-
- IUDateString( now, shortDate, thestring);
- writePString( theFile, thestring);
-
- writeATab( theFile);
-
- IUTimeString( now, true, thestring);
- writePString( theFile, thestring);
-
- writeATab( theFile);
-
- size = 4;
- (void)FSWrite( theFile, &size, &theType);
- }
-
- void TimeStamp( short theFile, OSType theType)
- {
- static TimeStampInfo theInfo =
- {
- 0L, // unsigned long starting_time;
- '????', // OSType theType;
- 0, // short theFile;
- };
- //
- // First log the previous entry, if there was one:
- //
- unsigned long now;
- GetDateTime( &now);
-
- if( theInfo.theFile != 0)
- {
- Str255 thestring;
- long size;
- long numseconds = now - theInfo.starting_time;
-
- basicTimeStamp( theInfo.theFile, theInfo.theType, theInfo.starting_time);
-
- writeATab( theInfo.theFile);
-
- NumToString( numseconds, thestring);
- writePString( theInfo.theFile, thestring);
-
- writeAReturn( theInfo.theFile);
- }
- //
- // Then update the record
- //
- theInfo.starting_time = now;
- theInfo.theType = theType;
- theInfo.theFile = theFile;
- }
-
- void NotifyUserAndQuit( const short messageno)
- {
- NMRec the_note;
-
- the_note.qType = nmType;
- the_note.nmMark = 0;
- the_note.nmIcon = 0L;
- the_note.nmSound = 0L;
- the_note.nmStr = *GetString( messageno); // resource must be locked!!
- the_note.nmResp = myResponse;
- the_note.nmRefCon = false;
-
- if( NMInstall( &the_note) == noErr)
- {
- while( the_note.nmRefCon == false)
- {
- EventRecord junk;
- (void)WaitNextEvent( 0, &junk, gSleepVal, nil);
- }
- } else {
- SysBeep( 9);
- }
- ExitToShell();
- }
-
- pascal void myResponse( NMRecPtr theNMRec)
- {
- theNMRec->nmRefCon = true;
- (void)NMRemove( theNMRec);
- }
-
- OSErr writeChar( short theFile, char theletter)
- {
- long one = 1;
- return FSWrite( theFile, &one, &theletter);
- }
-
- OSErr writePString( short theFile, StringPtr string)
- {
- long length = string[ 0];
-
- return FSWrite( theFile, &length, &string[ 1]);
- }
-