entity_t *
internal_service_new(const char *name)
{
	entity_t *s;

	s = internal_entity_new(SVCCFG_SERVICE_OBJECT);

	s->sc_name = name;
	s->sc_fmri = uu_msprintf("svc:/%s", name);
	if (s->sc_fmri == NULL)
		uu_die(gettext("couldn't allocate memory"));

	s->sc_dependents = uu_list_create(pgroup_pool, s, 0);
	if (s->sc_dependents == NULL) {
		uu_die(gettext("Unable to create list for service dependents.  "
		    "%s\n"), uu_strerror(uu_error()));
	}

	s->sc_u.sc_service.sc_service_type = SVCCFG_UNKNOWN_SERVICE;
	s->sc_u.sc_service.sc_service_instances = uu_list_create(entity_pool, s,
	    0);
	if (s->sc_u.sc_service.sc_service_instances == NULL) {
		uu_die(gettext("Unable to create list for service instances.  "
		    "%s\n"), uu_strerror(uu_error()));
	}

	return (s);
}
Beispiel #2
0
int
internal_attach_entity(entity_t *svc, entity_t *ent)
{
	if (ent->sc_etype == SVCCFG_TEMPLATE_OBJECT) {
		svc->sc_u.sc_service.sc_service_template = ent;
		return (0);
	}

	if (svc->sc_etype != SVCCFG_SERVICE_OBJECT)
		uu_die(gettext("bad entity attach: %s is not a service\n"),
		    svc->sc_name);

	if (uu_list_find(svc->sc_u.sc_service.sc_service_instances, ent, NULL,
	    NULL) != NULL) {
		semerr(gettext("Multiple definitions of entity %s in service "
		    "%s.\n"), ent->sc_name, svc->sc_name);
		return (-1);
	}

	(void) uu_list_prepend(svc->sc_u.sc_service.sc_service_instances, ent);
	ent->sc_parent = svc;
	ent->sc_fmri = uu_msprintf("%s:%s", svc->sc_fmri, ent->sc_name);
	if (ent->sc_fmri == NULL)
		uu_die(gettext("couldn't allocate memory"));

	return (0);
}
Beispiel #3
0
entity_t *
internal_service_new(const char *name)
{
	entity_t *s;

	if ((s = uu_zalloc(sizeof (entity_t))) == NULL)
		uu_die(gettext("couldn't allocate memory"));

	uu_list_node_init(s, &s->sc_node, entity_pool);

	s->sc_name = name;
	s->sc_fmri = uu_msprintf("svc:/%s", name);
	if (s->sc_fmri == NULL)
		uu_die(gettext("couldn't allocate memory"));

	s->sc_etype = SVCCFG_SERVICE_OBJECT;
	s->sc_pgroups = uu_list_create(pgroup_pool, s, 0);
	s->sc_dependents = uu_list_create(pgroup_pool, s, 0);

	s->sc_u.sc_service.sc_service_type = SVCCFG_UNKNOWN_SERVICE;
	s->sc_u.sc_service.sc_service_instances = uu_list_create(entity_pool, s,
	    0);

	return (s);
}
Beispiel #4
0
/*
 * int wait_register(pid_t, char *, int, int)
 *   wait_register is called after we have called fork(2), and know which pid we
 *   wish to monitor.  However, since the child may have already exited by the
 *   time we are called, we must handle the error cases from open(2)
 *   appropriately.  The am_parent flag is recorded to handle waitpid(2)
 *   behaviour on removal; similarly, the direct flag is passed through to a
 *   potential call to wait_remove() to govern its behaviour in different
 *   contexts.
 *
 *   Returns 0 if registration successful, 1 if child pid did not exist, and -1
 *   if a different error occurred.
 */
int
wait_register(pid_t pid, const char *inst_fmri, int am_parent, int direct)
{
	char *fname = uu_msprintf("/proc/%ld/psinfo", pid);
	int fd;
	wait_info_t *wi;

	assert(pid != 0);

	if (fname == NULL)
		return (-1);

	wi = startd_alloc(sizeof (wait_info_t));

	uu_list_node_init(wi, &wi->wi_link, wait_info_pool);

	wi->wi_fd = -1;
	wi->wi_pid = pid;
	wi->wi_fmri = inst_fmri;
	wi->wi_parent = am_parent;
	wi->wi_ignore = 0;

	MUTEX_LOCK(&wait_info_lock);
	(void) uu_list_insert_before(wait_info_list, NULL, wi);
	MUTEX_UNLOCK(&wait_info_lock);

	if ((fd = open(fname, O_RDONLY)) == -1) {
		if (errno == ENOENT) {
			/*
			 * Child has already exited.
			 */
			wait_remove(wi, direct);
			uu_free(fname);
			return (1);
		} else {
			log_error(LOG_WARNING,
			    "open %s failed; not monitoring %s: %s\n", fname,
			    inst_fmri, strerror(errno));
			uu_free(fname);
			return (-1);
		}
	}

	uu_free(fname);

	wi->wi_fd = fd;

	if (port_associate(port_fd, PORT_SOURCE_FD, fd, 0, wi)) {
		log_error(LOG_WARNING,
		    "initial port_association of %d / %s failed: %s\n", fd,
		    inst_fmri, strerror(errno));
		return (-1);
	}

	log_framework(LOG_DEBUG, "monitoring PID %ld on fd %d (%s)\n", pid, fd,
	    inst_fmri);

	return (0);
}
Beispiel #5
0
static void
exec_method(const restarter_inst_t *inst, int type, const char *method,
    struct method_context *mcp, uint8_t need_session)
{
	char *cmd;
	const char *errf;
	char **nenv;

	cmd = uu_msprintf("exec %s", method);

	if (inst->ri_utmpx_prefix[0] != '\0' && inst->ri_utmpx_prefix != NULL)
		(void) utmpx_mark_init(getpid(), inst->ri_utmpx_prefix);

	setlog(inst->ri_logstem);
	log_instance(inst, B_FALSE, "Executing %s method (\"%s\")",
	    method_names[type], method);

	if (need_session)
		(void) setpgrp();

	/* Set credentials. */
	errno = restarter_set_method_context(mcp, &errf);
	if (errno != 0) {
		(void) fputs("svc.startd could not set context for method: ",
		    stderr);

		if (errno == -1) {
			if (strcmp(errf, "core_set_process_path") == 0) {
				(void) fputs("Could not set corefile path.\n",
				    stderr);
			} else if (strcmp(errf, "setproject") == 0) {
				(void) fprintf(stderr, "%s: a resource control "
				    "assignment failed\n", errf);
			} else if (strcmp(errf, "pool_set_binding") == 0) {
				(void) fprintf(stderr, "%s: a system error "
				    "occurred\n", errf);
			} else {
#ifndef NDEBUG
				uu_warn("%s:%d: Bad function name \"%s\" for "
				    "error %d from "
				    "restarter_set_method_context().\n",
				    __FILE__, __LINE__, errf, errno);
#endif
				abort();
			}

			exit(1);
		}

		if (errf != NULL && strcmp(errf, "pool_set_binding") == 0) {
			switch (errno) {
			case ENOENT:
				(void) fprintf(stderr, "%s: the pool could not "
				    "be found\n", errf);
				break;

			case EBADF:
				(void) fprintf(stderr, "%s: the configuration "
				    "is invalid\n", errf);
				break;

			case EINVAL:
				(void) fprintf(stderr, "%s: pool name \"%s\" "
				    "is invalid\n", errf, mcp->resource_pool);
				break;

			default:
#ifndef NDEBUG
				uu_warn("%s:%d: Bad error %d for function %s "
				    "in restarter_set_method_context().\n",
				    __FILE__, __LINE__, errno, errf);
#endif
				abort();
			}

			exit(SMF_EXIT_ERR_CONFIG);
		}

		if (errf != NULL) {
			perror(errf);

			switch (errno) {
			case EINVAL:
			case EPERM:
			case ENOENT:
			case ENAMETOOLONG:
			case ERANGE:
			case ESRCH:
				exit(SMF_EXIT_ERR_CONFIG);
				/* NOTREACHED */

			default:
				exit(1);
			}
		}

		switch (errno) {
		case ENOMEM:
			(void) fputs("Out of memory.\n", stderr);
			exit(1);
			/* NOTREACHED */

		case ENOENT:
			(void) fputs("Missing passwd entry for user.\n",
			    stderr);
			exit(SMF_EXIT_ERR_CONFIG);
			/* NOTREACHED */

		default:
#ifndef NDEBUG
			uu_warn("%s:%d: Bad miscellaneous error %d from "
			    "restarter_set_method_context().\n", __FILE__,
			    __LINE__, errno);
#endif
			abort();
		}
	}

	nenv = set_smf_env(mcp->env, mcp->env_sz, NULL, inst, method);

	log_preexec();

	(void) execle(SBIN_SH, SBIN_SH, "-c", cmd, NULL, nenv);

	exit(10);
}