Introduce CLI
main: Parse args using getopt_long() in main(). Begin implementation of a CLI. It can be launched using ./qswiki config --cli. Allow connecting to another instance using "attach" command. This uses Unix domain sockets, and in the future can be used to drop caches, reload template, etc. Closes: #21
This commit is contained in:
		
							
								
								
									
										77
									
								
								cliserver.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								cliserver.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| #include <sys/socket.h> | ||||
| #include <sys/un.h> | ||||
| #include <unistd.h> | ||||
| #include "cliserver.h" | ||||
| #include "logger.h" | ||||
| CLIServer::CLIServer(CLIHandler &handler) | ||||
| { | ||||
| 	this->handler = &handler; | ||||
| } | ||||
|  | ||||
| bool CLIServer::detachServer(std::string socketpath) | ||||
| { | ||||
| 	struct sockaddr_un name; | ||||
| 	const int max_socket_length = sizeof(name.sun_path) - 1; | ||||
| 	if(socketpath.size() > max_socket_length) | ||||
| 	{ | ||||
| 		perror("socket path too long"); | ||||
| 		return false; | ||||
| 	} | ||||
| 	int s = socket(AF_UNIX, SOCK_DGRAM, 0); | ||||
| 	if(s == -1) | ||||
| 	{ | ||||
| 		perror("socket"); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	memset(&name, 0, sizeof(name)); | ||||
| 	name.sun_family = AF_UNIX; | ||||
| 	memcpy(&name.sun_path, socketpath.c_str(), socketpath.size()); | ||||
|  | ||||
| 	unlink(socketpath.c_str()); | ||||
| 	int ret = bind(s, (const struct sockaddr *)&name, sizeof(name)); | ||||
| 	if(ret == -1) | ||||
| 	{ | ||||
| 		perror("bind"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
|  | ||||
| 	auto worker = [=] | ||||
| 	{ | ||||
| 		while(true) | ||||
| 		{ | ||||
| 			char buffer[1024] = {0}; | ||||
| 			struct sockaddr_un peer; | ||||
| 			socklen_t peerlen = sizeof(peer); | ||||
|  | ||||
| 			int ret = recvfrom(s, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &peerlen); | ||||
| 			if(ret == -1) | ||||
| 			{ | ||||
| 				Logger::error() << "Error during recvfrom in CLI server: " << strerror(errno); | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| 			std::string input{buffer}; | ||||
|  | ||||
| 			auto pair = CLIHandler::splitCommand(input); | ||||
|  | ||||
| 			auto result = handler->processCommand(pair.first, pair.second); | ||||
| 			char resultCode = '0'; | ||||
| 			if(result.first) | ||||
| 			{ | ||||
| 				resultCode = '1'; | ||||
| 			} | ||||
| 			std::string resultString; | ||||
| 			resultString += resultCode; | ||||
| 			resultString += result.second; | ||||
| 			ret = sendto(s, resultString.c_str(), resultString.size(), 0, (struct sockaddr *)&peer, peerlen); | ||||
| 			if(ret == -1) | ||||
| 			{ | ||||
| 				Logger::error() << "Error during sendto in CLI server: " << strerror(errno); | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
| 	std::thread t1{worker}; | ||||
| 	t1.detach(); | ||||
| 	return true; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user