static int set_svc_enable_cb(void *data, scf_walkinfo_t *wip) { uint8_t desired = *(uint8_t *)data; const char *instname = wip->fmri; if (desired) { if (smf_enable_instance(instname, 0) == 0) return (0); } else { if (smf_disable_instance(instname, 0) == 0) return (0); } switch (scf_error()) { case SCF_ERROR_INVALID_ARGUMENT: uu_die(gettext("Error: \"%s\" is not a valid service " "instance.\n"), instname); break; case SCF_ERROR_NOT_FOUND: uu_die(gettext("Error: Service instance \"%s\" not found.\n"), instname); break; default: scfdie(); } return (0); }
void internal_init() { if ((entity_pool = uu_list_pool_create("entities", sizeof (entity_t), offsetof(entity_t, sc_node), entity_cmp, 0)) == NULL) uu_die(gettext("entity list pool creation failed: %s\n"), uu_strerror(uu_error())); if ((pgroup_pool = uu_list_pool_create("property_groups", sizeof (pgroup_t), offsetof(pgroup_t, sc_node), pgroup_cmp, 0)) == NULL) uu_die( gettext("property group list pool creation failed: %s\n"), uu_strerror(uu_error())); if ((property_pool = uu_list_pool_create("properties", sizeof (property_t), offsetof(property_t, sc_node), property_cmp, 0)) == NULL) uu_die(gettext("property list pool creation failed: %s\n"), uu_strerror(uu_error())); if ((value_pool = uu_list_pool_create("property_values", sizeof (value_t), offsetof(value_t, sc_node), value_cmp, 0)) == NULL) uu_die( gettext("property value list pool creation failed: %s\n"), uu_strerror(uu_error())); }
/* * Add the proto list contained in array 'plist' to entry 'entry', storing * aside the scf_value_t's created and added to the entry in a list that the * pointer referenced by sv_list is made to point at. */ static void add_proto_list(scf_transaction_entry_t *entry, scf_handle_t *hdl, char **plist, uu_list_t **sv_list) { scf_val_el_t *sv_el; int i; static uu_list_pool_t *sv_pool = NULL; if ((sv_pool == NULL) && ((sv_pool = uu_list_pool_create("sv_pool", sizeof (scf_val_el_t), offsetof(scf_val_el_t, link), NULL, UU_LIST_POOL_DEBUG)) == NULL)) uu_die(gettext("Error: %s.\n"), uu_strerror(uu_error())); if ((*sv_list = uu_list_create(sv_pool, NULL, 0)) == NULL) uu_die(gettext("Error: %s.\n"), uu_strerror(uu_error())); for (i = 0; plist[i] != NULL; i++) { if ((sv_el = malloc(sizeof (scf_val_el_t))) == NULL) uu_die(gettext("Error:")); if (((sv_el->val = scf_value_create(hdl)) == NULL) || (scf_value_set_astring(sv_el->val, plist[i]) != 0) || (scf_entry_add_value(entry, sv_el->val) != 0)) scfdie(); uu_list_node_init(sv_el, &sv_el->link, sv_pool); (void) uu_list_insert_after(*sv_list, NULL, sv_el); } }
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 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; 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); }
void wait_init() { struct rlimit fd_new; (void) getrlimit(RLIMIT_NOFILE, &init_fd_rlimit); (void) getrlimit(RLIMIT_NOFILE, &fd_new); fd_new.rlim_max = fd_new.rlim_cur = WAIT_FILES; (void) setrlimit(RLIMIT_NOFILE, &fd_new); if ((port_fd = port_create()) == -1) uu_die("wait_init couldn't port_create"); wait_info_pool = uu_list_pool_create("wait_info", sizeof (wait_info_t), offsetof(wait_info_t, wi_link), NULL, UU_LIST_POOL_DEBUG); if (wait_info_pool == NULL) uu_die("wait_init couldn't create wait_info_pool"); wait_info_list = uu_list_create(wait_info_pool, wait_info_list, 0); if (wait_info_list == NULL) uu_die("wait_init couldn't create wait_info_list"); (void) pthread_mutex_init(&wait_info_lock, &mutex_attrs); }
static void delete_prop(const scf_instance_t *inst, const char *pg, const char *prop) { scf_transaction_t *tx; scf_transaction_entry_t *ent; scf_propertygroup_t *gpg; scf_property_t *eprop; int ret; if ((gpg = scf_pg_create(h)) == NULL || (eprop = scf_property_create(h)) == NULL || (tx = scf_transaction_create(h)) == NULL || (ent = scf_entry_create(h)) == NULL) scfdie(); if (scf_instance_get_pg(inst, pg, gpg) != SCF_SUCCESS) { if (scf_error() != SCF_ERROR_NOT_FOUND) scfdie(); uu_die(gettext("Error: \"%s\" property group missing.\n"), pg); } do { if (scf_transaction_start(tx, gpg) != SCF_SUCCESS) { if (scf_error() != SCF_ERROR_PERMISSION_DENIED) scfdie(); uu_die(gettext("Error: Permission denied.\n")); } if (scf_transaction_property_delete(tx, ent, prop) != SCF_SUCCESS) { if (scf_error() != SCF_ERROR_NOT_FOUND) scfdie(); uu_die( gettext("Error: \"%s\" property does not exist.\n"), prop); } ret = scf_transaction_commit(tx); if (ret < 0) { if (scf_error() != SCF_ERROR_PERMISSION_DENIED) scfdie(); uu_die(gettext("Error: Permission denied.\n")); } if (ret == 0) { scf_transaction_reset(tx); if (scf_pg_update(gpg) == -1) scfdie(); } } while (ret == 0); (void) scf_entry_destroy(ent); scf_transaction_destroy(tx); scf_property_destroy(eprop); scf_pg_destroy(gpg); }
static pgroup_t * internal_pgroup_create_common(entity_t *e, const char *name, const char *type, boolean_t unique) { pgroup_t *pg; pg = internal_pgroup_find(e, name, type); if (pg != NULL) { if (unique == B_TRUE) { return (NULL); } else { return (pg); } } pg = internal_pgroup_new(); (void) internal_attach_pgroup(e, pg); pg->sc_pgroup_name = strdup(name); pg->sc_pgroup_flags = 0; if (type != NULL) { pg->sc_pgroup_type = strdup(type); } else { est->sc_miss_type = B_TRUE; pg->sc_pgroup_type = NULL; } if (pg->sc_pgroup_name == NULL || (e->sc_op != SVCCFG_OP_APPLY && pg->sc_pgroup_type == NULL)) uu_die(gettext("Could not duplicate string")); return (pg); }
bundle_t * internal_bundle_new() { bundle_t *b; if ((b = uu_zalloc(sizeof (bundle_t))) == NULL) uu_die(gettext("couldn't allocate memory")); b->sc_bundle_type = SVCCFG_UNKNOWN_BUNDLE; b->sc_bundle_services = uu_list_create(entity_pool, b, 0); if (b->sc_bundle_services == NULL) { uu_die(gettext("Unable to create list for bundle services. " "%s\n"), uu_strerror(uu_error())); } return (b); }
void * safe_malloc(size_t sz) { void *p; if ((p = calloc(1, sz)) == NULL) uu_die(gettext("Out of memory.\n")); return (p); }
entity_t * internal_entity_new(entity_type_t entity) { entity_t *e; if ((e = uu_zalloc(sizeof (entity_t))) == NULL) uu_die(gettext("couldn't allocate memory")); uu_list_node_init(e, &e->sc_node, entity_pool); e->sc_etype = entity; e->sc_pgroups = uu_list_create(pgroup_pool, e, 0); e->sc_op = SVCCFG_OP_NONE; if (e->sc_pgroups == NULL) { uu_die(gettext("Unable to create list for entity property " "groups. %s\n"), uu_strerror(uu_error())); } return (e); }
pgroup_t * internal_pgroup_new() { pgroup_t *p; if ((p = uu_zalloc(sizeof (pgroup_t))) == NULL) uu_die(gettext("couldn't allocate memory")); uu_list_node_init(p, &p->sc_node, pgroup_pool); p->sc_pgroup_props = uu_list_create(property_pool, p, UU_LIST_SORTED); if (p->sc_pgroup_props == NULL) { uu_die(gettext("Unable to create list for properties. %s\n"), uu_strerror(uu_error())); } p->sc_pgroup_name = "<unset>"; p->sc_pgroup_type = "<unset>"; return (p); }
char * safe_strdup(const char *cp) { char *result; result = strdup(cp); if (result == NULL) uu_die(gettext("Out of memory.\n")); return (result); }
value_t * internal_value_new() { value_t *v; if ((v = uu_zalloc(sizeof (value_t))) == NULL) uu_die(gettext("couldn't allocate memory")); uu_list_node_init(v, &v->sc_node, value_pool); return (v); }
property_t * internal_property_new() { property_t *p; if ((p = uu_zalloc(sizeof (property_t))) == NULL) uu_die(gettext("couldn't allocate memory")); uu_list_node_init(p, &p->sc_node, property_pool); p->sc_property_values = uu_list_create(value_pool, p, 0); if (p->sc_property_values == NULL) { uu_die(gettext("Unable to create list for property values. " "%s\n"), uu_strerror(uu_error())); } p->sc_property_name = "<unset>"; tmpl_property_init(p); return (p); }
bundle_t * internal_bundle_new() { bundle_t *b; if ((b = uu_zalloc(sizeof (bundle_t))) == NULL) uu_die(gettext("couldn't allocate memory")); b->sc_bundle_type = SVCCFG_UNKNOWN_BUNDLE; b->sc_bundle_services = uu_list_create(entity_pool, b, 0); return (b); }
property_t * internal_property_create(const char *name, scf_type_t vtype, uint_t nvals, ...) { va_list args; property_t *p; value_t *v; p = internal_property_new(); p->sc_property_name = (char *)name; p->sc_value_type = vtype; va_start(args, nvals); for (; nvals > 0; nvals--) { v = internal_value_new(); v->sc_type = vtype; switch (vtype) { case SCF_TYPE_BOOLEAN: case SCF_TYPE_COUNT: v->sc_u.sc_count = va_arg(args, uint64_t); break; case SCF_TYPE_INTEGER: v->sc_u.sc_integer = va_arg(args, int64_t); break; case SCF_TYPE_ASTRING: case SCF_TYPE_FMRI: case SCF_TYPE_HOST: case SCF_TYPE_HOSTNAME: case SCF_TYPE_NET_ADDR_V4: case SCF_TYPE_NET_ADDR_V6: case SCF_TYPE_OPAQUE: case SCF_TYPE_TIME: case SCF_TYPE_URI: case SCF_TYPE_USTRING: v->sc_u.sc_string = (char *)va_arg(args, uchar_t *); break; default: va_end(args); uu_die(gettext("unknown property type (%d)\n"), vtype); break; } internal_attach_value(p, v); } va_end(args); return (p); }
property_t * internal_property_new() { property_t *p; if ((p = uu_zalloc(sizeof (property_t))) == NULL) uu_die(gettext("couldn't allocate memory")); uu_list_node_init(p, &p->sc_node, property_pool); p->sc_property_values = uu_list_create(value_pool, p, UU_LIST_SORTED); p->sc_property_name = "<unset>"; return (p); }
entity_t * internal_template_new() { entity_t *t; if ((t = uu_zalloc(sizeof (entity_t))) == NULL) uu_die(gettext("couldn't allocate memory")); uu_list_node_init(t, &t->sc_node, entity_pool); t->sc_etype = SVCCFG_TEMPLATE_OBJECT; t->sc_pgroups = uu_list_create(pgroup_pool, t, 0); return (t); }
int engine_set(uu_list_t *args) { uu_list_walk_t *walk; string_list_t *slp; if (uu_list_first(args) == NULL) { /* Display current options. */ if (!g_verbose) (void) fputs("no", stdout); (void) puts("verbose"); return (0); } walk = uu_list_walk_start(args, UU_DEFAULT); if (walk == NULL) uu_die(gettext("Couldn't read arguments")); /* Use getopt? */ for (slp = uu_list_walk_next(walk); slp != NULL; slp = uu_list_walk_next(walk)) { if (slp->str[0] == '-') { char *op; for (op = &slp->str[1]; *op != '\0'; ++op) { switch (*op) { case 'v': g_verbose = 1; break; case 'V': g_verbose = 0; break; default: warn(gettext("Unknown option -%c.\n"), *op); } } } else { warn(gettext("No non-flag arguments defined.\n")); } } return (0); }
entity_t * internal_instance_new(const char *name) { entity_t *i; i = internal_entity_new(SVCCFG_INSTANCE_OBJECT); i->sc_name = name; /* Can't set i->sc_fmri until we're attached to a service. */ i->sc_dependents = uu_list_create(pgroup_pool, i, 0); if (i->sc_dependents == NULL) { uu_die(gettext("Unable to create list for instance " "dependents. %s\n"), uu_strerror(uu_error())); } return (i); }
entity_t * internal_instance_new(const char *name) { entity_t *i; if ((i = uu_zalloc(sizeof (entity_t))) == NULL) uu_die(gettext("couldn't allocate memory")); uu_list_node_init(i, &i->sc_node, entity_pool); i->sc_name = name; /* Can't set i->sc_fmri until we're attached to a service. */ i->sc_etype = SVCCFG_INSTANCE_OBJECT; i->sc_pgroups = uu_list_create(pgroup_pool, i, 0); i->sc_dependents = uu_list_create(pgroup_pool, i, 0); return (i); }
pgroup_t * internal_pgroup_find_or_create(entity_t *e, const char *name, const char *type) { pgroup_t *pg; pg = internal_pgroup_find(e, name, type); if (pg != NULL) return (pg); pg = internal_pgroup_new(); (void) internal_attach_pgroup(e, pg); pg->sc_pgroup_name = strdup(name); pg->sc_pgroup_type = strdup(type); pg->sc_pgroup_flags = 0; if (pg->sc_pgroup_name == NULL || pg->sc_pgroup_type == NULL) uu_die(gettext("Could not duplicate string")); return (pg); }
/* * Send a message to the user. If we're interactive, send it to stdout. * Otherwise send it to stderr. */ static void vmessage(const char *fmt, va_list va) { int interactive = est->sc_cmd_flags & SC_CMD_IACTIVE; FILE *strm = interactive ? stdout : stderr; const char *ptr; if (!interactive) { if (est->sc_cmd_file == NULL) (void) fprintf(stderr, "%s: ", myname); else (void) fprintf(stderr, "%s (%s, line %d): ", myname, est->sc_cmd_filename, est->sc_cmd_lineno - 1); } if (vfprintf(strm, fmt, va) < 0 && interactive) uu_die(gettext("printf() error")); ptr = strchr(fmt, '\0'); if (*(ptr - 1) != '\n') (void) fprintf(strm, ": %s.\n", strerror(errno)); }
/*ARGSUSED*/ static int internal_value_dump(void *v, void *pvt) { value_t *val = v; switch (val->sc_type) { case SCF_TYPE_BOOLEAN: (void) printf(" value = %s\n", val->sc_u.sc_count ? "true" : "false"); break; case SCF_TYPE_COUNT: (void) printf(" value = %llu\n", val->sc_u.sc_count); break; case SCF_TYPE_INTEGER: (void) printf(" value = %lld\n", val->sc_u.sc_integer); break; case SCF_TYPE_ASTRING: case SCF_TYPE_FMRI: case SCF_TYPE_HOST: case SCF_TYPE_HOSTNAME: case SCF_TYPE_NET_ADDR_V4: case SCF_TYPE_NET_ADDR_V6: case SCF_TYPE_OPAQUE: case SCF_TYPE_TIME: case SCF_TYPE_URI: case SCF_TYPE_USTRING: (void) printf(" value = %s\n", val->sc_u.sc_string ? val->sc_u.sc_string : "(nil)"); break; default: uu_die(gettext("unknown value type (%d)\n"), val->sc_type); break; } return (UU_WALK_NEXT); }
static void list_defaults() { scf_handle_t *h; scf_error_t err; int i; inetd_prop_t *proptable; size_t numprops; if (((h = scf_handle_create(SCF_VERSION)) == NULL) || (scf_handle_bind(h) == -1)) scfdie(); if ((proptable = read_default_props(h, &numprops, &err)) == NULL) { uu_die(gettext("Unexpected libscf error: %s. Exiting.\n"), scf_strerror(err)); } (void) printf("NAME=VALUE\n"); for (i = 0; i < numprops; i++) { if (!proptable[i].ip_default) continue; if (proptable[i].ip_error == IVE_UNSET) { (void) uu_warn(gettext("Error: Default property %s " "missing.\n"), proptable[i].ip_name); continue; } (void) printf("%s=", proptable[i].ip_name); print_prop_val(&proptable[i]); } free_instance_props(proptable); }
/* * void method_store_contract() * Store the newly created contract id into local structures and * the repository. If the repository connection is broken it is rebound. */ static void method_store_contract(restarter_inst_t *inst, int type, ctid_t *cid) { int r; boolean_t primary; if (errno = contract_latest(cid)) uu_die("%s: Couldn't get new contract's id", inst->ri_i.i_fmri); primary = !method_is_transient(inst, type); if (!primary) { if (inst->ri_i.i_transient_ctid != 0) { log_framework(LOG_INFO, "%s: transient ctid expected to be 0 but " "was set to %ld\n", inst->ri_i.i_fmri, inst->ri_i.i_transient_ctid); } inst->ri_i.i_transient_ctid = *cid; } else { if (inst->ri_i.i_primary_ctid != 0) { /* * There was an old contract that we transferred. * Remove it. */ method_remove_contract(inst, B_TRUE, B_FALSE); } if (inst->ri_i.i_primary_ctid != 0) { log_framework(LOG_INFO, "%s: primary ctid expected to be 0 but " "was set to %ld\n", inst->ri_i.i_fmri, inst->ri_i.i_primary_ctid); } inst->ri_i.i_primary_ctid = *cid; inst->ri_i.i_primary_ctid_stopped = 0; contract_hash_store(*cid, inst->ri_id); } again: if (inst->ri_mi_deleted) return; r = restarter_store_contract(inst->ri_m_inst, *cid, primary ? RESTARTER_CONTRACT_PRIMARY : RESTARTER_CONTRACT_TRANSIENT); switch (r) { case 0: break; case ECANCELED: inst->ri_mi_deleted = B_TRUE; break; case ECONNABORTED: libscf_handle_rebind(scf_instance_handle(inst->ri_m_inst)); /* FALLTHROUGH */ case EBADF: libscf_reget_instance(inst); goto again; case ENOMEM: case EPERM: case EACCES: case EROFS: uu_die("%s: Couldn't store contract id %ld", inst->ri_i.i_fmri, *cid); /* NOTREACHED */ case EINVAL: default: bad_error("restarter_store_contract", r); } }
int main(int argc, char *argv[]) { int c; scf_walk_callback callback; int flags; int err; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); return_code = UU_EXIT_OK; (void) uu_setpname(argv[0]); prop_pool = uu_list_pool_create("properties", sizeof (svcprop_prop_node_t), offsetof(svcprop_prop_node_t, spn_list_node), NULL, 0); if (prop_pool == NULL) uu_die("%s\n", uu_strerror(uu_error())); prop_list = uu_list_create(prop_pool, NULL, 0); hndl = scf_handle_create(SCF_VERSION); if (hndl == NULL) scfdie(); while ((c = getopt(argc, argv, "Ccfp:qs:tvwz:")) != -1) { switch (c) { case 'C': if (cflag || sflag || wait) usage(); /* Not with -c, -s or -w */ Cflag++; snapshot = NULL; break; case 'c': if (Cflag || sflag || wait) usage(); /* Not with -C, -s or -w */ cflag++; snapshot = NULL; break; case 'f': types = 1; fmris = 1; break; case 'p': add_prop(optarg); break; case 'q': quiet = 1; warn = quiet_warn; die = quiet_die; break; case 's': if (Cflag || cflag || wait) usage(); /* Not with -C, -c or -w */ snapshot = optarg; sflag++; break; case 't': types = 1; break; case 'v': verbose = 1; break; case 'w': if (Cflag || cflag || sflag) usage(); /* Not with -C, -c or -s */ wait = 1; break; case 'z': { scf_value_t *zone; scf_handle_t *h = hndl; if (getzoneid() != GLOBAL_ZONEID) uu_die(gettext("svcprop -z may only be used " "from the global zone\n")); if ((zone = scf_value_create(h)) == NULL) scfdie(); if (scf_value_set_astring(zone, optarg) != SCF_SUCCESS) scfdie(); if (scf_handle_decorate(h, "zone", zone) != SCF_SUCCESS) uu_die(gettext("invalid zone '%s'\n"), optarg); scf_value_destroy(zone); break; } case '?': switch (optopt) { case 'p': usage(); default: break; } /* FALLTHROUGH */ default: usage(); } } if (optind == argc) usage(); max_scf_name_length = scf_limit(SCF_LIMIT_MAX_NAME_LENGTH); max_scf_value_length = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH); max_scf_fmri_length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); if (max_scf_name_length == -1 || max_scf_value_length == -1 || max_scf_fmri_length == -1) scfdie(); if (scf_handle_bind(hndl) == -1) die(gettext("Could not connect to configuration repository: " "%s.\n"), scf_strerror(scf_error())); flags = SCF_WALK_PROPERTY | SCF_WALK_SERVICE | SCF_WALK_EXPLICIT; if (wait) { if (uu_list_numnodes(prop_list) > 1) usage(); if (argc - optind > 1) usage(); callback = do_wait; } else { callback = process_fmri; flags |= SCF_WALK_MULTIPLE; } if ((err = scf_walk_fmri(hndl, argc - optind, argv + optind, flags, callback, NULL, &return_code, warn)) != 0) { warn(gettext("failed to iterate over instances: %s\n"), scf_strerror(err)); return_code = UU_EXIT_FATAL; } scf_handle_destroy(hndl); return (return_code); }
/* * int method_ready_contract(restarter_inst_t *, int, method_restart_t, int) * * Activate a contract template for the type method of inst. type, * restart_on, and cte_mask dictate the critical events term of the contract. * Returns * 0 - success * ECANCELED - inst has been deleted from the repository */ static int method_ready_contract(restarter_inst_t *inst, int type, method_restart_t restart_on, uint_t cte_mask) { int tmpl, err, istrans, iswait, ret; uint_t cevents, fevents; /* * Correctly supporting wait-style services is tricky without * rearchitecting startd to cope with multiple event sources * simultaneously trying to stop an instance. Until a better * solution is implemented, we avoid this problem for * wait-style services by making contract events fatal and * letting the wait code alone handle stopping the service. */ iswait = instance_is_wait_style(inst); istrans = method_is_transient(inst, type); tmpl = open64(CTFS_ROOT "/process/template", O_RDWR); if (tmpl == -1) uu_die("Could not create contract template"); /* * We assume non-login processes are unlikely to create * multiple process groups, and set CT_PR_PGRPONLY for all * wait-style services' contracts. */ err = ct_pr_tmpl_set_param(tmpl, CT_PR_INHERIT | CT_PR_REGENT | (iswait ? CT_PR_PGRPONLY : 0)); assert(err == 0); if (istrans) { cevents = 0; fevents = 0; } else { assert(restart_on >= 0); assert(restart_on <= METHOD_RESTART_ANY_FAULT); cevents = method_events[restart_on] & ~cte_mask; fevents = iswait ? (method_events[restart_on] & ~cte_mask & CT_PR_ALLFATAL) : 0; } err = ct_tmpl_set_critical(tmpl, cevents); assert(err == 0); err = ct_tmpl_set_informative(tmpl, 0); assert(err == 0); err = ct_pr_tmpl_set_fatal(tmpl, fevents); assert(err == 0); err = ct_tmpl_set_cookie(tmpl, istrans ? METHOD_OTHER_COOKIE : METHOD_START_COOKIE); assert(err == 0); if (type == METHOD_START && inst->ri_i.i_primary_ctid != 0) { ret = ct_pr_tmpl_set_transfer(tmpl, inst->ri_i.i_primary_ctid); switch (ret) { case 0: break; case ENOTEMPTY: /* No contracts for you! */ method_remove_contract(inst, B_TRUE, B_TRUE); if (inst->ri_mi_deleted) { ret = ECANCELED; goto out; } break; case EINVAL: case ESRCH: case EACCES: default: bad_error("ct_pr_tmpl_set_transfer", ret); } } err = ct_tmpl_activate(tmpl); assert(err == 0); ret = 0; out: err = close(tmpl); assert(err == 0); return (ret); }