示例#1
0
文件: server.c 项目: aoa141/samba
static void smbd_parent_loop(struct tevent_context *ev_ctx,
			     struct smbd_parent_context *parent)
{
	struct smbd_parent_tevent_trace_state trace_state = {
		.frame = NULL,
	};
	int ret = 0;

	tevent_set_trace_callback(ev_ctx, smbd_parent_tevent_trace_callback,
				  &trace_state);

	/* now accept incoming connections - forking a new process
	   for each incoming connection */
	DEBUG(2,("waiting for connections\n"));

	ret = tevent_loop_wait(ev_ctx);
	if (ret != 0) {
		DEBUG(0, ("tevent_loop_wait failed: %d, %s, exiting\n",
			  ret, strerror(errno)));
	}

	TALLOC_FREE(trace_state.frame);

/* NOTREACHED	return True; */
}
示例#2
0
int main(void) {
	
	TALLOC_CTX *mem_ctx;						// pointer to talloc context
	struct tevent_context *ctx;			// pointer to tevent context
	struct tevent_req *event_req;		// pointer to tevent request

	// parent - top level talloc context
	mem_ctx = talloc_new(NULL); 
	if (mem_ctx == NULL) {
		fprintf(stderr, "Not enough memory.\n");
		return -1;
	}
	
	ctx = tevent_context_init(mem_ctx);

	// create tevent request, set callback and continue
	if (foo_send(mem_ctx, &event_req) != 0) {
		return -1;
	}

	printf("prg> I've created tevent request and now I continue.\n");

	/******************************************************************************
	 * A FEW EXAMPLES OF FINISHIN REQUEST
	/*****************************************************************************/
	// mark request af finished immediatly
	foo_done(mem_ctx, &event_req);

	// mark request as finished after 1s
	//tevent_req_set_endtime(event_req, ctx, tevent_timeval_current_ofs(1, 0));

	tevent_loop_wait(ctx);
	talloc_free(mem_ctx);
	return EXIT_SUCCESS;
}
示例#3
0
static PyObject *py_tevent_context_loop_wait(TeventContext_Object *self)
{
	if (tevent_loop_wait(self->ev) != 0) {
		PyErr_SetNone(PyExc_RuntimeError);
		return NULL;
	}
	Py_RETURN_NONE;
}
示例#4
0
/*
  called to create a new server task
*/
static void standard_new_task(struct tevent_context *ev, 
			      struct loadparm_context *lp_ctx,
			      const char *service_name,
			      void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *),
			      void *private_data)
{
	pid_t pid;

	pid = fork();

	if (pid != 0) {
		/* parent or error code ... go back to the event loop */
		return;
	}

	pid = getpid();

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}

	/* ldb/tdb need special fork handling */
	ldb_wrap_fork_hook();

	tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	close(child_pipe[1]);

	/* Ensure that the forked children do not expose identical random streams */
	set_need_random_reseed();

	setproctitle("task %s server_id[%d]", service_name, (int)pid);

	/* setup this new task.  Cluster ID is PID based for this process model */
	new_task(ev, lp_ctx, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	tevent_loop_wait(ev);

	talloc_free(ev);
	exit(0);
}
示例#5
0
int main()
{
    struct main_context *ctx = NULL;
    int ret;

    /* Create main context */
    ctx = talloc_zero(NULL, struct main_context);
    if (ctx == NULL) {
        DEBUG("talloc_zero() failed");
        goto fail;
    }
    ctx->is_sigint_enabled = 0;

    /* Create main event context */
    ctx->event_ctx = tevent_context_init(ctx);
    if (ctx->event_ctx == NULL) {
        DEBUG("talloc_context_init() failed");
        goto fail;
    }

    /* Setup event handlers on event context */
    ret = setup_event_handlers(ctx, ctx->event_ctx);
    if (ret != EOK) {
        DEBUG("setup_event_handlers() failed");
        goto fail;
    }

    /* Enter event loop */
    tevent_loop_wait(ctx->event_ctx);

    ret = EXIT_SUCCESS;
    goto done;
fail:
    ret = EXIT_FAILURE;

done:
    talloc_free(ctx);

    return ret;
}
示例#6
0
文件: epmd.c 项目: sprymak/samba
void start_epmd(struct tevent_context *ev_ctx,
		struct messaging_context *msg_ctx)
{
	struct rpc_srv_callbacks epmapper_cb;
	NTSTATUS status;
	pid_t pid;
	bool ok;
	int rc;

	epmapper_cb.init = NULL;
	epmapper_cb.shutdown = epmapper_shutdown_cb;
	epmapper_cb.private_data = NULL;

	DEBUG(1, ("Forking Endpoint Mapper Daemon\n"));

	pid = fork();

	if (pid == -1) {
		DEBUG(0, ("Failed to fork Endpoint Mapper [%s], aborting ...\n",
			  strerror(errno)));
		exit(1);
	}

	if (pid) {
		/* parent */
		return;
	}

	status = reinit_after_fork(msg_ctx,
				   ev_ctx,
				   true);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("reinit_after_fork() failed\n"));
		smb_panic("reinit_after_fork() failed");
	}

	epmd_reopen_logs();

	epmd_setup_sig_term_handler(ev_ctx);
	epmd_setup_sig_hup_handler(ev_ctx, msg_ctx);

	ok = serverid_register(procid_self(),
			       FLAG_MSG_GENERAL |
			       FLAG_MSG_PRINT_GENERAL);
	if (!ok) {
		DEBUG(0, ("Failed to register serverid in epmd!\n"));
		exit(1);
	}

	messaging_register(msg_ctx,
			   ev_ctx,
			   MSG_SMB_CONF_UPDATED,
			   epmd_smb_conf_updated);

	status = rpc_epmapper_init(&epmapper_cb);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to register epmd rpc inteface! (%s)\n",
			  nt_errstr(status)));
		exit(1);
	}

	status = rpc_setup_tcpip_sockets(ev_ctx,
					 msg_ctx,
					 &ndr_table_epmapper,
					 NULL,
					 135);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to open epmd tcpip sockets!\n"));
		exit(1);
	}

	ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
					 msg_ctx,
					 "EPMAPPER",
					 srv_epmapper_delete_endpoints);
	if (!ok) {
		DEBUG(0, ("Failed to open epmd ncalrpc pipe!\n"));
		exit(1);
	}

	ok = setup_named_pipe_socket("epmapper", ev_ctx, msg_ctx);
	if (!ok) {
		DEBUG(0, ("Failed to open epmd named pipe!\n"));
		exit(1);
	}

	DEBUG(1, ("Endpoint Mapper Daemon Started (%d)\n", getpid()));

	/* loop forever */
	rc = tevent_loop_wait(ev_ctx);

	/* should not be reached */
	DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
		 rc, (rc == 0) ? "out of events" : strerror(errno)));

	exit(1);
}
示例#7
0
/*
  called to create a new server task
*/
static void standard_new_task(struct tevent_context *ev, 
			      struct loadparm_context *lp_ctx,
			      const char *service_name,
			      void (*new_task)(struct tevent_context *, struct loadparm_context *lp_ctx, struct server_id , void *),
			      void *private_data)
{
	pid_t pid;
	NTSTATUS status;
	struct standard_child_state *state;
	struct tevent_fd *fde = NULL;
	struct tevent_signal *se = NULL;

	state = setup_standard_child_pipe(ev, service_name);
	if (state == NULL) {
		return;
	}

	pid = fork();

	if (pid != 0) {
		close(state->to_parent_fd);
		state->to_parent_fd = -1;

		if (pid > 0) {
			state->pid = pid;
		} else {
			TALLOC_FREE(state);
		}

		/* parent or error code ... go back to the event loop */
		return;
	}

	/* this leaves state->to_parent_fd open */
	TALLOC_FREE(state);

	pid = getpid();

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}

	/* ldb/tdb need special fork handling */
	ldb_wrap_fork_hook();

	/* Must be done after a fork() to reset messaging contexts. */
	status = imessaging_reinit_all();
	if (!NT_STATUS_IS_OK(status)) {
		smb_panic("Failed to re-initialise imessaging after fork");
	}

	fde = tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	if (fde == NULL) {
		smb_panic("Failed to add fd handler after fork");
	}
	if (child_pipe[1] != -1) {
		close(child_pipe[1]);
		child_pipe[1] = -1;
	}

	se = tevent_add_signal(ev,
				ev,
				SIGHUP,
				0,
				sighup_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGHUP handler after fork");
	}

	se = tevent_add_signal(ev,
				ev,
				SIGTERM,
				0,
				sigterm_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGTERM handler after fork");
	}

	setproctitle("task %s server_id[%d]", service_name, (int)pid);

	/* setup this new task.  Cluster ID is PID based for this process model */
	new_task(ev, lp_ctx, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	tevent_loop_wait(ev);

	talloc_free(ev);
	exit(0);
}
示例#8
0
/*
  called when a listening socket becomes readable. 
*/
static void standard_accept_connection(struct tevent_context *ev, 
				       struct loadparm_context *lp_ctx,
				       struct socket_context *sock, 
				       void (*new_conn)(struct tevent_context *,
							struct loadparm_context *, struct socket_context *, 
							struct server_id , void *), 
				       void *private_data)
{
	NTSTATUS status;
	struct socket_context *sock2;
	pid_t pid;
	struct socket_address *c, *s;
	struct standard_child_state *state;
	struct tevent_fd *fde = NULL;
	struct tevent_signal *se = NULL;

	state = setup_standard_child_pipe(ev, NULL);
	if (state == NULL) {
		return;
	}

	/* accept an incoming connection. */
	status = socket_accept(sock, &sock2);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("standard_accept_connection: accept: %s\n",
			 nt_errstr(status)));
		/* this looks strange, but is correct. We need to throttle things until
		   the system clears enough resources to handle this new socket */
		sleep(1);
		close(state->to_parent_fd);
		state->to_parent_fd = -1;
		TALLOC_FREE(state);
		return;
	}

	pid = fork();

	if (pid != 0) {
		close(state->to_parent_fd);
		state->to_parent_fd = -1;

		if (pid > 0) {
			state->pid = pid;
		} else {
			TALLOC_FREE(state);
		}

		/* parent or error code ... */
		talloc_free(sock2);
		/* go back to the event loop */
		return;
	}

	/* this leaves state->to_parent_fd open */
	TALLOC_FREE(state);

	pid = getpid();

	/* This is now the child code. We need a completely new event_context to work with */

	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	talloc_free(sock);

	/* we don't care if the dup fails, as its only a select()
	   speed optimisation */
	socket_dup(sock2);
			
	/* tdb needs special fork handling */
	ldb_wrap_fork_hook();

	/* Must be done after a fork() to reset messaging contexts. */
	status = imessaging_reinit_all();
	if (!NT_STATUS_IS_OK(status)) {
		smb_panic("Failed to re-initialise imessaging after fork");
	}

	fde = tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	if (fde == NULL) {
		smb_panic("Failed to add fd handler after fork");
	}

	if (child_pipe[1] != -1) {
		close(child_pipe[1]);
		child_pipe[1] = -1;
	}

	se = tevent_add_signal(ev,
				ev,
				SIGHUP,
				0,
				sighup_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGHUP handler after fork");
	}

	se = tevent_add_signal(ev,
				ev,
				SIGTERM,
				0,
				sigterm_signal_handler,
				NULL);
	if (se == NULL) {
		smb_panic("Failed to add SIGTERM handler after fork");
	}

	/* setup the process title */
	c = socket_get_peer_addr(sock2, ev);
	s = socket_get_my_addr(sock2, ev);
	if (s && c) {
		setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]",
			     c->addr, c->port, s->addr, s->port, (int)pid);
	}
	talloc_free(c);
	talloc_free(s);

	/* setup this new connection.  Cluster ID is PID based for this process model */
	new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	tevent_loop_wait(ev);

	talloc_free(ev);
	exit(0);
}
示例#9
0
文件: fssd.c 项目: 285858315/samba
void start_fssd(struct tevent_context *ev_ctx,
		struct messaging_context *msg_ctx)
{
	struct rpc_srv_callbacks fss_cb;
	NTSTATUS status;
	pid_t pid;
	bool ok;
	int rc;

	fss_cb.init = fss_init_cb;
	fss_cb.shutdown = fss_shutdown_cb;
	fss_cb.private_data = msg_ctx;

	DEBUG(1, ("Forking File Server Shadow-copy Daemon\n"));

	pid = fork();

	if (pid == -1) {
		DEBUG(0, ("failed to fork file server shadow-copy daemon [%s], "
			  "aborting ...\n", strerror(errno)));
		exit(1);
	}

	if (pid) {
		/* parent */
		return;
	}

	/* child */
	status = smbd_reinit_after_fork(msg_ctx, ev_ctx, true);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("reinit_after_fork() failed\n"));
		smb_panic("reinit_after_fork() failed");
	}

	fssd_reopen_logs();

	fssd_setup_sig_term_handler(ev_ctx);
	fssd_setup_sig_hup_handler(ev_ctx, msg_ctx);

	ok = serverid_register(procid_self(),
			       FLAG_MSG_GENERAL |
			       FLAG_MSG_PRINT_GENERAL);
	if (!ok) {
		DEBUG(0, ("Failed to register serverid in fssd!\n"));
		exit(1);
	}

	messaging_register(msg_ctx,
			   ev_ctx,
			   MSG_SMB_CONF_UPDATED,
			   fssd_smb_conf_updated);

	status = rpc_FileServerVssAgent_init(&fss_cb);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to register fssd rpc inteface! (%s)\n",
			  nt_errstr(status)));
		exit(1);
	}

	/* case is normalized by smbd on connection */
	ok = setup_named_pipe_socket("fssagentrpc", ev_ctx, msg_ctx);
	if (!ok) {
		DEBUG(0, ("Failed to open fssd named pipe!\n"));
		exit(1);
	}

	DEBUG(1, ("File Server Shadow-copy Daemon Started (%d)\n",
		  (int)getpid()));

	/* loop forever */
	rc = tevent_loop_wait(ev_ctx);

	/* should not be reached */
	DEBUG(0,("tevent_loop_wait() exited with %d - %s\n",
		 rc, (rc == 0) ? "out of events" : strerror(errno)));

	exit(1);
}
示例#10
0
文件: server.c 项目: rti7743/samba
/*
 main server.
*/
static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
{
	bool opt_daemon = false;
	bool opt_interactive = false;
	int opt;
	poptContext pc;
#define _MODULE_PROTO(init) extern NTSTATUS init(void);
	STATIC_service_MODULES_PROTO;
	init_module_fn static_init[] = { STATIC_service_MODULES };
	init_module_fn *shared_init;
	struct tevent_context *event_ctx;
	uint16_t stdin_event_flags;
	NTSTATUS status;
	const char *model = "standard";
	int max_runtime = 0;
	enum {
		OPT_DAEMON = 1000,
		OPT_INTERACTIVE,
		OPT_PROCESS_MODEL,
		OPT_SHOW_BUILD
	};
	struct poptOption long_options[] = {
		POPT_AUTOHELP
		{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON,
		 "Become a daemon (default)", NULL },
		{"interactive",	'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE,
		 "Run interactive (not a daemon)", NULL},
		{"model", 'M', POPT_ARG_STRING,	NULL, OPT_PROCESS_MODEL, 
		 "Select process model", "MODEL"},
		{"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0, 
		 "set maximum runtime of the server process, till autotermination", "seconds"},
		{"show-build", 'b', POPT_ARG_NONE, NULL, OPT_SHOW_BUILD, "show build info", NULL },
		POPT_COMMON_SAMBA
		POPT_COMMON_VERSION
		{ NULL }
	};

	pc = poptGetContext(binary_name, argc, argv, long_options, 0);
	while((opt = poptGetNextOpt(pc)) != -1) {
		switch(opt) {
		case OPT_DAEMON:
			opt_daemon = true;
			break;
		case OPT_INTERACTIVE:
			opt_interactive = true;
			break;
		case OPT_PROCESS_MODEL:
			model = poptGetOptArg(pc);
			break;
		case OPT_SHOW_BUILD:
			show_build();
			break;
		default:
			fprintf(stderr, "\nInvalid option %s: %s\n\n",
				  poptBadOption(pc, 0), poptStrerror(opt));
			poptPrintUsage(pc, stderr, 0);
			return 1;
		}
	}

	if (opt_daemon && opt_interactive) {
		fprintf(stderr,"\nERROR: "
			  "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
		poptPrintUsage(pc, stderr, 0);
		return 1;
	} else if (!opt_interactive) {
		/* default is --daemon */
		opt_daemon = true;
	}

	poptFreeContext(pc);

	setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
	setup_signals();

	/* we want total control over the permissions on created files,
	   so set our umask to 0 */
	umask(0);

	DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
	DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2011\n"));

	if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
		DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n",
			    (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t)));
		return 1;
	}

	if (opt_daemon) {
		DEBUG(3,("Becoming a daemon.\n"));
		become_daemon(true, false, false);
	}

	cleanup_tmp_files(cmdline_lp_ctx);

	if (!directory_exist(lpcfg_lockdir(cmdline_lp_ctx))) {
		mkdir(lpcfg_lockdir(cmdline_lp_ctx), 0755);
	}

	pidfile_create(lpcfg_piddir(cmdline_lp_ctx), binary_name);

	/* Set up a database to hold a random seed, in case we don't
	 * have /dev/urandom */
	if (!randseed_init(talloc_autofree_context(), cmdline_lp_ctx)) {
		return 1;
	}

	if (lpcfg_server_role(cmdline_lp_ctx) == ROLE_DOMAIN_CONTROLLER) {
		if (!open_schannel_session_store(talloc_autofree_context(), lpcfg_private_dir(cmdline_lp_ctx))) {
			DEBUG(0,("ERROR: Samba cannot open schannel store for secured NETLOGON operations.\n"));
			exit(1);
		}
	}

	gensec_init(); /* FIXME: */

	ntptr_init();	/* FIXME: maybe run this in the initialization function 
						of the spoolss RPC server instead? */

	ntvfs_init(cmdline_lp_ctx); 	/* FIXME: maybe run this in the initialization functions 
						of the SMB[,2] server instead? */

	process_model_init(cmdline_lp_ctx); 

	shared_init = load_samba_modules(NULL, "service");

	run_init_functions(static_init);
	run_init_functions(shared_init);

	talloc_free(shared_init);
	
	/* the event context is the top level structure in smbd. Everything else
	   should hang off that */
	event_ctx = s4_event_context_init(talloc_autofree_context());

	if (event_ctx == NULL) {
		DEBUG(0,("Initializing event context failed\n"));
		return 1;
	}

	if (opt_interactive) {
		/* terminate when stdin goes away */
		stdin_event_flags = TEVENT_FD_READ;
	} else {
		/* stay alive forever */
		stdin_event_flags = 0;
	}

	/* catch EOF on stdin */
#ifdef SIGTTIN
	signal(SIGTTIN, SIG_IGN);
#endif
	tevent_add_fd(event_ctx, event_ctx, 0, stdin_event_flags,
		      server_stdin_handler,
		      discard_const(binary_name));

	if (max_runtime) {
		DEBUG(0,("Called with maxruntime %d - current ts %llu\n",
		      max_runtime, (unsigned long long) time(NULL)));
		tevent_add_timer(event_ctx, event_ctx,
				 timeval_current_ofs(max_runtime, 0),
				 max_runtime_handler,
				 discard_const(binary_name));
	}

	prime_ldb_databases(event_ctx);

	status = setup_parent_messaging(event_ctx, cmdline_lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Failed to setup parent messaging - %s\n", nt_errstr(status)));
		return 1;
	}

	DEBUG(0,("%s: using '%s' process model\n", binary_name, model));

	status = server_service_startup(event_ctx, cmdline_lp_ctx, model, 
					lpcfg_server_services(cmdline_lp_ctx));
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
		return 1;
	}

	/* wait for events - this is where smbd sits for most of its
	   life */
	tevent_loop_wait(event_ctx);

	/* as everything hangs off this event context, freeing it
	   should initiate a clean shutdown of all services */
	talloc_free(event_ctx);

	return 0;
}
示例#11
0
/****************************************************************************
main thread of the background lpq updater
****************************************************************************/
pid_t start_background_queue(struct tevent_context *ev,
			     struct messaging_context *msg_ctx,
			     char *logfile)
{
	pid_t pid;

	/* Use local variables for this as we don't
	 * need to save the parent side of this, just
	 * ensure it closes when the process exits.
	 */
	int pause_pipe[2];

	DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));

	if (pipe(pause_pipe) == -1) {
		DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
		exit(1);
	}

	/*
	 * Block signals before forking child as it will have to
	 * set its own handlers. Child will re-enable SIGHUP as
	 * soon as the handlers are set up.
	 */
	BlockSignals(true, SIGTERM);
	BlockSignals(true, SIGHUP);

	pid = sys_fork();

	/* parent or error */
	if (pid != 0) {
		/* Re-enable SIGHUP before returnig */
		BlockSignals(false, SIGTERM);
		BlockSignals(false, SIGHUP);
		return pid;
	}

	if (pid == -1) {
		DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
		exit(1);
	}

	if (pid == 0) {
		struct tevent_fd *fde;
		int ret;
		NTSTATUS status;

		/* Child. */
		DEBUG(5,("start_background_queue: background LPQ thread started\n"));

		close(pause_pipe[0]);
		pause_pipe[0] = -1;

		status = reinit_after_fork(msg_ctx, ev, true);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0,("reinit_after_fork() failed\n"));
			smb_panic("reinit_after_fork() failed");
		}

		bq_reopen_logs(logfile);
		bq_setup_sig_term_handler();
		bq_setup_sig_hup_handler(ev, msg_ctx);
		bq_setup_sig_chld_handler(ev);

		BlockSignals(false, SIGTERM);
		BlockSignals(false, SIGHUP);

		if (!printing_subsystem_queue_tasks(ev, msg_ctx)) {
			exit(1);
		}

		if (!serverid_register(messaging_server_id(msg_ctx),
				       FLAG_MSG_GENERAL |
				       FLAG_MSG_PRINT_GENERAL)) {
			exit(1);
		}

		if (!locking_init()) {
			exit(1);
		}
		messaging_register(msg_ctx, ev, MSG_SMB_CONF_UPDATED,
				   bq_smb_conf_updated);
		messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
				   print_queue_receive);

		fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
				    printing_pause_fd_handler,
				    NULL);
		if (!fde) {
			DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
			smb_panic("tevent_add_fd() failed for pause_pipe");
		}

		pcap_cache_reload(ev, msg_ctx, &reload_pcap_change_notify);

		DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
		ret = tevent_loop_wait(ev);
		/* should not be reached */
		DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
			 ret, (ret == 0) ? "out of events" : strerror(errno)));
		exit(1);
	}

	close(pause_pipe[1]);

	return pid;
}
示例#12
0
/*
  called when a listening socket becomes readable. 
*/
static void standard_accept_connection(struct tevent_context *ev, 
				       struct loadparm_context *lp_ctx,
				       struct socket_context *sock, 
				       void (*new_conn)(struct tevent_context *,
							struct loadparm_context *, struct socket_context *, 
							struct server_id , void *), 
				       void *private_data)
{
	NTSTATUS status;
	struct socket_context *sock2;
	pid_t pid;
	struct socket_address *c, *s;

	/* accept an incoming connection. */
	status = socket_accept(sock, &sock2);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("standard_accept_connection: accept: %s\n",
			 nt_errstr(status)));
		/* this looks strange, but is correct. We need to throttle things until
		   the system clears enough resources to handle this new socket */
		sleep(1);
		return;
	}

	pid = fork();

	if (pid != 0) {
		/* parent or error code ... */
		talloc_free(sock2);
		/* go back to the event loop */
		return;
	}

	pid = getpid();

	/* This is now the child code. We need a completely new event_context to work with */

	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}

	/* this will free all the listening sockets and all state that
	   is not associated with this new connection */
	talloc_free(sock);

	/* we don't care if the dup fails, as its only a select()
	   speed optimisation */
	socket_dup(sock2);
			
	/* tdb needs special fork handling */
	ldb_wrap_fork_hook();

	tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
		      standard_pipe_handler, NULL);
	close(child_pipe[1]);

	/* Ensure that the forked children do not expose identical random streams */
	set_need_random_reseed();

	/* setup the process title */
	c = socket_get_peer_addr(sock2, ev);
	s = socket_get_my_addr(sock2, ev);
	if (s && c) {
		setproctitle("conn c[%s:%u] s[%s:%u] server_id[%d]",
			     c->addr, c->port, s->addr, s->port, (int)pid);
	}
	talloc_free(c);
	talloc_free(s);

	/* setup this new connection.  Cluster ID is PID based for this process model */
	new_conn(ev, lp_ctx, sock2, cluster_id(pid, 0), private_data);

	/* we can't return to the top level here, as that event context is gone,
	   so we now process events in the new event context until there are no
	   more to process */	   
	tevent_loop_wait(ev);

	talloc_free(ev);
	exit(0);
}
int main(int argc, char *argv[])
{
	int ret;
	struct ctdb_mutex_rados_state *cmr_state;

	progname = argv[0];

	if (argc != 5) {
		fprintf(stderr, "Usage: %s <Ceph Cluster> <Ceph user> "
				"<RADOS pool> <RADOS object>\n",
			progname);
		ret = -EINVAL;
		goto err_out;
	}

	ret = setvbuf(stdout, NULL, _IONBF, 0);
	if (ret != 0) {
		fprintf(stderr, "Failed to configure unbuffered stdout I/O\n");
	}

	cmr_state = talloc_zero(NULL, struct ctdb_mutex_rados_state);
	if (cmr_state == NULL) {
		fprintf(stdout, CTDB_MUTEX_STATUS_ERROR);
		ret = -ENOMEM;
		goto err_out;
	}

	cmr_state->ceph_cluster_name = argv[1];
	cmr_state->ceph_auth_name = argv[2];
	cmr_state->pool_name = argv[3];
	cmr_state->object = argv[4];

	cmr_state->ppid = getppid();
	if (cmr_state->ppid == 1) {
		/*
		 * The original parent is gone and the process has
		 * been reparented to init.  This can happen if the
		 * helper is started just as the parent is killed
		 * during shutdown.  The error message doesn't need to
		 * be stellar, since there won't be anything around to
		 * capture and log it...
		 */
		fprintf(stderr, "%s: PPID == 1\n", progname);
		ret = -EPIPE;
		goto err_state_free;
	}

	cmr_state->ev = tevent_context_init(cmr_state);
	if (cmr_state->ev == NULL) {
		fprintf(stderr, "tevent_context_init failed\n");
		fprintf(stdout, CTDB_MUTEX_STATUS_ERROR);
		ret = -ENOMEM;
		goto err_state_free;
	}

	/* wait for sigterm */
	cmr_state->sig_ev = tevent_add_signal(cmr_state->ev, cmr_state, SIGTERM, 0,
					      ctdb_mutex_rados_sigterm_cb,
					      cmr_state);
	if (cmr_state->sig_ev == NULL) {
		fprintf(stderr, "Failed to create signal event\n");
		fprintf(stdout, CTDB_MUTEX_STATUS_ERROR);
		ret = -ENOMEM;
		goto err_state_free;
	}

	/* periodically check parent */
	cmr_state->timer_ev = tevent_add_timer(cmr_state->ev, cmr_state,
					       tevent_timeval_current_ofs(5, 0),
					       ctdb_mutex_rados_timer_cb,
					       cmr_state);
	if (cmr_state->timer_ev == NULL) {
		fprintf(stderr, "Failed to create timer event\n");
		fprintf(stdout, CTDB_MUTEX_STATUS_ERROR);
		ret = -ENOMEM;
		goto err_state_free;
	}

	ret = ctdb_mutex_rados_ctx_create(cmr_state->ceph_cluster_name,
					  cmr_state->ceph_auth_name,
					  cmr_state->pool_name,
					  &cmr_state->ceph_cluster,
					  &cmr_state->ioctx);
	if (ret < 0) {
		fprintf(stdout, CTDB_MUTEX_STATUS_ERROR);
		goto err_state_free;
	}

	ret = ctdb_mutex_rados_lock(cmr_state->ioctx, cmr_state->object);
	if ((ret == -EEXIST) || (ret == -EBUSY)) {
		fprintf(stdout, CTDB_MUTEX_STATUS_CONTENDED);
		goto err_ctx_cleanup;
	} else if (ret < 0) {
		fprintf(stdout, CTDB_MUTEX_STATUS_ERROR);
		goto err_ctx_cleanup;
	}

	cmr_state->holding_mutex = true;
	fprintf(stdout, CTDB_MUTEX_STATUS_HOLDING);

	/* wait for the signal / timer events to do their work */
	ret = tevent_loop_wait(cmr_state->ev);
	if (ret < 0) {
		goto err_ctx_cleanup;
	}
err_ctx_cleanup:
	ctdb_mutex_rados_ctx_destroy(cmr_state->ceph_cluster,
				     cmr_state->ioctx);
err_state_free:
	talloc_free(cmr_state);
err_out:
	return ret ? 1 : 0;
}
示例#14
0
void start_spoolssd(struct tevent_context *ev_ctx,
		    struct messaging_context *msg_ctx)
{
	struct rpc_srv_callbacks spoolss_cb;
	pid_t pid;
	NTSTATUS status;
	int ret;

	DEBUG(1, ("Forking SPOOLSS Daemon\n"));

	pid = sys_fork();

	if (pid == -1) {
		DEBUG(0, ("Failed to fork SPOOLSS [%s], aborting ...\n",
			   strerror(errno)));
		exit(1);
	}

	if (pid) {
		/* parent */
		return;
	}

	/* child */
	close_low_fds(false);

	status = reinit_after_fork(msg_ctx,
				   ev_ctx,
				   procid_self(), true);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("reinit_after_fork() failed\n"));
		smb_panic("reinit_after_fork() failed");
	}

	spoolss_reopen_logs();

	spoolss_setup_sig_term_handler(ev_ctx);
	spoolss_setup_sig_hup_handler(ev_ctx, msg_ctx);

	if (!serverid_register(procid_self(),
				FLAG_MSG_GENERAL|FLAG_MSG_SMBD
				|FLAG_MSG_PRINT_GENERAL)) {
		exit(1);
	}

	if (!locking_init()) {
		exit(1);
	}

	messaging_register(msg_ctx, NULL,
			   MSG_PRINTER_UPDATE, print_queue_receive);
	messaging_register(msg_ctx, ev_ctx,
			   MSG_SMB_CONF_UPDATED, smb_conf_updated);

	/*
	 * Initialize spoolss with an init function to convert printers first.
	 * static_init_rpc will try to initialize the spoolss server too but you
	 * can't register it twice.
	 */
	spoolss_cb.init = spoolss_init_cb;
	spoolss_cb.shutdown = spoolss_shutdown_cb;
	spoolss_cb.private_data = msg_ctx;

	status = rpc_winreg_init(NULL);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
			  nt_errstr(status)));
		exit(1);
	}

	status = rpc_spoolss_init(&spoolss_cb);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
			  nt_errstr(status)));
		exit(1);
	}

	if (!setup_named_pipe_socket(SPOOLSS_PIPE_NAME, ev_ctx)) {
		exit(1);
	}

	status = rpc_ep_setup_register(ev_ctx, msg_ctx, &ndr_table_spoolss, NULL, 0);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to register spoolss endpoint! (%s)\n",
			  nt_errstr(status)));
		exit(1);
	}

	DEBUG(1, ("SPOOLSS Daemon Started (%d)\n", getpid()));

	/* loop forever */
	ret = tevent_loop_wait(ev_ctx);

	/* should not be reached */
	DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
		 ret, (ret == 0) ? "out of events" : strerror(errno)));
	exit(1);
}
示例#15
0
文件: server.c 项目: miguelinux/samba
/*
 main server.
*/
static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
{
	bool opt_daemon = false;
	bool opt_interactive = false;
	int opt;
	poptContext pc;
#define _MODULE_PROTO(init) extern NTSTATUS init(void);
	STATIC_service_MODULES_PROTO;
	init_module_fn static_init[] = { STATIC_service_MODULES };
	init_module_fn *shared_init;
	struct tevent_context *event_ctx;
	uint16_t stdin_event_flags;
	NTSTATUS status;
	const char *model = "standard";
	int max_runtime = 0;
	struct stat st;
	enum {
		OPT_DAEMON = 1000,
		OPT_INTERACTIVE,
		OPT_PROCESS_MODEL,
		OPT_SHOW_BUILD
	};
	struct poptOption long_options[] = {
		POPT_AUTOHELP
		{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON,
		 "Become a daemon (default)", NULL },
		{"interactive",	'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE,
		 "Run interactive (not a daemon)", NULL},
		{"model", 'M', POPT_ARG_STRING,	NULL, OPT_PROCESS_MODEL, 
		 "Select process model", "MODEL"},
		{"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0, 
		 "set maximum runtime of the server process, till autotermination", "seconds"},
		{"show-build", 'b', POPT_ARG_NONE, NULL, OPT_SHOW_BUILD, "show build info", NULL },
		POPT_COMMON_SAMBA
		POPT_COMMON_VERSION
		{ NULL }
	};

	pc = poptGetContext(binary_name, argc, argv, long_options, 0);
	while((opt = poptGetNextOpt(pc)) != -1) {
		switch(opt) {
		case OPT_DAEMON:
			opt_daemon = true;
			break;
		case OPT_INTERACTIVE:
			opt_interactive = true;
			break;
		case OPT_PROCESS_MODEL:
			model = poptGetOptArg(pc);
			break;
		case OPT_SHOW_BUILD:
			show_build();
			break;
		default:
			fprintf(stderr, "\nInvalid option %s: %s\n\n",
				  poptBadOption(pc, 0), poptStrerror(opt));
			poptPrintUsage(pc, stderr, 0);
			return 1;
		}
	}

	if (opt_daemon && opt_interactive) {
		fprintf(stderr,"\nERROR: "
			  "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
		poptPrintUsage(pc, stderr, 0);
		return 1;
	} else if (!opt_interactive) {
		/* default is --daemon */
		opt_daemon = true;
	}

	poptFreeContext(pc);

	talloc_enable_null_tracking();

	setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
	setup_signals();

	/* we want total control over the permissions on created files,
	   so set our umask to 0 */
	umask(0);

	DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
	DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2016\n"));

	if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
		DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n",
			    (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t)));
		return 1;
	}

	if (opt_daemon) {
		DEBUG(3,("Becoming a daemon.\n"));
		become_daemon(true, false, false);
	}

	cleanup_tmp_files(cmdline_lp_ctx);

	if (!directory_exist(lpcfg_lock_directory(cmdline_lp_ctx))) {
		mkdir(lpcfg_lock_directory(cmdline_lp_ctx), 0755);
	}

	pidfile_create(lpcfg_pid_directory(cmdline_lp_ctx), binary_name);

	if (lpcfg_server_role(cmdline_lp_ctx) == ROLE_ACTIVE_DIRECTORY_DC) {
		if (!open_schannel_session_store(talloc_autofree_context(), cmdline_lp_ctx)) {
			exit_daemon("Samba cannot open schannel store for secured NETLOGON operations.", EACCES);
		}
	}

	/* make sure we won't go through nss_winbind */
	if (!winbind_off()) {
		exit_daemon("Samba failed to disable recusive winbindd calls.", EACCES);
	}

	gensec_init(); /* FIXME: */

	ntptr_init();	/* FIXME: maybe run this in the initialization function 
						of the spoolss RPC server instead? */

	ntvfs_init(cmdline_lp_ctx); 	/* FIXME: maybe run this in the initialization functions 
						of the SMB[,2] server instead? */

	process_model_init(cmdline_lp_ctx); 

	shared_init = load_samba_modules(NULL, "service");

	run_init_functions(static_init);
	run_init_functions(shared_init);

	talloc_free(shared_init);
	
	/* the event context is the top level structure in smbd. Everything else
	   should hang off that */
	event_ctx = s4_event_context_init(talloc_autofree_context());

	if (event_ctx == NULL) {
		exit_daemon("Initializing event context failed", EACCES);
	}

	if (opt_interactive) {
		/* terminate when stdin goes away */
		stdin_event_flags = TEVENT_FD_READ;
	} else {
		/* stay alive forever */
		stdin_event_flags = 0;
	}

	/* catch EOF on stdin */
#ifdef SIGTTIN
	signal(SIGTTIN, SIG_IGN);
#endif

	if (fstat(0, &st) != 0) {
		exit_daemon("Samba failed to set standard input handler", ENOTTY);
	}

	if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
		tevent_add_fd(event_ctx,
				event_ctx,
				0,
				stdin_event_flags,
				server_stdin_handler,
				discard_const(binary_name));
	}

	if (max_runtime) {
		DEBUG(0,("Called with maxruntime %d - current ts %llu\n",
		      max_runtime, (unsigned long long) time(NULL)));
		tevent_add_timer(event_ctx, event_ctx,
				 timeval_current_ofs(max_runtime, 0),
				 max_runtime_handler,
				 discard_const(binary_name));
	}

	if (lpcfg_server_role(cmdline_lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC
	    && !lpcfg_parm_bool(cmdline_lp_ctx, NULL, "server role check", "inhibit", false)
	    && !str_list_check_ci(lpcfg_server_services(cmdline_lp_ctx), "smb") 
	    && !str_list_check_ci(lpcfg_dcerpc_endpoint_servers(cmdline_lp_ctx), "remote")
	    && !str_list_check_ci(lpcfg_dcerpc_endpoint_servers(cmdline_lp_ctx), "mapiproxy")) {
		DEBUG(0, ("At this time the 'samba' binary should only be used for either:\n"));
		DEBUGADD(0, ("'server role = active directory domain controller' or to access the ntvfs file server with 'server services = +smb' or the rpc proxy with 'dcerpc endpoint servers = remote'\n"));
		DEBUGADD(0, ("You should start smbd/nmbd/winbindd instead for domain member and standalone file server tasks\n"));
		exit_daemon("Samba detected misconfigured 'server role' and exited. Check logs for details", EINVAL);
	};

	prime_ldb_databases(event_ctx);

	status = setup_parent_messaging(event_ctx, cmdline_lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba failed to setup parent messaging", NT_STATUS_V(status));
	}

	DEBUG(0,("%s: using '%s' process model\n", binary_name, model));

	status = server_service_startup(event_ctx, cmdline_lp_ctx, model, 
					lpcfg_server_services(cmdline_lp_ctx));
	if (!NT_STATUS_IS_OK(status)) {
		exit_daemon("Samba failed to start services", NT_STATUS_V(status));
	}

	if (opt_daemon) {
		daemon_ready("samba");
	}

	/* wait for events - this is where smbd sits for most of its
	   life */
	tevent_loop_wait(event_ctx);

	/* as everything hangs off this event context, freeing it
	   should initiate a clean shutdown of all services */
	talloc_free(event_ctx);

	return 0;
}
示例#16
0
/*
 * called to create a new server task
 */
static void prefork_new_task(
	struct tevent_context *ev,
	struct loadparm_context *lp_ctx,
	const char *service_name,
	void (*new_task_fn)(struct tevent_context *,
			    struct loadparm_context *lp_ctx,
			    struct server_id , void *, void *),
	void *private_data,
	const struct service_details *service_details,
	int from_parent_fd)
{
	pid_t pid;
	struct tfork* t = NULL;
	int i, num_children;

	struct tevent_context *ev2;

	t = tfork_create();
	if (t == NULL) {
		smb_panic("failure in tfork\n");
	}

	pid = tfork_child_pid(t);
	if (pid != 0) {
		struct tevent_fd *fde = NULL;
		int fd = tfork_event_fd(t);

		/* Register a pipe handler that gets called when the prefork
		 * master process terminates.
		 */
		fde = tevent_add_fd(ev, ev, fd, TEVENT_FD_READ,
				    prefork_child_pipe_handler, t);
		if (fde == NULL) {
			smb_panic("Failed to add child pipe handler, "
				  "after fork");
		}
		tevent_fd_set_auto_close(fde);
		return;
	}

	pid = getpid();
	setproctitle("task[%s] pre-fork master", service_name);

	/*
	 * this will free all the listening sockets and all state that
	 * is not associated with this new connection
	 */
	if (tevent_re_initialise(ev) != 0) {
		smb_panic("Failed to re-initialise tevent after fork");
	}
	prefork_reload_after_fork();
	setup_handlers(ev, from_parent_fd);

	if (service_details->inhibit_pre_fork) {
		new_task_fn(ev, lp_ctx, cluster_id(pid, 0), private_data, NULL);
		/* The task does not support pre-fork */
		tevent_loop_wait(ev);
		TALLOC_FREE(ev);
		exit(0);
	}

	/*
	 * This is now the child code. We need a completely new event_context
	 * to work with
	 */
	ev2 = s4_event_context_init(NULL);

	/* setup this new connection: process will bind to it's sockets etc
	 *
	 * While we can use ev for the child, which has been re-initialised
	 * above we must run the new task under ev2 otherwise the children would
	 * be listening on the sockets.  Also we don't want the top level
	 * process accepting and handling requests, it's responsible for
	 * monitoring and controlling the child work processes.
	 */
	new_task_fn(ev2, lp_ctx, cluster_id(pid, 0), private_data, NULL);

	{
		int default_children;
		default_children = lpcfg_prefork_children(lp_ctx);
		num_children = lpcfg_parm_int(lp_ctx, NULL, "prefork children",
			                      service_name, default_children);
	}
	if (num_children == 0) {
		DBG_WARNING("Number of pre-fork children for %s is zero, "
			    "NO worker processes will be started for %s\n",
			    service_name, service_name);
	}
	DBG_NOTICE("Forking %d %s worker processes\n",
		   num_children, service_name);
	/* We are now free to spawn some worker processes */
	for (i=0; i < num_children; i++) {
		struct tfork* w = NULL;

		w = tfork_create();
		if (w == NULL) {
			smb_panic("failure in tfork\n");
		}

		pid = tfork_child_pid(w);
		if (pid != 0) {
			struct tevent_fd *fde = NULL;
			int fd = tfork_event_fd(w);

			fde = tevent_add_fd(ev, ev, fd, TEVENT_FD_READ,
					    prefork_child_pipe_handler, w);
			if (fde == NULL) {
				smb_panic("Failed to add child pipe handler, "
					  "after fork");
			}
			tevent_fd_set_auto_close(fde);
		} else {
			/* tfork uses malloc */
			free(w);

			TALLOC_FREE(ev);
			setproctitle("task[%s] pre-forked worker",
				     service_name);
			prefork_reload_after_fork();
			setup_handlers(ev2, from_parent_fd);
			tevent_loop_wait(ev2);
			talloc_free(ev2);
			exit(0);
		}
	}

	/* Don't listen on the sockets we just gave to the children */
	tevent_loop_wait(ev);
	TALLOC_FREE(ev);
	/* We need to keep ev2 until we're finished for the messaging to work */
	TALLOC_FREE(ev2);
	exit(0);

}