示例#1
0
void	temp_fstream::open (std::ios_base::openmode mode)
{
    close();

    const char*		tmpdir = getenv("TMPDIR");
    size_t			tmpdir_len = tmpdir ? std::strlen(tmpdir) : 0;
    if (tmpdir_len == 0 || tmpdir_len > 4096) {
        // no $TMPDIR or it's excessively long => fall back to /tmp
        tmpdir = "/tmp";
        tmpdir_len = 4;
    }
    std::vector<char>	path_buffer(tmpdir_len + 18);
    char*			path = &path_buffer[0];
    std::strcpy(path, tmpdir);
    std::strcpy(path + tmpdir_len, "/git-crypt.XXXXXX");
    mode_t			old_umask = umask(0077);
    int			fd = mkstemp(path);
    if (fd == -1) {
        int		mkstemp_errno = errno;
        umask(old_umask);
        throw System_error("mkstemp", "", mkstemp_errno);
    }
    umask(old_umask);
    std::fstream::open(path, mode);
    if (!std::fstream::is_open()) {
        unlink(path);
        ::close(fd);
        throw System_error("std::fstream::open", path, 0);
    }
    unlink(path);
    ::close(fd);
}
示例#2
0
std::vector<std::string> get_directory_contents (const char* path)
{
	std::vector<std::string>	filenames;
	std::string			patt(path);
	if (!patt.empty() && patt[patt.size() - 1] != '/' && patt[patt.size() - 1] != '\\') {
		patt.push_back('\\');
	}
	patt.push_back('*');

	WIN32_FIND_DATAA		ffd;
	HANDLE				h = FindFirstFileA(patt.c_str(), &ffd);
	if (h == INVALID_HANDLE_VALUE) {
		throw System_error("FindFirstFileA", patt, GetLastError());
	}
	do {
		if (std::strcmp(ffd.cFileName, ".") != 0 && std::strcmp(ffd.cFileName, "..") != 0) {
			filenames.push_back(ffd.cFileName);
		}
	} while (FindNextFileA(h, &ffd) != 0);

	DWORD				err = GetLastError();
	if (err != ERROR_NO_MORE_FILES) {
		throw System_error("FileNextFileA", patt, err);
	}
	FindClose(h);
	return filenames;
}
示例#3
0
std::vector<std::string> get_directory_contents (const char* path)
{
    std::vector<std::string>		contents;

    DIR*					dir = opendir(path);
    if (!dir) {
        throw System_error("opendir", path, errno);
    }
    try {
        std::vector<unsigned char>	buffer(sizeof_dirent_for(dir));
        struct dirent*			dirent_buffer = reinterpret_cast<struct dirent*>(&buffer[0]);
        struct dirent*			ent = NULL;
        int				err = 0;
        while ((err = readdir_r(dir, dirent_buffer, &ent)) == 0 && ent != NULL) {
            if (std::strcmp(ent->d_name, ".") == 0 || std::strcmp(ent->d_name, "..") == 0) {
                continue;
            }
            contents.push_back(ent->d_name);
        }
        if (err != 0) {
            throw System_error("readdir_r", path, errno);
        }
    } catch (...) {
        closedir(dir);
        throw;
    }
    closedir(dir);

    std::sort(contents.begin(), contents.end());
    return contents;
}
示例#4
0
void	temp_fstream::open (std::ios_base::openmode mode)
{
	close();

	char			tmpdir[MAX_PATH + 1];

	DWORD			ret = GetTempPath(sizeof(tmpdir), tmpdir);
	if (ret == 0) {
		throw System_error("GetTempPath", "", GetLastError());
	} else if (ret > sizeof(tmpdir) - 1) {
		throw System_error("GetTempPath", "", ERROR_BUFFER_OVERFLOW);
	}

	char			tmpfilename[MAX_PATH + 1];
	if (GetTempFileName(tmpdir, TEXT("git-crypt"), 0, tmpfilename) == 0) {
		throw System_error("GetTempFileName", "", GetLastError());
	}

	filename = tmpfilename;

	std::fstream::open(filename.c_str(), mode);
	if (!std::fstream::is_open()) {
		DeleteFile(filename.c_str());
		throw System_error("std::fstream::open", filename, 0);
	}
}
示例#5
0
int		Coprocess::wait ()
{
	if (WaitForSingleObject(proc_handle, INFINITE) == WAIT_FAILED) {
		throw System_error("WaitForSingleObject", "", GetLastError());
	}

	DWORD			exit_code;
	if (!GetExitCodeProcess(proc_handle, &exit_code)) {
		throw System_error("GetExitCodeProcess", "", GetLastError());
	}

	return exit_code;
}
示例#6
0
static int wait_for_child (HANDLE child_handle)
{
	if (WaitForSingleObject(child_handle, INFINITE) == WAIT_FAILED) {
		throw System_error("WaitForSingleObject", "", GetLastError());
	}

	DWORD			exit_code;
	if (!GetExitCodeProcess(child_handle, &exit_code)) {
		throw System_error("GetExitCodeProcess", "", GetLastError());
	}

	return exit_code;
}
示例#7
0
void		Coprocess::spawn (const std::vector<std::string>& args)
{
	pid = fork();
	if (pid == -1) {
		throw System_error("fork", "", errno);
	}
	if (pid == 0) {
		if (stdin_pipe_writer != -1) {
			close(stdin_pipe_writer);
		}
		if (stdout_pipe_reader != -1) {
			close(stdout_pipe_reader);
		}
		if (stdin_pipe_reader != -1) {
			dup2(stdin_pipe_reader, 0);
			close(stdin_pipe_reader);
		}
		if (stdout_pipe_writer != -1) {
			dup2(stdout_pipe_writer, 1);
			close(stdout_pipe_writer);
		}

		execvp(args[0], args);
		perror(args[0].c_str());
		_exit(-1);
	}
	if (stdin_pipe_reader != -1) {
		close(stdin_pipe_reader);
		stdin_pipe_reader = -1;
	}
	if (stdout_pipe_writer != -1) {
		close(stdout_pipe_writer);
		stdout_pipe_writer = -1;
	}
}
示例#8
0
static HANDLE spawn_command (const std::vector<std::string>& command, HANDLE stdin_handle, HANDLE stdout_handle, HANDLE stderr_handle)
{
	PROCESS_INFORMATION	proc_info;
	ZeroMemory(&proc_info, sizeof(proc_info));

	STARTUPINFO		start_info;
	ZeroMemory(&start_info, sizeof(start_info));

	start_info.cb = sizeof(STARTUPINFO);
	start_info.hStdInput = stdin_handle ? stdin_handle : GetStdHandle(STD_INPUT_HANDLE);
	start_info.hStdOutput = stdout_handle ? stdout_handle : GetStdHandle(STD_OUTPUT_HANDLE);
	start_info.hStdError = stderr_handle ? stderr_handle : GetStdHandle(STD_ERROR_HANDLE);
	start_info.dwFlags |= STARTF_USESTDHANDLES;

	std::string		cmdline(format_cmdline(command));

	if (!CreateProcessA(NULL,		// application name (NULL to use command line)
				const_cast<char*>(cmdline.c_str()),
				NULL,		// process security attributes
				NULL,		// primary thread security attributes
				TRUE,		// handles are inherited
				0,		// creation flags
				NULL,		// use parent's environment
				NULL,		// use parent's current directory
				&start_info,
				&proc_info)) {
		throw System_error("CreateProcess", cmdline, GetLastError());
	}

	CloseHandle(proc_info.hThread);

	return proc_info.hProcess;
}
示例#9
0
int		Coprocess::wait ()
{
	int		status = 0;
	if (waitpid(pid, &status, 0) == -1) {
		throw System_error("waitpid", "", errno);
	}
	return status;
}
示例#10
0
void	create_protected_file (const char* path)
{
    int	fd = open(path, O_WRONLY | O_CREAT, 0600);
    if (fd == -1) {
        throw System_error("open", path, errno);
    }
    close(fd);
}
示例#11
0
size_t		Coprocess::write_stdin (void* handle, const void* buf, size_t count)
{
	DWORD		bytes_written;
	if (!WriteFile(static_cast<Coprocess*>(handle)->stdin_pipe_writer, buf, count, &bytes_written, nullptr)) {
		throw System_error("WriteFile", "", GetLastError());
	}
	return bytes_written;
}
示例#12
0
int exec_command (const std::vector<std::string>& command, std::ostream& output)
{
	HANDLE			stdout_pipe_reader = NULL;
	HANDLE			stdout_pipe_writer = NULL;
	SECURITY_ATTRIBUTES	sec_attr;

	// Set the bInheritHandle flag so pipe handles are inherited.
	sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
	sec_attr.bInheritHandle = TRUE;
	sec_attr.lpSecurityDescriptor = NULL;

	// Create a pipe for the child process's STDOUT.
	if (!CreatePipe(&stdout_pipe_reader, &stdout_pipe_writer, &sec_attr, 0)) {
		throw System_error("CreatePipe", "", GetLastError());
	}

	// Ensure the read handle to the pipe for STDOUT is not inherited.
	if (!SetHandleInformation(stdout_pipe_reader, HANDLE_FLAG_INHERIT, 0)) {
		throw System_error("SetHandleInformation", "", GetLastError());
	}

	HANDLE			child_handle = spawn_command(command, NULL, stdout_pipe_writer, NULL);
	CloseHandle(stdout_pipe_writer);

	// Read from stdout_pipe_reader.
	// Note that ReadFile on a pipe may return with bytes_read==0 if the other
	// end of the pipe writes zero bytes, so don't break out of the read loop
	// when this happens.  When the other end of the pipe closes, ReadFile
	// fails with ERROR_BROKEN_PIPE.
	char			buffer[1024];
	DWORD			bytes_read;
	while (ReadFile(stdout_pipe_reader, buffer, sizeof(buffer), &bytes_read, NULL)) {
		output.write(buffer, bytes_read);
	}
	const DWORD		read_error = GetLastError();
	if (read_error != ERROR_BROKEN_PIPE) {
		throw System_error("ReadFile", "", read_error);
	}

	CloseHandle(stdout_pipe_reader);

	int			exit_code = wait_for_child(child_handle);
	CloseHandle(child_handle);
	return exit_code;
}
示例#13
0
void	touch_file (const std::string& filename)
{
	HANDLE	fh = CreateFileA(filename.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (fh == INVALID_HANDLE_VALUE) {
		throw System_error("CreateFileA", filename, GetLastError());
	}
	SYSTEMTIME	system_time;
	GetSystemTime(&system_time);
	FILETIME	file_time;
	SystemTimeToFileTime(&system_time, &file_time);

	if (!SetFileTime(fh, NULL, NULL, &file_time)) {
		DWORD	error = GetLastError();
		CloseHandle(fh);
		throw System_error("SetFileTime", filename, error);
	}
	CloseHandle(fh);
}
示例#14
0
size_t		Coprocess::write_stdin (void* handle, const void* buf, size_t count)
{
	const int	fd = static_cast<Coprocess*>(handle)->stdin_pipe_writer;
	ssize_t		ret;
	while ((ret = write(fd, buf, count)) == -1 && errno == EINTR); // restart if interrupted
	if (ret < 0) {
		throw System_error("write", "", errno);
	}
	return ret;
}
示例#15
0
size_t		Coprocess::read_stdout (void* handle, void* buf, size_t count)
{
	const int	fd = static_cast<Coprocess*>(handle)->stdout_pipe_reader;
	ssize_t		ret;
	while ((ret = read(fd, buf, count)) == -1 && errno == EINTR); // restart if interrupted
	if (ret < 0) {
		throw System_error("read", "", errno);
	}
	return ret;
}
示例#16
0
void	remove_file (const std::string& filename)
{
	if (!DeleteFileA(filename.c_str())) {
		DWORD	error = GetLastError();
		if (error == ERROR_FILE_NOT_FOUND) {
			return;
		} else {
			throw System_error("DeleteFileA", filename, error);
		}
	}
}
示例#17
0
int exec_command_with_input (const std::vector<std::string>& command, const char* p, size_t len)
{
	HANDLE			stdin_pipe_reader = NULL;
	HANDLE			stdin_pipe_writer = NULL;
	SECURITY_ATTRIBUTES	sec_attr;

	// Set the bInheritHandle flag so pipe handles are inherited.
	sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
	sec_attr.bInheritHandle = TRUE;
	sec_attr.lpSecurityDescriptor = NULL;

	// Create a pipe for the child process's STDIN.
	if (!CreatePipe(&stdin_pipe_reader, &stdin_pipe_writer, &sec_attr, 0)) {
		throw System_error("CreatePipe", "", GetLastError());
	}

	// Ensure the write handle to the pipe for STDIN is not inherited.
	if (!SetHandleInformation(stdin_pipe_writer, HANDLE_FLAG_INHERIT, 0)) {
		throw System_error("SetHandleInformation", "", GetLastError());
	}

	HANDLE			child_handle = spawn_command(command, stdin_pipe_reader, NULL, NULL);
	CloseHandle(stdin_pipe_reader);

	// Write to stdin_pipe_writer.
	while (len > 0) {
		DWORD		bytes_written;
		if (!WriteFile(stdin_pipe_writer, p, len, &bytes_written, NULL)) {
			throw System_error("WriteFile", "", GetLastError());
		}
		p += bytes_written;
		len -= bytes_written;
	}

	CloseHandle(stdin_pipe_writer);

	int			exit_code = wait_for_child(child_handle);
	CloseHandle(child_handle);
	return exit_code;
}
示例#18
0
std::ostream*	Coprocess::stdin_pipe ()
{
	if (!stdin_pipe_ostream) {
		int	fds[2];
		if (pipe(fds) == -1) {
			throw System_error("pipe", "", errno);
		}
		stdin_pipe_reader = fds[0];
		stdin_pipe_writer = fds[1];
		stdin_pipe_ostream = new ofhstream(this, write_stdin);
	}
	return stdin_pipe_ostream;
}
示例#19
0
std::istream*	Coprocess::stdout_pipe ()
{
	if (!stdout_pipe_istream) {
		int	fds[2];
		if (pipe(fds) == -1) {
			throw System_error("pipe", "", errno);
		}
		stdout_pipe_reader = fds[0];
		stdout_pipe_writer = fds[1];
		stdout_pipe_istream = new ifhstream(this, read_stdout);
	}
	return stdout_pipe_istream;
}
示例#20
0
std::string our_exe_path ()
{
	std::vector<char>	buffer(128);
	size_t			len;

	while ((len = GetModuleFileNameA(NULL, &buffer[0], buffer.size())) == buffer.size()) {
		// buffer may have been truncated - grow and try again
		buffer.resize(buffer.size() * 2);
	}
	if (len == 0) {
		throw System_error("GetModuleFileNameA", "", GetLastError());
	}

	return std::string(buffer.begin(), buffer.begin() + len);
}
示例#21
0
std::istream*	Coprocess::stdout_pipe ()
{
	if (!stdout_pipe_istream) {
		SECURITY_ATTRIBUTES	sec_attr;

		// Set the bInheritHandle flag so pipe handles are inherited.
		sec_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
		sec_attr.bInheritHandle = TRUE;
		sec_attr.lpSecurityDescriptor = nullptr;

		// Create a pipe for the child process's STDOUT.
		if (!CreatePipe(&stdout_pipe_reader, &stdout_pipe_writer, &sec_attr, 0)) {
			throw System_error("CreatePipe", "", GetLastError());
		}

		// Ensure the read handle to the pipe for STDOUT is not inherited.
		if (!SetHandleInformation(stdout_pipe_reader, HANDLE_FLAG_INHERIT, 0)) {
			throw System_error("SetHandleInformation", "", GetLastError());
		}

		stdout_pipe_istream = new ifhstream(this, read_stdout);
	}
	return stdout_pipe_istream;
}
示例#22
0
void	mkdir_parent (const std::string& path)
{
	std::string::size_type		slash(path.find('/', 1));
	while (slash != std::string::npos) {
		std::string		prefix(path.substr(0, slash));
		if (GetFileAttributes(prefix.c_str()) == INVALID_FILE_ATTRIBUTES) {
			// prefix does not exist, so try to create it
			if (!CreateDirectory(prefix.c_str(), NULL)) {
				throw System_error("CreateDirectory", prefix, GetLastError());
			}
		}

		slash = path.find('/', slash + 1);
	}
}
示例#23
0
void	mkdir_parent (const std::string& path)
{
    std::string::size_type		slash(path.find('/', 1));
    while (slash != std::string::npos) {
        std::string		prefix(path.substr(0, slash));
        struct stat		status;
        if (stat(prefix.c_str(), &status) == 0) {
            // already exists - make sure it's a directory
            if (!S_ISDIR(status.st_mode)) {
                throw System_error("mkdir_parent", prefix, ENOTDIR);
            }
        } else {
            if (errno != ENOENT) {
                throw System_error("mkdir_parent", prefix, errno);
            }
            // doesn't exist - mkdir it
            if (mkdir(prefix.c_str(), 0777) == -1) {
                throw System_error("mkdir", prefix, errno);
            }
        }

        slash = path.find('/', slash + 1);
    }
}
示例#24
0
size_t		Coprocess::read_stdout (void* handle, void* buf, size_t count)
{
	// Note that ReadFile on a pipe may return with bytes_read==0 if the other
	// end of the pipe writes zero bytes, so retry when this happens.
	// When the other end of the pipe actually closes, ReadFile
	// fails with ERROR_BROKEN_PIPE.
	DWORD bytes_read;
	do {
		if (!ReadFile(static_cast<Coprocess*>(handle)->stdout_pipe_reader, buf, count, &bytes_read, nullptr)) {
			const DWORD	read_error = GetLastError();
			if (read_error != ERROR_BROKEN_PIPE) {
				throw System_error("ReadFile", "", read_error);
			}
			return 0;
		}
	} while (bytes_read == 0);
	return bytes_read;
}
示例#25
0
void	remove_file (const std::string& filename)
{
    if (unlink(filename.c_str()) == -1 && errno != ENOENT) {
        throw System_error("unlink", filename, errno);
    }
}
示例#26
0
void	touch_file (const std::string& filename)
{
    if (utimes(filename.c_str(), NULL) == -1 && errno != ENOENT) {
        throw System_error("utimes", filename, errno);
    }
}
示例#27
0
文件: titus.cpp 项目: AGWA/titus
int main (int argc, char** argv)
try {
	init_signals();

	// Initialize OpenSSL
	ERR_load_crypto_strings();
	SSL_library_init();
	SSL_load_error_strings();

	// This cipher list is the "Intermediate compatibility" list from https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 as of 2014-12-09
	vhost_defaults.ciphers = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
	vhost_defaults.dhgroup = make_dh(dh_group14_prime, dh_group14_generator); // 2048 bit group
	vhost_defaults.ecdhcurve = get_ecdhcurve("prime256v1"); // a.k.a. secp256r1

	// Set default SSL options, which can be overridden by config file
	vhost_defaults.ssl_options[SSL_OP_NO_COMPRESSION] = true;
	vhost_defaults.ssl_options[SSL_OP_NO_SSLv3] = true;
	vhost_defaults.ssl_options[SSL_OP_NO_TLSv1] = false;
	vhost_defaults.ssl_options[SSL_OP_NO_TLSv1_1] = false;
	vhost_defaults.ssl_options[SSL_OP_NO_TLSv1_2] = false;
	vhost_defaults.ssl_options[SSL_OP_CIPHER_SERVER_PREFERENCE] = true;

	// These can't be overriden by config file:
	vhost_defaults.ssl_options[SSL_OP_SINGLE_DH_USE] = true;
	vhost_defaults.ssl_options[SSL_OP_SINGLE_ECDH_USE] = true;
	vhost_defaults.ssl_options[SSL_OP_NO_SSLv2] = true;

	// Command line arguments come in pairs of the form "--name value" and correspond
	// directly to the name/value option pairs in the config file (a la OpenVPN).
	for (int i = 1; i < argc; ) {
		if (std::strncmp(argv[i], "--", 2) == 0 && i + 1 < argc) {
			process_config_param(argv[i] + 2, argv[i+1]);
			i += 2;
		} else {
			std::clog << argv[0] << ": Bad arguments" << std::endl;
			return 2;
		}
	}

	if (vhost_configs.empty()) {
		// No vhosts specified, so add one implicitly that matches all local addresses / SNI names.
		// It will use the options from vhost_defaults.
		vhost_configs.emplace_back();
	}

	for (size_t i = 0; i < vhost_configs.size(); ++i) {
		vhosts.emplace_back();
		Vhost&		vhost(vhosts.back());
		Vhost_config&	config(vhost_configs[i]);

		vhost.id = i;
		vhost.servername_set = config.servername_set;
		vhost.servername = config.servername;
		init_ssl_ctx(vhost, config);
		resolve_addresses(vhost, config);
	}
	// Free up some memory that's no longer needed:
	vhost_configs.clear();
	vhost_defaults = Basic_vhost_config();

	// Listen
	listening_sock = socket(AF_INET6, SOCK_STREAM, 0);
	if (listening_sock == -1) {
		throw System_error("socket", "", errno);
	}
	set_reuseaddr(listening_sock);
	set_not_v6only(listening_sock);
	if (transparent == TRANSPARENT_ON) {
		set_transparent(listening_sock);
	}

	// TODO: support binding to specific IP addresses
	struct sockaddr_in6	listening_address;
	std::memset(&listening_address, '\0', sizeof(listening_address));
	listening_address.sin6_family = AF_INET6;
	listening_address.sin6_addr = in6addr_any;
	listening_address.sin6_port = htons(listening_port);
	if (bind(listening_sock, reinterpret_cast<const struct sockaddr*>(&listening_address), sizeof(listening_address)) == -1) {
		throw System_error("bind", "", errno);
	}

	if (listen(listening_sock, SOMAXCONN) == -1) {
		throw System_error("listen", "", errno);
	}

	// Set up UNIX domain socket for communicating with the key server.
	// Put it in a temporary directory with restrictive permissions so
	// other users can't traverse its path.  We have to use a named
	// socket as opposed to a socketpair because we need every child process
	// to communicate with the key server using its own socket.  (Duping one
	// end of a socketpair wouldn't work because then every child would
	// be referring to the same underlying socket, which provides
	// insufficient isolation.)
	temp_directory = make_temp_directory();
	filedesc keyserver_sock(make_unix_socket(temp_directory + "/server.sock", &keyserver_sockaddr, &keyserver_sockaddr_len));
	if (listen(keyserver_sock, SOMAXCONN) == -1) {
		throw System_error("listen", "", errno);
	}

	// Write PID file, daemonize, etc.
	std::ofstream		pid_file_out;
	if (!pid_file.empty()) {
		// Open PID file before forking so we can report errors
		pid_file_out.open(pid_file.c_str(), std::ofstream::out | std::ofstream::trunc);
		if (!pid_file_out) {
			throw Configuration_error("Unable to open PID file " + pid_file + " for writing.");
		}
		pid_file_created = true;
	}
	if (run_as_daemon) {
		daemonize();
	}
	if (pid_file_out) {
		pid_file_out << getpid() << '\n';
		pid_file_out.close();
	}

	// Spawn the master key server process
	keyserver_pid = spawn(keyserver_main, std::move(keyserver_sock));

	// Spawn spare children to accept() and service connections
	if (pipe(children_pipe) == -1) {
		throw System_error("pipe", "", errno);
	}
	set_nonblocking(children_pipe[0], true);

	spawn_children();

	// Wait for signals and readability on children_pipe
	sigset_t		empty_sigset;
	sigemptyset(&empty_sigset);
	fd_set			readfds;
	FD_ZERO(&readfds);
	FD_SET(children_pipe[0], &readfds);

	is_running = 1;
	struct timespec		timeout = { 2, 0 };
	int			select_res = 0;
	while (is_running && ((select_res = pselect(children_pipe[0] + 1, &readfds, NULL, NULL, failed_children ? &timeout : NULL, &empty_sigset)) >= 0 || errno == EINTR)) {
		if (failed_children && std::time(NULL) >= last_failed_child_time + 2) {
			failed_children = 0;
		}
		if (pending_sigchld) {
			on_sigchld();
			pending_sigchld = 0;
		}
		if (select_res > 0) {
			read_children_pipe();
		}
		FD_SET(children_pipe[0], &readfds);
	}

	if (is_running && select_res == -1) {
		throw System_error("pselect", "", errno);
	}


	cleanup();
	return 0;
} catch (const System_error& error) {
	std::clog << "titus: System error: " << error.syscall;
	if (!error.target.empty()) {
		std::clog << ": " << error.target;
	}
	std::clog << ": " << std::strerror(error.number) << std::endl;
	cleanup();
	return 3;
} catch (const Openssl_error& error) {
	std::clog << "titus: OpenSSL error: " << error.message() << std::endl;
	cleanup();
	return 4;
} catch (const Configuration_error& error) {
	std::clog << "titus: Configuration error: " << error.message << std::endl;
	cleanup();
	return 5;
} catch (const Too_many_failed_children& error) {
	// TODO: better error reporting when this happens
	std::clog << "titus: Too many child processes failed." << std::endl;
	cleanup();
	return 7;
} catch (const Keyserver_died& error) {
	// TODO: better error reporting when this happens
	std::clog << "titus: Key server died." << std::endl;
	cleanup();
	return 8;
}
示例#28
0
void	remove_file (const std::string& filename)
{
	if (!DeleteFileA(filename.c_str())) {
		throw System_error("DeleteFileA", filename, GetLastError());
	}
}