int main(int argc, char **argv)
{
	static const daemon_winsvc_options svc_opts = {
	"-s", "test", "Test Service", "Service to test daemon_win32.c Module"
	};

	return daemon_main("testd", &svc_opts, test_main, argc, argv);
}
Exemple #2
0
int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
	// t1031 - tell dprintf not to exit if it can't write to the log
	// we have to do this before dprintf_config is called
	// (which happens inside dc_main), otherwise KBDD on Win32 will
	// except in dprintf_config if the log directory isn't writable
	// by the current user.
	dprintf_config_ContinueOnFailure( TRUE );

	// cons up a "standard" argc,argv for daemon_main.

	/*
	Due to the risk of spaces in paths on Windows, we use the function
	CommandLineToArgvW to extract a list of arguments instead of parsing
	the string using a delimiter.
	*/
	LPWSTR cmdLine = GetCommandLineW();	 // do not free this pointer!
	if(!cmdLine)
	{
		return GetLastError();
	}

	int cArgs = 0;
	LPWSTR* cmdArgs = CommandLineToArgvW(cmdLine, &cArgs);
	if(!cmdArgs)
	{
		return GetLastError();
	}
	char **parameters = (char**)malloc(sizeof(char*)*cArgs + 1);
	ASSERT( parameters != NULL );
	parameters[0] = "condor_kbdd";
	parameters[cArgs] = NULL;

	/*
	List of strings is in unicode so we need to downconvert it into ascii strings.
	*/
	for(int counter = 1; counter < cArgs; ++counter)
	{
		//There's a *2 on the size to provide some leeway for non-ascii characters being split.  Suggested by TJ.
		int argSize = ((wcslen(cmdArgs[counter]) + 1) * sizeof(char)) * 2;
		parameters[counter] = (char*)malloc(argSize);
		ASSERT( parameters[counter] != NULL );
		int converted = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, cmdArgs[counter], -1, parameters[counter], argSize, NULL, NULL);
		if(converted == 0)
		{
			return GetLastError();
		}
	}
	LocalFree((HLOCAL)cmdArgs);

	// check to see if we are running as a service, and if we are
	// add a Run key value to the registry for HKLM so that the kbdd
	// will run as the user whenever a user logs on.
	hack_kbdd_registry();

	// call the daemon main function which is common between Windows and ! Windows.
	return daemon_main(cArgs, parameters);
}
Exemple #3
0
int main(int argc, char *argv[]) 
{
	int ret;

	co_debug_start();

	ret = daemon_main(argc, argv);

	co_debug_end();

	return ret;
}
Exemple #4
0
int main(int argc, char **argv)
{
	std::string config_filename = sdns::conf[sdns::CONFIG_FILE], daemon_name = "sdns";
	bool daemonize = false;
#ifndef WINDOWS
	srandom((size_t)(&sdns::conf) + time(nullptr));
	for(int opt; (opt = getopt(argc, argv, "c:ds:")) != -1;) {
		switch(opt) {
		case 'c': // config filename
			config_filename = optarg;
			break;
		case 'd': // daemonize
			daemonize = true;
			break;
		case 's': // syslog daemon name
			daemon_name = optarg;
		default: // '?'
			std::cerr << "Usage: " << argv[0] << " [-c config_filename] [-d (daemonize)] [-s syslog_daemon_name]" << std::endl;
			exit(EXIT_FAILURE);
		}
	}
	if(optind < argc) {
		eout() << "Unexpected argument: " << argv[optind];
		exit(EXIT_FAILURE);
	}
#endif
	sdns::conf.set_config_file(config_filename);
	try {
		if(daemonize)
			return daemon_start(&daemon_main, daemon_name.c_str());
		else
			return daemon_main();
	} catch(const e_exception &e) {
		eout() << "main() caught fatal or unhandled error: " << e;
		std::cerr << daemon_name << " main() caught fatal or unhandled error: " << e << std::endl;
	}
	return EXIT_FAILURE;
}
Exemple #5
0
int main(int argc, char* argv[]) {
	pid_t pid = 0;
	pid_t sid = 0;
	pid_t pid2 = 0;
	int status;

	pid = fork();

	if(pid < 0) {
		puts("first fork failed!");
		exit(1);
	} else if(pid > 0) {
		waitpid(pid, &status, NULL);
		exit(0);
	} else {
		umask(0);
		sid = setsid();

		if(sid < 0) {
			puts("set session id failed!");
			exit(1);
		}

		chdir("/");

		pid2 = fork();
		
		if(pid2 < 0) {
			puts("second fork failed!");
			exit(1);
		} else if(pid2 > 0) {
			exit(0);
		} else {
			daemon_main();
		}
	}
}
Exemple #6
0
int main(int argc, char* argv[]) {
	char opts[] = "dDi:";
	char c;
	int isDebug = 0, isDaemon = 0, res = 0;
	char *cmd = NULL, *comp = NULL, inst[2] = {0};
	progName = argv[0];
	if(argc < 2)
		Usage(1);
	while((c = getopt(argc, argv, opts)) != -1) {
		switch (c) {
		case 'd':
			isDebug = 1;
			// fall through
		case 'D':
			isDaemon = 1;
			break;
		case 'i':
			memcpy(inst, optarg, 1);
			break;
		case '?':
			if (optopt == 'c')
				fprintf(stderr, "Missing argument for option -%c\n", optopt);
			else if (isprint(optopt))
				fprintf(stderr, "Unknown option -%c\n", optopt);
			Usage(0);
			break;
		}
	}
	if(optind < argc && isDaemon){
		fprintf(stderr, "Cannot start daemon with additional arguments.\n");
		Usage(1);
	}
	while (optind < argc) {
		char *arg = argv[optind++];
		switch(arg[0]){
		case 's':
			switch(arg[1]){
			case 't':
				if(strcmp(arg, "start"))
					cmd = "stop";
				else
					cmd = "start";
				break;
			case 'm':
				comp = "sm";
				break;
			default:
				fprintf(stderr, "Unknown parameter %s\n", arg);
				Usage(1);
			}
			break;
		case 'r':
			if (strcmp(arg, "restart")) {
				fprintf(stderr, "Unknown parameter %s\n", arg);
				Usage(1);
			} else {
				cmd = "restart";
			}
			break;
		case 'f':
			if (strcmp(arg, "fe")) {
				fprintf(stderr, "Unknown parameter %s\n", arg);
				Usage(1);
			} else {
				comp = "fe";
			}
			break;
		case 'h':
			if (strcmp(arg, "halt")){
				fprintf(stderr, "Unknown parameter %s\n", arg);
				Usage(1);
			} else {
				int fd;
				if((fd = open(OPAFMD_PIPE, O_WRONLY|O_NONBLOCK)) == -1){
					// Daemon is already stopped
					exit(0);
				}
				res = write(fd, "stop\n", 5);	// write stop command without parameters to named pipe to kill it softly. With our words.
				if(res <= 0){
					//Something went wrong while writing to pipe.
					fprintf(stderr, "Failed to send stop command to daemon: %s\n", strerror(errno));
					close(fd);
					exit(2);
				}
				close(fd);

				// Wait until the pipe stops existing.
				while (access(OPAFMD_PIPE, F_OK) != -1) {
					usleep(100000);
				}
				exit(0);
			}
		default:
			fprintf(stderr, "Unknown parameter %s\n", arg);
			Usage(1);
		}
	}
	if(isDaemon){
		if (isDebug) {
			// don't fork if debug
			return daemon_main();
		}
		// Here we fork the daemon and if successful...
		switch(fork()){
		case 0:
			// daemon inits it's main loop
			return daemon_main();
		case -1:
			fprintf(stderr, "Failed to fork.\n");
			return 2;
		default:
			return 0;
		}
	} else {
		char prog[] = "/usr/lib/opa-fm/bin/opafmctrl";
		if(inst[0] != 0){
			if(comp != NULL)
				execle(prog, prog, cmd, "-i", inst, comp, NULL, nullEnv);	// Call opafmctl with instance number and component,
			else
				execle(prog, prog, cmd, "-i", inst, NULL, nullEnv);			// only with instance number,
		} else {
			if(comp != NULL)
				execle(prog, prog, cmd, comp, NULL, nullEnv);				// only with component,
			else
				execle(prog, prog, cmd, NULL, nullEnv);						// or without additional arguments.
		}
	}
	return 0;
}
Exemple #7
0
int neverbleed_init(neverbleed_t *nb, char *errbuf)
{
    int pipe_fds[2] = {-1, -1}, listen_fd = -1;
    char *tempdir = NULL;

    const RSA_METHOD *default_method = RSA_PKCS1_SSLeay();
    rsa_method.rsa_pub_enc = default_method->rsa_pub_enc;
    rsa_method.rsa_pub_dec = default_method->rsa_pub_dec;
    rsa_method.rsa_verify = default_method->rsa_verify;

    /* setup the daemon */
    if (pipe(pipe_fds) != 0) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "pipe(2) failed:%s", strerror(errno));
        goto Fail;
    }
    fcntl(pipe_fds[1], F_SETFD, O_CLOEXEC);
    if ((tempdir = strdup("/tmp/openssl-privsep.XXXXXX")) == NULL) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "no memory");
        goto Fail;
    }
    if (mkdtemp(tempdir) == NULL) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to create temporary directory under /tmp:%s", strerror(errno));
        goto Fail;
    }
    memset(&nb->sun_, 0, sizeof(nb->sun_));
    nb->sun_.sun_family = AF_UNIX;
    snprintf(nb->sun_.sun_path, sizeof(nb->sun_.sun_path), "%s/_", tempdir);
    RAND_bytes(nb->auth_token, sizeof(nb->auth_token));
    if ((listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "socket(2) failed:%s", strerror(errno));
        goto Fail;
    }
    if (bind(listen_fd, (void *)&nb->sun_, sizeof(nb->sun_)) != 0) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to bind to %s:%s", nb->sun_.sun_path, strerror(errno));
        goto Fail;
    }
    if (listen(listen_fd, SOMAXCONN) != 0) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "listen(2) failed:%s", strerror(errno));
        goto Fail;
    }
    switch (fork()) {
    case -1:
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "fork(2) failed:%s", strerror(errno));
        goto Fail;
    case 0:
        close(pipe_fds[1]);
#ifdef __linux__
        prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
#endif
        memcpy(daemon_auth_token, nb->auth_token, NEVERBLEED_AUTH_TOKEN_SIZE);
        daemon_main(listen_fd, pipe_fds[0], tempdir);
        break;
    default:
        break;
    }
    close(listen_fd);
    listen_fd = -1;
    close(pipe_fds[0]);
    pipe_fds[0] = -1;

    /* setup engine */
    if ((nb->engine = ENGINE_new()) == NULL ||
        !ENGINE_set_id(nb->engine, "neverbleed") ||
        !ENGINE_set_name(nb->engine, "privilege separation software engine") ||
        !ENGINE_set_RSA(nb->engine, &rsa_method)) {
        snprintf(errbuf, NEVERBLEED_ERRBUF_SIZE, "failed to initialize the OpenSSL engine");
        goto Fail;
    }
    ENGINE_add(nb->engine);

    /* setup thread key */
    pthread_key_create(&nb->thread_key, dispose_thread_data);

    free(tempdir);
    return 0;
Fail:
    if (pipe_fds[0] != -1)
        close(pipe_fds[0]);
    if (pipe_fds[1] != -1)
        close(pipe_fds[1]);
    if (tempdir != NULL) {
        unlink_dir(tempdir);
        free(tempdir);
    }
    if (listen_fd != -1)
        close(listen_fd);
    if (nb->engine != NULL) {
        ENGINE_free(nb->engine);
        nb->engine = NULL;
    }
    return -1;
}
Exemple #8
0
int
main( int argc, char **argv )
{
	return daemon_main(argc, argv);
}
Exemple #9
0
Fichier : god.c Projet : 7AC/beats
int main(int argc, char **argv) {
	char rundir[PATH_MAX];
	char user[64];
	char group[64];
	int foreground = 0;
	struct stat exec_stat;

	memset(logfile, 0, sizeof logfile);
	memset(pidfile, 0, sizeof pidfile);
	memset(rundir, 0, sizeof rundir);
	memset(user, 0, sizeof user);
	memset(group, 0, sizeof group);

	static struct option opts[] = {
		{ "help",      no_argument,       NULL, 'h' },
		{ "version",   no_argument,       NULL, 'v' },
		{ "foreground", no_argument,      NULL, 'f' },
		{ "nohup",     no_argument,       NULL, 'n' },
		{ "logfile",   required_argument, NULL, 'l' },
		{ "pidfile",   required_argument, NULL, 'p' },
		{ "rundir",    required_argument, NULL, 'r' },
		{ "user",      required_argument, NULL, 'u' },
		{ "group",     required_argument, NULL, 'g' },
		{ NULL, 0, NULL, 0 },
	};

	int ch;
	while (1) {
		ch = getopt_long(argc, argv, "l:p:r:u:g:hvfns", opts, NULL);
		if (ch == -1)
			break;

		switch (ch) {
			case 'v':
				printf("Go daemon v1.2\n");
				printf("http://github.com/fiorix/go-daemon\n");
				return 0;
			case 'f':
				foreground = 1;
				break;
			case 'n':
				nohup = 1;
				break;
			case 'l':
				strncpy(logfile, optarg, sizeof logfile - 1);
				break;
			case 'p':
				strncpy(pidfile, optarg, sizeof pidfile - 1);
				break;
			case 'r':
				strncpy(rundir, optarg, sizeof rundir - 1);
				break;
			case 'u':
				strncpy(user, optarg, sizeof user - 1);
				break;
			case 'g':
				strncpy(group, optarg, sizeof group - 1);
				break;
			default:
				usage();
		}
	}

	// utility is expected to be argv's leftovers.
	if (optind >= argc)
		usage();

	if (*rundir != 0 && chdir(rundir) == -1) {
		perror("failed to switch to rundir");
		return 1;
	}

	if (*user != 0 && (pwd = getpwnam(user)) == NULL) {
		fprintf(stderr, "failed to switch to user %s: %s\n",
				user, strerror(errno));
		return 1;
	}

	if (*group != 0 && (grp = getgrnam(group)) == NULL) {
		fprintf(stderr, "failed to switch to group %s: %s\n",
				group, strerror(errno));
		return 1;
	}

	if (*logfile != 0 && (logfp = fopen(logfile, "a")) == NULL) {
		perror("failed to open logfile");
		return 1;
	}
	if (logfp)
		setvbuf(logfp, linebuf, _IOLBF, sizeof linebuf);

	if (*pidfile != 0 && (pidfp = fopen(pidfile, "w+")) == NULL) {
		perror("failed to open pidfile");
		return 1;
	}

	if (grp != NULL && setegid(grp->gr_gid) == -1) {
		fprintf(stderr, "failed to switch to group %s: %s\n",
				group, strerror(errno));
		return 1;
	}

	if (pwd != NULL && seteuid(pwd->pw_uid) == -1) {
		fprintf(stderr, "failed to switch to user %s: %s\n",
				user, strerror(errno));
		return 1;
	}

	if (stat(argv[optind], &exec_stat) < 0) {
		fprintf(stderr, "failed to stat %s: %s\n",
				 argv[optind], strerror(errno));
		return 1;
	}
	if (!(exec_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
		fprintf(stderr, "permission denied: %s\n",
				argv[optind]);
		return 1;
	}

        if (foreground) {
                daemon_main(optind, argv);
        } else {
		// Daemonize.
		pid_t pid = fork();
		if (pid) {
			waitpid(pid, NULL, 0);
		} else if (!pid) {
			if ((pid = fork())) {
				exit(0);
			} else if (!pid) {
				close(0);
				close(1);
				close(2);
				daemon_main(optind, argv);
			} else {
				perror("fork");
				exit(1);
			}
		} else {
			perror("fork");
			exit(1);
		}
	}

	return 0;
}
Exemple #10
0
int ACEApp::init(int argc, ACE_TCHAR* argv[])
{
    // get the program name
#ifdef WIN32
    char* ptr = ACE_OS::strrchr(argv[0], '\\');
#else
    char* ptr = ACE_OS::strrchr(argv[0], '/');
#endif    
    if (ptr)
    {
        // strip path name
        strcpy(program_, ptr + 1);
    }
    else
    {
        strcpy(program_, argv[0]);
    }
#ifdef WIN32
    // strip .exe extension on WIN32
    ptr = strchr(program_, '.');
    if (ptr)
    {
        *ptr = '\0';
    }
#endif

    int child_proc_num = 0;
    ACE_Get_Opt get_opt(argc, argv, "vdp:c:"); 
    char c;
    while ((c = get_opt()) != EOF)
    {
        switch (c)
        {
            case 'd': // run as daemon
                ACE::daemonize();
                break;
            case 'p': // specified program name
                strcpy(program_, get_opt.opt_arg());
                break;
            case 'c': // child process number
                child_proc_num = atoi(get_opt.opt_arg());
                break;
            case 'v':
                //disp version info
                disp_version();
                return 0;
            default:
                break;
        }
    }

    ACE_OS::signal (SIGPIPE, SIG_IGN);
    ACE_OS::signal (SIGTERM, SIG_IGN);
    ACE_OS::signal (SIGCHLD, SIG_IGN);
    ACE_Sig_Action sig_int((ACE_SignalHandler)daemon_quit, SIGINT);
    //ACE_Sig_Action sig_term((ACE_SignalHandler)daemon_quit, SIGTERM);
    //ACE_Sig_Action sig_chld((ACE_SignalHandler)child_sighdr, SIGCHLD);
    ACE_UNUSED_ARG(sig_int);
    //ACE_UNUSED_ARG(sig_term);
    //ACE_UNUSED_ARG(sig_chld);
    
    //在 init_log() 之前即可    
    if (init_reactor() != 0)
    {
        ACE_DEBUG((LM_ERROR, "[%D] init reactor failed, program exit\n"));
        return -1;
    }
    ACE_DEBUG((LM_INFO, "[%D] init reactor succ\n"));

    if (init_sys_path(program_) != 0)
    {
        ACE_DEBUG((LM_ERROR, "[%D] init sys path failed, program exit\n"));
        return -1;
    }

    if (init_conf() != 0)
    {
        ACE_DEBUG((LM_ERROR, "[%D] init conf failed, program exit\n"));
        return -1;
    }
    ACE_DEBUG((LM_INFO, "[%D] init conf succeed\n"));

    if (init_log() != 0)
    {
        ACE_DEBUG((LM_ERROR, "[%D] init log failed, program exit\n"));
        return -1;
    }
    ACE_DEBUG((LM_INFO, "[%D] init log succ\n"));
    
    //版本信息记录日志
    disp_version();

    if (init_app(argc, argv) != 0)
    {
        ACE_DEBUG((LM_ERROR, "[%D] init app failed, program exit\n"));
        return -1;
    }
    ACE_DEBUG((LM_INFO, "[%D] init app succ\n"));

    write_pid_file();
    ACE_DEBUG((LM_INFO, "[%D] write pid file succ\n"));

    if (child_proc_num > 0)
    {
        parent_main(child_proc_num);
    }
    else
    {
        ACE_DEBUG((LM_INFO, "[%D] enter daemon main pid: %d\n",
            ACE_OS::getpid()));

        daemon_main();

        ACE_DEBUG((LM_INFO, "[%D] leave daemon main pid: %d\n",
            ACE_OS::getpid()));
    }

    quit_app();

    return 0;
}
Exemple #11
0
void ACEApp::child_main()
{
    daemon_main();
}
Exemple #12
0
/**
 * Main fake event test program. Setup, teardown and report errors.
 * @param argc: arg count.
 * @param argv: array of commandline arguments.
 * @return program failure if test fails.
 */
int
main(int argc, char* argv[])
{
    int c, res;
    int pass_argc = 0;
    char* pass_argv[MAXARG];
    char* playback_file = NULL;
    int init_optind = optind;
    char* init_optarg = optarg;
    struct replay_scenario* scen = NULL;

    /* we do not want the test to depend on the timezone */
    (void)putenv("TZ=UTC");

    log_init(NULL, 0, NULL);
    /* determine commandline options for the daemon */
    pass_argc = 1;
    pass_argv[0] = "unbound";
    add_opts("-d", &pass_argc, pass_argv);
    while( (c=getopt(argc, argv, "2egho:p:s")) != -1) {
        switch(c) {
        case 's':
            free(pass_argv[1]);
            testbound_selftest();
            printf("selftest successful\n");
            exit(0);
        case '2':
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS)) && defined(USE_SHA2)
            printf("SHA256 supported\n");
            exit(0);
#else
            printf("SHA256 not supported\n");
            exit(1);
#endif
            break;
        case 'e':
#if defined(USE_ECDSA)
            printf("ECDSA supported\n");
            exit(0);
#else
            printf("ECDSA not supported\n");
            exit(1);
#endif
            break;
        case 'g':
#ifdef USE_GOST
            if(ldns_key_EVP_load_gost_id()) {
                printf("GOST supported\n");
                exit(0);
            } else {
                printf("GOST not supported\n");
                exit(1);
            }
#else
            printf("GOST not supported\n");
            exit(1);
#endif
            break;
        case 'p':
            playback_file = optarg;
            break;
        case 'o':
            add_opts(optarg, &pass_argc, pass_argv);
            break;
        case '?':
        case 'h':
        default:
            testbound_usage();
            return 1;
        }
    }
    argc -= optind;
    argv += optind;
    if(argc != 0) {
        testbound_usage();
        return 1;
    }
    log_info("Start of %s testbound program.", PACKAGE_STRING);
    if(atexit(&remove_configfile) != 0)
        fatal_exit("atexit() failed: %s", strerror(errno));

    /* setup test environment */
    scen = setup_playback(playback_file, &pass_argc, pass_argv);
    /* init fake event backend */
    fake_event_init(scen);

    pass_argv[pass_argc] = NULL;
    echo_cmdline(pass_argc, pass_argv);

    /* reset getopt processing */
    optind = init_optind;
    optarg = init_optarg;

    /* run the normal daemon */
    res = daemon_main(pass_argc, pass_argv);

    fake_event_cleanup();
    for(c=1; c<pass_argc; c++)
        free(pass_argv[c]);
    if(res == 0) {
        log_info("Testbound Exit Success");
#ifdef HAVE_PTHREAD
        /* dlopen frees its thread state (dlopen of gost engine) */
        pthread_exit(NULL);
#endif
    }
    return res;
}
Exemple #13
0
int main(int argc, char **argv)
{
    int err = daemon_init(argc, argv);

    return err == 0 ? daemon_main() : 1;
}
Exemple #14
0
int main(int argc,char *argv[])
{
	int ret;
	int orig_argc = argc;
	char **orig_argv = argv;

	signal(SIGUSR1, sigusr1_handler);
	signal(SIGUSR2, sigusr2_handler);
	signal(SIGCHLD, sigchld_handler);
#ifdef MAINTAINER_MODE
	signal(SIGSEGV, rsync_panic_handler);
	signal(SIGFPE, rsync_panic_handler);
	signal(SIGABRT, rsync_panic_handler);
	signal(SIGBUS, rsync_panic_handler);
#endif /* def MAINTAINER_MODE */

	starttime = time(NULL);
	am_root = (MY_UID() == 0);

	memset(&stats, 0, sizeof(stats));

	if (argc < 2) {
		usage(FERROR);
		exit_cleanup(RERR_SYNTAX);
	}

	/* we set a 0 umask so that correct file permissions can be
	 * carried across */
	orig_umask = (int)umask(0);

	if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
		/* FIXME: We ought to call the same error-handling
		 * code here, rather than relying on getopt. */
		option_error();
		exit_cleanup(RERR_SYNTAX);
	}

	signal(SIGINT,SIGNAL_CAST sig_int);
	signal(SIGHUP,SIGNAL_CAST sig_int);
	signal(SIGTERM,SIGNAL_CAST sig_int);

	/* Ignore SIGPIPE; we consistently check error codes and will
	 * see the EPIPE. */
	signal(SIGPIPE, SIG_IGN);

#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
	setlocale(LC_CTYPE, "");
#endif

	/* Initialize push_dir here because on some old systems getcwd
	 * (implemented by forking "pwd" and reading its output) doesn't
	 * work when there are other child processes.  Also, on all systems
	 * that implement getcwd that way "pwd" can't be found after chroot. */
	push_dir(NULL);

	init_flist();

	if ((write_batch || read_batch) && !am_server) {
		if (write_batch)
			write_batch_shell_file(orig_argc, orig_argv, argc);

		if (read_batch && strcmp(batch_name, "-") == 0)
			batch_fd = STDIN_FILENO;
		else {
			batch_fd = do_open(batch_name,
				   write_batch ? O_WRONLY | O_CREAT | O_TRUNC
				   : O_RDONLY, S_IRUSR | S_IWUSR);
		}
		if (batch_fd < 0) {
			rsyserr(FERROR, errno, "Batch file %s open error",
				full_fname(batch_name));
			exit_cleanup(RERR_FILEIO);
		}
		if (read_batch)
			read_stream_flags(batch_fd);
	}
	if (write_batch < 0)
		dry_run = 1;

	if (am_daemon && !am_server)
		return daemon_main();

	if (argc < 1) {
		usage(FERROR);
		exit_cleanup(RERR_SYNTAX);
	}

	if (am_server) {
		set_nonblocking(STDIN_FILENO);
		set_nonblocking(STDOUT_FILENO);
		if (am_daemon)
			return start_daemon(STDIN_FILENO, STDOUT_FILENO);
		start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
	}

	ret = start_client(argc, argv);
	if (ret == -1)
		exit_cleanup(RERR_STARTCLIENT);
	else
		exit_cleanup(ret);

	return ret;
}