/*ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ*/ /*Ý Þ*/ /*Ý DOWNSERV NLM Þ*/ /*Ý Þ*/ /*Ý NetWare Loadable Module to schedule shutdown of a NetWare 386 Þ*/ /*Ý file server at a later time. Þ*/ /*Ý Þ*/ /*Ý written by: Morgan Adair Þ*/ /*Ý date: 15 July 1991 Þ*/ /*Ý Þ*/ /*ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß*/ #include #include #include #include #include #define DELAY_AMOUNT 9 #define TIME_FOR_FIRST_WARNING 10 #define TIME_FOR_SECOND_WARNING 5 LONG AESEventTag; struct AESProcessStructure ClockEvent, WarningEvent1, WarningEvent2, ShutdownEvent; LONG MyNLMHandle; int myThreadID; int timeRemaining = -1; int shutdownTime = FALSE; int firstTry = TRUE; void Usage(void); LONG TimeToTicks(char *timeIn); void WakeUp(void); void SetTimeRemaining(void); void SetShutdownFlag(void); void ExitProcedure(void); void ShutdownServer(void); void WarnUsers(void); void main(int argc, char *argv[]) { time_t currentTime; char timeBuf[30]; LONG nTicks; LONG warningTimeInTicks; int ccode; if (argc != 2) { printf("Incorrect number of command line parameters\n"); Usage(); exit(-1); } SecondsToTicks((TIME_FOR_FIRST_WARNING * 60L), 0L, &warningTimeInTicks); nTicks = TimeToTicks(argv[1]); if (nTicks == -1L) { printf("Invalid time entered"); exit(-1); } else if (nTicks < warningTimeInTicks) { printf("Shutdown time must be more than %d minutes away", TIME_FOR_FIRST_WARNING); exit(-1); } myThreadID = GetThreadID(); MyNLMHandle = GetNLMHandle(); /* AES Event Resource Tag */ AESEventTag = AllocateResourceTag(MyNLMHandle, (BYTE *)"AES Events", AESProcessSignature); if (AESEventTag == NULL) { printf("Unable to get AES Event resource tag\n"); exit(-1); } /* Register exit procedure to return AES Event Resource Tag */ if (atexit(ExitProcedure) == EFAILURE) { printf("Unable to register exit procedure:\n"); printf(" AES Events resources will not be released when NLM is unloaded\n"); } /* Initialize AESProcessStructure for screen clock */ ClockEvent.AWakeUpDelayAmount = DELAY_AMOUNT; ClockEvent.AProcessToCall = WakeUp; ClockEvent.ARTag = AESEventTag; /* Initialize AESProcessStructure for first warning */ WarningEvent1.AWakeUpDelayAmount = nTicks - warningTimeInTicks; WarningEvent1.AProcessToCall = SetTimeRemaining; WarningEvent1.ARTag = AESEventTag; /* Schedule first warning */ ScheduleSleepAESProcessEvent(&WarningEvent1); SecondsToTicks((TIME_FOR_SECOND_WARNING * 60L), 0L, &warningTimeInTicks); /* Initialize AESProcessStructure for second warning */ WarningEvent2.AWakeUpDelayAmount = nTicks - warningTimeInTicks; WarningEvent2.AProcessToCall = SetTimeRemaining; WarningEvent2.ARTag = AESEventTag; /* Schedule second warning */ ScheduleSleepAESProcessEvent(&WarningEvent2); /* Initialize AESProcessStructure for shutdown procedure */ ShutdownEvent.AWakeUpDelayAmount = nTicks; ShutdownEvent.AProcessToCall = SetShutdownFlag; ShutdownEvent.ARTag = AESEventTag; /* Schedule shutdown */ ScheduleSleepAESProcessEvent(&ShutdownEvent); HideInputCursor(); gotoxy(10, 10); printf("Server shutdown scheduled for: %s:00", argv[1]); do { /* Get the time */ currentTime = time(NULL); if (!currentTime) printf("Unable to get current time\n"); else { /* Display time */ strftime(timeBuf, 28, "%H:%M:%S (%I:%M:%S %p)", localtime(¤tTime)); gotoxy(27, 12); printf( "Current time: %s", timeBuf); } /* Check flags and take appropriate actions */ if ((timeRemaining == TIME_FOR_FIRST_WARNING) || (timeRemaining == TIME_FOR_SECOND_WARNING) || (timeRemaining == 0)) WarnUsers(); if (shutdownTime == TRUE) ShutdownServer(); /* Schedule a wakeup call */ ScheduleSleepAESProcessEvent(&ClockEvent); /* Go to sleep */ ccode = SuspendThread(myThreadID); if (ccode != ESUCCESS) printf("Suspend thread failed, ccode = %d\r\n", ccode); } while (1); } void Usage (void) { ConsolePrintf("DOWNSERV: Schedule server shutdown\n"); ConsolePrintf("Usage: load downserv \n"); ConsolePrintf("Uses 24-hour clock (22:30 = 10:30 pm)\n"); } LONG TimeToTicks(char *timeIn) { char hourStr[3]; char minStr[3]; int hour, min; LONG nSec; LONG nTicks; time_t timeInSec; struct tm *currentTime; if ((strlen(timeIn) < 4) || (strlen(timeIn) > 5)) { printf("Invalid time specification\n"); Usage(); exit(-1); } if (strlen(timeIn) == 4) { if (timeIn[1] != ':') { printf("Missing ':' in time specification\n"); return((LONG)-1L); } hourStr[0] = timeIn[0]; hourStr[1] = '\0'; minStr[0] = timeIn[2]; minStr[1] = timeIn[3]; minStr[2] = '\0'; } else { if (timeIn[2] != ':') { printf("Missing ':' in time specification\n"); return((LONG)-1L); } hourStr[0] = timeIn[0]; hourStr[1] = timeIn[1]; hourStr[2] = '\0'; minStr[0] = timeIn[3]; minStr[1] = timeIn[4]; minStr[2] = '\0'; } hour = atoi(hourStr); min = atoi(minStr); if ((hour > 23) || (min > 59)) { printf("Hour must be 0-23 and minutes must be 0-59\n"); return((LONG)-1L); } timeInSec = time(NULL); currentTime = localtime(&timeInSec); if ((*currentTime).tm_hour > hour) hour = 24 - (*currentTime).tm_hour + hour; else hour = hour - (*currentTime).tm_hour; nSec = 3600 * hour; nSec = nSec + (60 * min); nSec = nSec - (60 * (*currentTime).tm_min); SecondsToTicks(nSec, 0L, &nTicks); return(nTicks); } void WakeUp(void) { int ccode; ccode = ResumeThread(myThreadID); if (ccode != ESUCCESS) ConsolePrintf("DOWNSERV: ResumeThread failed, ccode = %d\r\n", ccode); } void ExitProcedure(void) { CancelSleepAESProcessEvent(&ClockEvent); CancelSleepAESProcessEvent(&WarningEvent1); CancelSleepAESProcessEvent(&WarningEvent2); CancelSleepAESProcessEvent(&ShutdownEvent); } void SetTimeRemaining(void) { if (timeRemaining == -1) timeRemaining = TIME_FOR_FIRST_WARNING; else if (timeRemaining == TIME_FOR_FIRST_WARNING - 1) timeRemaining = TIME_FOR_SECOND_WARNING; else timeRemaining = 0; } void SetShutdownFlag(void) { shutdownTime = TRUE; } void WarnUsers(void) { int ccode; char serverName[49]; char buffer[80]; GetFileServerName(0, serverName); sprintf(buffer, "%s shutting down in %d min", serverName, timeRemaining); ConsolePrintf("DOWNSERV NLM: Server shutdown in %d minutes\n", timeRemaining); gotoxy(20,15); if (timeRemaining == TIME_FOR_FIRST_WARNING) printf("STATUS: Broadcasting first server shutdown warning"); else if (timeRemaining == TIME_FOR_SECOND_WARNING) printf("STATUS: Broadcasting second server shutdown warning"); /* Send warning to all connected stations */ ccode = SendConsoleBroadcast(buffer, 0, (WORD *)NULL); if (ccode != ESUCCESS) { gotoxy(20,15); printf("STATUS: Unable to notify connections of server shutdown. ccode = %x\n", ccode); } timeRemaining--; } void ShutdownServer(void) { char serverName[49]; char buffer[80]; int ccode; LONG oneMinInTicks; /* Clear old status messages, if any */ gotoxy(20,15); printf("\n\n"); /* Do not force server to shut down if files are open */ if (firstTry) { ccode = DownFileServer(0); firstTry = FALSE; if (ccode == ESUCCESS) exit(0); else { shutdownTime = FALSE; gotoxy(20,15); printf("STATUS: Files open--can't shut down. ccode = %x. Force shutdown in 1 minute.\n", ccode); SecondsToTicks(60L, 0L, &oneMinInTicks); /* Reset time in AESProcessStructure for shutdown procedure */ ShutdownEvent.AWakeUpDelayAmount = oneMinInTicks; /* Reschedule shutdown */ ScheduleSleepAESProcessEvent(&ShutdownEvent); /* Send warning to all connected stations */ sprintf(buffer, "%s shutting down. Logout now.", serverName); ccode = SendConsoleBroadcast(buffer, 0, (WORD *)NULL); if (ccode != ESUCCESS) printf("Unable to notify connections of server shutdown. ccode = %x\n", ccode); } } else { ccode = DownFileServer(1); if (ccode == ESUCCESS) exit(0); else { gotoxy(20,15); printf("STATUS: Unable to shut down. ccode = %xh.\n", ccode); } } }