warden.c 5.59 KB
/* File Name: warden.c
 * Version: 0.2
 * Author: Brodey Dover
 * Date: May 1, 2016
*/

/* warden header file */
#include "warden.h"

int main(void) {
	float serverVersion = 0.0f;
	int serverPort = 0, serverStatus = 0, serverPID = 0;
	struct Log log;

	/* 	if (readLogFile("./test/latest.log", &log) < 0) { */
	if (readLogFile("/var/log/minecraft-server/latest.log", &log) < 0) {
		cleanup(&log);	
		return READ_LOG_FAIL;
	}

	/*if (printBuffer(&log) < 0) {
		cleanup(&log);	
		return READ_LOG_FAIL;
	}*/
	serverVersion = getServerVersion(&log);
	if (serverVersion == 0.0f) {
		cleanup(&log);	
		return ERROR_UNABLETOGETVERSION;
	}
	printf("Server Version: %1.1f\n", serverVersion);

	serverPort = getServerPort(&log);
	if (serverPort == 0) {
		cleanup(&log);	
		return ERROR_UNABLETOGETPORT;
	}
	printf("Server Port: %i\n", serverPort);
	
	serverStatus = getServerStatus(&log);
	serverPID = getServerPID();
	if ((serverStatus != 0) || (serverPID <= 0)) {
		printf("server status: %i, server PID: %i\n", serverStatus, serverPID);		
        startServer();
	}	
	
	cleanup(&log);
	return 0;
}

void cleanup(struct Log *log) {
	int i;
	for (i = 0; i <= (log->numberOfLines - 1); ++i) {
		free(log->logBuffer[i]);
	}
	free(log->logBuffer);
}

int getServerPID() {
	int serverPID = 0;
	char *pidBuffer;
	FILE *fp;	

	if (system("pgrep -u mcserver -n > /tmp/Minecraft.pid") < 0) {
		return ERROR_UNABLETOGETPID;
	} 

	pidBuffer = calloc(SMALL_BUFFER, sizeof(char));
	if (pidBuffer == NULL) {
		return ERROR_FATAL_NOMEMORY;
	}

	fp = fopen("/tmp/Minecraft.pid" , "r");
	if (fp == NULL) {
		fprintf(stderr, "Error opening file\n");
		free (pidBuffer);
		return(ERROR_OPENING_FILE);
	}

	if (fgets(pidBuffer, SMALL_BUFFER, fp) != NULL ) {
		puts(pidBuffer);
	} else {
		fclose(fp);
		free (pidBuffer);
		fprintf(stderr, "No entry in PID File, starting server.\n");
		return SERVER_NOT_STARTED;
	}
	fclose(fp);

	serverPID = atoi(pidBuffer);

	if (serverPID == 0) {
		free (pidBuffer);
		return ERROR_UNABLETOGETPID;
	}
	free (pidBuffer);
	return serverPID;
}

int getServerPort(struct Log *log) {
	int i, serverPort;
	char *returnCheck;
	const char needle[20] = "*:";
	char tempPort[5];

	if (log->logBuffer == NULL)
		return ERROR_UNABLETOGETPORT;

	i = (log->numberOfLines - 1);
	while (i >= 0) {
		returnCheck = strstr(log->logBuffer[i], needle);
		if (returnCheck != NULL) {
			strncpy(tempPort, returnCheck + 2, 5);
			break;
		}
		--i;
	}
	serverPort = atoi(tempPort);
	return serverPort;
	return 0;
}

int getServerStatus(struct Log *log) {
	int i, startIndex = 0, doneIndex = 0;
	char *startCheck = NULL, *doneCheck = NULL;
	const char needleStart[20] = "Starting", needleDone[20] = "Done";

	if (log->logBuffer == NULL)
		return ERROR_UNABLETOGETPORT;

	i = (log->numberOfLines - 1);
	while (i >= 0) {
		if (startIndex == 0) {
			startCheck = strstr(log->logBuffer[i], needleStart);
			if (startCheck != NULL) {
				startIndex = i;
			}
		}
		if (doneIndex == 0) {
			doneCheck = strstr(log->logBuffer[i], needleDone);
			if (doneCheck != NULL) {
				doneIndex = i;
			}
		}
		if ((startIndex != 0) && (doneIndex != 0))
			break;
		--i;
	}

	if ((startIndex == 0) && (doneIndex == 0))
		return -9;
	else if (doneIndex <= startIndex) 
		return -10;
	return SERVER_STARTED;
}

float getServerVersion(struct Log *log) {
	float serverVersion = 0.0f;
	int i;
	char *returnCheck;
	const char needle[20] = "version";
	char tempVersion[3];

	if (log->logBuffer == NULL)
		return ERROR_UNABLETOGETVERSION;

	i = (log->numberOfLines - 1);
	while (i >= 0) {
		returnCheck = strstr(log->logBuffer[i], needle);
		if (returnCheck != NULL) {
			strncpy(tempVersion, returnCheck + 8, 3);
			break;
		}
		--i;
	}
	serverVersion = atof(tempVersion);
	return serverVersion;
}

int readLogFile(char *fileName, struct Log *log) {
	int i;
	int maxLineLength = 0, numberOfLines = 0, tempLineLength = 0;
	char *tempLineBuffer, **logBuffer;
	FILE *fp, *sp;

	/*
	 * Open the file the first time to get information 
	 */
	tempLineBuffer = (char *)calloc(LINE_BUFFER, sizeof(char));
	if (tempLineBuffer == NULL) {
		return ERROR_FATAL_NOMEMORY;
	}

	fp = fopen(fileName , "r");
	if (fp == NULL) {
		fprintf(stderr, "Error opening file\n");
		free (tempLineBuffer);
		return ERROR_OPENING_FILE;
	}

	while (fgets(tempLineBuffer, LINE_BUFFER, fp) != NULL)
	{
		tempLineLength = (int)strlen(tempLineBuffer);
		if (tempLineLength > maxLineLength) {
			maxLineLength = tempLineLength;
		}
		++numberOfLines;		
	}
	fclose(fp);
	free(tempLineBuffer);

	/*
	 * Open the file the second time to populate the array
	 */
	logBuffer = (char **)calloc(numberOfLines, sizeof(char)*numberOfLines);
	if (logBuffer == NULL) {
		return ERROR_FATAL_NOMEMORY;
	}

	sp = fopen(fileName , "r");
	if (sp == NULL) {
		fprintf(stderr, "Error opening file\n");
		free(logBuffer);
		return ERROR_OPENING_FILE;
	}

	for (i = 0; i <= (numberOfLines - 1); ++i) {
		logBuffer[i] = (char *)calloc((maxLineLength), sizeof(char)*(maxLineLength));
		if (logBuffer[i] == NULL)
			return ERROR_FATAL_NOMEMORY;
	}
	
	/* Populate the Buffer */
	i = 0;
	while (fgets(logBuffer[i], (sizeof(char)*maxLineLength), sp) != NULL) {
		logBuffer[i][(int)strlen(logBuffer[i]) - 1] = '\0';
		if (i < (numberOfLines - 1))
			++i;
	}
	fclose(sp);

	log->maxLineLength = maxLineLength;
	log->numberOfLines = numberOfLines;
	log->logBuffer = logBuffer;
	return 0;
}

int startServer() {
    if (system("/usr/local/bin/minecraft-server &") < 0)
 		return SERVER_NOT_STARTED;
 	return SERVER_STARTED;
}

int printBuffer(struct Log *log) {
	int i;	
	if (log == NULL)
		return READ_LOG_FAIL;

	for (i = 0; i < (log->numberOfLines - 1); ++i)
		printf ("Line %i: %s", (i + 1), log->logBuffer[i]);
	return 0;
}