//================================================ file = idleCollect.c ===== //= Program to collect idle time data for a Windows PC = //= - Logs idle/busy/sleep by minute = //=========================================================================== //= Notes: = //= 1) Output is to OUT_FILE = //= 2) Single command-line argument is number of hours to monitor for = //=-------------------------------------------------------------------------= //= Example execution (data from OUT_FILE): = //= = //= ---------------------------------------------------------- = //= - This is the output file from idleCollect. Data is - = //= - collected once per minute. Output data is '0' for no - = //= - user keyboard or mouse activity in the last minute, - = //= - '1' for activity, and 'X' for system in sleep mode. - = //= ---------------------------------------------------------- = //= Collecting data for 1 hours = //= Program start time = Sun Jul 15 22:36:32 2007 = //= Data collection start time = Sun Jul 15 23:00:00 2007 = //= ---------------------------------------------------------- = //= 11111111111111111111111111XXXXXXXXX10000011XXXXXX11111111111 : Mon = //= Jul 16 00:00:00 2007 = //=-------------------------------------------------------------------------= //= Build: bcc32 idleCollect.c (must use Borland 5.5, 5.2 will not work) = //=-------------------------------------------------------------------------= //= Execute: idleCollect number_of_days = //=-------------------------------------------------------------------------= //= Author: Ken Christensen = //= University of South Florida = //= WWW: http://www.csee.usf.edu/~christen = //= Email: christen@csee.usf.edu = //=-------------------------------------------------------------------------= //= History: KJC (07/22/07) - Genesis = //= KJC (02/18/08) - Minor clean-up = //=========================================================================== //----- Include files ------------------------------------------------------- #include // Needed for printf() #include // Needed for atoi() #include // Needed for time stuff #include // Needed for Sleep() //----- Defines ------------------------------------------------------------- #define FALSE 0 // Boolean false #define TRUE 1 // Boolean true #define OUT_FILE "idleData.txt" // Output file name //----- Defines ------------------------------------------------------------- int NumHoursMonitor; // Number of hours to monitor for //----- Function prototypes ------------------------------------------------- int testBusy(void); void sleepTime(time_t timeNow, time_t timeLast, int *sampleCount, FILE *fp); //=========================================================================== //= Main program = //=========================================================================== int main(int argc, char *argv[]) { FILE *fp; // File pointer for output file struct tm *tblock; // Structure for time block time_t timeNow; // Current sample time time_t timeLast; // Last sample time int sample; // Busy/idle sample int sampleCount; // Counter for samples int i; // Loop counter // Grab the command line argument for number of hours to monitor for if (argc == 2) { NumHoursMonitor = atoi(argv[1]) * 24; if (NumHoursMonitor <= 0) { printf("*** ERROR - number of days = %d and is invalid \n", atoi(argv[1])); return -1; } } else { printf("Usage: 'idleCollect numHours' where numHours is the number of \n"); printf(" hours to monitor for. Output is in 'idleData.txt'. \n"); return -1; } // Open the output file in append mode fp = fopen(OUT_FILE, "a"); if (fp == NULL) { printf("*** ERROR - fopen() of %s failed \n", OUT_FILE); return -1; } // Output explanatory banner fprintf(fp,"---------------------------------------------------------- \n"); fprintf(fp,"- This is the output file from idleCollect. Data is - \n"); fprintf(fp,"- collected once per minute. Output data is '0' for no - \n"); fprintf(fp,"- user keyboard or mouse activity in the last minute, - \n"); fprintf(fp,"- '1' for activity, and 'X' for system in sleep mode. - \n"); fprintf(fp,"- Output is written to file 'idleData.txt'. - \n"); fprintf(fp,"---------------------------------------------------------- \n"); fprintf(fp,"Collecting data for %d hours \n", NumHoursMonitor); fflush(fp); // Get and output program start time timeNow = time(NULL); tblock = localtime(&timeNow); fprintf(fp, "Program start time = %s", asctime(tblock)); fflush(fp); // Synchronize to next top-of-the-hour timeNow = time(NULL); tblock = localtime(&timeNow); while(tblock->tm_min < 59) { Sleep(500); timeNow = time(NULL); tblock = localtime(&timeNow); } while(tblock->tm_min == 59) { Sleep(10); timeNow = time(NULL); tblock = localtime(&timeNow); } // Output data collection start time fprintf(fp, "Data collection start time = %s", asctime(tblock)); fprintf(fp,"---------------------------------------------------------- \n"); fflush(fp); // *** Main loop for data collection *** sampleCount = 0; timeLast = time(NULL); while(NumHoursMonitor > 0) { // Sleep for 59 seconds Sleep(59000); // Synchronize to next top-of-the-minute timeNow = time(NULL); tblock = localtime(&timeNow); while (tblock->tm_sec != 0) { Sleep(10); timeNow = time(NULL); tblock = localtime(&timeNow); } // If negative time has passed then something is wrong and we abort if (difftime(timeNow, timeLast) < 0.0) { fprintf(fp, "*** ERROR - negative difftime at = %s \n", asctime(tblock)); fflush(fp); fclose(fp); return -1; } // If more than one minute has passed then we have been sleeping if (difftime(timeNow, timeLast) > 60.0) { sleepTime(timeNow, timeLast, &sampleCount, fp); timeLast = timeNow; continue; } timeLast = timeNow; // Get busy status, output it, and increment sampleCount sample = testBusy(); fprintf(fp, "%d", sample); fflush(fp); sampleCount++; // After 60 samples clear sampleCount and output timestamp if (sampleCount >= 60) { // Set sampleCount to zero sampleCount = 0; // Output timestamp fprintf(fp, " : %s", asctime(tblock)); fflush(fp); // Decrement NumHoursMonitor NumHoursMonitor = NumHoursMonitor - 1; // Synchronize to top-of-the-hour if somehow have slipped timeNow = time(NULL); tblock = localtime(&timeNow); while (tblock->tm_min != 0) { Sleep(100); timeNow = time(NULL); tblock = localtime(&timeNow); } } } // Output completed message, close the file pointer, and return fprintf(fp,"--- Monitoring completed --- \n"); fclose(fp); return 1; } //=========================================================================== //= Function to test if busy = //= - Returns true if keyboard or mouse activity detected since last test = //=========================================================================== int testBusy(void) { LASTINPUTINFO lii; // Structure for Windows time stuff static long int newTicks; // Time value for new ticks static long int lastTicks; // Time value for last ticks int busyFlag; // Flag for idle since last test // Set size of lii.cbsize lii.cbSize = sizeof(lii); // Get the time of the most recent (new) user activity GetLastInputInfo(&lii); newTicks = lii.dwTime; // Test if any user activity since last test and set busyFlag accordingly if (newTicks > lastTicks) busyFlag = TRUE; else busyFlag = FALSE; // Assign lastTicks to newTicks lastTicks = newTicks; // Return busyFlag return(busyFlag); } //=========================================================================== //= Function to handle any time detected as sleeping = //= - Outputs sleep samples and adjusts sampleCount as needed = //=========================================================================== void sleepTime(time_t timeNow, time_t timeLast, int *sampleCount, FILE *fp) { int numMinutes; // Calculated number of minutes for sleeping int numHours; // Calculated number of hours for sleeping int fillCount; // Calculated number of fill minutes int i, j; // Loop counters // Determine number of minutes that we have been sleeping numMinutes = ((int) difftime(timeNow, timeLast)) / 60; // Handle simple case of sleep does not cross an hour boundary if ((*sampleCount + numMinutes) < 60) { // Output numMinutes X's for (i=0; i