static bool run(int argc, char *const argv[])
{
    struct passwd* userInfo = getpwuid(getuid());
    if (!userInfo) {
        fprintf(stderr, "Couldn't get the current user: %s.\n", strerror(errno));
        return false;
    }
    appendDirectoryComponent(sandboxDirectory, userInfo->pw_dir, "/.wk2-sandbox");

    // Currently we use 'nobody' user as the sandbox user and fall back to the real user
    // if we failed to get it (we could extend this in the future with a specific restricted user).
    if (struct passwd* nobodyUser = getpwnam("nobody")) {
        sandboxUserUID = nobodyUser->pw_uid;
        sandboxUserGID = nobodyUser->pw_gid;
    } else {
        sandboxUserUID = getuid();
        sandboxUserGID = getgid();
    }

    // We should have three parameters:
    // path_of_this_binary path_of_the_webprocess socket_to_communicate_with_uiprocess
    if (argc != 3) {
        fprintf(stderr, "Starting SandboxProcess requires 3 parameters!\n");
        return false;
    }

    // SandboxProcess should be run with suid flag ...
    if (geteuid()) {
        fprintf(stderr, "The sandbox is not seteuid root.\n");
        return false;
    }

    // ... but not as root (not with sudo).
    if (!getuid()) {
        fprintf(stderr, "The sandbox is not designed to be run by root.\n");
        return false;
    }

    if (!initializeSandbox())
        return false;

    if (!restrictCapabilities())
        return false;

    // We move ourself and our children into a new PID namespace,
    // where process IDs start from 0 again.
    if (!moveToNewPIDNamespace())
        return false;

    // Starting a helper what will waiting for the "chrootme" message from WebProcess.
    if (!prepareAndStartChangeRootHelper())
        return false;

    // We don't need any special privileges anymore.
    if (!dropPrivileges())
        return false;

    // Sanity check: if our effective or real uid/gid is still 0 (root) or
    // we can set any of them to 0, then the dropping of privileges is failed.
    // We ensure here that we cannot set root id after here.
    if (!geteuid() || !getegid() || !setuid(0) || !setgid(0)) {
        fprintf(stderr, "Dropping privileges failed!\n");
        return false;
    }

    // Start the WebProcess.
    if (execl(argv[1], argv[1], argv[2], reinterpret_cast<char*>(0)) == -1) {
        fprintf(stderr, "Couldn't start WebProcess: %s\n", strerror(errno));
        return false;
    }
    return true;
}
int main(int argc, char * const argv[])
{
	struct option long_options[] = {
		{ "daemon", no_argument, nullptr, 'd' },
		{ "user", required_argument, nullptr, 'u' },
		{ "varnish", required_argument, nullptr, 'v' },
		{ "redis", required_argument, nullptr, 'r' },
		{ 0, 0, 0, 0 }
	};

	bool daemonize = false;
	std::string userName;
	std::string varnishAddr;
	std::string redisAddr;

	for (bool done = false; !done; ) {
		int long_index = 0;
		switch (getopt_long(argc, argv, "hdu:v:r:", long_options, &long_index)) {
			case 'h':
				printHelp();
				return 0;
			case 'd':
				daemonize = true;
				break;
			case 'u':
				userName = optarg;
				break;
			case 'v':
				varnishAddr = optarg;
				break;
			case 'r':
				redisAddr = optarg;
				break;
			case 0: // long opt with value != NULL
				done = true;
				break;
			case '?': // ambiguous match / unknown arg
				printHelp();
				return 1;
			default:
				done = true;
				break;
		}
	}

	if (varnishAddr.empty() || redisAddr.empty()) {
		printf("varnish: %s\n", varnishAddr.c_str());
		printf("redis: %s\n", redisAddr.c_str());
		printHelp();
		return 2;
	}

	if (!dropPrivileges(userName))
		return 3;

	ev::default_loop ev;

	auto varnish_config = std::make_shared<varnish_cfg>();
	if (!parseAddress(varnishAddr, varnish_config->host, varnish_config->port))
		return 4;

	auto redis_config = std::make_shared<redis_cfg>();
	redis_config->skey = REDIS_QUEUE_KEY;
	if (!parseAddress(redisAddr, redis_config->host, redis_config->port))
		return 5;

	std::unique_ptr<PurgeWorker> worker(new PurgeWorker(ev, redis_config.get(), varnish_config.get()));

	if (daemonize && ::daemon(false /*no chdir?*/, false /*no close?*/) < 0) {
		fprintf(stderr, "Daemonizing failed: %s\n", strerror(errno));
		return 6;
	}

	worker->run();

	return 0;
}