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); }
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); }
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); }
/* * 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); }
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); }