Exemplo n.º 1
0
int Disconnected (Stream)
{
	struct UserInfo * user = NULL;
	ChatCIRCUIT * conn;
	int n;
	char Msg[255];
	int len;
	struct _EXCEPTION_POINTERS exinfo;

	for (n = 0; n <= NumberofChatStreams-1; n++)
	{
		conn=&ChatConnections[n];

		if (Stream == conn->BPQStream)
		{
			if (conn->Active == FALSE)
			{
				return 0;
			}

			ChatClearQueue(conn);

			conn->Active = FALSE;
			RefreshMainWindow();

			if (conn->Flags & CHATMODE)
			{
				if (conn->Flags & CHATLINK)
				{
					len=sprintf_s(Msg, sizeof(Msg), "Chat Node %s Disconnected", conn->u.link->call);
					WriteLogLine(conn, '|',Msg, len, LOG_CHAT);
					__try {link_drop(conn);} My__except_Routine("link_drop");
				}
				else
				{
					len=sprintf_s(Msg, sizeof(Msg), "Chat User %s Disconnected", conn->Callsign);
					WriteLogLine(conn, '|',Msg, len, LOG_CHAT);
					__try
					{
						logout(conn);
					}
					#define EXCEPTMSG "logout"
					#include "StdExcept.c"
					}
				}

				conn->Flags = 0;
				conn->u.link = NULL;
				conn->UserPointer = NULL;	
				return 0;
			}
Exemplo n.º 2
0
void Logger::WriteLogLine(std::string LogLine) { WriteLogLine(LogLine, false); }
Exemplo n.º 3
0
void ParseMemBus(void)
{ /*This function handles EVERYTHING passed to us via membus. It's truly vast.*/
#define BusDataIs(x) !strncmp(x, BusData, strlen(x))
	char BusData[MEMBUS_MSGSIZE];

	if (!BusRunning) return;
	
	if (!MemBus_Read(BusData, true))
	{
		return;
	}
	
	/*If we got a signal over the membus.*/
	if (BusDataIs(MEMBUS_CODE_RESET))
	{
		if (ReloadConfig())
		{
			MemBus_Write(MEMBUS_CODE_ACKNOWLEDGED " " MEMBUS_CODE_RESET, true);
		}
		else
		{
			MemBus_Write(MEMBUS_CODE_FAILURE " " MEMBUS_CODE_RESET, true);
		}
	}
	else if (BusDataIs(MEMBUS_CODE_OBJSTART) || BusDataIs(MEMBUS_CODE_OBJSTOP))
	{
		unsigned LOffset = strlen((BusDataIs(MEMBUS_CODE_OBJSTART) ? MEMBUS_CODE_OBJSTART " " : MEMBUS_CODE_OBJSTOP " "));
		char *TWorker = BusData + LOffset;
		ObjTable *CurObj = LookupObjectInTable(TWorker);
		char TmpBuf[MEMBUS_MSGSIZE], *MCode = MEMBUS_CODE_FAILURE;
		ReturnCode DidWork;
		
		if (LOffset >= strlen(BusData) || BusData[LOffset] == ' ')
		{ /*No argument?*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
			MemBus_Write(TmpBuf, true);
			
			return;
		}
		
		if (CurObj)
		{ /*If we ask to start a HaltCmdOnly command, run the stop command instead, because that's all that we use.*/
			DidWork = ProcessConfigObject(CurObj, (BusDataIs(MEMBUS_CODE_OBJSTART) && !CurObj->Opts.HaltCmdOnly), false);
			
			snprintf(TmpBuf, sizeof TmpBuf, "Manual %s of object %s %s%s", (BusDataIs(MEMBUS_CODE_OBJSTART) ? "start" : "stop"),
					CurObj->ObjectID, (DidWork ? "succeeded" : "failed"), ((DidWork == WARNING) ? " with a warning" : ""));
			WriteLogLine(TmpBuf, true);
		}
		else
		{
			DidWork = FAILURE;
		}
		
		switch (DidWork)
		{
			case SUCCESS:
				MCode = MEMBUS_CODE_ACKNOWLEDGED;
				break;
			case WARNING:
				MCode = MEMBUS_CODE_WARNING;
				break;
			case FAILURE:
				MCode = MEMBUS_CODE_FAILURE;
				break;
				
		}
		
		snprintf(TmpBuf, sizeof TmpBuf, "%s %s %s",
				MCode, (BusDataIs(MEMBUS_CODE_OBJSTART) ? MEMBUS_CODE_OBJSTART : MEMBUS_CODE_OBJSTOP), TWorker);
		
		MemBus_Write(TmpBuf, true);
	}
	else if (BusDataIs(MEMBUS_CODE_CFMERGE) || BusDataIs(MEMBUS_CODE_CFUMERGE))
	{
		const char *const MainCode = BusDataIs(MEMBUS_CODE_CFMERGE) ? MEMBUS_CODE_CFMERGE : MEMBUS_CODE_CFUMERGE;
		const char *MemBusReturnCode = NULL;
		const int LOffset = strlen(MainCode) + (sizeof " " - 1);
		const char *Filename = BusData + LOffset;
		
		switch (BusDataIs(MEMBUS_CODE_CFMERGE) ? MergeImportLine(Filename) : UnmergeImportLine(Filename))
		{
			case SUCCESS:
				MemBusReturnCode = MEMBUS_CODE_ACKNOWLEDGED;
				break;
			case WARNING:
				MemBusReturnCode = MEMBUS_CODE_WARNING;
				break;
			default:
				MemBusReturnCode = MEMBUS_CODE_FAILURE;
				break;
		}
		
		char OutBuf[MEMBUS_MSGSIZE];
		snprintf(OutBuf, sizeof OutBuf, "%s %s %s", MemBusReturnCode, MainCode, Filename);
		
		MemBus_Write(OutBuf, true);
		
	}
	else if (BusDataIs(MEMBUS_CODE_LSOBJS))
	{ /*Done for mostly third party stuff.*/
		int Inc = 0;
		char OutBuf[MEMBUS_MSGSIZE];
		unsigned char *BinWorker = (void*)OutBuf;
		ObjTable *Worker = ObjectTable;
		unsigned TPID = 0;
		const unsigned Length = strlen(MEMBUS_CODE_LSOBJS " " MEMBUS_LSOBJS_VERSION) + 1;
		
		for (; Worker->Next; Worker = Worker->Next)
		{
			const struct _RLTree *RLWorker = Worker->ObjectRunlevels;
			
			
			if (strlen(BusData) > strlen(MEMBUS_CODE_LSOBJS) &&
				strcmp(BusData + strlen(MEMBUS_CODE_LSOBJS " "), Worker->ObjectID) != 0)
			{ /*Allow for getting status of just one object.*/
					continue;
			}
			
			if (!Worker->Opts.HasPIDFile || !(TPID = ReadPIDFile(Worker)))
			{
				TPID = Worker->ObjectPID;
			}
			
			/*We need a version for this protocol, because relevant options can change with updates.
			 * Not all options are here, because some are not really useful.*/
						
			strncpy(OutBuf, MEMBUS_CODE_LSOBJS " " MEMBUS_LSOBJS_VERSION, Length);
			
			BinWorker = (unsigned char*)OutBuf + Length;
			
			*BinWorker++ = (Worker->Started && !Worker->Opts.HaltCmdOnly);
			*BinWorker++ = ObjectProcessRunning(Worker);
			*BinWorker++ = Worker->Enabled;
			*BinWorker++ = Worker->TermSignal;
			*BinWorker++ = Worker->ReloadCommandSignal;
			
			memcpy(BinWorker, &Worker->UserID, sizeof(int));
			memcpy((BinWorker += sizeof(int)), &Worker->GroupID, sizeof(int));
			
			memcpy((BinWorker += sizeof(int)), &Worker->Opts.StopMode, sizeof(enum _StopMode));
			memcpy((BinWorker += sizeof(enum _StopMode)), &TPID, sizeof(int));
			
			memcpy((BinWorker += sizeof(int)), &Worker->StartedSince, sizeof(int));
			memcpy(BinWorker + sizeof(int), &Worker->Opts.StopTimeout, sizeof(int));
			
			
			MemBus_BinWrite(OutBuf, MEMBUS_MSGSIZE, true);
			
			snprintf(OutBuf, sizeof OutBuf, "%s %s", Worker->ObjectID, Worker->ObjectDescription);
			
			MemBus_Write(OutBuf, true);
			
			*OutBuf = '\0';
			
			BinWorker = (void*)OutBuf;
			/*Write it over binary now.*/
			if (Worker->Opts.RawDescription) *BinWorker++ = COPT_RAWDESCRIPTION;
			if (Worker->Opts.HaltCmdOnly) *BinWorker++ = COPT_HALTONLY;
			if (Worker->Opts.Persistent) *BinWorker++ = COPT_PERSISTENT;
#ifndef NOMMU
			if (Worker->Opts.Fork) *BinWorker++ = COPT_FORK;
			if (Worker->Opts.ForkScanOnce) *BinWorker++ = COPT_FORKSCANONCE;
#endif /*NOMMU*/
			if (Worker->Opts.IsService) *BinWorker++ = COPT_SERVICE;
			if (Worker->Opts.AutoRestart) *BinWorker++ = COPT_AUTORESTART;
			if (Worker->Opts.ForceShell) *BinWorker++ = COPT_FORCESHELL;
			if (Worker->Opts.NoStopWait) *BinWorker++ = COPT_NOSTOPWAIT;
			if (Worker->Opts.Exec) *BinWorker++ = COPT_EXEC;
			if (Worker->Opts.PivotRoot) *BinWorker++ = COPT_PIVOTROOT;
			if (Worker->Opts.RunOnce) *BinWorker++ = COPT_RUNONCE;
			if (Worker->Opts.NoTrack) *BinWorker++ = COPT_NOTRACK;
			if (Worker->Opts.StartFailIsCritical) *BinWorker++ = COPT_STARTFAILCRITICAL;
			if (Worker->Opts.StopFailIsCritical) *BinWorker++ = COPT_STOPFAILCRITICAL;
			
			*BinWorker = 0;
			
			MemBus_BinWrite(OutBuf, MEMBUS_MSGSIZE, true);
			
			/*Now onto exit status mapping.*/
			snprintf(OutBuf, sizeof OutBuf, MEMBUS_CODE_LSOBJS " MXS");
			
			BinWorker = (void*)(OutBuf + sizeof MEMBUS_CODE_LSOBJS " MXS" + 1);

			
			for (Inc = 0; Worker->ExitStatuses[Inc].Value != 3 && Inc < sizeof Worker->ExitStatuses / sizeof Worker->ExitStatuses[0]; ++Inc)		
			{ /*Found one.*/
				*BinWorker++ = Worker->ExitStatuses[Inc].Value;
				*BinWorker++ = Worker->ExitStatuses[Inc].ExitStatus;
			}
			BinWorker = (void*)(OutBuf + sizeof MEMBUS_CODE_LSOBJS " MXS");
			*BinWorker = Inc;

			MemBus_BinWrite(OutBuf, MEMBUS_MSGSIZE, true);
			/**We know we're going to the runlevels now because we only send this one chunk before we ever do.**/
			
			if (RLWorker)
			{
				for (; RLWorker->Next; RLWorker = RLWorker->Next)
				{ /*Send all runlevels.*/
					snprintf(OutBuf, sizeof OutBuf, "%s %s %s %s", MEMBUS_CODE_LSOBJS,
							MEMBUS_LSOBJS_VERSION, Worker->ObjectID, RLWorker->RL);

					MemBus_Write(OutBuf, true);
				}
			}
		}
		
		/*This says we are done.*/
		MemBus_Write(MEMBUS_CODE_ACKNOWLEDGED " " MEMBUS_CODE_LSOBJS, true);

		return;
	}					
	else if (BusDataIs(MEMBUS_CODE_GETRL))
	{
		char TmpBuf[MEMBUS_MSGSIZE];
		
		snprintf(TmpBuf, sizeof TmpBuf, MEMBUS_CODE_GETRL " %s", CurRunlevel);
		MemBus_Write(TmpBuf, true);
	}		
	else if (BusDataIs(MEMBUS_CODE_OBJENABLE) || BusDataIs(MEMBUS_CODE_OBJDISABLE))
	{
		Bool EnablingThis = (BusDataIs(MEMBUS_CODE_OBJENABLE) ? true : false);
		unsigned LOffset = strlen(EnablingThis ? MEMBUS_CODE_OBJENABLE " " : MEMBUS_CODE_OBJDISABLE " ");
		char *OurSignal = EnablingThis ? MEMBUS_CODE_OBJENABLE : MEMBUS_CODE_OBJDISABLE;
		char *TWorker = BusData + LOffset;
		ObjTable *CurObj = LookupObjectInTable(TWorker);
		char TmpBuf[MEMBUS_MSGSIZE];
		ReturnCode DidWork = FAILURE;
		
		if (LOffset >= strlen(BusData) || BusData[LOffset] == ' ')
		{ /*No argument?*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
			MemBus_Write(TmpBuf, true);
			
			return;
		}
		
		if (!CurObj)
		{
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s %s", MEMBUS_CODE_FAILURE, OurSignal, TWorker);
			MemBus_Write(TmpBuf, true);
			
			return;
		}
		
		CurObj->Enabled = (EnablingThis ? true : false);
		DidWork = EditConfigValue(CurObj->ConfigFile, TWorker, "ObjectEnabled", EnablingThis ? "true" : "false");
		
		switch (DidWork)
		{
			case SUCCESS:
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_ACKNOWLEDGED, BusData);
				break;
			case WARNING:
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_WARNING, BusData);
				break;
			case FAILURE:
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
				break;
			default:
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
				break;
		}
			
			
		MemBus_Write(TmpBuf, true);
	}
	else if (BusDataIs(MEMBUS_CODE_RUNLEVEL))
	{
		unsigned LOffset = strlen(MEMBUS_CODE_RUNLEVEL " ");
		char *TWorker = BusData + LOffset;
		char TmpBuf[MEMBUS_MSGSIZE];
		
		if (LOffset >= strlen(BusData) || BusData[LOffset] == ' ')
		{ /*No argument?*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
			MemBus_Write(TmpBuf, true);
			
			return;
		}
		
		if (ObjRL_ValidRunlevel(TWorker))
		{
			/*Tell them everything is OK, because we don't want to wait the whole time for the runlevel to start up.*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s %s", MEMBUS_CODE_ACKNOWLEDGED, MEMBUS_CODE_RUNLEVEL, TWorker);
			MemBus_Write(TmpBuf, true);
		}
		else
		{
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s %s", MEMBUS_CODE_FAILURE, MEMBUS_CODE_RUNLEVEL, TWorker);
			MemBus_Write(TmpBuf, true);
			return;
		}
		
		snprintf(TmpBuf, sizeof TmpBuf, CONSOLE_COLOR_CYAN "Changing runlevel to \"%s\"...\n" CONSOLE_ENDCOLOR, TWorker);
		WriteLogLine(TmpBuf, true);
		
		printf("%s", TmpBuf);
		
		if (!SwitchRunlevels(TWorker)) /*Switch to it.*/
		{
			char TmpBuf[1024];
			
			snprintf(TmpBuf, sizeof TmpBuf, "Failed to switch to runlevel \"%s\".", TWorker);
			SpitError(TmpBuf);
			WriteLogLine(TmpBuf, true);
		}
		else
		{
			snprintf(TmpBuf, sizeof TmpBuf, CONSOLE_COLOR_GREEN "Switched to runlevel \"%s\"." CONSOLE_ENDCOLOR, TWorker);
			puts(TmpBuf);
			WriteLogLine(TmpBuf, true);
		}
	}
	else if (BusDataIs(MEMBUS_CODE_OBJRLS))
	{
		char *Worker = NULL;
		char ObjectID[MAX_DESCRIPT_SIZE], SpecRunlevel[MAX_DESCRIPT_SIZE];
		enum ObjRLS { OBJRLS_CHECK, OBJRLS_ADD, OBJRLS_DEL } Mode;
		int LOffset = 0, Inc = 0;
		char OutBuf[MEMBUS_MSGSIZE] = { '\0' };
		ObjTable *CurObj = NULL;
		char *RunlevelText = NULL;
		unsigned RequiredRLTLength = 0;
		struct _RLTree *RLWorker = NULL;
		
		if (BusDataIs(MEMBUS_CODE_OBJRLS_CHECK)) LOffset = sizeof MEMBUS_CODE_OBJRLS_CHECK " " - 1, Mode = OBJRLS_CHECK;
		else if (BusDataIs(MEMBUS_CODE_OBJRLS_ADD)) LOffset = sizeof MEMBUS_CODE_OBJRLS_ADD " " - 1, Mode = OBJRLS_ADD;
		else if (BusDataIs(MEMBUS_CODE_OBJRLS_DEL)) LOffset = sizeof MEMBUS_CODE_OBJRLS_DEL " " - 1, Mode = OBJRLS_DEL;
		else return;
		
		Worker = BusData + LOffset;
		
		for (; Worker[Inc] != ' ' && Worker[Inc] != '\0' && Inc < sizeof ObjectID - 1; ++Inc) 
		{ /*Get the object ID.*/
			ObjectID[Inc] = Worker[Inc];
		}
		ObjectID[Inc] = '\0';
		
		if ((Worker += Inc) == '\0')
		{ /*Malformed.*/
			snprintf(OutBuf, sizeof OutBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
			MemBus_Write(OutBuf, true);
			return;
		}
		++Worker; /*Past the space.*/
		
		for (Inc = 0; Worker[Inc] != '\0' && Inc < sizeof SpecRunlevel - 1; ++Inc) 
		{ /*Get the runlevel.*/
			SpecRunlevel[Inc] = Worker[Inc];
		}
		SpecRunlevel[Inc] = '\0';
		
		if (!(CurObj = LookupObjectInTable(ObjectID)))
		{ /*Object sent to us doesn't exist.*/
			snprintf(OutBuf, sizeof OutBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
			MemBus_Write(OutBuf, true);
			return;
		}
		
		/*Now process the commands.*/
		switch (Mode)
		{
			case OBJRLS_CHECK:
				snprintf(OutBuf, sizeof OutBuf, MEMBUS_CODE_OBJRLS_CHECK " %s %s %d",
						ObjectID, SpecRunlevel, ObjRL_CheckRunlevel(SpecRunlevel, CurObj, true));
				MemBus_Write(OutBuf, true);
				return;
			case OBJRLS_ADD:
				/*Add the runlevel in memory.*/
				if (!ObjRL_CheckRunlevel(SpecRunlevel, CurObj, false))
				{
					ObjRL_AddRunlevel(SpecRunlevel, CurObj);
				}
				else
				{
					snprintf(OutBuf, sizeof OutBuf, MEMBUS_CODE_FAILURE " %s", BusData);
					MemBus_Write(OutBuf, true);
				}
				break;
			case OBJRLS_DEL:
				if (!ObjRL_DelRunlevel(SpecRunlevel, CurObj))
				{
					snprintf(OutBuf, sizeof OutBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
					MemBus_Write(OutBuf, true);
					return;
				}
				break;
			default:
				break;
		}
		
		/*File editing. We already returned if we were just checking, so I won't handle that here.*/
		if (CurObj->ObjectRunlevels)
		{
			for (RLWorker = CurObj->ObjectRunlevels; RLWorker->Next; RLWorker = RLWorker->Next)
			{
				RequiredRLTLength += strlen(RLWorker->RL) + 2;
			}
			++RequiredRLTLength; /*For the null terminator.*/
			
			*(RunlevelText = malloc(RequiredRLTLength)) = '\0'; /*I'm only going to say this once.
			* This is a Linux program. In Linux programs, most of the time, even if something is wrong,
			* malloc will NEVER return NULL. I will not dirty up my code with a hundred thousand
			* checks for a value that will never come to pass.*/
			
			for (RLWorker = CurObj->ObjectRunlevels; RLWorker->Next; RLWorker = RLWorker->Next)
			{
				strncat(RunlevelText, RLWorker->RL, RequiredRLTLength - 1);
				strncat(RunlevelText, " ", 1);
			}
			
			/*Get rid of the space at the end.*/
			RunlevelText[strlen(RunlevelText) - 1] = '\0';
		}
		
		if (Mode == OBJRLS_ADD)
		{
			if (!EditConfigValue(CurObj->ConfigFile, CurObj->ObjectID, "ObjectRunlevels", RunlevelText))
			{
				const int Length = MAX_LINE_SIZE + strlen(RunlevelText);
				char *TrickyBuf = malloc(Length);
				/*Special trick to attempt to add the ObjectRunlevels attribute.*/
				snprintf(TrickyBuf, Length, "%s\n\tObjectRunlevels=%s",
						CurObj->Enabled ? "true" : "false", RunlevelText);
						
				if (!EditConfigValue(CurObj->ConfigFile, CurObj->ObjectID, "ObjectEnabled", TrickyBuf))
				{ /*Darn, we can't even do it the sneaky way!*/
					free(TrickyBuf);
					free(RunlevelText);
					snprintf(OutBuf, sizeof OutBuf, MEMBUS_CODE_FAILURE " %s", BusData);
					MemBus_Write(OutBuf, true);
					return;
				}
				free(TrickyBuf);
			}
			
		}
		else
		{ /*OBJRLS_DEL*/
			/*Delete the line.*/
			if (!EditConfigValue(CurObj->ConfigFile, CurObj->ObjectID, "ObjectRunlevels",
								CurObj->ObjectRunlevels ? RunlevelText : NULL))
			{ /*If we pass NULL to EditConfigValue(), it means we want to DELETE that line.*/
				if (RunlevelText) free(RunlevelText);
				snprintf(OutBuf, sizeof OutBuf, MEMBUS_CODE_FAILURE " %s", BusData);
				MemBus_Write(OutBuf, true);
				return;
			}
		
		}
		
		if (RunlevelText) free(RunlevelText), RunlevelText = NULL;
		
		snprintf(OutBuf, sizeof OutBuf, MEMBUS_CODE_ACKNOWLEDGED " %s", BusData);
		MemBus_Write(OutBuf, true);
		return;
	}
	/*Power functions that close everything first.*/
	else if (BusDataIs(MEMBUS_CODE_HALT) || BusDataIs(MEMBUS_CODE_POWEROFF) || BusDataIs(MEMBUS_CODE_REBOOT))
	{
	unsigned LOffset = 0, Signal = OSCTL_REBOOT;
		char *TWorker = NULL, *MSig = NULL;
		char TmpBuf[MEMBUS_MSGSIZE];
		
		if (BusDataIs(MEMBUS_CODE_HALT))
		{
			LOffset = strlen(MEMBUS_CODE_HALT " ");
			Signal = OSCTL_HALT;
			MSig = MEMBUS_CODE_HALT;
			
		}
		else if (BusDataIs(MEMBUS_CODE_POWEROFF))
		{
			LOffset = strlen(MEMBUS_CODE_POWEROFF " ");
			Signal = OSCTL_POWEROFF;
			MSig = MEMBUS_CODE_POWEROFF;
		}
		else if (BusDataIs(MEMBUS_CODE_REBOOT))
		{
			LOffset = strlen(MEMBUS_CODE_REBOOT " ");
			Signal = OSCTL_REBOOT;
			MSig = MEMBUS_CODE_REBOOT;
		}
		
		
		TWorker = BusData + LOffset;
		
		if (LOffset >= strlen(BusData) || BusData[LOffset] == ' ')
		{ /*No argument? Just do the action.*/
			
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_ACKNOWLEDGED, MSig);
			MemBus_Write(TmpBuf, true);
			
			while (!MemBus_Read(TmpBuf, true)) usleep(100); /*Wait to be told they received it.*/
			
			LaunchShutdown(Signal);

			return;
		}
		
		if (strchr(TWorker, ':') && strchr(TWorker, '/'))
		{
			char MsgBuf[MAX_LINE_SIZE];
			const char *HType = NULL;
			Bool H;
			Bool M;
			Bool S;
			
			if (HaltParams.HaltMode != -1)
			{/*Don't let us schedule two shutdowns.*/
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
				
				MemBus_Write(TmpBuf, true);
				return;
			}
				
			if (sscanf(TWorker, "%u:%u:%u %u/%u/%u", &HaltParams.TargetHour, &HaltParams.TargetMin,
				&HaltParams.TargetSec, &HaltParams.TargetMonth, &HaltParams.TargetDay, &HaltParams.TargetYear) != 6)
			{
				SpitError("Invalid time signature for HALT/REBOOT/POWEROFF over membus.\n"
							"Please report to Epoch. This is probably a bug.");

				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
				MemBus_Write(TmpBuf, true);
				
				return;
			}
			
			H = HaltParams.TargetHour >= 10;
			M = HaltParams.TargetMin >= 10;
			S = HaltParams.TargetSec >= 10;
			
			++HaltParams.JobID;
			HaltParams.HaltMode = Signal;

			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_ACKNOWLEDGED, BusData);
			MemBus_Write(TmpBuf, true);

			if (Signal == OSCTL_HALT) HType = "halt";
			else if (Signal == OSCTL_POWEROFF) HType = "poweroff";
			else if (Signal == OSCTL_REBOOT) HType = "reboot";
			
			snprintf(MsgBuf, sizeof MsgBuf, "System is going down for %s at %s%u:%s%u:%s%u %u/%u/%u!",
				HType, H?"":"0", HaltParams.TargetHour, M?"":"0", HaltParams.TargetMin, S?"":"0",
				HaltParams.TargetSec, HaltParams.TargetMonth, HaltParams.TargetDay, HaltParams.TargetYear);
					
			EmulWall(MsgBuf, false);
			return;
		}
		else
		{
				SpitError("Time signature doesn't even contain a semicolon and a slash!\n"
						"This is probably a bug, please report to Epoch.");

				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
				MemBus_Write(TmpBuf, true);
				return;
		}
	}
	else if (BusDataIs(MEMBUS_CODE_ABORTHALT))
	{
		char MsgBuf[MAX_LINE_SIZE];
		const Bool H = HaltParams.TargetHour >= 10;
		const Bool M = HaltParams.TargetMin >= 10;
		const Bool S = HaltParams.TargetSec >= 10;
		
		if (HaltParams.HaltMode != -1)
		{
			HaltParams.HaltMode = -1; /*-1 does the real cancellation.*/
		}
		else
		{ /*Nothing scheduled?*/
			MemBus_Write(MEMBUS_CODE_FAILURE " " MEMBUS_CODE_ABORTHALT, true);
			return;
		}
		
		snprintf(MsgBuf, sizeof MsgBuf, "%s %s%u:%s%u:%s%u %u/%u/%u %s", "The shutdown scheduled for",
				H?"":"0", HaltParams.TargetHour, M?"":"0", HaltParams.TargetMin, S?"":"0", HaltParams.TargetSec,
				HaltParams.TargetMonth, HaltParams.TargetDay, HaltParams.TargetYear,
				"has been aborted.");

		EmulWall(MsgBuf, false);

		MemBus_Write(MEMBUS_CODE_ACKNOWLEDGED " " MEMBUS_CODE_ABORTHALT, true);
		return;
	}
	/*Ctrl-Alt-Del control.*/
	else if (BusDataIs(MEMBUS_CODE_CADOFF))
	{
		if (!reboot(OSCTL_DISABLE_CTRLALTDEL))
		{
			MemBus_Write(MEMBUS_CODE_ACKNOWLEDGED " " MEMBUS_CODE_CADOFF, true);
		}
		else
		{
			MemBus_Write(MEMBUS_CODE_FAILURE " " MEMBUS_CODE_CADOFF, true);
		}
	}
	else if (BusDataIs(MEMBUS_CODE_CADON))
	{
		if (!reboot(OSCTL_ENABLE_CTRLALTDEL))
		{
			MemBus_Write(MEMBUS_CODE_ACKNOWLEDGED " " MEMBUS_CODE_CADON, true);
		}
		else
		{
			MemBus_Write(MEMBUS_CODE_FAILURE " " MEMBUS_CODE_CADON, true);
		}
	}
	else if (BusDataIs(MEMBUS_CODE_SENDPID))
	{
		char TmpBuf[MEMBUS_MSGSIZE];
		unsigned LOffset = strlen(MEMBUS_CODE_SENDPID " ");
		const char *TWorker = BusData + LOffset;
		const ObjTable *TmpObj = NULL;
		
		if (LOffset >= strlen(BusData) || BusData[LOffset] == ' ')
		{ /*No argument?*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
			MemBus_Write(TmpBuf, true);
	
			return;
		}
		
		if (!(TmpObj = LookupObjectInTable(TWorker)) || !TmpObj->Started)
		{ /*Bad argument?*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
			MemBus_Write(TmpBuf, true);
			
			return;
		}
		
		snprintf(TmpBuf, sizeof TmpBuf, "%s %s %u", MEMBUS_CODE_SENDPID, TWorker,
				(TmpObj->Opts.HasPIDFile ? ReadPIDFile(TmpObj) : TmpObj->ObjectPID));
		MemBus_Write(TmpBuf, true);
	}
	else if (BusDataIs(MEMBUS_CODE_KILLOBJ) || BusDataIs(MEMBUS_CODE_OBJRELOAD))
	{
		char TmpBuf[MEMBUS_MSGSIZE];
		unsigned LOffset = (BusDataIs(MEMBUS_CODE_KILLOBJ) ? strlen(MEMBUS_CODE_KILLOBJ " ")
								: strlen(MEMBUS_CODE_OBJRELOAD " "));
		const char *TWorker = BusData + LOffset;
		ObjTable *TmpObj = NULL;
		
		if (LOffset >= strlen(BusData) || BusData[LOffset] == ' ')
		{ /*No argument?*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
			MemBus_Write(TmpBuf, true);
			
			return;
		}
		
		if (!(TmpObj = LookupObjectInTable(TWorker)) || !TmpObj->Started)
		{ /*Bad argument?*/
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
			MemBus_Write(TmpBuf, true);
			
			return;
		}
		
		if (BusDataIs(MEMBUS_CODE_KILLOBJ))
		{
			/*Attempt to send SIGKILL to the PID.*/
			if (!TmpObj->ObjectPID || 
				kill((TmpObj->Opts.HasPIDFile ? ReadPIDFile(TmpObj) : TmpObj->ObjectPID), SIGKILL) != 0)
			{
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
			}
			else
			{
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_ACKNOWLEDGED, BusData);
				TmpObj->Started = false; /*Mark it as stopped now that it's dead.*/
				TmpObj->ObjectPID = 0; /*Erase the PID.*/
				TmpObj->StartedSince = 0;
			}
			MemBus_Write(TmpBuf, true);
		}
		else
		{
			ReturnCode RV = SUCCESS;
			const char *MCode = MEMBUS_CODE_ACKNOWLEDGED, *RMsg = NULL;
			char LogOut[MAX_LINE_SIZE];
			
			if (TmpObj->ObjectReloadCommand == NULL && TmpObj->ReloadCommandSignal == 0)
			{
				snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_FAILURE, BusData);
				MemBus_Write(TmpBuf, true);
				return;
			}
			
			RV = ProcessReloadCommand(TmpObj, false);
			
			switch (RV)
			{
				case SUCCESS:
					MCode = MEMBUS_CODE_ACKNOWLEDGED;
					RMsg = "succeeded";
					break;
				case WARNING:
					MCode = MEMBUS_CODE_WARNING;
					RMsg = "succeeded with a warning";
					break;
				case FAILURE:
					MCode = MEMBUS_CODE_FAILURE;
					RMsg = "failed";
					break;
				default:
					break;
			}
			
			snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MCode, BusData);
			
			MemBus_Write(TmpBuf, true);
			
			snprintf(LogOut, MAX_LINE_SIZE, "Reload of object %s %s.", TWorker, RMsg);
			WriteLogLine(LogOut, true);
		}
	}
	else if (BusDataIs(MEMBUS_CODE_RXD))
	{ /*Restart Epoch from disk, but saves object states and whatnot.
		* Done mainly so we can unmount the filesystem after someone updates /sbin/epoch.*/
		
		/**We set this so when we come back we'll know if we are doing a regular reexec.**/
		setenv("EPOCHRXDMEMBUS", "1", true);
		
		ReexecuteEpoch();
	}
	/*Something we don't understand. Send BADPARAM.*/
	else
	{
		char TmpBuf[MEMBUS_MSGSIZE];
		
		snprintf(TmpBuf, sizeof TmpBuf, "%s %s", MEMBUS_CODE_BADPARAM, BusData);
		
		MemBus_Write(TmpBuf, true);
	}
}
Exemplo n.º 4
0
int Connected(Stream)
{
	int n;
	ChatCIRCUIT * conn;
	struct UserInfo * user = NULL;
	char callsign[10];
	int port, paclen, maxframe, l4window;
	char ConnectedMsg[] = "*** CONNECTED    ";
	char Msg[100];
	LINK    *link;
	KNOWNNODE *node;

	for (n = 0; n < NumberofChatStreams; n++)
	{
  		conn = &ChatConnections[n];
		
		if (Stream == conn->BPQStream)
		{
			if (conn->Active)
			{
				// Probably an outgoing connect
		
				if (conn->rtcflags == p_linkini)
				{
					conn->paclen = 236;
					nprintf(conn, "c %s\r", conn->u.link->call);
					return 0;
				}
			}
	
			memset(conn, 0, sizeof(ChatCIRCUIT));		// Clear everything
			conn->Active = TRUE;
			conn->BPQStream = Stream;

			conn->Secure_Session = GetConnectionInfo(Stream, callsign,
				&port, &conn->SessType, &paclen, &maxframe, &l4window);

			conn->paclen = paclen;

			strlop(callsign, ' ');		// Remove trailing spaces

			memcpy(conn->Callsign, callsign, 10);

			strlop(callsign, '-');		// Remove any SSID

			user = zalloc(sizeof(struct UserInfo));

			strcpy(user->Call, callsign);

			conn->UserPointer = user;

			n=sprintf_s(Msg, sizeof(Msg), "Incoming Connect from %s", user->Call);
			
			// Send SID and Prompt

			WriteLogLine(conn, '|',Msg, n, LOG_CHAT);
			conn->Flags |= CHATMODE;

			nodeprintf(conn, ChatSID, Ver[0], Ver[1], Ver[2], Ver[3]);

			// See if from a defined node
				
			for (link = link_hd; link; link = link->next)
			{
				if (matchi(conn->Callsign, link->call))
				{
					conn->rtcflags = p_linkwait;
					return 0;						// Wait for *RTL
				}
			}

			// See if from a previously known node

			node = knownnode_find(conn->Callsign);

			if (node)
			{
				// A node is trying to link, but we don't have it defined - close

				Logprintf(LOG_CHAT, conn, '!', "Node %s connected, but is not defined as a Node - closing",
					conn->Callsign);

				nodeprintf(conn, "Node %s does not have %s defined as a node to link to - closing.\r",
					OurNode, conn->Callsign);

				ChatFlush(conn);

				Sleep(500);

				Disconnect(conn->BPQStream);

				return 0;
			}

			if (user->Name[0] == 0)
			{
				char * Name = lookupuser(user->Call);

				if (Name)
				{
					if (strlen(Name) > 17)
						Name[17] = 0;

					strcpy(user->Name, Name);
					free(Name);
				}
				else
				{
					conn->Flags |= GETTINGUSER;
					nputs(conn, NewUserPrompt);
					return TRUE;
				}
			}

			SendWelcomeMsg(Stream, conn, user);
			RefreshMainWindow();
			ChatFlush(conn);
			
			return 0;
		}
	}

	return 0;
}